Files
openidea/src/editor/lsp/semantic/php/constructs.ts
T
Muuandmuutot 200ab10e65 refactor(lsp): register per-language semantics under lsp/semantic (#1687)
Python's highlighting hooks, member intentions and Implement Methods, and PHP's construct docs move under semantic/python and semantic/php behind a small registry of language-specific behaviour. Intentions now run only for the current document's language. Behaviour is otherwise unchanged; the generic language sets stay next to their users.

Co-authored-by: muutot <[email protected]>
2026-11-08 02:42:53 +08:00

41 lines
1.8 KiB
TypeScript

import type { EditorState } from "@codemirror/state";
import { syntaxTree } from "@codemirror/language";
const CONSTRUCTS: Readonly<Record<string, { signature: string; description: string }>> = {
empty: {
signature: "empty(mixed $var): bool",
description:
"Returns true when the value is falsey or the variable does not exist. Checking an undefined variable does not emit a warning.",
},
isset: {
signature: "isset(mixed $var, mixed ...$vars): bool",
description:
"Returns true only when every supplied variable exists and is not null. Checks stop at the first unset or null variable.",
},
};
export function phpConstructDocumentation(language: string | null, name: string): string | null {
if (language?.toLowerCase() !== "php") return null;
const key = name.toLowerCase();
const entry = Object.hasOwn(CONSTRUCTS, key) ? CONSTRUCTS[key] : undefined;
if (!entry) return null;
return [
"```php\n" + entry.signature + "\n```",
entry.description,
"PHP language construct; there is no source declaration to navigate to.",
`[PHP manual](https://www.php.net/manual/en/function.${key}.php)`,
].join("\n\n");
}
/** Only an unqualified call, never a method, variable, string, comment or HTML text. */
export function phpConstructAt(state: EditorState, pos: number, language: string | null) {
if (language?.toLowerCase() !== "php") return null;
for (const side of [-1, 1] as const) {
const node = syntaxTree(state).resolveInner(pos, side);
if (node.name !== "Name" || node.parent?.name !== "CallExpression" || node.parent.from !== node.from) continue;
const markdown = phpConstructDocumentation(language, state.sliceDoc(node.from, node.to));
if (markdown) return { from: node.from, to: node.to, markdown };
}
return null;
}