@astrojs/language-server 0.16.0 → 0.18.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/CHANGELOG.md +30 -0
- package/dist/core/config/ConfigManager.d.ts +25 -16
- package/dist/core/config/ConfigManager.js +160 -46
- package/dist/core/config/interfaces.d.ts +4 -51
- package/dist/core/documents/AstroDocument.d.ts +1 -0
- package/dist/core/documents/AstroDocument.js +1 -0
- package/dist/core/documents/DocumentMapper.d.ts +2 -0
- package/dist/core/documents/DocumentMapper.js +7 -5
- package/dist/core/documents/utils.d.ts +1 -0
- package/dist/core/documents/utils.js +16 -1
- package/dist/plugins/PluginHost.d.ts +3 -1
- package/dist/plugins/PluginHost.js +8 -0
- package/dist/plugins/astro/AstroPlugin.d.ts +1 -6
- package/dist/plugins/astro/AstroPlugin.js +10 -85
- package/dist/plugins/astro/features/CompletionsProvider.d.ts +4 -5
- package/dist/plugins/astro/features/CompletionsProvider.js +53 -58
- package/dist/plugins/css/CSSPlugin.d.ts +5 -5
- package/dist/plugins/css/CSSPlugin.js +36 -31
- package/dist/plugins/html/HTMLPlugin.d.ts +6 -5
- package/dist/plugins/html/HTMLPlugin.js +38 -16
- package/dist/plugins/html/features/astro-attributes.js +1 -0
- package/dist/plugins/interfaces.d.ts +5 -2
- package/dist/plugins/typescript/TypeScriptPlugin.d.ts +7 -4
- package/dist/plugins/typescript/TypeScriptPlugin.js +34 -110
- package/dist/plugins/typescript/features/CodeActionsProvider.d.ts +3 -1
- package/dist/plugins/typescript/features/CodeActionsProvider.js +82 -17
- package/dist/plugins/typescript/features/CompletionsProvider.d.ts +5 -3
- package/dist/plugins/typescript/features/CompletionsProvider.js +112 -56
- package/dist/plugins/typescript/features/DefinitionsProvider.d.ts +9 -0
- package/dist/plugins/typescript/features/DefinitionsProvider.js +57 -0
- package/dist/plugins/typescript/features/DiagnosticsProvider.js +58 -15
- package/dist/plugins/typescript/features/FoldingRangesProvider.js +13 -6
- package/dist/plugins/typescript/features/FormattingProvider.d.ts +11 -0
- package/dist/plugins/typescript/features/FormattingProvider.js +132 -0
- package/dist/plugins/typescript/features/HoverProvider.js +14 -1
- package/dist/plugins/typescript/features/InlayHintsProvider.d.ts +12 -0
- package/dist/plugins/typescript/features/InlayHintsProvider.js +36 -0
- package/dist/plugins/typescript/features/SignatureHelpProvider.js +9 -1
- package/dist/plugins/typescript/language-service.js +18 -0
- package/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts +22 -2
- package/dist/plugins/typescript/snapshots/DocumentSnapshot.js +48 -1
- package/dist/plugins/typescript/snapshots/SnapshotManager.js +1 -0
- package/dist/plugins/typescript/snapshots/utils.js +3 -2
- package/dist/plugins/typescript/utils.d.ts +11 -1
- package/dist/plugins/typescript/utils.js +17 -1
- package/dist/server.js +27 -15
- package/package.json +7 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CodeAction, CodeActionContext, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FileChangeType, FoldingRange, FormattingOptions, Hover, LinkedEditingRanges, Position, Range, ReferenceContext, SelectionRange, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, TextDocumentIdentifier, TextEdit, WorkspaceEdit } from 'vscode-languageserver';
|
|
1
|
+
import { CodeAction, CodeActionContext, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FileChangeType, FoldingRange, FormattingOptions, Hover, InlayHint, LinkedEditingRanges, Position, Range, ReferenceContext, SelectionRange, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, TextDocumentIdentifier, TextEdit, WorkspaceEdit } from 'vscode-languageserver';
|
|
2
2
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
3
|
export declare type Resolvable<T> = T | Promise<T>;
|
|
4
4
|
export interface AppCompletionItem<T extends TextDocumentIdentifier = any> extends CompletionItem {
|
|
@@ -52,6 +52,9 @@ export interface FileRename {
|
|
|
52
52
|
export interface UpdateImportsProvider {
|
|
53
53
|
updateImports(fileRename: FileRename): Resolvable<WorkspaceEdit | null>;
|
|
54
54
|
}
|
|
55
|
+
export interface InlayHintsProvider {
|
|
56
|
+
getInlayHints(document: TextDocument, range: Range): Resolvable<InlayHint[]>;
|
|
57
|
+
}
|
|
55
58
|
export interface RenameProvider {
|
|
56
59
|
rename(document: TextDocument, position: Position, newName: string): Resolvable<WorkspaceEdit | null>;
|
|
57
60
|
prepareRename(document: TextDocument, position: Position): Resolvable<Range | null>;
|
|
@@ -81,7 +84,7 @@ export interface OnWatchFileChangesProvider {
|
|
|
81
84
|
export interface UpdateNonAstroFile {
|
|
82
85
|
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): void;
|
|
83
86
|
}
|
|
84
|
-
declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & DefinitionsProvider & FormattingProvider & FoldingRangesProvider & TagCompleteProvider & DocumentColorsProvider & ColorPresentationsProvider & DocumentSymbolsProvider & UpdateImportsProvider & CodeActionsProvider & FindReferencesProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & SelectionRangeProvider & OnWatchFileChangesProvider & LinkedEditingRangesProvider & UpdateNonAstroFile;
|
|
87
|
+
declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & DefinitionsProvider & FormattingProvider & FoldingRangesProvider & TagCompleteProvider & DocumentColorsProvider & ColorPresentationsProvider & DocumentSymbolsProvider & UpdateImportsProvider & CodeActionsProvider & FindReferencesProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & SelectionRangeProvider & OnWatchFileChangesProvider & LinkedEditingRangesProvider & InlayHintsProvider & UpdateNonAstroFile;
|
|
85
88
|
export declare type LSProvider = ProviderBase;
|
|
86
89
|
export declare type Plugin = Partial<ProviderBase> & {
|
|
87
90
|
__name: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CancellationToken, CodeAction, CodeActionContext, CompletionContext, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
|
|
1
|
+
import { CancellationToken, CodeAction, CodeActionContext, CompletionContext, DefinitionLink, Diagnostic, FoldingRange, FormattingOptions, Hover, InlayHint, Position, Range, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, TextEdit, WorkspaceEdit } from 'vscode-languageserver';
|
|
2
2
|
import { ConfigManager } from '../../core/config';
|
|
3
3
|
import { AstroDocument, DocumentManager } from '../../core/documents';
|
|
4
4
|
import { AppCompletionItem, AppCompletionList, OnWatchFileChangesParam, Plugin } from '../interfaces';
|
|
@@ -10,26 +10,29 @@ export declare class TypeScriptPlugin implements Plugin {
|
|
|
10
10
|
private readonly codeActionsProvider;
|
|
11
11
|
private readonly completionProvider;
|
|
12
12
|
private readonly hoverProvider;
|
|
13
|
+
private readonly definitionsProvider;
|
|
13
14
|
private readonly signatureHelpProvider;
|
|
14
15
|
private readonly diagnosticsProvider;
|
|
15
16
|
private readonly documentSymbolsProvider;
|
|
17
|
+
private readonly inlayHintsProvider;
|
|
16
18
|
private readonly semanticTokensProvider;
|
|
17
19
|
private readonly foldingRangesProvider;
|
|
20
|
+
private readonly formattingProvider;
|
|
18
21
|
constructor(docManager: DocumentManager, configManager: ConfigManager, workspaceUris: string[]);
|
|
19
22
|
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
|
|
20
23
|
rename(document: AstroDocument, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
|
24
|
+
formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
|
|
21
25
|
getFoldingRanges(document: AstroDocument): Promise<FoldingRange[] | null>;
|
|
22
|
-
getSemanticTokens(
|
|
26
|
+
getSemanticTokens(document: AstroDocument, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
|
|
23
27
|
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
|
|
24
28
|
getCodeActions(document: AstroDocument, range: Range, context: CodeActionContext, cancellationToken?: CancellationToken): Promise<CodeAction[]>;
|
|
25
29
|
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<AppCompletionList<CompletionItemData> | null>;
|
|
26
30
|
resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionItemData>, cancellationToken?: CancellationToken): Promise<AppCompletionItem<CompletionItemData>>;
|
|
31
|
+
getInlayHints(document: AstroDocument, range: Range): Promise<InlayHint[]>;
|
|
27
32
|
getDefinitions(document: AstroDocument, position: Position): Promise<DefinitionLink[]>;
|
|
28
33
|
getDiagnostics(document: AstroDocument, cancellationToken?: CancellationToken): Promise<Diagnostic[]>;
|
|
29
34
|
onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesParam[]): Promise<void>;
|
|
30
35
|
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): Promise<void>;
|
|
31
36
|
getSignatureHelp(document: AstroDocument, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
|
|
32
|
-
private goToDefinitionFoundOnlyAlias;
|
|
33
|
-
private getGoToDefinitionRefsForImportSpecifier;
|
|
34
37
|
private featureEnabled;
|
|
35
38
|
}
|
|
@@ -1,60 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
4
|
};
|
|
25
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
6
|
exports.TypeScriptPlugin = void 0;
|
|
27
|
-
const typescript_1 =
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
28
8
|
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
29
|
-
const path_1 = require("path");
|
|
30
|
-
const utils_1 = require("../../utils");
|
|
31
9
|
const CompletionsProvider_1 = require("./features/CompletionsProvider");
|
|
32
10
|
const DiagnosticsProvider_1 = require("./features/DiagnosticsProvider");
|
|
33
11
|
const HoverProvider_1 = require("./features/HoverProvider");
|
|
34
12
|
const SignatureHelpProvider_1 = require("./features/SignatureHelpProvider");
|
|
35
|
-
const utils_2 = require("./features/utils");
|
|
36
13
|
const LanguageServiceManager_1 = require("./LanguageServiceManager");
|
|
37
|
-
const
|
|
14
|
+
const utils_1 = require("./utils");
|
|
38
15
|
const DocumentSymbolsProvider_1 = require("./features/DocumentSymbolsProvider");
|
|
39
16
|
const SemanticTokenProvider_1 = require("./features/SemanticTokenProvider");
|
|
40
17
|
const FoldingRangesProvider_1 = require("./features/FoldingRangesProvider");
|
|
41
18
|
const CodeActionsProvider_1 = require("./features/CodeActionsProvider");
|
|
19
|
+
const DefinitionsProvider_1 = require("./features/DefinitionsProvider");
|
|
20
|
+
const InlayHintsProvider_1 = require("./features/InlayHintsProvider");
|
|
21
|
+
const FormattingProvider_1 = require("./features/FormattingProvider");
|
|
42
22
|
class TypeScriptPlugin {
|
|
43
23
|
constructor(docManager, configManager, workspaceUris) {
|
|
44
24
|
this.__name = 'typescript';
|
|
45
25
|
this.configManager = configManager;
|
|
46
26
|
this.languageServiceManager = new LanguageServiceManager_1.LanguageServiceManager(docManager, workspaceUris, configManager);
|
|
47
|
-
this.codeActionsProvider = new CodeActionsProvider_1.CodeActionsProviderImpl(this.languageServiceManager);
|
|
48
|
-
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager);
|
|
27
|
+
this.codeActionsProvider = new CodeActionsProvider_1.CodeActionsProviderImpl(this.languageServiceManager, this.configManager);
|
|
28
|
+
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager, this.configManager);
|
|
49
29
|
this.hoverProvider = new HoverProvider_1.HoverProviderImpl(this.languageServiceManager);
|
|
30
|
+
this.definitionsProvider = new DefinitionsProvider_1.DefinitionsProviderImpl(this.languageServiceManager);
|
|
50
31
|
this.signatureHelpProvider = new SignatureHelpProvider_1.SignatureHelpProviderImpl(this.languageServiceManager);
|
|
51
32
|
this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
|
|
52
33
|
this.documentSymbolsProvider = new DocumentSymbolsProvider_1.DocumentSymbolsProviderImpl(this.languageServiceManager);
|
|
53
34
|
this.semanticTokensProvider = new SemanticTokenProvider_1.SemanticTokensProviderImpl(this.languageServiceManager);
|
|
35
|
+
this.inlayHintsProvider = new InlayHintsProvider_1.InlayHintsProviderImpl(this.languageServiceManager, this.configManager);
|
|
54
36
|
this.foldingRangesProvider = new FoldingRangesProvider_1.FoldingRangesProviderImpl(this.languageServiceManager);
|
|
37
|
+
this.formattingProvider = new FormattingProvider_1.FormattingProviderImpl(this.languageServiceManager, this.configManager);
|
|
55
38
|
}
|
|
56
39
|
async doHover(document, position) {
|
|
57
|
-
if (!this.featureEnabled('hover')) {
|
|
40
|
+
if (!(await this.featureEnabled(document, 'hover'))) {
|
|
58
41
|
return null;
|
|
59
42
|
}
|
|
60
43
|
return this.hoverProvider.doHover(document, position);
|
|
@@ -63,7 +46,7 @@ class TypeScriptPlugin {
|
|
|
63
46
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
64
47
|
const fragment = await tsDoc.createFragment();
|
|
65
48
|
const offset = fragment.offsetAt(fragment.getGeneratedPosition(position));
|
|
66
|
-
let renames = lang.findRenameLocations((0,
|
|
49
|
+
let renames = lang.findRenameLocations((0, utils_1.toVirtualAstroFilePath)(tsDoc.filePath), offset, false, false, true);
|
|
67
50
|
if (!renames) {
|
|
68
51
|
return null;
|
|
69
52
|
}
|
|
@@ -71,41 +54,44 @@ class TypeScriptPlugin {
|
|
|
71
54
|
changes: {},
|
|
72
55
|
};
|
|
73
56
|
renames.forEach((rename) => {
|
|
74
|
-
const filePath = (0,
|
|
57
|
+
const filePath = (0, utils_1.ensureRealFilePath)(rename.fileName);
|
|
75
58
|
if (!(filePath in edit.changes)) {
|
|
76
59
|
edit.changes[filePath] = [];
|
|
77
60
|
}
|
|
78
61
|
edit.changes[filePath].push({
|
|
79
62
|
newText: newName,
|
|
80
|
-
range: (0,
|
|
63
|
+
range: (0, utils_1.convertToLocationRange)(fragment, rename.textSpan),
|
|
81
64
|
});
|
|
82
65
|
});
|
|
83
66
|
return edit;
|
|
84
67
|
}
|
|
68
|
+
async formatDocument(document, options) {
|
|
69
|
+
return this.formattingProvider.formatDocument(document, options);
|
|
70
|
+
}
|
|
85
71
|
async getFoldingRanges(document) {
|
|
86
72
|
return this.foldingRangesProvider.getFoldingRanges(document);
|
|
87
73
|
}
|
|
88
|
-
async getSemanticTokens(
|
|
89
|
-
if (!this.featureEnabled('semanticTokens')) {
|
|
74
|
+
async getSemanticTokens(document, range, cancellationToken) {
|
|
75
|
+
if (!(await this.featureEnabled(document, 'semanticTokens'))) {
|
|
90
76
|
return null;
|
|
91
77
|
}
|
|
92
|
-
return this.semanticTokensProvider.getSemanticTokens(
|
|
78
|
+
return this.semanticTokensProvider.getSemanticTokens(document, range, cancellationToken);
|
|
93
79
|
}
|
|
94
80
|
async getDocumentSymbols(document) {
|
|
95
|
-
if (!this.featureEnabled('documentSymbols')) {
|
|
81
|
+
if (!(await this.featureEnabled(document, 'documentSymbols'))) {
|
|
96
82
|
return [];
|
|
97
83
|
}
|
|
98
84
|
const symbols = await this.documentSymbolsProvider.getDocumentSymbols(document);
|
|
99
85
|
return symbols;
|
|
100
86
|
}
|
|
101
87
|
async getCodeActions(document, range, context, cancellationToken) {
|
|
102
|
-
if (!this.featureEnabled('codeActions')) {
|
|
88
|
+
if (!(await this.featureEnabled(document, 'codeActions'))) {
|
|
103
89
|
return [];
|
|
104
90
|
}
|
|
105
91
|
return this.codeActionsProvider.getCodeActions(document, range, context, cancellationToken);
|
|
106
92
|
}
|
|
107
93
|
async getCompletions(document, position, completionContext, cancellationToken) {
|
|
108
|
-
if (!this.featureEnabled('completions')) {
|
|
94
|
+
if (!(await this.featureEnabled(document, 'completions'))) {
|
|
109
95
|
return null;
|
|
110
96
|
}
|
|
111
97
|
const completions = await this.completionProvider.getCompletions(document, position, completionContext, cancellationToken);
|
|
@@ -114,37 +100,14 @@ class TypeScriptPlugin {
|
|
|
114
100
|
async resolveCompletion(document, completionItem, cancellationToken) {
|
|
115
101
|
return this.completionProvider.resolveCompletion(document, completionItem, cancellationToken);
|
|
116
102
|
}
|
|
103
|
+
async getInlayHints(document, range) {
|
|
104
|
+
return this.inlayHintsProvider.getInlayHints(document, range);
|
|
105
|
+
}
|
|
117
106
|
async getDefinitions(document, position) {
|
|
118
|
-
|
|
119
|
-
const mainFragment = await tsDoc.createFragment();
|
|
120
|
-
const filePath = tsDoc.filePath;
|
|
121
|
-
const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(filePath);
|
|
122
|
-
const fragmentPosition = mainFragment.getGeneratedPosition(position);
|
|
123
|
-
const fragmentOffset = mainFragment.offsetAt(fragmentPosition);
|
|
124
|
-
let defs = lang.getDefinitionAndBoundSpan(tsFilePath, fragmentOffset);
|
|
125
|
-
if (!defs || !defs.definitions) {
|
|
126
|
-
return [];
|
|
127
|
-
}
|
|
128
|
-
// Resolve all imports if we can
|
|
129
|
-
if (this.goToDefinitionFoundOnlyAlias(tsFilePath, defs.definitions)) {
|
|
130
|
-
let importDef = this.getGoToDefinitionRefsForImportSpecifier(tsFilePath, fragmentOffset, lang);
|
|
131
|
-
if (importDef) {
|
|
132
|
-
defs = importDef;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
const docs = new utils_2.SnapshotFragmentMap(this.languageServiceManager);
|
|
136
|
-
docs.set(tsDoc.filePath, { fragment: mainFragment, snapshot: tsDoc });
|
|
137
|
-
const result = await Promise.all(defs.definitions.map(async (def) => {
|
|
138
|
-
const { fragment, snapshot } = await docs.retrieve(def.fileName);
|
|
139
|
-
const fileName = (0, utils_3.ensureRealFilePath)(def.fileName);
|
|
140
|
-
// Since we converted our files to TSX and we don't have sourcemaps, we don't know where the function is, unfortunate
|
|
141
|
-
const textSpan = (0, utils_3.isVirtualFilePath)(tsFilePath) ? { start: 0, length: 0 } : def.textSpan;
|
|
142
|
-
return vscode_languageserver_1.LocationLink.create((0, utils_1.pathToUrl)(fileName), (0, utils_3.convertToLocationRange)(fragment, textSpan), (0, utils_3.convertToLocationRange)(fragment, textSpan), (0, utils_3.convertToLocationRange)(mainFragment, defs.textSpan));
|
|
143
|
-
}));
|
|
144
|
-
return result.filter(utils_1.isNotNullOrUndefined);
|
|
107
|
+
return this.definitionsProvider.getDefinitions(document, position);
|
|
145
108
|
}
|
|
146
109
|
async getDiagnostics(document, cancellationToken) {
|
|
147
|
-
if (!this.featureEnabled('diagnostics')) {
|
|
110
|
+
if (!(await this.featureEnabled(document, 'diagnostics'))) {
|
|
148
111
|
return [];
|
|
149
112
|
}
|
|
150
113
|
return this.diagnosticsProvider.getDiagnostics(document, cancellationToken);
|
|
@@ -152,7 +115,7 @@ class TypeScriptPlugin {
|
|
|
152
115
|
async onWatchFileChanges(onWatchFileChangesParas) {
|
|
153
116
|
let doneUpdateProjectFiles = false;
|
|
154
117
|
for (const { fileName, changeType } of onWatchFileChangesParas) {
|
|
155
|
-
const scriptKind = (0,
|
|
118
|
+
const scriptKind = (0, utils_1.getScriptKindFromFileName)(fileName);
|
|
156
119
|
if (scriptKind === typescript_1.default.ScriptKind.Unknown) {
|
|
157
120
|
continue;
|
|
158
121
|
}
|
|
@@ -174,48 +137,9 @@ class TypeScriptPlugin {
|
|
|
174
137
|
async getSignatureHelp(document, position, context, cancellationToken) {
|
|
175
138
|
return this.signatureHelpProvider.getSignatureHelp(document, position, context, cancellationToken);
|
|
176
139
|
}
|
|
177
|
-
|
|
178
|
-
return
|
|
179
|
-
|
|
180
|
-
getGoToDefinitionRefsForImportSpecifier(tsFilePath, offset, lang) {
|
|
181
|
-
const program = lang.getProgram();
|
|
182
|
-
const sourceFile = program?.getSourceFile(tsFilePath);
|
|
183
|
-
if (sourceFile) {
|
|
184
|
-
let node = typescript_1.default.getTouchingPropertyName(sourceFile, offset);
|
|
185
|
-
if (node && node.kind === typescript_1.SyntaxKind.Identifier) {
|
|
186
|
-
if (node.parent.kind === typescript_1.SyntaxKind.ImportClause) {
|
|
187
|
-
let decl = node.parent.parent;
|
|
188
|
-
let spec = typescript_1.default.isStringLiteral(decl.moduleSpecifier) && decl.moduleSpecifier.text;
|
|
189
|
-
if (spec) {
|
|
190
|
-
let fileName = (0, path_1.join)((0, path_1.dirname)(tsFilePath), spec);
|
|
191
|
-
let start = node.pos + 1;
|
|
192
|
-
let def = {
|
|
193
|
-
definitions: [
|
|
194
|
-
{
|
|
195
|
-
kind: 'alias',
|
|
196
|
-
fileName,
|
|
197
|
-
name: '',
|
|
198
|
-
containerKind: '',
|
|
199
|
-
containerName: '',
|
|
200
|
-
textSpan: {
|
|
201
|
-
start: 0,
|
|
202
|
-
length: 0,
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
],
|
|
206
|
-
textSpan: {
|
|
207
|
-
start,
|
|
208
|
-
length: node.end - start,
|
|
209
|
-
},
|
|
210
|
-
};
|
|
211
|
-
return def;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
featureEnabled(feature) {
|
|
218
|
-
return (this.configManager.enabled('typescript.enabled') && this.configManager.enabled(`typescript.${feature}.enabled`));
|
|
140
|
+
async featureEnabled(document, feature) {
|
|
141
|
+
return ((await this.configManager.isEnabled(document, 'typescript')) &&
|
|
142
|
+
(await this.configManager.isEnabled(document, 'typescript', feature)));
|
|
219
143
|
}
|
|
220
144
|
}
|
|
221
145
|
exports.TypeScriptPlugin = TypeScriptPlugin;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { CancellationToken } from 'vscode-languageserver';
|
|
2
2
|
import { CodeAction, CodeActionContext, Range } from 'vscode-languageserver-types';
|
|
3
|
+
import { ConfigManager } from '../../../core/config';
|
|
3
4
|
import { AstroDocument } from '../../../core/documents';
|
|
4
5
|
import { CodeActionsProvider } from '../../interfaces';
|
|
5
6
|
import { LanguageServiceManager } from '../LanguageServiceManager';
|
|
6
7
|
export declare const sortImportKind: string;
|
|
7
8
|
export declare class CodeActionsProviderImpl implements CodeActionsProvider {
|
|
8
9
|
private languageServiceManager;
|
|
9
|
-
|
|
10
|
+
private configManager;
|
|
11
|
+
constructor(languageServiceManager: LanguageServiceManager, configManager: ConfigManager);
|
|
10
12
|
getCodeActions(document: AstroDocument, range: Range, context: CodeActionContext, cancellationToken?: CancellationToken): Promise<CodeAction[]>;
|
|
11
13
|
private getComponentQuickFix;
|
|
12
14
|
private organizeSortImports;
|
|
@@ -15,15 +15,16 @@ const utils_3 = require("./utils");
|
|
|
15
15
|
// These are VS Code specific CodeActionKind so they're not in the language server protocol
|
|
16
16
|
exports.sortImportKind = `${vscode_languageserver_types_1.CodeActionKind.Source}.sortImports`;
|
|
17
17
|
class CodeActionsProviderImpl {
|
|
18
|
-
constructor(languageServiceManager) {
|
|
18
|
+
constructor(languageServiceManager, configManager) {
|
|
19
19
|
this.languageServiceManager = languageServiceManager;
|
|
20
|
+
this.configManager = configManager;
|
|
20
21
|
}
|
|
21
22
|
async getCodeActions(document, range, context, cancellationToken) {
|
|
22
23
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
23
24
|
const filePath = (0, utils_2.toVirtualAstroFilePath)(tsDoc.filePath);
|
|
24
25
|
const fragment = await tsDoc.createFragment();
|
|
25
|
-
const
|
|
26
|
-
const
|
|
26
|
+
const tsPreferences = await this.configManager.getTSPreferences(document);
|
|
27
|
+
const formatOptions = await this.configManager.getTSFormatConfig(document);
|
|
27
28
|
let result = [];
|
|
28
29
|
if (cancellationToken?.isCancellationRequested) {
|
|
29
30
|
return [];
|
|
@@ -47,21 +48,57 @@ class CodeActionsProviderImpl {
|
|
|
47
48
|
.map((diag) => Number(diag.code))
|
|
48
49
|
// We currently cannot support quick fix for unreachable code properly due to the way our TSX output is structured
|
|
49
50
|
.filter((code) => code !== 7027);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const html = document.html;
|
|
52
|
+
const node = html.findNodeAt(document.offsetAt(range.start));
|
|
53
|
+
let codeFixes;
|
|
54
|
+
let isInsideScript = false;
|
|
55
|
+
if (node.tag === 'script') {
|
|
56
|
+
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node);
|
|
57
|
+
const start = scriptTagSnapshot.offsetAt(scriptTagSnapshot.getGeneratedPosition(range.start));
|
|
58
|
+
const end = scriptTagSnapshot.offsetAt(scriptTagSnapshot.getGeneratedPosition(range.end));
|
|
59
|
+
codeFixes = lang.getCodeFixesAtPosition(scriptFilePath, start, end, errorCodes, formatOptions, tsPreferences);
|
|
60
|
+
codeFixes = codeFixes.map((fix) => ({
|
|
61
|
+
...fix,
|
|
62
|
+
changes: mapScriptTagFixToOriginal(fix.changes, scriptTagSnapshot),
|
|
63
|
+
}));
|
|
64
|
+
isInsideScript = true;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const start = fragment.offsetAt(fragment.getGeneratedPosition(range.start));
|
|
68
|
+
const end = fragment.offsetAt(fragment.getGeneratedPosition(range.end));
|
|
69
|
+
codeFixes = errorCodes.includes(2304)
|
|
70
|
+
? this.getComponentQuickFix(start, end, lang, filePath, formatOptions, tsPreferences)
|
|
71
|
+
: undefined;
|
|
72
|
+
codeFixes =
|
|
73
|
+
codeFixes ?? lang.getCodeFixesAtPosition(filePath, start, end, errorCodes, formatOptions, tsPreferences);
|
|
74
|
+
}
|
|
75
|
+
const codeActions = codeFixes.map((fix) => codeFixToCodeAction(fix, context.diagnostics, context.only ? vscode_languageserver_types_1.CodeActionKind.QuickFix : vscode_languageserver_types_1.CodeActionKind.Empty, isInsideScript));
|
|
53
76
|
result.push(...codeActions);
|
|
54
77
|
}
|
|
55
78
|
return result;
|
|
56
|
-
function codeFixToCodeAction(codeFix, diagnostics, kind) {
|
|
79
|
+
function codeFixToCodeAction(codeFix, diagnostics, kind, isInsideScript) {
|
|
57
80
|
const documentChanges = codeFix.changes.map((change) => {
|
|
58
81
|
return vscode_languageserver_types_1.TextDocumentEdit.create(vscode_languageserver_types_1.OptionalVersionedTextDocumentIdentifier.create(document.getURL(), null), change.textChanges.map((edit) => {
|
|
59
82
|
let originalRange = (0, documents_1.mapRangeToOriginal)(fragment, (0, utils_2.convertRange)(fragment, edit.span));
|
|
60
|
-
|
|
61
|
-
|
|
83
|
+
// Inside scripts, we don't need to restrain the insertion of code inside a specific zone as it will be
|
|
84
|
+
// restricted to the area of the script tag by default
|
|
85
|
+
if (!isInsideScript) {
|
|
86
|
+
if (codeFix.fixName === 'import') {
|
|
87
|
+
return (0, CompletionsProvider_1.codeActionChangeToTextEdit)(document, fragment, false, edit);
|
|
88
|
+
}
|
|
89
|
+
if (codeFix.fixName === 'fixMissingFunctionDeclaration') {
|
|
90
|
+
originalRange = (0, utils_2.checkEndOfFileCodeInsert)(originalRange, document);
|
|
91
|
+
}
|
|
62
92
|
}
|
|
63
|
-
|
|
64
|
-
|
|
93
|
+
else {
|
|
94
|
+
// Make sure new imports are not added on the file line of the script tag
|
|
95
|
+
if (codeFix.fixName === 'import') {
|
|
96
|
+
const existingLine = (0, documents_1.getLineAtPosition)(document.positionAt(edit.span.start), document.getText());
|
|
97
|
+
const isNewImport = !existingLine.trim().startsWith('import');
|
|
98
|
+
if (!(edit.newText.startsWith('\n') || edit.newText.startsWith('\r\n')) && isNewImport) {
|
|
99
|
+
edit.newText = typescript_1.default.sys.newLine + edit.newText;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
65
102
|
}
|
|
66
103
|
return vscode_languageserver_types_1.TextEdit.replace(originalRange, edit.newText);
|
|
67
104
|
}));
|
|
@@ -72,8 +109,17 @@ class CodeActionsProviderImpl {
|
|
|
72
109
|
codeAction.diagnostics = diagnostics;
|
|
73
110
|
return codeAction;
|
|
74
111
|
}
|
|
112
|
+
function mapScriptTagFixToOriginal(changes, scriptTagSnapshot) {
|
|
113
|
+
return changes.map((change) => {
|
|
114
|
+
change.textChanges.map((edit) => {
|
|
115
|
+
edit.span.start = fragment.offsetAt(scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(edit.span.start)));
|
|
116
|
+
return edit;
|
|
117
|
+
});
|
|
118
|
+
return change;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
75
121
|
}
|
|
76
|
-
getComponentQuickFix(start, end, lang, filePath) {
|
|
122
|
+
getComponentQuickFix(start, end, lang, filePath, formatOptions, tsPreferences) {
|
|
77
123
|
const sourceFile = lang.getProgram()?.getSourceFile(filePath);
|
|
78
124
|
if (!sourceFile) {
|
|
79
125
|
return;
|
|
@@ -87,7 +133,7 @@ class CodeActionsProviderImpl {
|
|
|
87
133
|
}
|
|
88
134
|
const tagName = node.tagName;
|
|
89
135
|
// Unlike quick fixes, completions will be able to find the component, so let's use those to get it
|
|
90
|
-
const completion = lang.getCompletionsAtPosition(filePath, tagName.getEnd(),
|
|
136
|
+
const completion = lang.getCompletionsAtPosition(filePath, tagName.getEnd(), tsPreferences, formatOptions);
|
|
91
137
|
if (!completion) {
|
|
92
138
|
return;
|
|
93
139
|
}
|
|
@@ -101,16 +147,35 @@ class CodeActionsProviderImpl {
|
|
|
101
147
|
return (0, lodash_1.flatten)(completion.entries.filter((c) => c.name === name || c.name === suffixedName).map(toFix));
|
|
102
148
|
}
|
|
103
149
|
async organizeSortImports(document, skipDestructiveCodeActions = false, cancellationToken) {
|
|
104
|
-
if (document.astroMeta.frontmatter.state !== 'closed') {
|
|
105
|
-
return [];
|
|
106
|
-
}
|
|
107
150
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
108
151
|
const filePath = (0, utils_2.toVirtualAstroFilePath)(tsDoc.filePath);
|
|
109
152
|
const fragment = await tsDoc.createFragment();
|
|
110
153
|
if (cancellationToken?.isCancellationRequested) {
|
|
111
154
|
return [];
|
|
112
155
|
}
|
|
113
|
-
|
|
156
|
+
let changes = [];
|
|
157
|
+
if (document.astroMeta.frontmatter.state === 'closed') {
|
|
158
|
+
changes.push(...lang.organizeImports({ fileName: filePath, type: 'file', skipDestructiveCodeActions }, {}, {}));
|
|
159
|
+
}
|
|
160
|
+
document.scriptTags.forEach((scriptTag) => {
|
|
161
|
+
const { filePath: scriptFilePath, snapshot: scriptTagSnapshot } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, scriptTag.container);
|
|
162
|
+
const edits = lang.organizeImports({ fileName: scriptFilePath, type: 'file', skipDestructiveCodeActions }, {}, {});
|
|
163
|
+
edits.forEach((edit) => {
|
|
164
|
+
edit.fileName = tsDoc.filePath;
|
|
165
|
+
edit.textChanges = edit.textChanges
|
|
166
|
+
.map((change) => {
|
|
167
|
+
change.span.start = fragment.offsetAt(scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(change.span.start)));
|
|
168
|
+
return change;
|
|
169
|
+
})
|
|
170
|
+
// Since our last line is a (virtual) export, organize imports will try to rewrite it, so let's only take
|
|
171
|
+
// changes that actually happens inside the script tag
|
|
172
|
+
.filter((change) => {
|
|
173
|
+
return scriptTagSnapshot.isInGenerated(document.positionAt(change.span.start));
|
|
174
|
+
});
|
|
175
|
+
return edit;
|
|
176
|
+
});
|
|
177
|
+
changes.push(...edits);
|
|
178
|
+
});
|
|
114
179
|
const documentChanges = changes.map((change) => {
|
|
115
180
|
return vscode_languageserver_types_1.TextDocumentEdit.create(vscode_languageserver_types_1.OptionalVersionedTextDocumentIdentifier.create(document.url, null), change.textChanges.map((edit) => {
|
|
116
181
|
const range = (0, documents_1.mapRangeToOriginal)(fragment, (0, utils_2.convertRange)(fragment, edit.span));
|
|
@@ -4,15 +4,17 @@ import { AstroDocument } from '../../../core/documents';
|
|
|
4
4
|
import ts from 'typescript';
|
|
5
5
|
import { AppCompletionItem, AppCompletionList, CompletionsProvider } from '../../interfaces';
|
|
6
6
|
import { AstroSnapshotFragment } from '../snapshots/DocumentSnapshot';
|
|
7
|
-
|
|
7
|
+
import { ConfigManager } from '../../../core/config';
|
|
8
8
|
export interface CompletionItemData extends TextDocumentIdentifier {
|
|
9
9
|
filePath: string;
|
|
10
10
|
offset: number;
|
|
11
|
+
scriptTagIndex: number | undefined;
|
|
11
12
|
originalItem: ts.CompletionEntry;
|
|
12
13
|
}
|
|
13
14
|
export declare class CompletionsProviderImpl implements CompletionsProvider<CompletionItemData> {
|
|
14
15
|
private languageServiceManager;
|
|
15
|
-
|
|
16
|
+
private configManager;
|
|
17
|
+
constructor(languageServiceManager: LanguageServiceManager, configManager: ConfigManager);
|
|
16
18
|
private readonly validTriggerCharacters;
|
|
17
19
|
private isValidTriggerCharacter;
|
|
18
20
|
private lastCompletion?;
|
|
@@ -31,4 +33,4 @@ export declare class CompletionsProviderImpl implements CompletionsProvider<Comp
|
|
|
31
33
|
private getExistingImports;
|
|
32
34
|
private isAstroComponentImport;
|
|
33
35
|
}
|
|
34
|
-
export declare function codeActionChangeToTextEdit(document: AstroDocument, fragment: AstroSnapshotFragment, change: ts.TextChange): TextEdit;
|
|
36
|
+
export declare function codeActionChangeToTextEdit(document: AstroDocument, fragment: AstroSnapshotFragment, isInsideScriptTag: boolean, change: ts.TextChange): TextEdit;
|