diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1a6cf71..3673a4e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -39,6 +39,7 @@
"OpenVSX",
"ovsx",
"resthumb",
+ "themable",
"tropy",
"tscn",
"typeparameters",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5caad80..6415cca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,18 @@
Features currently in early access are marked with 🔒 as they're restricted to [supporters].
Features previously in early access are marked with ***vX.Y.Z*** 🔓 as they're unlocked for everyone since that version.
+## [0.1.1] - 2024-10-28
+### Added
+- GDAsset: Show engine classes as inlay hints on `ExtResource(…)` and `SubResource(…)` references.
+- GDAsset: Show file paths as inlay hints on `ExtResource(…)` references.
+- GDShader: Add `#error` directive to preprocessor and to syntax coloring.
+- Docs: Add text content provider for doc URI, so it shows the webpage URL when peeking a class/member definition.
+### Fixed
+- Stronger pattern to match files with more priority than other extensions like godot-tools.
+- GDAsset: Bypass max limit of 44 inlay hint characters shown per line on vector|color array parentheses.
+ This feature will still respect `editor.maxTokenizationLineLength` to avoid potential performance issues.
+- GDAsset: Use `$"../TopNode"` instead of `$"/root/TopNode"` in the outline, as scenes are not always under root.
+
## [0.1.0] - 2024-10-16
### Changed
- GDShader: Disable url detection by default, since in BBCode it incorrectly includes the `[/url]` end tag too.
@@ -147,7 +159,8 @@ Features previously in early access are marked with ***vX.Y.Z*** 🔓 as they're
- GDAsset: Image and font previews by hovering references and paths.
- GDAsset: Hover resource references to show GDScript preload code.
-[Unreleased]: https://github.com/AlfishSoftware/godot-files-vscode/compare/v0.1.0...develop
+[Unreleased]: https://github.com/AlfishSoftware/godot-files-vscode/compare/v0.1.1...develop
+[0.1.1]: https://github.com/AlfishSoftware/godot-files-vscode/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/AlfishSoftware/godot-files-vscode/compare/v0.0.10...v0.1.0
[0.0.10]: https://github.com/AlfishSoftware/godot-files-vscode/compare/v0.0.9...v0.0.10
[0.0.9]: https://github.com/AlfishSoftware/godot-files-vscode/compare/v0.0.8...v0.0.9
diff --git a/README.md b/README.md
index febf7f4..b74c21c 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,24 @@
# Godot Files
-Basic GDShader support, better syntax-coloring and additional features for some Godot files.
-This is *not* meant to replace the official [godot-tools] extension, but to improve on its supported files. This plugin is designed so it can work alongside it, but it's completely independent. If you're using GDScript, you'll likely want to install godot-tools too; if not, just this one is enough.
+**Basic GDShader support, better syntax-coloring and additional features for some Godot files.**
+Godot Editor does NOT need to be running for any features here.
[godot-tools]: https://github.com/godotengine/godot-vscode-plugin
-> 🥺 Please help prevent this extension from being abandoned by [donating to the crowdfunding][donate]!
+> 🥺 Please help prevent this extension from being abandoned in 2025-01-31 by [donating to the crowdfunding goal][donate]!
> 🔑 With a donation, you can **unlock early access and other rewards**! More info below.
![Showcasing various features, like GDShader errors, hovering, navigating and documentation pages](docs/showcase-all.png "* Features showcased here include those restricted to early access.")
+This is not meant to fully replace the official [godot-tools] extension, but to improve on its supported files. This plugin is designed so it can work alongside it, but it's completely independent. If you're using GDScript, you'll likely want to install godot-tools too; if not, just this one is enough.
+🔧 You can use the setting `files.associations` to set your preferred extension to handle `*.tscn`, `*.tres`, etc.
+
**Compatibility**:
-- Godot: 3.x LTS and 4.0 to 4.x; official and flathub builds
-- godot-tools: v2.3.0
+- **Godot**: 3.x LTS and 4.0 to 4.x; official and flathub builds
+- **godot-tools**: v2.3.0; *("view documentation" feature can use godot-tools)*
-🌐 This extension also works on browser IDEs ([vscode.dev](https://vscode.dev) and [github.dev](https://github.dev)), with limited functionality.
+🌐 This extension also works on browser IDEs ([vscode.dev](https://vscode.dev) and [github.dev](https://github.dev)), with minor limitations.
## Features
Features are supported on these languages:
@@ -43,7 +46,7 @@ Syntax-coloring of valid embedded code is supported.
Note that you should always put the inner code in its own lines verbatim, without the leading `*`, or any extra leading indentation.
![Showcasing how you should embed code in GDShader docs BBCode](docs/showcase-gdshader-docs-embed-code.webp)
-The inner code doesn't break the container code syntax, as long as it's valid code (without partial contructs like unterminated strings/comments, mismatched brackets, etc). Some cases are being handled, but it's not viable to try to safeguard against every possible case of invalid code; this is a limitation of the IDE.
+The inner code doesn't break the container code syntax, as long as it's valid code (without partial constructs like unterminated strings/comments, mismatched brackets, etc). Some cases are being handled, but it's not viable to try to safeguard against every possible case of invalid code; this is a limitation of the IDE.
### Document Symbols
Symbol definitions are provided for:
@@ -58,7 +61,7 @@ These features are supported in textual Scene and Resource files.
- **Navigate to the definition** of `SubResource` and `ExtResource` references, and to resource paths.
![Showcasing navigate to definition](docs/showcase-goto-definition.png)
- Going to the definition of a built-in engine type (on `type="SomeType"` or `some_field = SomeType(...)`) will open its Godot API Documentation. This will be handled by the *godot-tools* extension, unless you're online and enabled [early access][donate] (see below).
+ Going to the definition of a built-in engine type (on `type="SomeType"`, `some_field = SomeType(...)` or in inlay hints) will open its Godot API Documentation. This will be handled by the *godot-tools* extension, unless you're online and enabled [early access][donate] (see below).
- **See GDScript code for loading** a resource reference or path by hovering (`preload(…)`, `load(…)` or `FileAccess.open(…)`).
![Showcasing code for loading when previewing user path](docs/showcase-user-path-load.webp)
@@ -86,6 +89,12 @@ These features are supported in textual Scene and Resource files.
As well as any other resource files that have a thumbnail in Godot Editor:
![Showcasing thumbnail preview of a material resource](docs/showcase-material-thumb.webp)
+- 🌟 **New**:
+ **See inferred class and path of resource references** in inlay hints. You can Ctrl+Click them to navigate. You can also hover paths.
+ ✳️ Paths are only shown at the end of a line (so not within arrays, you can still hover the code itself to see the path in this case).
+ 🔧 You can control this feature in the settings under `godotFiles.clarifyReferences` (`.class` and `.filePath`). By default, the class is only hinted where it cannot be inferred from the context, so in Godot 4 it will typically not be shown for `SubResource`, as it's already in the id (unless you set it to `always`).
+ ![Showcasing classes and paths as inlay hints on resource references](docs/showcase-inlay-hints-resource-refs.webp)
+
- **Edit a color by hovering its inline decorator** on `Color(…)` values or within an array. You can also see its hex value.
🔧 You can disable this feature with the settings under `godotFiles.inlineColors` (`.single` and `.array`).
![Showcasing inline color decorators](docs/showcase-color-decorators.webp)
@@ -94,9 +103,9 @@ These features are supported in textual Scene and Resource files.
#### Latest feature no longer restricted
🌟 This is now out of early access:
-- **See implied parentheses in packed arrays** of vectors or colors with the inlay hints that surround items.
- ✳️ This is *not* supported syntax in asset files! These parentheses are only shown for clarity.
+- **See implied parentheses in packed arrays** of vectors or colors that surround items, similar to inlay hints.
🔧 You can toggle this feature with the settings under `godotFiles.clarifyArrays` (`.vector` and `.color`).
+ ✳️ This feature respects `editor.maxTokenizationLineLength` to avoid potential performance issues on very long lines.
![Showcasing implied parentheses in array items as inlay hints](docs/showcase-parentheses-hint-in-arrays.webp)
If you want **more features**, check the sections **Early Access**, **Crowdfunding** and **Potential Future Development** below.
diff --git a/docs/showcase-inlay-hints-resource-refs.webp b/docs/showcase-inlay-hints-resource-refs.webp
new file mode 100644
index 0000000..7d5d72b
Binary files /dev/null and b/docs/showcase-inlay-hints-resource-refs.webp differ
diff --git a/lang.gdshader/gdshader.tmLanguage.json b/lang.gdshader/gdshader.tmLanguage.json
index 877eb73..4b497c2 100644
--- a/lang.gdshader/gdshader.tmLanguage.json
+++ b/lang.gdshader/gdshader.tmLanguage.json
@@ -17,11 +17,16 @@
]
},
"text": {
+ "patterns": [
+ { "include": "#comment" },
+ { "include": "#string" }
+ ]
+ },
+ "comment": {
"patterns": [
{ "include": "#commentLine" },
{ "include": "#commentBlockDocumentation" },
- { "include": "#commentBlock" },
- { "include": "#string" }
+ { "include": "#commentBlock" }
]
},
"code": {
@@ -595,7 +600,8 @@
{ "include": "#directivePragma" },
{ "include": "#directiveDefineMacro" },
{ "include": "#directiveDefine" },
- { "include": "#directiveConditional" }
+ { "include": "#directiveConditional" },
+ { "include": "#directiveError" }
]
},
"directiveInclude": {
@@ -662,6 +668,20 @@
"1": { "name": "punctuation.definition.directive.gdshader" }
}
},
+ "directiveError": {
+ "name": "meta.preprocessor.error.gdshader",
+ "begin": "((\\#)error)\\b\\s*",
+ "beginCaptures": {
+ "1": { "name": "keyword.control.directive.error.gdshader" },
+ "2": { "name": "punctuation.definition.directive.gdshader" }
+ },
+ "end": "(? {
- const settings = workspace.getConfiguration('godotFiles', document);
- const clarifyVectors = settings.get('clarifyArrays.vector')!;
- const clarifyColors = settings.get('clarifyArrays.color')!;
- if (!clarifyVectors && !clarifyColors) return null;
+ async provideInlayHints(document: TextDocument, range: Range, token: CancellationToken
+ ): Promise {
+ const settings = workspace.getConfiguration('godotFiles.clarifyReferences', document);
+ const sClass = settings.get('class') ?? 'auto';
+ const sFilePaths = settings.get('filePath')!;
+ if (sClass == 'never' && sFilePaths == 'none') return null;
const gdasset = await this.parsedGDAsset(document, token);
if (!gdasset || token.isCancellationRequested) return null;
const hints: InlayHint[] = [];
- // locate all packed vector arrays using regex, skipping occurrences inside a comment or string
const reqStart = document.offsetAt(range.start);
const reqSrc = document.getText(range);
- for (const m of reqSrc.matchAll(/\b(P(?:acked|ool)(?:Vector([234])|Color)Array)(\s*\(\s*)([\s,\w.+-]*?)\s*\)/g)) {
+ // locate all calls using regex, skipping occurrences inside a comment or string
+ for (const m of reqSrc.matchAll(
+ /\b(?<=(instance[ \t]*=)?[ \t]*)((?:Ext|Sub)Resource|NodePath)[ \t]*\(\s*(?:(\d+)|"([^"\r\n]*)")\s*\)(?=([ \t]*\])?[ \t]*([^;\r\n]?))/g
+ )) {
+ const matchStart = reqStart + m.index, matchEnd = matchStart + m[0].length;
+ const matchRange = new Range(document.positionAt(matchStart), document.positionAt(matchEnd));
+ if (gdasset.isNonCode(matchRange)) continue;
+ const bracket = m[5], instancing = !!(m[1] && bracket);
+ const fn = m[2] as 'ExtResource' | 'SubResource' | 'NodePath', eol = !m[6] && (!bracket || instancing);
+ if (fn == 'NodePath') {
+ continue; //TODO
+ } else {
+ const id = m[3] ?? GDAssetProvider.unescapeString(m[4]!);
+ const resource = gdasset.refs[fn][id];
+ if (!resource) continue;
+ const { type, typeRange, pathRange } = resource, { end } = matchRange;
+ if (sClass == 'always' ||
+ sClass == 'auto' && !(instancing && type == 'PackedScene') && type != 'Resource' && !id.startsWith(type + '_')
+ ) {
+ const typePos = end;
+ hints.push(new InlayHint(typePos, ' as '));
+ const typeLabel = new InlayHintLabelPart(type);
+ if (typeRange) typeLabel.location = new Location(document.uri, typeRange);
+ const typeHint = new InlayHint(typePos, [typeLabel], InlayHintKind.Type);
+ hints.push(typeHint);
+ }
+ if (pathRange && eol && sFilePaths != 'none') {
+ const pathPos = bracket ? end.translate(0, bracket.length) : end;
+ const { path } = resource, pathLabel = new InlayHintLabelPart(path);
+ pathLabel.location = new Location(document.uri, pathRange);
+ const pathHint = new InlayHint(pathPos, [new InlayHintLabelPart('; '), pathLabel]);
+ hints.push(pathHint);
+ }
+ }
+ }
+ return hints;
+ }
+ decorateVectorParentheses(document: TextDocument, gdasset: GDAsset): Range[] {
+ const settings = workspace.getConfiguration('godotFiles.clarifyArrays', document);
+ const clarifyVectors = settings.get('vector')!;
+ const clarifyColors = settings.get('color')!;
+ if (!clarifyVectors && !clarifyColors) return [];
+ const maxChars = workspace.getConfiguration('editor', document).get('maxTokenizationLineLength')!;
+ const ranges: Range[] = [];
+ const src = document.getText();
+ // locate all packed vector arrays using regex, skipping occurrences inside a comment or string
+ for (const m of src.matchAll(/\b(P(?:acked|ool)(?:Vector([234])|Color)Array)(\s*\(\s*)([\s,\w.+-]*?)\s*\)/g)) {
+ const charLength = m[0].length;
+ if (charLength >= maxChars) continue;
const dim = m[2];
if (dim && !clarifyVectors || !dim && !clarifyColors) continue;
- const ctorStart = reqStart + m.index;
- const ctorRange = new Range(document.positionAt(ctorStart), document.positionAt(ctorStart + m[0].length));
+ const ctorStart = m.index;
+ const ctorRange = new Range(document.positionAt(ctorStart), document.positionAt(ctorStart + charLength));
if (gdasset.isNonCode(ctorRange)) continue;
const type = m[1]!, paren = m[3]!, allArgs = m[4]!;
const typeEnd = ctorStart + type.length;
@@ -399,18 +464,10 @@ export default class GDAssetProvider implements
const args = c[0];
const itemPos = argsStart + c.index!;
const itemRange = new Range(document.positionAt(itemPos), document.positionAt(itemPos + args.length));
- const head = new InlayHint(itemRange.start, '(');
- // head.tooltip = `[${i++}]`; // would need to provide 0-based indices for all types of array
- const tail = new InlayHint(itemRange.end, ')');
- // tail.tooltip = `vector #${i}`; // would need to provide 1-based indices for all types of array
- hints.push(head, tail);
+ ranges.push(itemRange);
}
- //TODO would need to provide size for all arrays and dictionary
- // const arrayHead = new InlayHint(document.positionAt(typeEnd), `[${i}]`);
- // arrayHead.tooltip = i == 0 ? 'empty' : `${i} vector${i == 1 ? '' : 's'}`;
- // hints.push(arrayHead);
}
- return hints;
+ return ranges;
}
async provideDocumentColors(document: TextDocument, token: CancellationToken): Promise {
@@ -465,7 +522,26 @@ export default class GDAssetProvider implements
function ok(c: number) { return c >= 0 && c <= 1; }
function hex(c: number) { return Math.round(c * 255).toString(16).toUpperCase().replace(/^.$/s, '0$&'); }
}
+
+ static updateDecorations(document: TextDocument, decorations: DecorationRanges): void {
+ for (const editor of window.visibleTextEditors.filter(e => e.document == document)) {
+ editor.setDecorations(parenthesesDecoration, decorations.vectorParentheses);
+ }
+ }
+}
+
+interface DecorationRanges {
+ vectorParentheses: Range[];
}
+const themeColorInlayFg = new ThemeColor('editorInlayHint.foreground');
+const themeColorInlayBg = new ThemeColor('editorInlayHint.background');
+const themeInlay: ThemableDecorationAttachmentRenderOptions = {
+ color: themeColorInlayFg, backgroundColor: themeColorInlayBg,
+ fontWeight: 'normal', fontStyle: 'normal', textDecoration: 'none',
+};
+const parenthesesDecoration = window.createTextEditorDecorationType({
+ before: { ...themeInlay, contentText: '(' }, after: { ...themeInlay, contentText: ')' },
+});
const regex2Floats = /(?:[\w.+-]+\s*,\s*)?[\w.+-]+/g;
const regex3Floats = /(?:[\w.+-]+\s*,\s*){0,2}[\w.+-]+/g;
diff --git a/src/GDShader/GDShaderPreprocessor.ts b/src/GDShader/GDShaderPreprocessor.ts
index e6bbd16..66fe3b3 100644
--- a/src/GDShader/GDShaderPreprocessor.ts
+++ b/src/GDShader/GDShaderPreprocessor.ts
@@ -579,6 +579,8 @@ export const preprocessorErrorTypes = {
PEvalDiv: docsUrl + '#if',
PPragmaExtra: docsUrl + '#pragma',
+
+ PErrorDirective: docsUrl + '#error',
};
/** Represents a parsed preprocessor construct from which code is replaced. */
@@ -739,6 +741,8 @@ async function directive(
return ifDirective(tokens, diagnostics, isActive(branchingStack), location, line, macros);
case 'pragma':
return pragmaDirective(tokens, diagnostics, isActive(branchingStack), location, line);
+ case 'error':
+ return errorDirective(tokens, diagnostics, isActive(branchingStack), location, line);
default:
const msg = `invalid or unsupported directive '#${directiveKeyword}' in: '${line}'`;
diagnostics.push({ location, msg, id: 'PDirectiveMiss' });
@@ -1332,7 +1336,7 @@ function parseExpressionAtom(uri: string, expr: ExpressionTokens): ExpressionAto
const msg = `unexpected extra code around condition atom`, { start, end } = errToken;
throw { location: { uri, start, end }, msg, id: 'PConditionSyntax' } as PreprocessorDiagnostic;
}
- if (token instanceof ExpressionTokens) {
+ if (token instanceof ParenthesizedTokens) {
const inner = parseExpressionTree(uri, token);
if (inner instanceof ExpressionTree) return new ParenthesizedExpression(token.open, inner, token.close);
if (inner) throw inner;
@@ -1507,7 +1511,6 @@ export class PragmaDirective extends PreprocessorDirective {
super(location, mainRange, line);
}
}
-
function pragmaDirective(
tokens: readonly PreprocessorToken[], diagnostics: PreprocessorDiagnostic[], activeParent: boolean,
location: CodeLocation, line: string
@@ -1536,3 +1539,31 @@ function pragmaDirective(
}
return { code: line, construct: new PragmaDirective(location, mainRange, line, command, afterCommand) };
}
+
+export class ErrorDirective extends PreprocessorDirective {
+ constructor(location: CodeLocation, mainRange: CodeRange, line: string,
+ readonly message: string,
+ ) {
+ super(location, mainRange, line);
+ }
+}
+function errorDirective(
+ tokens: readonly PreprocessorToken[], diagnostics: PreprocessorDiagnostic[], activeParent: boolean,
+ location: CodeLocation, line: string
+): PreprocessedOutput {
+ const n = tokens.length;
+ let i = 3, mainRange: CodeRange;
+ while (i < n && /^[ \t]*$/.test(tokens[i]!.code)) i++; // skip initial whitespace until first code token
+ let j = n - 1, message = '';
+ if (i >= n) mainRange = location;
+ else {
+ while (j > i && /^[ \t]*$/.test(tokens[j]!.code)) j--; // skip final whitespace until last code token
+ mainRange = { start: tokens[i]!.start, end: tokens[j]!.end };
+ for (let k = i; k <= j; k++) message += tokens[k]!.code;
+ }
+ const msg = message || '#error';
+ const construct = new ErrorDirective(location, mainRange, line, message);
+ if (activeParent)
+ diagnostics.push({ location, msg, id: 'PErrorDirective' });
+ return { code: commentOut(line), construct };
+}
diff --git a/src/GDShader/GDShaderProvider.ts b/src/GDShader/GDShaderProvider.ts
index 128fa3f..a2993b0 100644
--- a/src/GDShader/GDShaderProvider.ts
+++ b/src/GDShader/GDShaderProvider.ts
@@ -102,7 +102,7 @@ export default class GDShaderProvider implements
models: { [uri: string]: GDShaderModel | undefined; } = {};
async provideDocumentSymbols(document: TextDocument, _token: CancellationToken): Promise {
const config = workspace.getConfiguration('godotFiles');
- const analysisLevel = config.get('shader.analysisLevel', 'complete');
+ const analysisLevel = config.get('shader.analysisLevel') ?? 'complete';
if (analysisLevel == 'none') {
this.diagnostics.set(document.uri, []);
return [];
diff --git a/src/GodotContentTextProvider.ts b/src/GodotContentTextProvider.ts
new file mode 100644
index 0000000..da99763
--- /dev/null
+++ b/src/GodotContentTextProvider.ts
@@ -0,0 +1,17 @@
+import {
+ CancellationToken, TextDocumentContentProvider, Uri,
+} from 'vscode';
+import { GodotDocumentationProvider, onlineDocsHost } from './GodotDocs';
+
+export default class GodotContentTextProvider implements TextDocumentContentProvider {
+ async provideTextDocumentContent(uri: Uri, token: CancellationToken): Promise {
+ const { path } = uri;
+ if (path.match(/^.*?\/godot\.docs\.(?:[\w-]+):\//)) {
+ const { urlPath, title, urlFragment } = GodotDocumentationProvider.parseUri(uri);
+ const url = `https://${onlineDocsHost}/${urlPath}${urlFragment}`;
+ return `${title}\n\n${url}\n`;
+ // We could fetch the HTML or RST and show text here, like the description.
+ }
+ return null;
+ }
+}
diff --git a/src/GodotDocs.ts b/src/GodotDocs.ts
index 636a9a1..f067097 100644
--- a/src/GodotDocs.ts
+++ b/src/GodotDocs.ts
@@ -8,7 +8,7 @@ import GodotFiles, { ctx } from './ExtensionEntry';
import { GodotVersion, godotVersionOfDocument, godotVersionOfProject } from './GodotProject';
const toUTF8 = new TextDecoder();
-const onlineDocsHost = 'docs.godotengine.org';
+export const onlineDocsHost = 'docs.godotengine.org';
const latestApiGodot3 = '3.6';
const latestApiGodot2 = '2.1';
function apiVersion(gdVersion: GodotVersion | null) {
diff --git a/src/Parsing/LanguageSpec.ts b/src/Parsing/LanguageSpec.ts
index c658929..686d433 100644
--- a/src/Parsing/LanguageSpec.ts
+++ b/src/Parsing/LanguageSpec.ts
@@ -105,7 +105,11 @@ function tokenRange(symbol: Token) {
export default abstract class LanguageSpec {
abstract parserDefinitions(tree: ParserRule): DefinitionConstruct[] | DefinitionConstruct | null | string;
+ #parserDefinitions(
+ tree: ParserRule
+ ) { return this['parserDefinitions'](tree); }
abstract sourcemap(range: Range): Range | null;
+ #sourcemap(range: Range): Range | null { return this['sourcemap'](range); }
addParserSymbols(tree: ParseTree, symbols: DocumentSymbol[]): void {
if (!(tree instanceof ParserRuleContext)) return;
const branches = tree.children ?? [];
@@ -113,13 +117,13 @@ export default abstract class LanguageSpec {
for (const child of branches) {
this.addParserSymbols(child, subSymbols);
}
- const defConstructs = this.parserDefinitions(tree);
+ const defConstructs = this.#parserDefinitions(tree);
if (defConstructs == null) {
symbols.push(...subSymbols); // excluding a rule means any sub-symbols it may have are promoted to its level
return; // but the rule itself is not included
}
if (typeof defConstructs == 'string') {
- const range = this.sourcemap(ruleRange(tree));
+ const range = this.#sourcemap(ruleRange(tree));
if (!range) return;
const ruleName = tree.constructor.name.replace(/Context$/, '');
const symbol = new DocumentSymbol(defConstructs, ruleName, SymbolKind.Object, range, range);
@@ -138,10 +142,10 @@ export default abstract class LanguageSpec {
const constructName = typeof id == 'string' ? id
: id instanceof Token ? id.text : id?.getText() ?? '-';
const subRangeOutput = treeRange(defConstruct.range);
- const subRange = subRangeOutput ? this.sourcemap(subRangeOutput) : this.sourcemap(ruleRange(tree));
+ const subRange = subRangeOutput ? this.#sourcemap(subRangeOutput) : this.#sourcemap(ruleRange(tree));
if (!subRange) return;
const idRangeOutput = treeRange(id);
- const idRange = idRangeOutput ? this.sourcemap(idRangeOutput) : subRange;
+ const idRange = idRangeOutput ? this.#sourcemap(idRangeOutput) : subRange;
if (!idRange) return;
const symbol = new DocumentSymbol(constructName, defConstruct.detail, defConstruct.kind, subRange, idRange);
if (defConstruct.isDeprecated) symbol.tags = [SymbolTag.Deprecated];