@astrojs/language-server 0.28.3 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/documents/DocumentMapper.d.ts +13 -7
- package/dist/core/documents/DocumentMapper.js +30 -12
- package/dist/core/worker/TSXService.d.ts +7 -0
- package/dist/core/worker/TSXService.js +12 -0
- package/dist/core/worker/TSXWorker.d.ts +1 -0
- package/dist/core/worker/TSXWorker.js +9 -0
- package/dist/plugins/astro/AstroPlugin.d.ts +3 -2
- package/dist/plugins/astro/AstroPlugin.js +5 -1
- package/dist/plugins/astro/features/CompletionsProvider.d.ts +2 -2
- package/dist/plugins/astro/features/DiagnosticsProvider.d.ts +10 -0
- package/dist/plugins/astro/features/DiagnosticsProvider.js +23 -0
- package/dist/plugins/typescript/TypeScriptPlugin.d.ts +2 -2
- package/dist/plugins/typescript/TypeScriptPlugin.js +8 -10
- package/dist/plugins/typescript/astro2tsx.d.ts +2 -4
- package/dist/plugins/typescript/astro2tsx.js +4 -91
- package/dist/plugins/typescript/features/CodeActionsProvider.js +18 -9
- package/dist/plugins/typescript/features/CompletionsProvider.d.ts +2 -2
- package/dist/plugins/typescript/features/CompletionsProvider.js +15 -15
- package/dist/plugins/typescript/features/DefinitionsProvider.d.ts +1 -1
- package/dist/plugins/typescript/features/DefinitionsProvider.js +13 -11
- package/dist/plugins/typescript/features/DiagnosticsProvider.d.ts +0 -1
- package/dist/plugins/typescript/features/DiagnosticsProvider.js +8 -24
- package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +4 -7
- package/dist/plugins/typescript/features/FileReferencesProvider.js +4 -5
- package/dist/plugins/typescript/features/FoldingRangesProvider.js +6 -2
- package/dist/plugins/typescript/features/HoverProvider.js +4 -5
- package/dist/plugins/typescript/features/ImplementationsProvider.js +10 -8
- package/dist/plugins/typescript/features/InlayHintsProvider.js +3 -4
- package/dist/plugins/typescript/features/ReferencesProvider.js +9 -8
- package/dist/plugins/typescript/features/SemanticTokenProvider.js +8 -9
- package/dist/plugins/typescript/features/SignatureHelpProvider.js +1 -2
- package/dist/plugins/typescript/features/TypeDefinitionsProvider.js +7 -7
- package/dist/plugins/typescript/features/utils.d.ts +5 -16
- package/dist/plugins/typescript/features/utils.js +11 -18
- package/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts +30 -45
- package/dist/plugins/typescript/snapshots/DocumentSnapshot.js +50 -43
- package/dist/plugins/typescript/snapshots/SnapshotManager.js +0 -4
- package/dist/plugins/typescript/snapshots/utils.js +3 -2
- package/dist/plugins/typescript/utils.d.ts +2 -2
- package/dist/utils.js +3 -2
- package/package.json +5 -3
|
@@ -56,13 +56,14 @@ class CompletionsProviderImpl {
|
|
|
56
56
|
this.lastCompletion = undefined;
|
|
57
57
|
}
|
|
58
58
|
const html = document.html;
|
|
59
|
-
const
|
|
60
|
-
const node = html.findNodeAt(
|
|
59
|
+
const documentOffset = document.offsetAt(position);
|
|
60
|
+
const node = html.findNodeAt(documentOffset);
|
|
61
61
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
62
|
+
const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
|
|
62
63
|
let filePath = tsDoc.filePath;
|
|
63
64
|
let completions;
|
|
64
|
-
const isCompletionInsideFrontmatter = (0, utils_1.isInsideFrontmatter)(document.getText(),
|
|
65
|
-
const isCompletionInsideExpression = (0, utils_1.isInsideExpression)(document.getText(), node.start,
|
|
65
|
+
const isCompletionInsideFrontmatter = (0, utils_1.isInsideFrontmatter)(document.getText(), documentOffset);
|
|
66
|
+
const isCompletionInsideExpression = (0, utils_1.isInsideExpression)(document.getText(), node.start, documentOffset);
|
|
66
67
|
const tsPreferences = await this.configManager.getTSPreferences(document);
|
|
67
68
|
const formatOptions = await this.configManager.getTSFormatConfig(document);
|
|
68
69
|
let scriptTagIndex = undefined;
|
|
@@ -105,11 +106,10 @@ class CompletionsProviderImpl {
|
|
|
105
106
|
? vscode_languageserver_1.Range.create(document.positionAt(completions.optionalReplacementSpan.start), document.positionAt(completions.optionalReplacementSpan.start + completions.optionalReplacementSpan.length))
|
|
106
107
|
: undefined;
|
|
107
108
|
const wordRangeStartPosition = wordRange?.start;
|
|
108
|
-
const fragment = await tsDoc.createFragment();
|
|
109
109
|
const existingImports = this.getExistingImports(document);
|
|
110
110
|
const completionItems = completions.entries
|
|
111
111
|
.filter((completion) => this.isValidCompletion(completion, this.ts))
|
|
112
|
-
.map((entry) => this.toCompletionItem(
|
|
112
|
+
.map((entry) => this.toCompletionItem(tsDoc, entry, filePath, offset, isCompletionInsideFrontmatter, scriptTagIndex, existingImports))
|
|
113
113
|
.filter(utils_2.isNotNullOrUndefined)
|
|
114
114
|
.map((comp) => this.fixTextEditRange(wordRangeStartPosition, comp));
|
|
115
115
|
const completionList = vscode_languageserver_1.CompletionList.create(completionItems, true);
|
|
@@ -123,7 +123,6 @@ class CompletionsProviderImpl {
|
|
|
123
123
|
if (!data || !data.filePath || cancellationToken?.isCancellationRequested) {
|
|
124
124
|
return item;
|
|
125
125
|
}
|
|
126
|
-
const fragment = await tsDoc.createFragment();
|
|
127
126
|
const detail = lang.getCompletionEntryDetails(data.filePath, // fileName
|
|
128
127
|
data.offset, // position
|
|
129
128
|
data.originalItem.name, // entryName
|
|
@@ -154,17 +153,18 @@ class CompletionsProviderImpl {
|
|
|
154
153
|
for (const change of action.changes) {
|
|
155
154
|
if (isInsideScriptTag) {
|
|
156
155
|
change.textChanges.forEach((textChange) => {
|
|
157
|
-
|
|
156
|
+
const originalPosition = scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(textChange.span.start));
|
|
157
|
+
textChange.span.start = tsDoc.offsetAt(tsDoc.getGeneratedPosition(originalPosition));
|
|
158
158
|
});
|
|
159
159
|
}
|
|
160
|
-
edit.push(...change.textChanges.map((textChange) => codeActionChangeToTextEdit(document,
|
|
160
|
+
edit.push(...change.textChanges.map((textChange) => codeActionChangeToTextEdit(document, tsDoc, isInsideScriptTag, textChange, this.ts)));
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
item.additionalTextEdits = (item.additionalTextEdits ?? []).concat(edit);
|
|
164
164
|
}
|
|
165
165
|
return item;
|
|
166
166
|
}
|
|
167
|
-
toCompletionItem(
|
|
167
|
+
toCompletionItem(snapshot, comp, filePath, offset, insideFrontmatter, scriptTagIndex, existingImports) {
|
|
168
168
|
let item = vscode_languageserver_protocol_1.CompletionItem.create(comp.name);
|
|
169
169
|
const isAstroComponent = this.isAstroComponentImport(comp.name);
|
|
170
170
|
const isImport = comp.insertText?.includes('import');
|
|
@@ -212,13 +212,13 @@ class CompletionsProviderImpl {
|
|
|
212
212
|
item.insertText = comp.insertText ? (0, utils_3.removeAstroComponentSuffix)(comp.insertText) : undefined;
|
|
213
213
|
item.insertTextFormat = comp.isSnippet ? vscode_languageserver_1.InsertTextFormat.Snippet : vscode_languageserver_1.InsertTextFormat.PlainText;
|
|
214
214
|
item.textEdit = comp.replacementSpan
|
|
215
|
-
? vscode_languageserver_1.TextEdit.replace((0, utils_3.convertRange)(
|
|
215
|
+
? vscode_languageserver_1.TextEdit.replace((0, utils_3.convertRange)(snapshot, comp.replacementSpan), item.insertText ?? item.label)
|
|
216
216
|
: undefined;
|
|
217
217
|
}
|
|
218
218
|
return {
|
|
219
219
|
...item,
|
|
220
220
|
data: {
|
|
221
|
-
uri:
|
|
221
|
+
uri: snapshot.getURL(),
|
|
222
222
|
filePath,
|
|
223
223
|
scriptTagIndex,
|
|
224
224
|
offset,
|
|
@@ -303,12 +303,12 @@ class CompletionsProviderImpl {
|
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
305
|
exports.CompletionsProviderImpl = CompletionsProviderImpl;
|
|
306
|
-
function codeActionChangeToTextEdit(document,
|
|
306
|
+
function codeActionChangeToTextEdit(document, snapshot, isInsideScriptTag, change, ts) {
|
|
307
307
|
change.newText = (0, utils_3.removeAstroComponentSuffix)(change.newText);
|
|
308
308
|
const { span } = change;
|
|
309
309
|
let range;
|
|
310
|
-
const virtualRange = (0, utils_3.convertRange)(
|
|
311
|
-
range = (0, documents_1.mapRangeToOriginal)(
|
|
310
|
+
const virtualRange = (0, utils_3.convertRange)(snapshot, span);
|
|
311
|
+
range = (0, documents_1.mapRangeToOriginal)(snapshot, virtualRange);
|
|
312
312
|
if (!isInsideScriptTag) {
|
|
313
313
|
// If we don't have a frontmatter already, create one with the import
|
|
314
314
|
const frontmatterState = document.astroMeta.frontmatter.state;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LocationLink, Position } from 'vscode-languageserver-types';
|
|
2
|
-
import
|
|
2
|
+
import { AstroDocument } from '../../../core/documents';
|
|
3
3
|
import type { DefinitionsProvider } from '../../interfaces';
|
|
4
4
|
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
|
5
5
|
export declare class DefinitionsProviderImpl implements DefinitionsProvider {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DefinitionsProviderImpl = void 0;
|
|
4
4
|
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
|
5
|
+
const documents_1 = require("../../../core/documents");
|
|
5
6
|
const utils_1 = require("../../../utils");
|
|
6
7
|
const utils_2 = require("../utils");
|
|
7
8
|
const utils_3 = require("./utils");
|
|
@@ -11,9 +12,8 @@ class DefinitionsProviderImpl {
|
|
|
11
12
|
}
|
|
12
13
|
async getDefinitions(document, position) {
|
|
13
14
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const fragmentOffset = mainFragment.offsetAt(fragmentPosition);
|
|
15
|
+
const fragmentPosition = tsDoc.getGeneratedPosition(position);
|
|
16
|
+
const fragmentOffset = tsDoc.offsetAt(fragmentPosition);
|
|
17
17
|
let defs;
|
|
18
18
|
const html = document.html;
|
|
19
19
|
const offset = document.offsetAt(position);
|
|
@@ -26,11 +26,11 @@ class DefinitionsProviderImpl {
|
|
|
26
26
|
const isInSameFile = def.fileName === scriptFilePath;
|
|
27
27
|
def.fileName = isInSameFile ? tsDoc.filePath : def.fileName;
|
|
28
28
|
if (isInSameFile) {
|
|
29
|
-
def.textSpan.start =
|
|
29
|
+
def.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(def.textSpan, scriptTagSnapshot, tsDoc);
|
|
30
30
|
}
|
|
31
31
|
return def;
|
|
32
32
|
});
|
|
33
|
-
defs.textSpan.start =
|
|
33
|
+
defs.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(defs.textSpan, scriptTagSnapshot, tsDoc);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
@@ -39,16 +39,18 @@ class DefinitionsProviderImpl {
|
|
|
39
39
|
if (!defs || !defs.definitions) {
|
|
40
40
|
return [];
|
|
41
41
|
}
|
|
42
|
-
const
|
|
43
|
-
|
|
42
|
+
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
|
43
|
+
snapshots.set(tsDoc.filePath, tsDoc);
|
|
44
44
|
const result = await Promise.all(defs.definitions.map(async (def) => {
|
|
45
|
-
const
|
|
45
|
+
const snapshot = await snapshots.retrieve(def.fileName);
|
|
46
46
|
const fileName = (0, utils_2.ensureRealFilePath)(def.fileName);
|
|
47
47
|
// For Astro, Svelte and Vue, the position is wrongly mapped to the end of the file due to the TSX output
|
|
48
48
|
// So we'll instead redirect to the beginning of the file
|
|
49
|
-
const isFramework = (0, utils_2.isFrameworkFilePath)(def.fileName) || (0, utils_2.isAstroFilePath)(def.fileName);
|
|
50
|
-
const
|
|
51
|
-
|
|
49
|
+
const isFramework = ((0, utils_2.isFrameworkFilePath)(def.fileName) || (0, utils_2.isAstroFilePath)(def.fileName)) && tsDoc.filePath !== def.fileName;
|
|
50
|
+
const targetRange = isFramework
|
|
51
|
+
? (0, utils_2.convertRange)(document, { start: 0, length: 0 })
|
|
52
|
+
: (0, utils_2.convertToLocationRange)(snapshot, def.textSpan);
|
|
53
|
+
return vscode_languageserver_types_1.LocationLink.create((0, utils_1.pathToUrl)(fileName), targetRange, targetRange, (0, utils_2.convertToLocationRange)(tsDoc, defs.textSpan));
|
|
52
54
|
}));
|
|
53
55
|
return result.filter(utils_1.isNotNullOrUndefined);
|
|
54
56
|
}
|
|
@@ -7,7 +7,6 @@ export declare enum DiagnosticCodes {
|
|
|
7
7
|
SPREAD_EXPECTED = 1005,
|
|
8
8
|
IS_NOT_A_MODULE = 2306,
|
|
9
9
|
DUPLICATED_JSX_ATTRIBUTES = 17001,
|
|
10
|
-
MUST_HAVE_PARENT_ELEMENT = 2657,
|
|
11
10
|
CANT_RETURN_OUTSIDE_FUNC = 1108,
|
|
12
11
|
ISOLATED_MODULE_COMPILE_ERR = 1208,
|
|
13
12
|
TYPE_NOT_ASSIGNABLE = 2322,
|
|
@@ -12,7 +12,6 @@ var DiagnosticCodes;
|
|
|
12
12
|
DiagnosticCodes[DiagnosticCodes["SPREAD_EXPECTED"] = 1005] = "SPREAD_EXPECTED";
|
|
13
13
|
DiagnosticCodes[DiagnosticCodes["IS_NOT_A_MODULE"] = 2306] = "IS_NOT_A_MODULE";
|
|
14
14
|
DiagnosticCodes[DiagnosticCodes["DUPLICATED_JSX_ATTRIBUTES"] = 17001] = "DUPLICATED_JSX_ATTRIBUTES";
|
|
15
|
-
DiagnosticCodes[DiagnosticCodes["MUST_HAVE_PARENT_ELEMENT"] = 2657] = "MUST_HAVE_PARENT_ELEMENT";
|
|
16
15
|
DiagnosticCodes[DiagnosticCodes["CANT_RETURN_OUTSIDE_FUNC"] = 1108] = "CANT_RETURN_OUTSIDE_FUNC";
|
|
17
16
|
DiagnosticCodes[DiagnosticCodes["ISOLATED_MODULE_COMPILE_ERR"] = 1208] = "ISOLATED_MODULE_COMPILE_ERR";
|
|
18
17
|
DiagnosticCodes[DiagnosticCodes["TYPE_NOT_ASSIGNABLE"] = 2322] = "TYPE_NOT_ASSIGNABLE";
|
|
@@ -31,7 +30,11 @@ class DiagnosticsProviderImpl {
|
|
|
31
30
|
return [];
|
|
32
31
|
}
|
|
33
32
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
34
|
-
|
|
33
|
+
// If we have compiler errors, our TSX isn't valid so don't bother showing TS errors
|
|
34
|
+
if (tsDoc.compilerDiagnostics.filter((diag) => diag.severity === vscode_languageserver_1.DiagnosticSeverity.Error).length >
|
|
35
|
+
0) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
35
38
|
let scriptDiagnostics = [];
|
|
36
39
|
document.scriptTags.forEach((scriptTag) => {
|
|
37
40
|
const { filePath: scriptFilePath, snapshot: scriptTagSnapshot } = (0, utils_1.getScriptTagSnapshot)(tsDoc, document, scriptTag.container);
|
|
@@ -71,7 +74,7 @@ class DiagnosticsProviderImpl {
|
|
|
71
74
|
code: diagnostic.code,
|
|
72
75
|
tags: getDiagnosticTag(diagnostic),
|
|
73
76
|
}))
|
|
74
|
-
.map(mapRange(
|
|
77
|
+
.map(mapRange(tsDoc, document)),
|
|
75
78
|
...scriptDiagnostics,
|
|
76
79
|
]
|
|
77
80
|
.filter((diag) => {
|
|
@@ -79,8 +82,6 @@ class DiagnosticsProviderImpl {
|
|
|
79
82
|
// Make sure the diagnostic is inside the document and not in generated code
|
|
80
83
|
diag.range.start.line <= document.lineCount &&
|
|
81
84
|
hasNoNegativeLines(diag) &&
|
|
82
|
-
isNoJSXMustHaveOneParent(diag) &&
|
|
83
|
-
isNoSpreadExpected(diag, document) &&
|
|
84
85
|
isNoCantReturnOutsideFunction(diag) &&
|
|
85
86
|
isNoIsolatedModuleError(diag) &&
|
|
86
87
|
isNoJsxCannotHaveMultipleAttrsError(diag));
|
|
@@ -151,9 +152,9 @@ function diagnosticIsWithinBoundaries(sourceFile, boundaries, diagnostic, ts) {
|
|
|
151
152
|
function isNoWithinBoundary(boundaries, diagnostic, ts) {
|
|
152
153
|
return !diagnosticIsWithinBoundaries(undefined, boundaries, diagnostic, ts);
|
|
153
154
|
}
|
|
154
|
-
function mapRange(
|
|
155
|
+
function mapRange(snapshot, _document) {
|
|
155
156
|
return (diagnostic) => {
|
|
156
|
-
let range = (0, documents_1.mapRangeToOriginal)(
|
|
157
|
+
let range = (0, documents_1.mapRangeToOriginal)(snapshot, diagnostic.range);
|
|
157
158
|
return { ...diagnostic, range };
|
|
158
159
|
};
|
|
159
160
|
}
|
|
@@ -171,23 +172,6 @@ function hasNoNegativeLines(diagnostic) {
|
|
|
171
172
|
function isNoJsxCannotHaveMultipleAttrsError(diagnostic) {
|
|
172
173
|
return diagnostic.code !== DiagnosticCodes.DUPLICATED_JSX_ATTRIBUTES;
|
|
173
174
|
}
|
|
174
|
-
/** Astro allows component with multiple root elements */
|
|
175
|
-
function isNoJSXMustHaveOneParent(diagnostic) {
|
|
176
|
-
return diagnostic.code !== DiagnosticCodes.MUST_HAVE_PARENT_ELEMENT;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* When using the shorthand syntax for props TSX expects you to use the spread operator
|
|
180
|
-
* Since the shorthand syntax works differently in Astro and this is not required, hide this message
|
|
181
|
-
* However, the error code used here is quite generic, as such we need to make we only ignore in valid cases
|
|
182
|
-
*/
|
|
183
|
-
function isNoSpreadExpected(diagnostic, document) {
|
|
184
|
-
if (diagnostic.code === DiagnosticCodes.SPREAD_EXPECTED &&
|
|
185
|
-
diagnostic.message.includes('...') &&
|
|
186
|
-
document.offsetAt(diagnostic.range.start) > (document.astroMeta.frontmatter.endOffset ?? 0)) {
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
175
|
/**
|
|
192
176
|
* Ignore "Can't return outside of function body"
|
|
193
177
|
* Since the frontmatter is at the top level, users trying to return a Response for SSR mode run into this
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DocumentSymbolsProviderImpl = void 0;
|
|
4
4
|
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
|
5
|
-
const documents_1 = require("../../../core/documents");
|
|
6
5
|
const utils_1 = require("../utils");
|
|
7
6
|
class DocumentSymbolsProviderImpl {
|
|
8
7
|
constructor(languageServiceManager) {
|
|
@@ -11,13 +10,12 @@ class DocumentSymbolsProviderImpl {
|
|
|
11
10
|
}
|
|
12
11
|
async getDocumentSymbols(document) {
|
|
13
12
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
14
|
-
const fragment = await tsDoc.createFragment();
|
|
15
13
|
const navTree = lang.getNavigationTree(tsDoc.filePath + '?documentSymbols');
|
|
16
14
|
if (!navTree) {
|
|
17
15
|
return [];
|
|
18
16
|
}
|
|
19
17
|
const symbols = [];
|
|
20
|
-
this.collectSymbols(navTree,
|
|
18
|
+
this.collectSymbols(navTree, document, undefined, (symbol) => symbols.push(symbol));
|
|
21
19
|
const originalContainerName = symbols[0].name;
|
|
22
20
|
const result = [];
|
|
23
21
|
// Add a "Frontmatter" namespace for the frontmatter if we have a closed one
|
|
@@ -27,7 +25,6 @@ class DocumentSymbolsProviderImpl {
|
|
|
27
25
|
// Add a "Template" namespace for everything under the frontmatter
|
|
28
26
|
result.push(vscode_languageserver_types_1.SymbolInformation.create('Template', vscode_languageserver_types_1.SymbolKind.Namespace, vscode_languageserver_types_1.Range.create(document.positionAt(document.astroMeta.frontmatter.endOffset ?? 0), document.positionAt(document.getTextLength())), document.getURL()));
|
|
29
27
|
for (let symbol of symbols.splice(1)) {
|
|
30
|
-
symbol = (0, documents_1.mapSymbolInformationToOriginal)(fragment, symbol);
|
|
31
28
|
if (document.offsetAt(symbol.location.range.end) >= (document.astroMeta.content.firstNonWhitespaceOffset ?? 0)) {
|
|
32
29
|
if (symbol.containerName === originalContainerName) {
|
|
33
30
|
symbol.containerName = 'Template';
|
|
@@ -48,9 +45,9 @@ class DocumentSymbolsProviderImpl {
|
|
|
48
45
|
}
|
|
49
46
|
return result;
|
|
50
47
|
}
|
|
51
|
-
collectSymbols(item,
|
|
48
|
+
collectSymbols(item, document, container, cb) {
|
|
52
49
|
for (const span of item.spans) {
|
|
53
|
-
const symbol = vscode_languageserver_types_1.SymbolInformation.create(item.text, (0, utils_1.symbolKindFromString)(item.kind), vscode_languageserver_types_1.Range.create(
|
|
50
|
+
const symbol = vscode_languageserver_types_1.SymbolInformation.create(item.text, (0, utils_1.symbolKindFromString)(item.kind), vscode_languageserver_types_1.Range.create(document.positionAt(span.start), document.positionAt(span.start + span.length)), document.getURL(), container);
|
|
54
51
|
// TypeScript gives us kind modifiers as a string instead of an array
|
|
55
52
|
const kindModifiers = new Set(item.kindModifiers.split(/,|\s+/g));
|
|
56
53
|
if (kindModifiers.has(this.ts.ScriptElementKindModifier.deprecatedModifier)) {
|
|
@@ -62,7 +59,7 @@ class DocumentSymbolsProviderImpl {
|
|
|
62
59
|
}
|
|
63
60
|
if (item.childItems) {
|
|
64
61
|
for (const child of item.childItems) {
|
|
65
|
-
this.collectSymbols(child,
|
|
62
|
+
this.collectSymbols(child, document, item.text, cb);
|
|
66
63
|
}
|
|
67
64
|
}
|
|
68
65
|
}
|
|
@@ -11,16 +11,15 @@ class FileReferencesProviderImpl {
|
|
|
11
11
|
}
|
|
12
12
|
async fileReferences(document) {
|
|
13
13
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
14
|
-
const mainFragment = await tsDoc.createFragment();
|
|
15
14
|
const references = lang.getFileReferences(tsDoc.filePath);
|
|
16
15
|
if (!references) {
|
|
17
16
|
return null;
|
|
18
17
|
}
|
|
19
|
-
const
|
|
20
|
-
|
|
18
|
+
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
|
19
|
+
snapshots.set(tsDoc.filePath, tsDoc);
|
|
21
20
|
const locations = await Promise.all(references.map(async (ref) => {
|
|
22
|
-
const
|
|
23
|
-
return vscode_languageserver_1.Location.create((0, utils_1.pathToUrl)(ref.fileName), (0, utils_2.convertToLocationRange)(
|
|
21
|
+
const snapshot = await snapshots.retrieve(ref.fileName);
|
|
22
|
+
return vscode_languageserver_1.Location.create((0, utils_1.pathToUrl)(ref.fileName), (0, utils_2.convertToLocationRange)(snapshot, ref.textSpan));
|
|
24
23
|
}));
|
|
25
24
|
return locations;
|
|
26
25
|
}
|
|
@@ -27,13 +27,17 @@ class FoldingRangesProviderImpl {
|
|
|
27
27
|
});
|
|
28
28
|
const foldingRanges = [];
|
|
29
29
|
for (const span of [...outliningSpans, ...scriptOutliningSpans]) {
|
|
30
|
-
const start =
|
|
31
|
-
const end = adjustFoldingEnd(start, document.positionAt(
|
|
30
|
+
const start = tsDoc.getOriginalPosition(tsDoc.positionAt(span.textSpan.start));
|
|
31
|
+
const end = adjustFoldingEnd(start, document.positionAt(document.offsetAt(start) + span.textSpan.length), document);
|
|
32
32
|
// When using this method for generating folding ranges, TypeScript tend to return some
|
|
33
33
|
// one line / one character ones that we should be able to safely ignore
|
|
34
34
|
if (start.line === end.line && start.character === end.character) {
|
|
35
35
|
continue;
|
|
36
36
|
}
|
|
37
|
+
// Ignore folding ranges that are from unmapped regions
|
|
38
|
+
if (start.line < 0 || end.line < 0) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
37
41
|
foldingRanges.push(vscode_languageserver_1.FoldingRange.create(start.line, end.line, start.character, end.character, this.transformFoldingRangeKind(span.kind)));
|
|
38
42
|
}
|
|
39
43
|
return foldingRanges;
|
|
@@ -12,8 +12,7 @@ class HoverProviderImpl {
|
|
|
12
12
|
}
|
|
13
13
|
async doHover(document, position) {
|
|
14
14
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
15
|
-
const
|
|
16
|
-
const offset = fragment.offsetAt(fragment.getGeneratedPosition(position));
|
|
15
|
+
const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
|
|
17
16
|
const html = document.html;
|
|
18
17
|
const documentOffset = document.offsetAt(position);
|
|
19
18
|
const node = html.findNodeAt(documentOffset);
|
|
@@ -22,7 +21,7 @@ class HoverProviderImpl {
|
|
|
22
21
|
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_1.getScriptTagSnapshot)(tsDoc, document, node, position);
|
|
23
22
|
info = lang.getQuickInfoAtPosition(scriptFilePath, scriptOffset);
|
|
24
23
|
if (info) {
|
|
25
|
-
info.textSpan.start =
|
|
24
|
+
info.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(info.textSpan, scriptTagSnapshot, tsDoc);
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
else {
|
|
@@ -42,8 +41,8 @@ class HoverProviderImpl {
|
|
|
42
41
|
const contents = ['```typescript', declaration, '```']
|
|
43
42
|
.concat(documentation ? ['---', documentation] : [])
|
|
44
43
|
.join('\n');
|
|
45
|
-
return (0, documents_1.mapObjWithRangeToOriginal)(
|
|
46
|
-
range: (0, utils_1.convertRange)(
|
|
44
|
+
return (0, documents_1.mapObjWithRangeToOriginal)(tsDoc, {
|
|
45
|
+
range: (0, utils_1.convertRange)(tsDoc, textSpan),
|
|
47
46
|
contents,
|
|
48
47
|
});
|
|
49
48
|
}
|
|
@@ -12,8 +12,10 @@ class ImplementationsProviderImpl {
|
|
|
12
12
|
}
|
|
13
13
|
async getImplementation(document, position) {
|
|
14
14
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const fragmentPosition = tsDoc.getGeneratedPosition(position);
|
|
16
|
+
const fragmentOffset = tsDoc.offsetAt(fragmentPosition);
|
|
17
|
+
const html = document.html;
|
|
18
|
+
const offset = document.offsetAt(position);
|
|
17
19
|
const node = document.html.findNodeAt(offset);
|
|
18
20
|
let implementations;
|
|
19
21
|
if (node.tag === 'script') {
|
|
@@ -24,23 +26,23 @@ class ImplementationsProviderImpl {
|
|
|
24
26
|
const isInSameFile = impl.fileName === scriptFilePath;
|
|
25
27
|
impl.fileName = isInSameFile ? tsDoc.filePath : impl.fileName;
|
|
26
28
|
if (isInSameFile) {
|
|
27
|
-
impl.textSpan.start =
|
|
29
|
+
impl.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(impl.textSpan, scriptTagSnapshot, tsDoc);
|
|
28
30
|
}
|
|
29
31
|
return impl;
|
|
30
32
|
});
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
else {
|
|
34
|
-
implementations = lang.getImplementationAtPosition(tsDoc.filePath,
|
|
36
|
+
implementations = lang.getImplementationAtPosition(tsDoc.filePath, fragmentOffset);
|
|
35
37
|
}
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
+
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
|
39
|
+
snapshots.set(tsDoc.filePath, tsDoc);
|
|
38
40
|
if (!implementations) {
|
|
39
41
|
return null;
|
|
40
42
|
}
|
|
41
43
|
const result = await Promise.all(implementations.map(async (implementation) => {
|
|
42
|
-
const
|
|
43
|
-
const range = (0, documents_1.mapRangeToOriginal)(
|
|
44
|
+
const snapshot = await snapshots.retrieve(implementation.fileName);
|
|
45
|
+
const range = (0, documents_1.mapRangeToOriginal)(snapshot, (0, utils_2.convertRange)(snapshot, implementation.textSpan));
|
|
44
46
|
if (range.start.line >= 0 && range.end.line >= 0) {
|
|
45
47
|
return vscode_languageserver_types_1.Location.create((0, utils_1.pathToUrl)(implementation.fileName), range);
|
|
46
48
|
}
|
|
@@ -11,13 +11,12 @@ class InlayHintsProviderImpl {
|
|
|
11
11
|
}
|
|
12
12
|
async getInlayHints(document, range) {
|
|
13
13
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const end = fragment.offsetAt(fragment.getGeneratedPosition(range.end));
|
|
14
|
+
const start = tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.start));
|
|
15
|
+
const end = tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.end));
|
|
17
16
|
const tsPreferences = await this.configManager.getTSPreferences(document);
|
|
18
17
|
const inlayHints = lang.provideInlayHints(tsDoc.filePath, { start, length: end - start }, tsPreferences);
|
|
19
18
|
return inlayHints.map((hint) => {
|
|
20
|
-
const result = vscode_languageserver_1.InlayHint.create(
|
|
19
|
+
const result = vscode_languageserver_1.InlayHint.create(tsDoc.getOriginalPosition(tsDoc.positionAt(hint.position)), hint.text, hint.kind === this.ts.InlayHintKind.Type
|
|
21
20
|
? vscode_languageserver_types_1.InlayHintKind.Type
|
|
22
21
|
: hint.kind === this.ts.InlayHintKind.Parameter
|
|
23
22
|
? vscode_languageserver_types_1.InlayHintKind.Parameter
|
|
@@ -12,8 +12,9 @@ class FindReferencesProviderImpl {
|
|
|
12
12
|
}
|
|
13
13
|
async findReferences(document, position, context) {
|
|
14
14
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const fragmentPosition = tsDoc.getGeneratedPosition(position);
|
|
16
|
+
const fragmentOffset = tsDoc.offsetAt(fragmentPosition);
|
|
17
|
+
const offset = document.offsetAt(position);
|
|
17
18
|
const node = document.html.findNodeAt(offset);
|
|
18
19
|
let references;
|
|
19
20
|
if (node.tag === 'script') {
|
|
@@ -24,26 +25,26 @@ class FindReferencesProviderImpl {
|
|
|
24
25
|
const isInSameFile = ref.fileName === scriptFilePath;
|
|
25
26
|
ref.fileName = isInSameFile ? tsDoc.filePath : ref.fileName;
|
|
26
27
|
if (isInSameFile) {
|
|
27
|
-
ref.textSpan.start =
|
|
28
|
+
ref.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(ref.textSpan, scriptTagSnapshot, tsDoc);
|
|
28
29
|
}
|
|
29
30
|
return ref;
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
else {
|
|
34
|
-
references = lang.getReferencesAtPosition(tsDoc.filePath,
|
|
35
|
+
references = lang.getReferencesAtPosition(tsDoc.filePath, fragmentOffset);
|
|
35
36
|
}
|
|
36
37
|
if (!references) {
|
|
37
38
|
return null;
|
|
38
39
|
}
|
|
39
|
-
const
|
|
40
|
-
|
|
40
|
+
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
|
41
|
+
snapshots.set(tsDoc.filePath, tsDoc);
|
|
41
42
|
const result = await Promise.all(references.map(async (reference) => {
|
|
42
43
|
if (!context.includeDeclaration) {
|
|
43
44
|
return null;
|
|
44
45
|
}
|
|
45
|
-
const
|
|
46
|
-
const range = (0, documents_1.mapRangeToOriginal)(
|
|
46
|
+
const snapshot = await snapshots.retrieve(reference.fileName);
|
|
47
|
+
const range = (0, documents_1.mapRangeToOriginal)(snapshot, (0, utils_2.convertRange)(snapshot, reference.textSpan));
|
|
47
48
|
if (range.start.line >= 0 && range.end.line >= 0) {
|
|
48
49
|
return vscode_languageserver_types_1.Location.create((0, utils_1.pathToUrl)(reference.fileName), range);
|
|
49
50
|
}
|
|
@@ -10,17 +10,16 @@ class SemanticTokensProviderImpl {
|
|
|
10
10
|
}
|
|
11
11
|
async getSemanticTokens(document, range, cancellationToken) {
|
|
12
12
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
13
|
-
const fragment = (await tsDoc.createFragment());
|
|
14
13
|
if (cancellationToken?.isCancellationRequested) {
|
|
15
14
|
return null;
|
|
16
15
|
}
|
|
17
|
-
const start = range ?
|
|
16
|
+
const start = range ? tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.start)) : 0;
|
|
18
17
|
const { spans } = lang.getEncodedSemanticClassifications(tsDoc.filePath, {
|
|
19
18
|
start,
|
|
20
19
|
length: range
|
|
21
|
-
?
|
|
20
|
+
? tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.end)) - start
|
|
22
21
|
: // We don't want tokens for things added by astro2tsx
|
|
23
|
-
|
|
22
|
+
tsDoc.getFullText().lastIndexOf('export default function ') || tsDoc.getLength(),
|
|
24
23
|
}, this.ts.SemanticClassificationFormat.TwentyTwenty);
|
|
25
24
|
const tokens = [];
|
|
26
25
|
let i = 0;
|
|
@@ -28,7 +27,7 @@ class SemanticTokensProviderImpl {
|
|
|
28
27
|
const offset = spans[i++];
|
|
29
28
|
const generatedLength = spans[i++];
|
|
30
29
|
const classification = spans[i++];
|
|
31
|
-
const originalPosition = this.mapToOrigin(document,
|
|
30
|
+
const originalPosition = this.mapToOrigin(document, tsDoc, offset, generatedLength);
|
|
32
31
|
if (!originalPosition) {
|
|
33
32
|
continue;
|
|
34
33
|
}
|
|
@@ -50,12 +49,12 @@ class SemanticTokensProviderImpl {
|
|
|
50
49
|
const build = builder.build();
|
|
51
50
|
return build;
|
|
52
51
|
}
|
|
53
|
-
mapToOrigin(document,
|
|
52
|
+
mapToOrigin(document, snapshot, generatedOffset, generatedLength) {
|
|
54
53
|
const range = {
|
|
55
|
-
start:
|
|
56
|
-
end:
|
|
54
|
+
start: snapshot.positionAt(generatedOffset),
|
|
55
|
+
end: snapshot.positionAt(generatedOffset + generatedLength),
|
|
57
56
|
};
|
|
58
|
-
const { start: startPosition, end: endPosition } = (0, documents_1.mapRangeToOriginal)(
|
|
57
|
+
const { start: startPosition, end: endPosition } = (0, documents_1.mapRangeToOriginal)(snapshot, range);
|
|
59
58
|
if (startPosition.line < 0 || endPosition.line < 0) {
|
|
60
59
|
return;
|
|
61
60
|
}
|
|
@@ -11,11 +11,10 @@ class SignatureHelpProviderImpl {
|
|
|
11
11
|
}
|
|
12
12
|
async getSignatureHelp(document, position, context, cancellationToken) {
|
|
13
13
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
14
|
-
const fragment = await tsDoc.createFragment();
|
|
15
14
|
if (cancellationToken?.isCancellationRequested) {
|
|
16
15
|
return null;
|
|
17
16
|
}
|
|
18
|
-
const offset =
|
|
17
|
+
const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
|
|
19
18
|
const node = document.html.findNodeAt(offset);
|
|
20
19
|
let info;
|
|
21
20
|
const triggerReason = this.toTsTriggerReason(context);
|
|
@@ -12,8 +12,8 @@ class TypeDefinitionsProviderImpl {
|
|
|
12
12
|
}
|
|
13
13
|
async getTypeDefinitions(document, position) {
|
|
14
14
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
15
|
-
const
|
|
16
|
-
const fragmentOffset =
|
|
15
|
+
const fragmentPosition = tsDoc.getGeneratedPosition(position);
|
|
16
|
+
const fragmentOffset = tsDoc.offsetAt(fragmentPosition);
|
|
17
17
|
const html = document.html;
|
|
18
18
|
const offset = document.offsetAt(position);
|
|
19
19
|
const node = html.findNodeAt(offset);
|
|
@@ -26,7 +26,7 @@ class TypeDefinitionsProviderImpl {
|
|
|
26
26
|
const isInSameFile = def.fileName === scriptFilePath;
|
|
27
27
|
def.fileName = isInSameFile ? tsDoc.filePath : def.fileName;
|
|
28
28
|
if (isInSameFile) {
|
|
29
|
-
def.textSpan.start =
|
|
29
|
+
def.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(def.textSpan, scriptTagSnapshot, tsDoc);
|
|
30
30
|
}
|
|
31
31
|
return def;
|
|
32
32
|
});
|
|
@@ -35,15 +35,15 @@ class TypeDefinitionsProviderImpl {
|
|
|
35
35
|
else {
|
|
36
36
|
typeDefs = lang.getTypeDefinitionAtPosition(tsDoc.filePath, fragmentOffset);
|
|
37
37
|
}
|
|
38
|
-
const
|
|
39
|
-
|
|
38
|
+
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
|
39
|
+
snapshots.set(tsDoc.filePath, tsDoc);
|
|
40
40
|
if (!typeDefs) {
|
|
41
41
|
return [];
|
|
42
42
|
}
|
|
43
43
|
const result = await Promise.all(typeDefs.map(async (typeDef) => {
|
|
44
|
-
const
|
|
44
|
+
const snapshot = await snapshots.retrieve(typeDef.fileName);
|
|
45
45
|
const fileName = (0, utils_2.ensureRealFilePath)(typeDef.fileName);
|
|
46
|
-
const range = (0, documents_1.mapRangeToOriginal)(
|
|
46
|
+
const range = (0, documents_1.mapRangeToOriginal)(snapshot, (0, utils_2.convertRange)(snapshot, typeDef.textSpan));
|
|
47
47
|
if (range.start.line >= 0 && range.end.line >= 0) {
|
|
48
48
|
return vscode_languageserver_protocol_1.Location.create((0, utils_1.pathToUrl)(fileName), range);
|
|
49
49
|
}
|
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
import type ts from 'typescript';
|
|
2
2
|
import type { Position } from 'vscode-languageserver';
|
|
3
3
|
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
|
4
|
-
import type { DocumentSnapshot
|
|
4
|
+
import type { DocumentSnapshot } from '../snapshots/DocumentSnapshot';
|
|
5
5
|
export declare function isPartOfImportStatement(text: string, position: Position): boolean;
|
|
6
|
-
export declare class
|
|
6
|
+
export declare class SnapshotMap {
|
|
7
7
|
private languageServiceManager;
|
|
8
8
|
private map;
|
|
9
9
|
constructor(languageServiceManager: LanguageServiceManager);
|
|
10
|
-
set(fileName: string,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}): void;
|
|
14
|
-
get(fileName: string): {
|
|
15
|
-
fragment: SnapshotFragment;
|
|
16
|
-
snapshot: DocumentSnapshot;
|
|
17
|
-
} | undefined;
|
|
18
|
-
getFragment(fileName: string): SnapshotFragment | undefined;
|
|
19
|
-
retrieve(fileName: string): Promise<{
|
|
20
|
-
fragment: SnapshotFragment;
|
|
21
|
-
snapshot: DocumentSnapshot;
|
|
22
|
-
}>;
|
|
23
|
-
retrieveFragment(fileName: string): Promise<SnapshotFragment>;
|
|
10
|
+
set(fileName: string, snapshot: DocumentSnapshot): void;
|
|
11
|
+
get(fileName: string): DocumentSnapshot | undefined;
|
|
12
|
+
retrieve(fileName: string): Promise<DocumentSnapshot>;
|
|
24
13
|
}
|
|
25
14
|
export declare function findContainingNode<T extends ts.Node>(node: ts.Node, textSpan: ts.TextSpan, predicate: (node: ts.Node) => node is T): T | undefined;
|