@astrojs/language-server 0.13.4 → 0.16.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 +43 -0
- package/dist/check.js +1 -2
- package/dist/core/documents/DocumentMapper.js +2 -4
- package/dist/core/documents/parseAstro.js +1 -1
- package/dist/core/documents/utils.d.ts +5 -0
- package/dist/core/documents/utils.js +18 -5
- package/dist/plugins/PluginHost.d.ts +3 -2
- package/dist/plugins/PluginHost.js +37 -10
- package/dist/plugins/astro/AstroPlugin.js +1 -1
- package/dist/plugins/astro/features/CompletionsProvider.js +30 -15
- package/dist/plugins/css/CSSPlugin.js +20 -4
- package/dist/plugins/html/features/astro-attributes.js +43 -27
- package/dist/plugins/interfaces.d.ts +2 -2
- package/dist/plugins/typescript/LanguageServiceManager.js +1 -1
- package/dist/plugins/typescript/TypeScriptPlugin.d.ts +8 -4
- package/dist/plugins/typescript/TypeScriptPlugin.js +18 -5
- package/dist/plugins/typescript/astro-sys.js +3 -5
- package/dist/plugins/typescript/astro2tsx.d.ts +1 -1
- package/dist/plugins/typescript/astro2tsx.js +12 -8
- package/dist/plugins/typescript/features/CodeActionsProvider.d.ts +14 -0
- package/dist/plugins/typescript/features/CodeActionsProvider.js +141 -0
- package/dist/plugins/typescript/features/CompletionsProvider.d.ts +24 -6
- package/dist/plugins/typescript/features/CompletionsProvider.js +262 -52
- package/dist/plugins/typescript/features/DiagnosticsProvider.js +45 -60
- package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +5 -6
- package/dist/plugins/typescript/features/FoldingRangesProvider.d.ts +9 -0
- package/dist/plugins/typescript/features/FoldingRangesProvider.js +64 -0
- package/dist/plugins/typescript/features/SemanticTokenProvider.js +2 -2
- package/dist/plugins/typescript/features/SignatureHelpProvider.js +2 -2
- package/dist/plugins/typescript/features/utils.d.ts +4 -0
- package/dist/plugins/typescript/features/utils.js +25 -3
- package/dist/plugins/typescript/language-service.d.ts +1 -1
- package/dist/plugins/typescript/language-service.js +44 -24
- package/dist/plugins/typescript/module-loader.js +1 -1
- package/dist/plugins/typescript/previewer.js +1 -1
- package/dist/plugins/typescript/snapshots/SnapshotManager.js +1 -1
- package/dist/plugins/typescript/snapshots/utils.js +27 -9
- package/dist/plugins/typescript/utils.d.ts +4 -0
- package/dist/plugins/typescript/utils.js +29 -1
- package/dist/server.js +44 -7
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +72 -3
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @astrojs/language-server
|
|
2
2
|
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9abff62: Add support for code actions
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- b485acd: Fixed bug where nonexistent server settings would result in a crash
|
|
12
|
+
- 1cff04c: Fix Emmet settings not being loaded, add support for Emmet in CSS
|
|
13
|
+
- 1bcae45: Remove support for Node 12 (VS Code versions under 1.56)
|
|
14
|
+
- c8d81a1: Update directives tooltips, add missing `is:raw`
|
|
15
|
+
- Updated dependencies [1bcae45]
|
|
16
|
+
- @astrojs/svelte-language-integration@0.1.4
|
|
17
|
+
|
|
18
|
+
## 0.15.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- 6bb45cb: Overhaul TypeScript completions
|
|
23
|
+
|
|
24
|
+
- Add support for completions inside expressions
|
|
25
|
+
- Add support for auto imports on completion
|
|
26
|
+
- Fix misc issues in completions (missing description, deprecated stuff not showing as deprecated)
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- 7978de1: Add support for folding JavaScript
|
|
31
|
+
- 3ac74bc: Improve props completions on components
|
|
32
|
+
- Updated dependencies [6bb45cb]
|
|
33
|
+
- @astrojs/svelte-language-integration@0.1.3
|
|
34
|
+
|
|
35
|
+
## 0.14.0
|
|
36
|
+
|
|
37
|
+
### Minor Changes
|
|
38
|
+
|
|
39
|
+
- 9118c46: Add support for loading type definitions from Astro itself
|
|
40
|
+
|
|
41
|
+
### Patch Changes
|
|
42
|
+
|
|
43
|
+
- 9ea5b97: Make TypeScript ignore content of Markdown tags
|
|
44
|
+
- dbf624a: Fix error when returning a response from the frontmatter
|
|
45
|
+
|
|
3
46
|
## 0.13.4
|
|
4
47
|
|
|
5
48
|
### Patch Changes
|
package/dist/check.js
CHANGED
|
@@ -37,11 +37,10 @@ class AstroCheck {
|
|
|
37
37
|
this.pluginHost.registerPlugin(new plugins_1.TypeScriptPlugin(this.docManager, this.configManager, [workspacePath]));
|
|
38
38
|
}
|
|
39
39
|
async getDiagnosticsForFile(uri) {
|
|
40
|
-
var _a;
|
|
41
40
|
const diagnostics = await this.pluginHost.getDiagnostics({ uri });
|
|
42
41
|
return {
|
|
43
42
|
filePath: new URL(uri).pathname || '',
|
|
44
|
-
text:
|
|
43
|
+
text: this.docManager.get(uri)?.getText() || '',
|
|
45
44
|
diagnostics,
|
|
46
45
|
};
|
|
47
46
|
}
|
|
@@ -33,8 +33,7 @@ class IdentityMapper {
|
|
|
33
33
|
return this.url;
|
|
34
34
|
}
|
|
35
35
|
destroy() {
|
|
36
|
-
|
|
37
|
-
(_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.destroy) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
36
|
+
this.parent?.destroy?.();
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
exports.IdentityMapper = IdentityMapper;
|
|
@@ -130,8 +129,7 @@ class SourceMapDocumentMapper {
|
|
|
130
129
|
* Needs to be called when source mapper is no longer needed in order to prevent memory leaks.
|
|
131
130
|
*/
|
|
132
131
|
destroy() {
|
|
133
|
-
|
|
134
|
-
(_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.destroy) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
132
|
+
this.parent?.destroy?.();
|
|
135
133
|
this.consumer.destroy();
|
|
136
134
|
}
|
|
137
135
|
}
|
|
@@ -55,7 +55,7 @@ function getContent(content, frontmatter) {
|
|
|
55
55
|
}
|
|
56
56
|
case 'closed': {
|
|
57
57
|
const { endOffset } = frontmatter;
|
|
58
|
-
const end = (endOffset
|
|
58
|
+
const end = (endOffset ?? 0) + 3;
|
|
59
59
|
const offset = (0, utils_1.getFirstNonWhitespaceIndex)(content.slice(end));
|
|
60
60
|
return { firstNonWhitespaceOffset: end + offset };
|
|
61
61
|
}
|
|
@@ -15,6 +15,11 @@ export interface TagInformation {
|
|
|
15
15
|
}
|
|
16
16
|
export declare function walk(node: Node): Generator<Node, void, unknown>;
|
|
17
17
|
export declare function extractStyleTags(source: string, html?: HTMLDocument): TagInformation[];
|
|
18
|
+
export declare function getLineAtPosition(position: Position, text: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Returns the node if offset is inside a HTML start tag
|
|
21
|
+
*/
|
|
22
|
+
export declare function getNodeIfIsInHTMLStartTag(html: HTMLDocument, offset: number): Node | undefined;
|
|
18
23
|
/**
|
|
19
24
|
* Return if a Node is a Component
|
|
20
25
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getFirstNonWhitespaceIndex = exports.getLineOffsets = exports.offsetAt = exports.positionAt = exports.isInsideFrontmatter = exports.isInsideExpression = exports.isInTag = exports.isInComponentStartTag = exports.isComponentTag = exports.extractStyleTags = exports.walk = void 0;
|
|
3
|
+
exports.getFirstNonWhitespaceIndex = exports.getLineOffsets = exports.offsetAt = exports.positionAt = exports.isInsideFrontmatter = exports.isInsideExpression = exports.isInTag = exports.isInComponentStartTag = exports.isComponentTag = exports.getNodeIfIsInHTMLStartTag = exports.getLineAtPosition = exports.extractStyleTags = exports.walk = void 0;
|
|
4
4
|
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
5
5
|
const utils_1 = require("../../utils");
|
|
6
6
|
const parseHtml_1 = require("./parseHtml");
|
|
@@ -19,7 +19,7 @@ exports.walk = walk;
|
|
|
19
19
|
* @param tag the tag to extract
|
|
20
20
|
*/
|
|
21
21
|
function extractTags(text, tag, html) {
|
|
22
|
-
const rootNodes =
|
|
22
|
+
const rootNodes = html?.roots || (0, parseHtml_1.parseHtml)(text).roots;
|
|
23
23
|
const matchedNodes = rootNodes.filter((node) => node.tag === tag);
|
|
24
24
|
if (tag === 'style' && !matchedNodes.length && rootNodes.length) {
|
|
25
25
|
for (let child of walk(rootNodes[0])) {
|
|
@@ -30,9 +30,8 @@ function extractTags(text, tag, html) {
|
|
|
30
30
|
}
|
|
31
31
|
return matchedNodes.map(transformToTagInfo);
|
|
32
32
|
function transformToTagInfo(matchedNode) {
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const end = (_b = matchedNode.endTagStart) !== null && _b !== void 0 ? _b : matchedNode.end;
|
|
33
|
+
const start = matchedNode.startTagEnd ?? matchedNode.start;
|
|
34
|
+
const end = matchedNode.endTagStart ?? matchedNode.end;
|
|
36
35
|
const startPos = positionAt(start, text);
|
|
37
36
|
const endPos = positionAt(end, text);
|
|
38
37
|
const container = {
|
|
@@ -79,6 +78,20 @@ function parseAttributes(rawAttrs) {
|
|
|
79
78
|
return attrValue;
|
|
80
79
|
}
|
|
81
80
|
}
|
|
81
|
+
function getLineAtPosition(position, text) {
|
|
82
|
+
return text.substring(offsetAt({ line: position.line, character: 0 }, text), offsetAt({ line: position.line, character: Number.MAX_VALUE }, text));
|
|
83
|
+
}
|
|
84
|
+
exports.getLineAtPosition = getLineAtPosition;
|
|
85
|
+
/**
|
|
86
|
+
* Returns the node if offset is inside a HTML start tag
|
|
87
|
+
*/
|
|
88
|
+
function getNodeIfIsInHTMLStartTag(html, offset) {
|
|
89
|
+
const node = html.findNodeAt(offset);
|
|
90
|
+
if (!!node.tag && node.tag[0] === node.tag[0].toLowerCase() && (!node.startTagEnd || offset < node.startTagEnd)) {
|
|
91
|
+
return node;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.getNodeIfIsInHTMLStartTag = getNodeIfIsInHTMLStartTag;
|
|
82
95
|
/**
|
|
83
96
|
* Return if a Node is a Component
|
|
84
97
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CancellationToken, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, Location, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, TextDocumentIdentifier, WorkspaceEdit, SymbolInformation, SemanticTokens } from 'vscode-languageserver';
|
|
1
|
+
import { CancellationToken, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, Location, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, TextDocumentIdentifier, WorkspaceEdit, SymbolInformation, SemanticTokens, CodeActionContext, CodeAction } from 'vscode-languageserver';
|
|
2
2
|
import type { AppCompletionItem, Plugin } from './interfaces';
|
|
3
3
|
import { DocumentManager } from '../core/documents/DocumentManager';
|
|
4
4
|
interface PluginHostConfig {
|
|
@@ -12,10 +12,11 @@ export declare class PluginHost {
|
|
|
12
12
|
constructor(docManager: DocumentManager);
|
|
13
13
|
initialize(pluginHostConfig: PluginHostConfig): void;
|
|
14
14
|
registerPlugin(plugin: Plugin): void;
|
|
15
|
-
getCompletions(textDocument: TextDocumentIdentifier, position: Position, completionContext?: CompletionContext): Promise<CompletionList>;
|
|
15
|
+
getCompletions(textDocument: TextDocumentIdentifier, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<CompletionList>;
|
|
16
16
|
resolveCompletion(textDocument: TextDocumentIdentifier, completionItem: AppCompletionItem): Promise<CompletionItem>;
|
|
17
17
|
getDiagnostics(textDocument: TextDocumentIdentifier): Promise<Diagnostic[]>;
|
|
18
18
|
doHover(textDocument: TextDocumentIdentifier, position: Position): Promise<Hover | null>;
|
|
19
|
+
getCodeActions(textDocument: TextDocumentIdentifier, range: Range, context: CodeActionContext, cancellationToken: CancellationToken): Promise<CodeAction[]>;
|
|
19
20
|
doTagComplete(textDocument: TextDocumentIdentifier, position: Position): Promise<string | null>;
|
|
20
21
|
getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[] | null>;
|
|
21
22
|
getDocumentSymbols(textDocument: TextDocumentIdentifier, cancellationToken: CancellationToken): Promise<SymbolInformation[]>;
|
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PluginHost = void 0;
|
|
4
4
|
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
const documents_1 = require("../core/documents");
|
|
6
8
|
var ExecuteMode;
|
|
7
9
|
(function (ExecuteMode) {
|
|
8
10
|
ExecuteMode[ExecuteMode["None"] = 0] = "None";
|
|
@@ -24,17 +26,40 @@ class PluginHost {
|
|
|
24
26
|
registerPlugin(plugin) {
|
|
25
27
|
this.plugins.push(plugin);
|
|
26
28
|
}
|
|
27
|
-
async getCompletions(textDocument, position, completionContext) {
|
|
29
|
+
async getCompletions(textDocument, position, completionContext, cancellationToken) {
|
|
28
30
|
const document = this.getDocument(textDocument.uri);
|
|
29
|
-
const completions =
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
const completions = await Promise.all(this.plugins.map(async (plugin) => {
|
|
32
|
+
const result = await this.tryExecutePlugin(plugin, 'getCompletions', [document, position, completionContext, cancellationToken], null);
|
|
33
|
+
if (result) {
|
|
34
|
+
return { result: result, plugin: plugin.__name };
|
|
35
|
+
}
|
|
36
|
+
})).then((fullCompletions) => fullCompletions.filter(utils_1.isNotNullOrUndefined));
|
|
37
|
+
const html = completions.find((completion) => completion.plugin === 'html');
|
|
38
|
+
const ts = completions.find((completion) => completion.plugin === 'typescript');
|
|
39
|
+
const astro = completions.find((completion) => completion.plugin === 'astro');
|
|
40
|
+
if (html && ts) {
|
|
41
|
+
if ((0, documents_1.getNodeIfIsInHTMLStartTag)(document.html, document.offsetAt(position))) {
|
|
42
|
+
ts.result.items = [];
|
|
43
|
+
}
|
|
44
|
+
// If the Astro plugin has completions for us, don't show TypeScript's as they're most likely duplicates
|
|
45
|
+
if (astro && astro.result.items.length > 0 && (0, documents_1.isInComponentStartTag)(document.html, document.offsetAt(position))) {
|
|
46
|
+
ts.result.items = [];
|
|
47
|
+
}
|
|
48
|
+
ts.result.items = ts.result.items.map((item) => {
|
|
49
|
+
if (item.sortText != '-1') {
|
|
50
|
+
item.sortText = 'Z' + (item.sortText || '');
|
|
51
|
+
}
|
|
52
|
+
return item;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
let flattenedCompletions = (0, lodash_1.flatten)(completions.map((completion) => completion.result.items));
|
|
56
|
+
const isIncomplete = completions.reduce((incomplete, completion) => incomplete || completion.result.isIncomplete, false);
|
|
32
57
|
return vscode_languageserver_1.CompletionList.create(flattenedCompletions, isIncomplete);
|
|
33
58
|
}
|
|
34
59
|
async resolveCompletion(textDocument, completionItem) {
|
|
35
60
|
const document = this.getDocument(textDocument.uri);
|
|
36
61
|
const result = await this.execute('resolveCompletion', [document, completionItem], ExecuteMode.FirstNonNull);
|
|
37
|
-
return result
|
|
62
|
+
return result ?? completionItem;
|
|
38
63
|
}
|
|
39
64
|
async getDiagnostics(textDocument) {
|
|
40
65
|
const document = this.getDocument(textDocument.uri);
|
|
@@ -44,13 +69,17 @@ class PluginHost {
|
|
|
44
69
|
const document = this.getDocument(textDocument.uri);
|
|
45
70
|
return this.execute('doHover', [document, position], ExecuteMode.FirstNonNull);
|
|
46
71
|
}
|
|
72
|
+
async getCodeActions(textDocument, range, context, cancellationToken) {
|
|
73
|
+
const document = this.getDocument(textDocument.uri);
|
|
74
|
+
return (0, lodash_1.flatten)(await this.execute('getCodeActions', [document, range, context, cancellationToken], ExecuteMode.Collect));
|
|
75
|
+
}
|
|
47
76
|
async doTagComplete(textDocument, position) {
|
|
48
77
|
const document = this.getDocument(textDocument.uri);
|
|
49
78
|
return this.execute('doTagComplete', [document, position], ExecuteMode.FirstNonNull);
|
|
50
79
|
}
|
|
51
80
|
async getFoldingRanges(textDocument) {
|
|
52
81
|
const document = this.getDocument(textDocument.uri);
|
|
53
|
-
const foldingRanges = (0, lodash_1.flatten)(await this.execute('getFoldingRanges', [document], ExecuteMode.Collect))
|
|
82
|
+
const foldingRanges = (0, lodash_1.flatten)(await this.execute('getFoldingRanges', [document], ExecuteMode.Collect));
|
|
54
83
|
return foldingRanges;
|
|
55
84
|
}
|
|
56
85
|
async getDocumentSymbols(textDocument, cancellationToken) {
|
|
@@ -91,15 +120,13 @@ class PluginHost {
|
|
|
91
120
|
return await this.execute('getSignatureHelp', [document, position, context, cancellationToken], ExecuteMode.FirstNonNull);
|
|
92
121
|
}
|
|
93
122
|
onWatchFileChanges(onWatchFileChangesParams) {
|
|
94
|
-
var _a;
|
|
95
123
|
for (const support of this.plugins) {
|
|
96
|
-
|
|
124
|
+
support.onWatchFileChanges?.(onWatchFileChangesParams);
|
|
97
125
|
}
|
|
98
126
|
}
|
|
99
127
|
updateNonAstroFile(fileName, changes) {
|
|
100
|
-
var _a;
|
|
101
128
|
for (const support of this.plugins) {
|
|
102
|
-
|
|
129
|
+
support.updateNonAstroFile?.(fileName, changes);
|
|
103
130
|
}
|
|
104
131
|
}
|
|
105
132
|
getDocument(uri) {
|
|
@@ -77,7 +77,7 @@ class AstroPlugin {
|
|
|
77
77
|
const filePath = (0, utils_1.urlToPath)(document.uri);
|
|
78
78
|
const tsFilePath = (0, utils_2.toVirtualAstroFilePath)(filePath);
|
|
79
79
|
const program = lang.getProgram();
|
|
80
|
-
const sourceFile = program
|
|
80
|
+
const sourceFile = program?.getSourceFile(tsFilePath);
|
|
81
81
|
if (!sourceFile) {
|
|
82
82
|
return undefined;
|
|
83
83
|
}
|
|
@@ -26,19 +26,19 @@ class CompletionsProviderImpl {
|
|
|
26
26
|
if (!doc)
|
|
27
27
|
return null;
|
|
28
28
|
let items = [];
|
|
29
|
-
if (
|
|
29
|
+
if (completionContext?.triggerCharacter === '-') {
|
|
30
30
|
const frontmatter = this.getComponentScriptCompletion(doc, position, completionContext);
|
|
31
31
|
if (frontmatter)
|
|
32
32
|
items.push(frontmatter);
|
|
33
33
|
}
|
|
34
34
|
const html = document.html;
|
|
35
35
|
const offset = document.offsetAt(position);
|
|
36
|
-
|
|
36
|
+
const node = html.findNodeAt(offset);
|
|
37
|
+
if ((0, utils_1.isInComponentStartTag)(html, offset) && !(0, utils_1.isInsideExpression)(document.getText(), node.start, offset)) {
|
|
37
38
|
const props = await this.getPropCompletions(document, position, completionContext);
|
|
38
39
|
if (props.length) {
|
|
39
40
|
items.push(...props);
|
|
40
41
|
}
|
|
41
|
-
const node = html.findNodeAt(offset);
|
|
42
42
|
const isAstro = await this.isAstroComponent(document, node);
|
|
43
43
|
if (!isAstro) {
|
|
44
44
|
const directives = (0, utils_4.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items);
|
|
@@ -89,7 +89,7 @@ class CompletionsProviderImpl {
|
|
|
89
89
|
if (!inAttribute) {
|
|
90
90
|
return [];
|
|
91
91
|
}
|
|
92
|
-
if (
|
|
92
|
+
if (completionContext?.triggerCharacter === '/' || completionContext?.triggerCharacter === '>') {
|
|
93
93
|
return [];
|
|
94
94
|
}
|
|
95
95
|
// If inside of attribute value, skip.
|
|
@@ -103,8 +103,8 @@ class CompletionsProviderImpl {
|
|
|
103
103
|
// Get the source file
|
|
104
104
|
const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(tsDoc.filePath);
|
|
105
105
|
const program = lang.getProgram();
|
|
106
|
-
const sourceFile = program
|
|
107
|
-
const typeChecker = program
|
|
106
|
+
const sourceFile = program?.getSourceFile(tsFilePath);
|
|
107
|
+
const typeChecker = program?.getTypeChecker();
|
|
108
108
|
if (!sourceFile || !typeChecker) {
|
|
109
109
|
return [];
|
|
110
110
|
}
|
|
@@ -123,7 +123,8 @@ class CompletionsProviderImpl {
|
|
|
123
123
|
// Add completions for this component's props type properties
|
|
124
124
|
const properties = componentType.getProperties().filter((property) => property.name !== 'children') || [];
|
|
125
125
|
properties.forEach((property) => {
|
|
126
|
-
|
|
126
|
+
const type = typeChecker.getTypeOfSymbolAtLocation(property, imp);
|
|
127
|
+
let completionItem = this.getCompletionItemForProperty(property, typeChecker, type);
|
|
127
128
|
completionItems.push(completionItem);
|
|
128
129
|
});
|
|
129
130
|
// Ensure that props shows up first as a completion, despite this plugin being ran after the HTML one
|
|
@@ -159,11 +160,11 @@ class CompletionsProviderImpl {
|
|
|
159
160
|
return null;
|
|
160
161
|
}
|
|
161
162
|
getPropType(type, typeChecker) {
|
|
162
|
-
const sym = type
|
|
163
|
+
const sym = type?.getSymbol();
|
|
163
164
|
if (!sym) {
|
|
164
165
|
return null;
|
|
165
166
|
}
|
|
166
|
-
for (const decl of
|
|
167
|
+
for (const decl of sym?.getDeclarations() || []) {
|
|
167
168
|
const fileName = (0, utils_3.toVirtualFilePath)(decl.getSourceFile().fileName);
|
|
168
169
|
if (fileName.endsWith('.tsx') || fileName.endsWith('.jsx')) {
|
|
169
170
|
if (!typescript_1.default.isFunctionDeclaration(decl)) {
|
|
@@ -180,10 +181,25 @@ class CompletionsProviderImpl {
|
|
|
180
181
|
}
|
|
181
182
|
return null;
|
|
182
183
|
}
|
|
183
|
-
getCompletionItemForProperty(mem, typeChecker) {
|
|
184
|
+
getCompletionItemForProperty(mem, typeChecker, type) {
|
|
185
|
+
const typeString = typeChecker.typeToString(type);
|
|
186
|
+
let insertText = mem.name;
|
|
187
|
+
switch (typeString) {
|
|
188
|
+
case 'string':
|
|
189
|
+
insertText = `${mem.name}="$1"`;
|
|
190
|
+
break;
|
|
191
|
+
case 'boolean':
|
|
192
|
+
insertText = mem.name;
|
|
193
|
+
break;
|
|
194
|
+
default:
|
|
195
|
+
insertText = `${mem.name}={$1}`;
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
184
198
|
let item = {
|
|
185
199
|
label: mem.name,
|
|
186
|
-
|
|
200
|
+
detail: typeString,
|
|
201
|
+
insertText: insertText,
|
|
202
|
+
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
|
|
187
203
|
commitCharacters: [],
|
|
188
204
|
};
|
|
189
205
|
mem.getDocumentationComment(typeChecker);
|
|
@@ -201,13 +217,12 @@ class CompletionsProviderImpl {
|
|
|
201
217
|
return item;
|
|
202
218
|
}
|
|
203
219
|
async isAstroComponent(document, node) {
|
|
204
|
-
var _a;
|
|
205
220
|
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
206
221
|
// Get the source file
|
|
207
222
|
const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(tsDoc.filePath);
|
|
208
223
|
const program = lang.getProgram();
|
|
209
|
-
const sourceFile = program
|
|
210
|
-
const typeChecker = program
|
|
224
|
+
const sourceFile = program?.getSourceFile(tsFilePath);
|
|
225
|
+
const typeChecker = program?.getTypeChecker();
|
|
211
226
|
if (!sourceFile || !typeChecker) {
|
|
212
227
|
return false;
|
|
213
228
|
}
|
|
@@ -217,7 +232,7 @@ class CompletionsProviderImpl {
|
|
|
217
232
|
if (!importType) {
|
|
218
233
|
return false;
|
|
219
234
|
}
|
|
220
|
-
const symbolDeclaration =
|
|
235
|
+
const symbolDeclaration = importType.getSymbol()?.declarations;
|
|
221
236
|
if (symbolDeclaration) {
|
|
222
237
|
const fileName = symbolDeclaration[0].getSourceFile().fileName;
|
|
223
238
|
return fileName.endsWith('.astro');
|
|
@@ -60,8 +60,8 @@ class CSSPlugin {
|
|
|
60
60
|
if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
|
-
const triggerCharacter = completionContext
|
|
64
|
-
const triggerKind = completionContext
|
|
63
|
+
const triggerCharacter = completionContext?.triggerCharacter;
|
|
64
|
+
const triggerKind = completionContext?.triggerKind;
|
|
65
65
|
const isCustomTriggerCharacter = triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter;
|
|
66
66
|
if (isCustomTriggerCharacter && triggerCharacter && !this.triggerCharacters.has(triggerCharacter)) {
|
|
67
67
|
return null;
|
|
@@ -97,10 +97,26 @@ class CSSPlugin {
|
|
|
97
97
|
}
|
|
98
98
|
const cssLang = extractLanguage(cssDocument);
|
|
99
99
|
const langService = (0, language_service_1.getLanguageService)(cssLang);
|
|
100
|
-
|
|
101
|
-
isIncomplete:
|
|
100
|
+
let emmetResults = {
|
|
101
|
+
isIncomplete: false,
|
|
102
102
|
items: [],
|
|
103
103
|
};
|
|
104
|
+
langService.setCompletionParticipants([
|
|
105
|
+
{
|
|
106
|
+
onCssProperty: (context) => {
|
|
107
|
+
if (context?.propertyName) {
|
|
108
|
+
emmetResults =
|
|
109
|
+
(0, emmet_helper_1.doComplete)(cssDocument, cssDocument.getGeneratedPosition(position), (0, language_service_1.getLanguage)(cssLang), this.configManager.getEmmetConfig()) || emmetResults;
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
onCssPropertyValue: (context) => {
|
|
113
|
+
if (context?.propertyValue) {
|
|
114
|
+
emmetResults =
|
|
115
|
+
(0, emmet_helper_1.doComplete)(cssDocument, cssDocument.getGeneratedPosition(position), (0, language_service_1.getLanguage)(cssLang), this.configManager.getEmmetConfig()) || emmetResults;
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
]);
|
|
104
120
|
const results = langService.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
|
|
105
121
|
return vscode_languageserver_1.CompletionList.create([...(results ? results.items : []), ...emmetResults.items].map((completionItem) => (0, documents_1.mapCompletionItemToOriginal)(cssDocument, completionItem)),
|
|
106
122
|
// Emmet completions change on every keystroke, so they are never complete
|
|
@@ -8,6 +8,12 @@ exports.classListAttribute = (0, vscode_html_languageservice_1.newHTMLDataProvid
|
|
|
8
8
|
{
|
|
9
9
|
name: 'class:list',
|
|
10
10
|
description: 'Utility to provide a list of class',
|
|
11
|
+
references: [
|
|
12
|
+
{
|
|
13
|
+
name: 'Astro reference',
|
|
14
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#classlist',
|
|
15
|
+
},
|
|
16
|
+
],
|
|
11
17
|
},
|
|
12
18
|
],
|
|
13
19
|
});
|
|
@@ -19,8 +25,8 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
19
25
|
description: 'Inject unescaped HTML into this tag',
|
|
20
26
|
references: [
|
|
21
27
|
{
|
|
22
|
-
name: 'Astro
|
|
23
|
-
url: 'https://docs.astro.build/en/
|
|
28
|
+
name: 'Astro reference',
|
|
29
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#sethtml',
|
|
24
30
|
},
|
|
25
31
|
],
|
|
26
32
|
},
|
|
@@ -29,8 +35,18 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
29
35
|
description: 'Inject escaped text into this tag',
|
|
30
36
|
references: [
|
|
31
37
|
{
|
|
32
|
-
name: 'Astro
|
|
33
|
-
url: 'https://docs.astro.build/en/
|
|
38
|
+
name: 'Astro reference',
|
|
39
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#settext',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'is:raw',
|
|
45
|
+
description: 'Instructs the Astro compiler to treat any children of this element as text',
|
|
46
|
+
references: [
|
|
47
|
+
{
|
|
48
|
+
name: 'Astro reference',
|
|
49
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#israw',
|
|
34
50
|
},
|
|
35
51
|
],
|
|
36
52
|
},
|
|
@@ -50,8 +66,8 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
50
66
|
description: 'Passes serializable server-side variables into a client-side script element',
|
|
51
67
|
references: [
|
|
52
68
|
{
|
|
53
|
-
name: 'Astro
|
|
54
|
-
url: 'https://docs.astro.build/en/
|
|
69
|
+
name: 'Astro reference',
|
|
70
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#definevars',
|
|
55
71
|
},
|
|
56
72
|
],
|
|
57
73
|
},
|
|
@@ -61,7 +77,7 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
61
77
|
valueSet: 'v',
|
|
62
78
|
references: [
|
|
63
79
|
{
|
|
64
|
-
name: 'Astro
|
|
80
|
+
name: 'Astro reference',
|
|
65
81
|
url: 'https://docs.astro.build/en/core-concepts/astro-components/#using-hoisted-scripts',
|
|
66
82
|
},
|
|
67
83
|
],
|
|
@@ -72,8 +88,8 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
72
88
|
valueSet: 'v',
|
|
73
89
|
references: [
|
|
74
90
|
{
|
|
75
|
-
name: 'Astro
|
|
76
|
-
url: 'https://docs.astro.build/en/
|
|
91
|
+
name: 'Astro reference',
|
|
92
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#isinline',
|
|
77
93
|
},
|
|
78
94
|
],
|
|
79
95
|
},
|
|
@@ -87,8 +103,8 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
87
103
|
description: 'Passes serializable server-side variables into a client-side style element',
|
|
88
104
|
references: [
|
|
89
105
|
{
|
|
90
|
-
name: 'Astro
|
|
91
|
-
url: 'https://docs.astro.build/en/
|
|
106
|
+
name: 'Astro reference',
|
|
107
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#definevars',
|
|
92
108
|
},
|
|
93
109
|
],
|
|
94
110
|
},
|
|
@@ -98,8 +114,8 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
98
114
|
valueSet: 'v',
|
|
99
115
|
references: [
|
|
100
116
|
{
|
|
101
|
-
name: 'Astro
|
|
102
|
-
url: 'https://docs.astro.build/en/
|
|
117
|
+
name: 'Astro reference',
|
|
118
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#isglobal',
|
|
103
119
|
},
|
|
104
120
|
],
|
|
105
121
|
},
|
|
@@ -109,8 +125,8 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
109
125
|
valueSet: 'v',
|
|
110
126
|
references: [
|
|
111
127
|
{
|
|
112
|
-
name: 'Astro
|
|
113
|
-
url: 'https://docs.astro.build/en/
|
|
128
|
+
name: 'Astro reference',
|
|
129
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#isglobal',
|
|
114
130
|
},
|
|
115
131
|
],
|
|
116
132
|
},
|
|
@@ -120,8 +136,8 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
120
136
|
valueSet: 'v',
|
|
121
137
|
references: [
|
|
122
138
|
{
|
|
123
|
-
name: 'Astro
|
|
124
|
-
url: 'https://docs.astro.build/en/
|
|
139
|
+
name: 'Astro reference',
|
|
140
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#isinline',
|
|
125
141
|
},
|
|
126
142
|
],
|
|
127
143
|
},
|
|
@@ -138,8 +154,8 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
138
154
|
valueSet: 'v',
|
|
139
155
|
references: [
|
|
140
156
|
{
|
|
141
|
-
name: 'Astro
|
|
142
|
-
url: 'https://docs.astro.build/en/
|
|
157
|
+
name: 'Astro reference',
|
|
158
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#clientload',
|
|
143
159
|
},
|
|
144
160
|
],
|
|
145
161
|
},
|
|
@@ -149,8 +165,8 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
149
165
|
valueSet: 'v',
|
|
150
166
|
references: [
|
|
151
167
|
{
|
|
152
|
-
name: 'Astro
|
|
153
|
-
url: 'https://docs.astro.build/en/
|
|
168
|
+
name: 'Astro reference',
|
|
169
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#clientidle',
|
|
154
170
|
},
|
|
155
171
|
],
|
|
156
172
|
},
|
|
@@ -160,8 +176,8 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
160
176
|
valueSet: 'v',
|
|
161
177
|
references: [
|
|
162
178
|
{
|
|
163
|
-
name: 'Astro
|
|
164
|
-
url: 'https://docs.astro.build/en/
|
|
179
|
+
name: 'Astro reference',
|
|
180
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#clientvisible',
|
|
165
181
|
},
|
|
166
182
|
],
|
|
167
183
|
},
|
|
@@ -170,8 +186,8 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
170
186
|
description: 'Start importing the component JS as soon as the browser matches the given media query (uses matchMedia). Hydrate the component when import completes. Useful for sidebar toggles, or other elements that should only display on mobile or desktop devices.',
|
|
171
187
|
references: [
|
|
172
188
|
{
|
|
173
|
-
name: 'Astro
|
|
174
|
-
url: 'https://docs.astro.build/en/
|
|
189
|
+
name: 'Astro reference',
|
|
190
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#clientmedia',
|
|
175
191
|
},
|
|
176
192
|
],
|
|
177
193
|
},
|
|
@@ -181,8 +197,8 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
181
197
|
valueSet: 'v',
|
|
182
198
|
references: [
|
|
183
199
|
{
|
|
184
|
-
name: 'Astro
|
|
185
|
-
url: 'https://docs.astro.build/en/
|
|
200
|
+
name: 'Astro reference',
|
|
201
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#clientonly',
|
|
186
202
|
},
|
|
187
203
|
],
|
|
188
204
|
},
|
|
@@ -13,7 +13,7 @@ export interface DiagnosticsProvider {
|
|
|
13
13
|
export interface HoverProvider {
|
|
14
14
|
doHover(document: TextDocument, position: Position): Resolvable<Hover | null>;
|
|
15
15
|
}
|
|
16
|
-
export interface
|
|
16
|
+
export interface FoldingRangesProvider {
|
|
17
17
|
getFoldingRanges(document: TextDocument): Resolvable<FoldingRange[] | null>;
|
|
18
18
|
}
|
|
19
19
|
export interface CompletionsProvider<T extends TextDocumentIdentifier = any> {
|
|
@@ -81,7 +81,7 @@ export interface OnWatchFileChangesProvider {
|
|
|
81
81
|
export interface UpdateNonAstroFile {
|
|
82
82
|
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): void;
|
|
83
83
|
}
|
|
84
|
-
declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & DefinitionsProvider & FormattingProvider &
|
|
84
|
+
declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & DefinitionsProvider & FormattingProvider & FoldingRangesProvider & TagCompleteProvider & DocumentColorsProvider & ColorPresentationsProvider & DocumentSymbolsProvider & UpdateImportsProvider & CodeActionsProvider & FindReferencesProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & SelectionRangeProvider & OnWatchFileChangesProvider & LinkedEditingRangesProvider & UpdateNonAstroFile;
|
|
85
85
|
export declare type LSProvider = ProviderBase;
|
|
86
86
|
export declare type Plugin = Partial<ProviderBase> & {
|
|
87
87
|
__name: string;
|
|
@@ -29,7 +29,7 @@ class LanguageServiceManager {
|
|
|
29
29
|
const handleDocumentChange = (document) => {
|
|
30
30
|
this.getSnapshot(document);
|
|
31
31
|
};
|
|
32
|
-
docManager.on('documentChange', (0, utils_1.debounceSameArg)(handleDocumentChange, (newDoc, prevDoc) => newDoc.uri ===
|
|
32
|
+
docManager.on('documentChange', (0, utils_1.debounceSameArg)(handleDocumentChange, (newDoc, prevDoc) => newDoc.uri === prevDoc?.uri, 1000));
|
|
33
33
|
docManager.on('documentOpen', handleDocumentChange);
|
|
34
34
|
}
|
|
35
35
|
async getSnapshot(pathOrDoc) {
|