@astrojs/language-server 0.20.1 → 0.21.1
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 +24 -0
- package/README.md +1 -2
- package/dist/check.js +4 -1
- package/dist/core/documents/utils.d.ts +4 -0
- package/dist/core/documents/utils.js +9 -1
- package/dist/importPackage.d.ts +1 -1
- package/dist/importPackage.js +11 -8
- package/dist/plugins/PluginHost.js +3 -8
- package/dist/plugins/astro/AstroPlugin.d.ts +3 -2
- package/dist/plugins/astro/AstroPlugin.js +2 -3
- package/dist/plugins/html/HTMLPlugin.js +8 -4
- package/dist/plugins/html/features/astro-attributes.d.ts +1 -0
- package/dist/plugins/html/features/astro-attributes.js +51 -26
- package/dist/plugins/typescript/TypeScriptPlugin.d.ts +5 -2
- package/dist/plugins/typescript/TypeScriptPlugin.js +7 -3
- package/dist/plugins/typescript/astro2tsx.d.ts +1 -2
- package/dist/plugins/typescript/astro2tsx.js +0 -4
- package/dist/plugins/typescript/features/CompletionsProvider.d.ts +0 -1
- package/dist/plugins/typescript/features/CompletionsProvider.js +29 -26
- package/dist/plugins/typescript/features/DiagnosticsProvider.js +0 -5
- package/dist/plugins/typescript/features/FoldingRangesProvider.js +1 -1
- package/dist/plugins/typescript/language-service.js +12 -38
- package/dist/plugins/typescript/snapshots/utils.d.ts +1 -0
- package/dist/plugins/typescript/snapshots/utils.js +2 -1
- package/dist/server.js +18 -4
- package/dist/utils.d.ts +9 -7
- package/dist/utils.js +25 -16
- package/package.json +3 -3
- package/types/README.md +5 -0
- package/types/astro-jsx.d.ts +854 -477
- package/types/env.d.ts +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @astrojs/language-server
|
|
2
2
|
|
|
3
|
+
## 0.21.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0e9d7d0: Improve error handling in cases where we can't load types from the user's project and when the project isn't at the root of the folder
|
|
8
|
+
- 3f79dbf: Fix `tsconfig.json` not loading properly in certain contexts on Windows
|
|
9
|
+
|
|
10
|
+
## 0.21.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- 574b75d: Remove support for the Markdown component
|
|
15
|
+
- d23ba22: Changed how Astro's types are consumed to avoid making type acquisition explicit inside Astro files
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 81f3aa5: Added a debug command to show the currently opened document's TSX output
|
|
20
|
+
|
|
21
|
+
## 0.20.3
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 081cf24: Fix completions not working inside script tags, fix duplicate completions in some cases, added completions for the slot element
|
|
26
|
+
|
|
3
27
|
## 0.20.1
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -11,6 +11,5 @@ The Astro language server, implement the [language server protocol](https://micr
|
|
|
11
11
|
│ ├── core # Core code such as .astro file parsing, configuration manager, document definition etc
|
|
12
12
|
│ └── plugins # Modules for the different languages supported in .astro files
|
|
13
13
|
├── test # Tests
|
|
14
|
-
|
|
15
|
-
└── astro.d.ts # Types injected into .astro files by the language server
|
|
14
|
+
└── types # Types injected into Astro files by the language server under certain conditions
|
|
16
15
|
```
|
package/dist/check.js
CHANGED
|
@@ -4,6 +4,8 @@ exports.AstroCheck = exports.DiagnosticSeverity = void 0;
|
|
|
4
4
|
const config_1 = require("./core/config");
|
|
5
5
|
const documents_1 = require("./core/documents");
|
|
6
6
|
const plugins_1 = require("./plugins");
|
|
7
|
+
const LanguageServiceManager_1 = require("./plugins/typescript/LanguageServiceManager");
|
|
8
|
+
const utils_1 = require("./utils");
|
|
7
9
|
var vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
|
8
10
|
Object.defineProperty(exports, "DiagnosticSeverity", { enumerable: true, get: function () { return vscode_languageserver_types_1.DiagnosticSeverity; } });
|
|
9
11
|
class AstroCheck {
|
|
@@ -37,7 +39,8 @@ class AstroCheck {
|
|
|
37
39
|
}));
|
|
38
40
|
}
|
|
39
41
|
initialize(workspacePath) {
|
|
40
|
-
|
|
42
|
+
const languageServiceManager = new LanguageServiceManager_1.LanguageServiceManager(this.docManager, [(0, utils_1.normalizeUri)(workspacePath)], this.configManager);
|
|
43
|
+
this.pluginHost.registerPlugin(new plugins_1.TypeScriptPlugin(this.configManager, languageServiceManager));
|
|
41
44
|
}
|
|
42
45
|
async getDiagnosticsForFile(uri) {
|
|
43
46
|
const diagnostics = await this.pluginHost.getDiagnostics({ uri });
|
|
@@ -21,6 +21,10 @@ export declare function getLineAtPosition(position: Position, text: string): str
|
|
|
21
21
|
* Return if a given offset is inside the start tag of a component
|
|
22
22
|
*/
|
|
23
23
|
export declare function isInComponentStartTag(html: HTMLDocument, offset: number): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Return if a given offset is inside the name of a tag
|
|
26
|
+
*/
|
|
27
|
+
export declare function isInTagName(html: HTMLDocument, offset: number): boolean;
|
|
24
28
|
/**
|
|
25
29
|
* Return true if a specific node could be a component.
|
|
26
30
|
* This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
|
|
@@ -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.isPossibleComponent = exports.isInComponentStartTag = exports.getLineAtPosition = exports.extractScriptTags = exports.extractStyleTags = exports.walk = void 0;
|
|
3
|
+
exports.getFirstNonWhitespaceIndex = exports.getLineOffsets = exports.offsetAt = exports.positionAt = exports.isInsideFrontmatter = exports.isInsideExpression = exports.isInTag = exports.isPossibleComponent = exports.isInTagName = exports.isInComponentStartTag = exports.getLineAtPosition = exports.extractScriptTags = 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");
|
|
@@ -105,6 +105,14 @@ function isInComponentStartTag(html, offset) {
|
|
|
105
105
|
return isPossibleComponent(node) && (!node.startTagEnd || offset < node.startTagEnd);
|
|
106
106
|
}
|
|
107
107
|
exports.isInComponentStartTag = isInComponentStartTag;
|
|
108
|
+
/**
|
|
109
|
+
* Return if a given offset is inside the name of a tag
|
|
110
|
+
*/
|
|
111
|
+
function isInTagName(html, offset) {
|
|
112
|
+
const node = html.findNodeAt(offset);
|
|
113
|
+
return offset > node.start && offset < node.start + (node.tag?.length ?? 0);
|
|
114
|
+
}
|
|
115
|
+
exports.isInTagName = isInTagName;
|
|
108
116
|
/**
|
|
109
117
|
* Return true if a specific node could be a component.
|
|
110
118
|
* This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
|
package/dist/importPackage.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as svelte from '@astrojs/svelte/dist/editor.cjs';
|
|
2
2
|
import type * as vue from '@astrojs/svelte/dist/editor.cjs';
|
|
3
3
|
export declare function setIsTrusted(_isTrusted: boolean): void;
|
|
4
|
-
export declare function getPackagePath(packageName: string, fromPath: string): string | undefined;
|
|
4
|
+
export declare function getPackagePath(packageName: string, fromPath: string[]): string | undefined;
|
|
5
5
|
export declare function importSvelteIntegration(fromPath: string): typeof svelte | undefined;
|
|
6
6
|
export declare function importVueIntegration(fromPath: string): typeof vue | undefined;
|
package/dist/importPackage.js
CHANGED
|
@@ -10,13 +10,10 @@ exports.setIsTrusted = setIsTrusted;
|
|
|
10
10
|
function getPackagePath(packageName, fromPath) {
|
|
11
11
|
const paths = [];
|
|
12
12
|
if (isTrusted) {
|
|
13
|
-
paths.unshift(fromPath);
|
|
13
|
+
paths.unshift(...fromPath);
|
|
14
14
|
}
|
|
15
15
|
try {
|
|
16
|
-
|
|
17
|
-
paths,
|
|
18
|
-
});
|
|
19
|
-
return (0, path_1.dirname)(packageJSONPath);
|
|
16
|
+
return (0, path_1.dirname)(require.resolve(packageName + '/package.json', { paths }));
|
|
20
17
|
}
|
|
21
18
|
catch (e) {
|
|
22
19
|
return undefined;
|
|
@@ -24,10 +21,16 @@ function getPackagePath(packageName, fromPath) {
|
|
|
24
21
|
}
|
|
25
22
|
exports.getPackagePath = getPackagePath;
|
|
26
23
|
function importEditorIntegration(packageName, fromPath) {
|
|
27
|
-
const pkgPath = getPackagePath(packageName, fromPath);
|
|
24
|
+
const pkgPath = getPackagePath(packageName, [fromPath]);
|
|
28
25
|
if (pkgPath) {
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
try {
|
|
27
|
+
const main = (0, path_1.resolve)(pkgPath, 'dist', 'editor.cjs');
|
|
28
|
+
return require(main);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
console.error(`Couldn't load editor module from ${pkgPath}. Make sure you're using at least version v0.2.1 of the corresponding integration`);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
31
34
|
}
|
|
32
35
|
return undefined;
|
|
33
36
|
}
|
|
@@ -38,19 +38,14 @@ class PluginHost {
|
|
|
38
38
|
const astro = completions.find((completion) => completion.plugin === 'astro');
|
|
39
39
|
if (html && ts) {
|
|
40
40
|
const inComponentStartTag = (0, documents_1.isInComponentStartTag)(document.html, document.offsetAt(position));
|
|
41
|
-
|
|
41
|
+
// If the HTML plugin returned completions, it's highly likely that TS ones are duplicate
|
|
42
|
+
if (html.result.items.length > 0) {
|
|
42
43
|
ts.result.items = [];
|
|
43
44
|
}
|
|
44
|
-
//
|
|
45
|
+
// Inside components, if the Astro plugin has completions we don't want the TS ones are they're duplicates
|
|
45
46
|
if (astro && astro.result.items.length > 0 && inComponentStartTag) {
|
|
46
47
|
ts.result.items = [];
|
|
47
48
|
}
|
|
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
49
|
}
|
|
55
50
|
let flattenedCompletions = completions.flatMap((completion) => completion.result.items);
|
|
56
51
|
const isIncomplete = completions.reduce((incomplete, completion) => incomplete || completion.result.isIncomplete, false);
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { CompletionContext, FoldingRange, Position } from 'vscode-languageserver';
|
|
2
2
|
import { ConfigManager } from '../../core/config';
|
|
3
|
-
import { AstroDocument
|
|
3
|
+
import { AstroDocument } from '../../core/documents';
|
|
4
4
|
import { AppCompletionList, Plugin } from '../interfaces';
|
|
5
|
+
import { LanguageServiceManager } from '../typescript/LanguageServiceManager';
|
|
5
6
|
export declare class AstroPlugin implements Plugin {
|
|
6
7
|
__name: string;
|
|
7
8
|
private configManager;
|
|
8
9
|
private readonly languageServiceManager;
|
|
9
10
|
private readonly completionProvider;
|
|
10
|
-
constructor(
|
|
11
|
+
constructor(configManager: ConfigManager, languageServiceManager: LanguageServiceManager);
|
|
11
12
|
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
|
|
12
13
|
getFoldingRanges(document: AstroDocument): FoldingRange[];
|
|
13
14
|
}
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AstroPlugin = void 0;
|
|
4
4
|
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
5
|
-
const LanguageServiceManager_1 = require("../typescript/LanguageServiceManager");
|
|
6
5
|
const CompletionsProvider_1 = require("./features/CompletionsProvider");
|
|
7
6
|
class AstroPlugin {
|
|
8
|
-
constructor(
|
|
7
|
+
constructor(configManager, languageServiceManager) {
|
|
9
8
|
this.__name = 'astro';
|
|
10
9
|
this.configManager = configManager;
|
|
11
|
-
this.languageServiceManager =
|
|
10
|
+
this.languageServiceManager = languageServiceManager;
|
|
12
11
|
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager);
|
|
13
12
|
}
|
|
14
13
|
async getCompletions(document, position, completionContext) {
|
|
@@ -11,7 +11,7 @@ class HTMLPlugin {
|
|
|
11
11
|
constructor(configManager) {
|
|
12
12
|
this.__name = 'html';
|
|
13
13
|
this.lang = (0, vscode_html_languageservice_1.getLanguageService)({
|
|
14
|
-
customDataProviders: [astro_attributes_1.astroAttributes, astro_attributes_1.classListAttribute],
|
|
14
|
+
customDataProviders: [astro_attributes_1.astroAttributes, astro_attributes_1.astroElements, astro_attributes_1.classListAttribute],
|
|
15
15
|
});
|
|
16
16
|
this.attributeOnlyLang = (0, vscode_html_languageservice_1.getLanguageService)({
|
|
17
17
|
customDataProviders: [astro_attributes_1.astroAttributes],
|
|
@@ -72,10 +72,14 @@ class HTMLPlugin {
|
|
|
72
72
|
}
|
|
73
73
|
// If we're in a component starting tag, we do not want HTML language completions
|
|
74
74
|
// as HTML attributes are not valid for components
|
|
75
|
-
const
|
|
75
|
+
const inComponentTag = (0, utils_1.isInComponentStartTag)(html, offset);
|
|
76
|
+
const inTagName = (0, utils_1.isInTagName)(html, offset);
|
|
77
|
+
const results = inComponentTag && !inTagName
|
|
76
78
|
? (0, utils_2.removeDataAttrCompletion)(this.attributeOnlyLang.doComplete(document, position, html).items)
|
|
77
|
-
:
|
|
78
|
-
|
|
79
|
+
: // We filter items with no documentation to prevent duplicates with our own defined script and style tags
|
|
80
|
+
this.lang.doComplete(document, position, html).items.filter((item) => item.documentation !== undefined);
|
|
81
|
+
const langCompletions = inComponentTag ? [] : this.getLangCompletions(results);
|
|
82
|
+
return vscode_languageserver_1.CompletionList.create([...results, ...langCompletions, ...emmetResults.items],
|
|
79
83
|
// Emmet completions change on every keystroke, so they are never complete
|
|
80
84
|
emmetResults.items.length > 0);
|
|
81
85
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const classListAttribute: import("vscode-html-languageservice").IHTMLDataProvider;
|
|
2
|
+
export declare const astroElements: import("vscode-html-languageservice").IHTMLDataProvider;
|
|
2
3
|
export declare const astroAttributes: import("vscode-html-languageservice").IHTMLDataProvider;
|
|
3
4
|
export declare const astroDirectives: import("vscode-html-languageservice").IHTMLDataProvider;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.astroDirectives = exports.astroAttributes = exports.classListAttribute = void 0;
|
|
3
|
+
exports.astroDirectives = exports.astroAttributes = exports.astroElements = exports.classListAttribute = void 0;
|
|
4
4
|
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
|
|
5
5
|
exports.classListAttribute = (0, vscode_html_languageservice_1.newHTMLDataProvider)('class-list', {
|
|
6
6
|
version: 1,
|
|
@@ -17,42 +17,31 @@ exports.classListAttribute = (0, vscode_html_languageservice_1.newHTMLDataProvid
|
|
|
17
17
|
},
|
|
18
18
|
],
|
|
19
19
|
});
|
|
20
|
-
exports.
|
|
20
|
+
exports.astroElements = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-elements', {
|
|
21
21
|
version: 1,
|
|
22
|
-
|
|
23
|
-
{
|
|
24
|
-
name: 'set:html',
|
|
25
|
-
description: 'Inject unescaped HTML into this tag',
|
|
26
|
-
references: [
|
|
27
|
-
{
|
|
28
|
-
name: 'Astro reference',
|
|
29
|
-
url: 'https://docs.astro.build/en/reference/directives-reference/#sethtml',
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
},
|
|
22
|
+
tags: [
|
|
33
23
|
{
|
|
34
|
-
name: '
|
|
35
|
-
description: '
|
|
24
|
+
name: 'slot',
|
|
25
|
+
description: 'The slot element is a placeholder for external HTML content, allowing you to inject (or “slot”) child elements from other files into your component template.',
|
|
36
26
|
references: [
|
|
37
27
|
{
|
|
38
28
|
name: 'Astro reference',
|
|
39
|
-
url: 'https://docs.astro.build/en/
|
|
29
|
+
url: 'https://docs.astro.build/en/core-concepts/astro-components/#slots',
|
|
40
30
|
},
|
|
41
31
|
],
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
name: 'is:raw',
|
|
45
|
-
description: 'Instructs the Astro compiler to treat any children of this element as text',
|
|
46
|
-
valueSet: 'v',
|
|
47
|
-
references: [
|
|
32
|
+
attributes: [
|
|
48
33
|
{
|
|
49
|
-
name: '
|
|
50
|
-
|
|
34
|
+
name: 'name',
|
|
35
|
+
description: 'The name attribute allows you to pass only HTML elements with the corresponding slot name into a slot’s location.',
|
|
36
|
+
references: [
|
|
37
|
+
{
|
|
38
|
+
name: 'Astro reference',
|
|
39
|
+
url: 'https://docs.astro.build/en/core-concepts/astro-components/#named-slots',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
51
42
|
},
|
|
52
43
|
],
|
|
53
44
|
},
|
|
54
|
-
],
|
|
55
|
-
tags: [
|
|
56
45
|
{
|
|
57
46
|
name: 'script',
|
|
58
47
|
attributes: [
|
|
@@ -146,6 +135,42 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
|
|
|
146
135
|
},
|
|
147
136
|
],
|
|
148
137
|
});
|
|
138
|
+
exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-attributes', {
|
|
139
|
+
version: 1,
|
|
140
|
+
globalAttributes: [
|
|
141
|
+
{
|
|
142
|
+
name: 'set:html',
|
|
143
|
+
description: 'Inject unescaped HTML into this tag',
|
|
144
|
+
references: [
|
|
145
|
+
{
|
|
146
|
+
name: 'Astro reference',
|
|
147
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#sethtml',
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: 'set:text',
|
|
153
|
+
description: 'Inject escaped text into this tag',
|
|
154
|
+
references: [
|
|
155
|
+
{
|
|
156
|
+
name: 'Astro reference',
|
|
157
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#settext',
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'is:raw',
|
|
163
|
+
description: 'Instructs the Astro compiler to treat any children of this element as text',
|
|
164
|
+
valueSet: 'v',
|
|
165
|
+
references: [
|
|
166
|
+
{
|
|
167
|
+
name: 'Astro reference',
|
|
168
|
+
url: 'https://docs.astro.build/en/reference/directives-reference/#israw',
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
});
|
|
149
174
|
exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-directives', {
|
|
150
175
|
version: 1,
|
|
151
176
|
globalAttributes: [
|
|
@@ -1,8 +1,10 @@
|
|
|
1
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
|
-
import { AstroDocument
|
|
3
|
+
import { AstroDocument } from '../../core/documents';
|
|
4
4
|
import { AppCompletionItem, AppCompletionList, OnWatchFileChangesParam, Plugin } from '../interfaces';
|
|
5
5
|
import { CompletionItemData } from './features/CompletionsProvider';
|
|
6
|
+
import { LanguageServiceManager } from './LanguageServiceManager';
|
|
7
|
+
import { Astro2TSXResult } from './astro2tsx';
|
|
6
8
|
export declare class TypeScriptPlugin implements Plugin {
|
|
7
9
|
__name: string;
|
|
8
10
|
private configManager;
|
|
@@ -18,7 +20,7 @@ export declare class TypeScriptPlugin implements Plugin {
|
|
|
18
20
|
private readonly semanticTokensProvider;
|
|
19
21
|
private readonly foldingRangesProvider;
|
|
20
22
|
private readonly formattingProvider;
|
|
21
|
-
constructor(
|
|
23
|
+
constructor(configManager: ConfigManager, languageServiceManager: LanguageServiceManager);
|
|
22
24
|
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
|
|
23
25
|
rename(document: AstroDocument, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
|
24
26
|
formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
|
|
@@ -34,5 +36,6 @@ export declare class TypeScriptPlugin implements Plugin {
|
|
|
34
36
|
onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesParam[]): Promise<void>;
|
|
35
37
|
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): Promise<void>;
|
|
36
38
|
getSignatureHelp(document: AstroDocument, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
|
|
39
|
+
getTSXForDocument(document: AstroDocument): Astro2TSXResult;
|
|
37
40
|
private featureEnabled;
|
|
38
41
|
}
|
|
@@ -10,7 +10,6 @@ const CompletionsProvider_1 = require("./features/CompletionsProvider");
|
|
|
10
10
|
const DiagnosticsProvider_1 = require("./features/DiagnosticsProvider");
|
|
11
11
|
const HoverProvider_1 = require("./features/HoverProvider");
|
|
12
12
|
const SignatureHelpProvider_1 = require("./features/SignatureHelpProvider");
|
|
13
|
-
const LanguageServiceManager_1 = require("./LanguageServiceManager");
|
|
14
13
|
const utils_1 = require("./utils");
|
|
15
14
|
const DocumentSymbolsProvider_1 = require("./features/DocumentSymbolsProvider");
|
|
16
15
|
const SemanticTokenProvider_1 = require("./features/SemanticTokenProvider");
|
|
@@ -19,11 +18,13 @@ const CodeActionsProvider_1 = require("./features/CodeActionsProvider");
|
|
|
19
18
|
const DefinitionsProvider_1 = require("./features/DefinitionsProvider");
|
|
20
19
|
const InlayHintsProvider_1 = require("./features/InlayHintsProvider");
|
|
21
20
|
const FormattingProvider_1 = require("./features/FormattingProvider");
|
|
21
|
+
const astro2tsx_1 = __importDefault(require("./astro2tsx"));
|
|
22
|
+
const utils_2 = require("./snapshots/utils");
|
|
22
23
|
class TypeScriptPlugin {
|
|
23
|
-
constructor(
|
|
24
|
+
constructor(configManager, languageServiceManager) {
|
|
24
25
|
this.__name = 'typescript';
|
|
25
26
|
this.configManager = configManager;
|
|
26
|
-
this.languageServiceManager =
|
|
27
|
+
this.languageServiceManager = languageServiceManager;
|
|
27
28
|
this.codeActionsProvider = new CodeActionsProvider_1.CodeActionsProviderImpl(this.languageServiceManager, this.configManager);
|
|
28
29
|
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager, this.configManager);
|
|
29
30
|
this.hoverProvider = new HoverProvider_1.HoverProviderImpl(this.languageServiceManager);
|
|
@@ -137,6 +138,9 @@ class TypeScriptPlugin {
|
|
|
137
138
|
async getSignatureHelp(document, position, context, cancellationToken) {
|
|
138
139
|
return this.signatureHelpProvider.getSignatureHelp(document, position, context, cancellationToken);
|
|
139
140
|
}
|
|
141
|
+
getTSXForDocument(document) {
|
|
142
|
+
return (0, astro2tsx_1.default)(document.getText(), (0, utils_2.classNameFromFilename)(document.getURL()));
|
|
143
|
+
}
|
|
140
144
|
async featureEnabled(document, feature) {
|
|
141
145
|
return ((await this.configManager.isEnabled(document, 'typescript')) &&
|
|
142
146
|
(await this.configManager.isEnabled(document, 'typescript', feature)));
|
|
@@ -41,10 +41,6 @@ function default_1(content, className) {
|
|
|
41
41
|
// Turn styles tags into internal strings
|
|
42
42
|
.replace(/<\s*style([^>]*)>(.*?)<\s*\/\s*style>/gs, (_whole, attrs, children) => {
|
|
43
43
|
return `<style${attrs}>{\`${escapeTemplateLiteralContent(children)}\`}</style>`;
|
|
44
|
-
})
|
|
45
|
-
// Turn Markdown tags into internal strings
|
|
46
|
-
.replace(/<\s*Markdown([^>]*)>(.*?)<\s*\/\s*Markdown>/gs, (_whole, attrs, children) => {
|
|
47
|
-
return `<Markdown${attrs}>{\`${escapeTemplateLiteralContent(children)}\`}</Markdown>`;
|
|
48
44
|
})
|
|
49
45
|
// Turn scripts into function calls
|
|
50
46
|
.replace(/<\s*script([^\/>]*)>(.*?)<\s*\/\s*script>/gs, (_whole, attrs, children, offset) => {
|
|
@@ -21,7 +21,6 @@ export declare class CompletionsProviderImpl implements CompletionsProvider<Comp
|
|
|
21
21
|
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<AppCompletionList<CompletionItemData> | null>;
|
|
22
22
|
resolveCompletion(document: AstroDocument, item: AppCompletionItem<CompletionItemData>, cancellationToken?: CancellationToken): Promise<AppCompletionItem<CompletionItemData>>;
|
|
23
23
|
private toCompletionItem;
|
|
24
|
-
private isValidCompletion;
|
|
25
24
|
private getCompletionDocument;
|
|
26
25
|
/**
|
|
27
26
|
* If the textEdit is out of the word range of the triggered position
|
|
@@ -78,26 +78,8 @@ class CompletionsProviderImpl {
|
|
|
78
78
|
scriptTagIndex = scriptIndex;
|
|
79
79
|
completions = lang.getCompletionsAtPosition(scriptFilePath, scriptOffset, {
|
|
80
80
|
...tsPreferences,
|
|
81
|
-
// File extensions are required inside script tags, however TypeScript can't return completions with the `ts`
|
|
82
|
-
// extension, so what we'll do instead is force `minimal` (aka, no extension) and manually add the extensions
|
|
83
|
-
importModuleSpecifierEnding: 'minimal',
|
|
84
81
|
triggerCharacter: validTriggerCharacter,
|
|
85
82
|
}, formatOptions);
|
|
86
|
-
if (completions) {
|
|
87
|
-
// Manually adds file extensions to js and ts files
|
|
88
|
-
completions.entries = completions?.entries.map((comp) => {
|
|
89
|
-
if (comp.kind === typescript_1.ScriptElementKind.scriptElement &&
|
|
90
|
-
(comp.kindModifiers === '.js' || comp.kindModifiers === '.ts')) {
|
|
91
|
-
return {
|
|
92
|
-
...comp,
|
|
93
|
-
name: comp.name + comp.kindModifiers,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
return comp;
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
83
|
}
|
|
102
84
|
else {
|
|
103
85
|
// PERF: Getting TS completions is fairly slow and I am currently not sure how to speed it up
|
|
@@ -132,7 +114,7 @@ class CompletionsProviderImpl {
|
|
|
132
114
|
const fragment = await tsDoc.createFragment();
|
|
133
115
|
const existingImports = this.getExistingImports(document);
|
|
134
116
|
const completionItems = completions.entries
|
|
135
|
-
.filter(
|
|
117
|
+
.filter(isValidCompletion)
|
|
136
118
|
.map((entry) => this.toCompletionItem(fragment, entry, filePath, offset, isCompletionInsideFrontmatter, scriptTagIndex, existingImports))
|
|
137
119
|
.filter(utils_3.isNotNullOrUndefined)
|
|
138
120
|
.map((comp) => this.fixTextEditRange(wordRangeStartPosition, comp));
|
|
@@ -250,13 +232,6 @@ class CompletionsProviderImpl {
|
|
|
250
232
|
},
|
|
251
233
|
};
|
|
252
234
|
}
|
|
253
|
-
isValidCompletion(completion) {
|
|
254
|
-
// Remove completion for default exported function
|
|
255
|
-
if (completion.name === 'default' && completion.kindModifiers == typescript_1.ScriptElementKindModifier.exportedModifier) {
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
return true;
|
|
259
|
-
}
|
|
260
235
|
getCompletionDocument(compDetail) {
|
|
261
236
|
const { sourceDisplay, documentation: tsDocumentation, displayParts } = compDetail;
|
|
262
237
|
let detail = (0, utils_2.removeAstroComponentSuffix)(typescript_1.default.displayPartsToString(displayParts));
|
|
@@ -355,3 +330,31 @@ function codeActionChangeToTextEdit(document, fragment, isInsideScriptTag, chang
|
|
|
355
330
|
return vscode_languageserver_1.TextEdit.replace(range, change.newText);
|
|
356
331
|
}
|
|
357
332
|
exports.codeActionChangeToTextEdit = codeActionChangeToTextEdit;
|
|
333
|
+
// When Svelte components are imported, we have to reference the svelte2tsx's types to properly type the component
|
|
334
|
+
// An unfortunate downside of this is that it polutes completions, so let's filter those internal types manually
|
|
335
|
+
const svelte2tsxTypes = new Set([
|
|
336
|
+
'Svelte2TsxComponent',
|
|
337
|
+
'Svelte2TsxComponentConstructorParameters',
|
|
338
|
+
'SvelteComponentConstructor',
|
|
339
|
+
'SvelteActionReturnType',
|
|
340
|
+
'SvelteTransitionConfig',
|
|
341
|
+
'SvelteTransitionReturnType',
|
|
342
|
+
'SvelteAnimationReturnType',
|
|
343
|
+
'SvelteWithOptionalProps',
|
|
344
|
+
'SvelteAllProps',
|
|
345
|
+
'SveltePropsAnyFallback',
|
|
346
|
+
'SvelteSlotsAnyFallback',
|
|
347
|
+
'SvelteRestProps',
|
|
348
|
+
'SvelteSlots',
|
|
349
|
+
'SvelteStore',
|
|
350
|
+
]);
|
|
351
|
+
function isValidCompletion(completion) {
|
|
352
|
+
// Remove completion for default exported function
|
|
353
|
+
const isDefaultExport = completion.name === 'default' && completion.kindModifiers == typescript_1.ScriptElementKindModifier.exportedModifier;
|
|
354
|
+
// Remove completion for svelte2tsx internal types
|
|
355
|
+
const isSvelte2tsxCompletion = completion.name.startsWith('__sveltets_') || svelte2tsxTypes.has(completion.name);
|
|
356
|
+
if (isDefaultExport || isSvelte2tsxCompletion) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
@@ -95,7 +95,6 @@ class DiagnosticsProviderImpl {
|
|
|
95
95
|
const sourceFile = program?.getSourceFile(tsFilePath);
|
|
96
96
|
const boundaries = {
|
|
97
97
|
script: [],
|
|
98
|
-
markdown: [],
|
|
99
98
|
};
|
|
100
99
|
if (!sourceFile) {
|
|
101
100
|
return boundaries;
|
|
@@ -110,10 +109,6 @@ class DiagnosticsProviderImpl {
|
|
|
110
109
|
boundaries.script.push([node.getStart(), node.getEnd()]);
|
|
111
110
|
break;
|
|
112
111
|
}
|
|
113
|
-
case 'Markdown': {
|
|
114
|
-
boundaries.markdown.push([node.getStart(), node.getEnd()]);
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
112
|
}
|
|
118
113
|
}
|
|
119
114
|
findTags(node);
|
|
@@ -19,7 +19,7 @@ class FoldingRangesProviderImpl {
|
|
|
19
19
|
const node = html.findNodeAt(span.textSpan.start);
|
|
20
20
|
// Due to how our TSX output transform those tags into function calls or template literals
|
|
21
21
|
// TypeScript thinks of those as outlining spans, which is fine but we don't want folding ranges for those
|
|
22
|
-
return node.tag !== 'script' && node.tag !== 'style'
|
|
22
|
+
return node.tag !== 'script' && node.tag !== 'style';
|
|
23
23
|
});
|
|
24
24
|
const scriptOutliningSpans = [];
|
|
25
25
|
document.scriptTags.forEach((scriptTag) => {
|
|
@@ -72,7 +72,7 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
|
|
72
72
|
const tsconfigRoot = tsconfigPath ? (0, path_1.dirname)(tsconfigPath) : process.cwd();
|
|
73
73
|
const workspacePaths = workspaceUris.map((uri) => (0, utils_1.urlToPath)(uri));
|
|
74
74
|
const workspacePath = workspacePaths.find((uri) => tsconfigRoot.startsWith(uri)) || workspacePaths[0];
|
|
75
|
-
const
|
|
75
|
+
const astroInstall = (0, utils_1.getAstroInstall)([tsconfigRoot, workspacePath]);
|
|
76
76
|
const config = (await docContext.configManager.getConfig('astro.typescript', workspacePath)) ?? {};
|
|
77
77
|
const allowArbitraryAttrs = config.allowArbitraryAttributes ?? false;
|
|
78
78
|
// `raw` here represent the tsconfig merged with any extended config
|
|
@@ -80,6 +80,10 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
|
|
80
80
|
let projectVersion = 0;
|
|
81
81
|
const snapshotManager = new SnapshotManager_1.SnapshotManager(docContext.globalSnapshotManager, files, fullConfig, tsconfigRoot || process.cwd());
|
|
82
82
|
const astroModuleLoader = (0, module_loader_1.createAstroModuleLoader)(getScriptSnapshot, compilerOptions);
|
|
83
|
+
const scriptFileNames = [];
|
|
84
|
+
if (astroInstall) {
|
|
85
|
+
scriptFileNames.push(...['./env.d.ts', './astro-jsx.d.ts'].map((f) => typescript_1.default.sys.resolvePath((0, path_1.resolve)(astroInstall.path, f))));
|
|
86
|
+
}
|
|
83
87
|
let languageServerDirectory;
|
|
84
88
|
try {
|
|
85
89
|
languageServerDirectory = (0, path_1.dirname)(require.resolve('@astrojs/language-server'));
|
|
@@ -87,15 +91,13 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
|
|
87
91
|
catch (e) {
|
|
88
92
|
languageServerDirectory = __dirname;
|
|
89
93
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
!astroVersion.full.startsWith('0.0.0-rc-') // 1.0.0's RC is considered to be 0.0.0, so we have to check for it
|
|
94
|
+
// Fallback to internal types when Astro is not installed or the Astro version is too old
|
|
95
|
+
if (!astroInstall ||
|
|
96
|
+
((astroInstall.version.major === 0 || astroInstall.version.full === '1.0.0-beta.0') &&
|
|
97
|
+
!astroInstall.version.full.startsWith('0.0.0-rc-')) // 1.0.0's RC is considered to be 0.0.0, so we have to check for it
|
|
95
98
|
) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
console.warn("Version lower than 1.0 detected, using internal types instead of Astro's");
|
|
99
|
+
scriptFileNames.push(...['../types/astro-jsx.d.ts', '../types/env.d.ts'].map((f) => typescript_1.default.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, f))));
|
|
100
|
+
console.warn("Couldn't load types from Astro, using internal types instead");
|
|
99
101
|
}
|
|
100
102
|
if (allowArbitraryAttrs) {
|
|
101
103
|
const arbitraryAttrsDTS = typescript_1.default.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, '../types/arbitrary-attrs.d.ts'));
|
|
@@ -221,23 +223,7 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
|
|
221
223
|
});
|
|
222
224
|
}
|
|
223
225
|
function getParsedTSConfig() {
|
|
224
|
-
let configJson = (tsconfigPath && typescript_1.default.readConfigFile(tsconfigPath, typescript_1.default.sys.readFile).config) || {
|
|
225
|
-
compilerOptions: getDefaultCompilerOptions(astroVersion),
|
|
226
|
-
};
|
|
227
|
-
// If our user has types in their config but it doesn't include the types needed for Astro, add them to the config
|
|
228
|
-
if (configJson.compilerOptions?.types) {
|
|
229
|
-
if (!configJson.compilerOptions?.types.includes('astro/env')) {
|
|
230
|
-
configJson.compilerOptions.types.push('astro/env');
|
|
231
|
-
}
|
|
232
|
-
if ((astroVersion.major >= 1 || astroVersion.full.startsWith('0.0.0-rc-')) &&
|
|
233
|
-
astroVersion.full !== '1.0.0-beta.0' &&
|
|
234
|
-
!configJson.compilerOptions?.types.includes('astro/astro-jsx')) {
|
|
235
|
-
configJson.compilerOptions.types.push('astro/astro-jsx');
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
configJson.compilerOptions = Object.assign(getDefaultCompilerOptions(astroVersion), configJson.compilerOptions);
|
|
240
|
-
}
|
|
226
|
+
let configJson = (tsconfigPath && typescript_1.default.readConfigFile(tsconfigPath, typescript_1.default.sys.readFile).config) || {};
|
|
241
227
|
// Delete include so that .astro files don't get mistakenly excluded by the user
|
|
242
228
|
delete configJson.include;
|
|
243
229
|
// If the user supplied exclude, let's use theirs otherwise, use ours
|
|
@@ -273,18 +259,6 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
|
|
273
259
|
};
|
|
274
260
|
}
|
|
275
261
|
}
|
|
276
|
-
/**
|
|
277
|
-
* Default compiler configuration used when the user doesn't have any
|
|
278
|
-
*/
|
|
279
|
-
function getDefaultCompilerOptions(astroVersion) {
|
|
280
|
-
const types = ['astro/env'];
|
|
281
|
-
if ((astroVersion.major >= 1 && astroVersion.full !== '1.0.0-beta.0') || astroVersion.full.startsWith('0.0.0-rc-')) {
|
|
282
|
-
types.push('astro/astro-jsx');
|
|
283
|
-
}
|
|
284
|
-
return {
|
|
285
|
-
types: types,
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
262
|
function getDefaultExclude() {
|
|
289
263
|
return ['dist', 'node_modules'];
|
|
290
264
|
}
|
|
@@ -26,3 +26,4 @@ export declare function createFromTSFilePath(filePath: string): TypeScriptDocume
|
|
|
26
26
|
*/
|
|
27
27
|
export declare function createFromAstroFilePath(filePath: string, createDocument: (filePath: string, text: string) => AstroDocument): AstroSnapshot;
|
|
28
28
|
export declare function createFromFrameworkFilePath(filePath: string, framework: FrameworkExt): TypeScriptDocumentSnapshot;
|
|
29
|
+
export declare function classNameFromFilename(filename: string): string;
|