@astrojs/language-server 0.21.0 → 0.23.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 +28 -0
- package/README.md +1 -2
- package/dist/check.js +4 -1
- package/dist/core/config/ConfigManager.d.ts +1 -2
- package/dist/core/config/ConfigManager.js +0 -7
- package/dist/importPackage.d.ts +4 -1
- package/dist/importPackage.js +22 -9
- package/dist/plugins/PluginHost.d.ts +1 -0
- package/dist/plugins/PluginHost.js +4 -0
- package/dist/plugins/astro/AstroPlugin.d.ts +5 -3
- package/dist/plugins/astro/AstroPlugin.js +35 -3
- package/dist/plugins/css/language-service.d.ts +1 -1
- package/dist/plugins/html/HTMLPlugin.d.ts +1 -2
- package/dist/plugins/html/HTMLPlugin.js +6 -20
- package/dist/plugins/interfaces.d.ts +5 -2
- package/dist/plugins/typescript/TypeScriptPlugin.d.ts +6 -5
- package/dist/plugins/typescript/TypeScriptPlugin.js +7 -8
- package/dist/plugins/typescript/astro2tsx.js +15 -1
- package/dist/plugins/typescript/features/TypeDefinitionsProvider.d.ts +9 -0
- package/dist/plugins/typescript/features/TypeDefinitionsProvider.js +55 -0
- package/dist/plugins/typescript/language-service.js +9 -11
- package/dist/server.js +10 -5
- package/dist/utils.d.ts +9 -7
- package/dist/utils.js +25 -16
- package/package.json +4 -1
- package/types/README.md +5 -0
- package/types/astro-jsx.d.ts +854 -477
- package/types/env.d.ts +22 -0
- package/dist/plugins/typescript/features/FormattingProvider.d.ts +0 -11
- package/dist/plugins/typescript/features/FormattingProvider.js +0 -132
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @astrojs/language-server
|
|
2
2
|
|
|
3
|
+
## 0.23.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1dcef68: Automatically type `Astro.props` using the Props interface when available
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- b6c95f2: Fix completions for HTML attributes not working anymore since 0.20.3
|
|
12
|
+
|
|
13
|
+
## 0.22.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- d5aafc0: Formatting is now powered by Prettier and our Prettier plugin. Going forward, this should result in a more stable and complete way of formatting Astro files
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- 61620f1: Add support for Go To Type Definition
|
|
22
|
+
- 9337f00: Fix language server not working when no initlizationOptions were passed
|
|
23
|
+
|
|
24
|
+
## 0.21.1
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- 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
|
|
29
|
+
- 3f79dbf: Fix `tsconfig.json` not loading properly in certain contexts on Windows
|
|
30
|
+
|
|
3
31
|
## 0.21.0
|
|
4
32
|
|
|
5
33
|
### Minor 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 });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VSCodeEmmetConfig } from '@vscode/emmet-helper';
|
|
2
|
-
import { LSConfig, LSCSSConfig,
|
|
2
|
+
import { LSConfig, LSCSSConfig, LSHTMLConfig, LSTypescriptConfig } from './interfaces';
|
|
3
3
|
import { Connection, FormattingOptions } from 'vscode-languageserver';
|
|
4
4
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
5
5
|
import { FormatCodeSettings, InlayHintsOptions, UserPreferences } from 'typescript';
|
|
@@ -23,7 +23,6 @@ export declare class ConfigManager {
|
|
|
23
23
|
removeDocument(scopeUri: string): void;
|
|
24
24
|
getConfig<T>(section: string, scopeUri: string): Promise<T | Record<string, any>>;
|
|
25
25
|
getEmmetConfig(document: TextDocument): Promise<VSCodeEmmetConfig>;
|
|
26
|
-
getAstroFormatConfig(document: TextDocument): Promise<LSFormatConfig>;
|
|
27
26
|
getTSFormatConfig(document: TextDocument, vscodeOptions?: FormattingOptions): Promise<FormatCodeSettings>;
|
|
28
27
|
getTSPreferences(document: TextDocument): Promise<UserPreferences>;
|
|
29
28
|
getTSInlayHintsPreferences(document: TextDocument): Promise<InlayHintsOptions>;
|
|
@@ -90,13 +90,6 @@ class ConfigManager {
|
|
|
90
90
|
showSuggestionsAsSnippets: emmetConfig.showSuggestionsAsSnippets ?? false,
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
|
-
async getAstroFormatConfig(document) {
|
|
94
|
-
const astroFormatConfig = (await this.getConfig('astro.format', document.uri)) ?? {};
|
|
95
|
-
return {
|
|
96
|
-
indentFrontmatter: astroFormatConfig.indentFrontmatter ?? exports.defaultLSConfig.format.indentFrontmatter,
|
|
97
|
-
newLineAfterFrontmatter: astroFormatConfig.newLineAfterFrontmatter ?? exports.defaultLSConfig.format.newLineAfterFrontmatter,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
93
|
async getTSFormatConfig(document, vscodeOptions) {
|
|
101
94
|
const formatConfig = (await this.getConfig('typescript.format', document.uri)) ?? {};
|
|
102
95
|
return {
|
package/dist/importPackage.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
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
|
+
import type * as prettier from 'prettier';
|
|
3
4
|
export declare function setIsTrusted(_isTrusted: boolean): void;
|
|
4
|
-
export declare function getPackagePath(packageName: string, fromPath: string): string | undefined;
|
|
5
|
+
export declare function getPackagePath(packageName: string, fromPath: string[]): string | undefined;
|
|
5
6
|
export declare function importSvelteIntegration(fromPath: string): typeof svelte | undefined;
|
|
6
7
|
export declare function importVueIntegration(fromPath: string): typeof vue | undefined;
|
|
8
|
+
export declare function importPrettier(fromPath: string): typeof prettier;
|
|
9
|
+
export declare function getPrettierPluginPath(fromPath: string): string;
|
package/dist/importPackage.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.importVueIntegration = exports.importSvelteIntegration = exports.getPackagePath = exports.setIsTrusted = void 0;
|
|
3
|
+
exports.getPrettierPluginPath = exports.importPrettier = exports.importVueIntegration = exports.importSvelteIntegration = exports.getPackagePath = exports.setIsTrusted = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
let isTrusted = true;
|
|
6
6
|
function setIsTrusted(_isTrusted) {
|
|
@@ -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
|
}
|
|
@@ -39,3 +42,13 @@ function importVueIntegration(fromPath) {
|
|
|
39
42
|
return importEditorIntegration('@astrojs/vue', fromPath);
|
|
40
43
|
}
|
|
41
44
|
exports.importVueIntegration = importVueIntegration;
|
|
45
|
+
function importPrettier(fromPath) {
|
|
46
|
+
// This shouldn't ever fail, because we bundle Prettier in the extension itself
|
|
47
|
+
const prettierPkg = getPackagePath('prettier', [fromPath, __dirname]);
|
|
48
|
+
return require(prettierPkg);
|
|
49
|
+
}
|
|
50
|
+
exports.importPrettier = importPrettier;
|
|
51
|
+
function getPrettierPluginPath(fromPath) {
|
|
52
|
+
return getPackagePath('prettier-plugin-astro', [fromPath, __dirname]);
|
|
53
|
+
}
|
|
54
|
+
exports.getPrettierPluginPath = getPrettierPluginPath;
|
|
@@ -24,6 +24,7 @@ export declare class PluginHost {
|
|
|
24
24
|
getSemanticTokens(textDocument: TextDocumentIdentifier, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
|
|
25
25
|
getLinkedEditingRanges(textDocument: TextDocumentIdentifier, position: Position): Promise<LinkedEditingRanges | null>;
|
|
26
26
|
getDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<DefinitionLink[] | Location[]>;
|
|
27
|
+
getTypeDefinition(textDocument: TextDocumentIdentifier, position: Position): Promise<Location[] | null>;
|
|
27
28
|
rename(textDocument: TextDocumentIdentifier, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
|
28
29
|
getDocumentColors(textDocument: TextDocumentIdentifier): Promise<ColorInformation[]>;
|
|
29
30
|
getColorPresentations(textDocument: TextDocumentIdentifier, range: Range, color: Color): Promise<ColorPresentation[]>;
|
|
@@ -115,6 +115,10 @@ class PluginHost {
|
|
|
115
115
|
return definitions.map((def) => ({ range: def.targetSelectionRange, uri: def.targetUri }));
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
|
+
getTypeDefinition(textDocument, position) {
|
|
119
|
+
const document = this.getDocument(textDocument.uri);
|
|
120
|
+
return this.execute('getTypeDefinitions', [document, position], ExecuteMode.FirstNonNull);
|
|
121
|
+
}
|
|
118
122
|
async rename(textDocument, position, newName) {
|
|
119
123
|
const document = this.getDocument(textDocument.uri);
|
|
120
124
|
return this.execute('rename', [document, position, newName], ExecuteMode.FirstNonNull);
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { CompletionContext, FoldingRange, Position } from 'vscode-languageserver';
|
|
1
|
+
import { CompletionContext, FoldingRange, Position, TextEdit, FormattingOptions } 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>;
|
|
13
|
+
formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
|
|
12
14
|
getFoldingRanges(document: AstroDocument): FoldingRange[];
|
|
13
15
|
}
|
|
@@ -2,19 +2,51 @@
|
|
|
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
|
|
5
|
+
const importPackage_1 = require("../../importPackage");
|
|
6
|
+
const utils_1 = require("../../utils");
|
|
6
7
|
const CompletionsProvider_1 = require("./features/CompletionsProvider");
|
|
7
8
|
class AstroPlugin {
|
|
8
|
-
constructor(
|
|
9
|
+
constructor(configManager, languageServiceManager) {
|
|
9
10
|
this.__name = 'astro';
|
|
10
11
|
this.configManager = configManager;
|
|
11
|
-
this.languageServiceManager =
|
|
12
|
+
this.languageServiceManager = languageServiceManager;
|
|
12
13
|
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager);
|
|
13
14
|
}
|
|
14
15
|
async getCompletions(document, position, completionContext) {
|
|
15
16
|
const completions = this.completionProvider.getCompletions(document, position, completionContext);
|
|
16
17
|
return completions;
|
|
17
18
|
}
|
|
19
|
+
async formatDocument(document, options) {
|
|
20
|
+
const filePath = document.getFilePath();
|
|
21
|
+
if (!filePath) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const prettier = (0, importPackage_1.importPrettier)(filePath);
|
|
25
|
+
const prettierConfig = await prettier.resolveConfig(filePath, { editorconfig: true, useCache: false });
|
|
26
|
+
const editorFormatConfig = options !== undefined
|
|
27
|
+
? {
|
|
28
|
+
tabWidth: prettierConfig?.tabWidth ?? options.tabSize,
|
|
29
|
+
useTabs: prettierConfig?.useTabs ?? !options.insertSpaces,
|
|
30
|
+
}
|
|
31
|
+
: {};
|
|
32
|
+
const resultConfig = (0, utils_1.mergeDeep)(prettierConfig ?? {}, editorFormatConfig);
|
|
33
|
+
const fileInfo = await prettier.getFileInfo(filePath, { ignorePath: '.prettierignore' });
|
|
34
|
+
if (fileInfo.ignored) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const result = prettier.format(document.getText(), {
|
|
38
|
+
...resultConfig,
|
|
39
|
+
plugins: getAstroPrettierPlugin(),
|
|
40
|
+
parser: 'astro',
|
|
41
|
+
});
|
|
42
|
+
return document.getText() === result
|
|
43
|
+
? []
|
|
44
|
+
: [vscode_languageserver_1.TextEdit.replace(vscode_languageserver_1.Range.create(document.positionAt(0), document.positionAt(document.getTextLength())), result)];
|
|
45
|
+
function getAstroPrettierPlugin() {
|
|
46
|
+
const hasPluginLoadedAlready = prettier.getSupportInfo().languages.some((l) => l.name === 'astro');
|
|
47
|
+
return hasPluginLoadedAlready ? [] : [(0, importPackage_1.getPrettierPluginPath)(filePath)];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
18
50
|
getFoldingRanges(document) {
|
|
19
51
|
const foldingRanges = [];
|
|
20
52
|
const { frontmatter } = document.astroMeta;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { LanguageService } from 'vscode-css-languageservice';
|
|
2
|
-
export declare function getLanguage(kind?: string): "css" | "
|
|
2
|
+
export declare function getLanguage(kind?: string): "css" | "less" | "scss";
|
|
3
3
|
export declare function getLanguageService(kind?: string): LanguageService;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CompletionList, Position,
|
|
1
|
+
import { CompletionList, Position, FoldingRange, Hover, SymbolInformation, LinkedEditingRanges } from 'vscode-languageserver';
|
|
2
2
|
import type { Plugin } from '../interfaces';
|
|
3
3
|
import { ConfigManager } from '../../core/config/ConfigManager';
|
|
4
4
|
import { AstroDocument } from '../../core/documents/AstroDocument';
|
|
@@ -15,7 +15,6 @@ export declare class HTMLPlugin implements Plugin {
|
|
|
15
15
|
* Get HTML completions
|
|
16
16
|
*/
|
|
17
17
|
getCompletions(document: AstroDocument, position: Position): Promise<CompletionList | null>;
|
|
18
|
-
formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
|
|
19
18
|
getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
|
|
20
19
|
getLinkedEditingRanges(document: AstroDocument, position: Position): LinkedEditingRanges | null;
|
|
21
20
|
doTagComplete(document: AstroDocument, position: Position): Promise<string | null>;
|
|
@@ -76,30 +76,16 @@ class HTMLPlugin {
|
|
|
76
76
|
const inTagName = (0, utils_1.isInTagName)(html, offset);
|
|
77
77
|
const results = inComponentTag && !inTagName
|
|
78
78
|
? (0, utils_2.removeDataAttrCompletion)(this.attributeOnlyLang.doComplete(document, position, html).items)
|
|
79
|
-
:
|
|
80
|
-
this.lang.doComplete(document, position, html).items.filter((item) => item.documentation !== undefined);
|
|
79
|
+
: this.lang.doComplete(document, position, html).items.filter(isNoAddedTagWithNoDocumentation);
|
|
81
80
|
const langCompletions = inComponentTag ? [] : this.getLangCompletions(results);
|
|
82
81
|
return vscode_languageserver_1.CompletionList.create([...results, ...langCompletions, ...emmetResults.items],
|
|
83
82
|
// Emmet completions change on every keystroke, so they are never complete
|
|
84
83
|
emmetResults.items.length > 0);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
start.character = 0;
|
|
91
|
-
}
|
|
92
|
-
const end = document.positionAt(document.getTextLength());
|
|
93
|
-
const htmlFormatConfig = (await this.configManager.getConfig('html.format', document.uri)) ?? {};
|
|
94
|
-
// The HTML plugin can't format script tags properly, we'll handle those inside the TypeScript plugin
|
|
95
|
-
if (htmlFormatConfig.contentUnformatted) {
|
|
96
|
-
htmlFormatConfig.contentUnformatted = htmlFormatConfig.contentUnformatted + ',script';
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
htmlFormatConfig.contentUnformatted = 'script';
|
|
100
|
-
}
|
|
101
|
-
const edits = this.lang.format(document, vscode_languageserver_1.Range.create(start, end), { ...htmlFormatConfig, ...options });
|
|
102
|
-
return edits;
|
|
84
|
+
// Filter script and style completions with no documentation to prevent duplicates
|
|
85
|
+
// due to our added definitions for those tags
|
|
86
|
+
function isNoAddedTagWithNoDocumentation(item) {
|
|
87
|
+
return !(['script', 'style'].includes(item.label) && item.documentation === undefined);
|
|
88
|
+
}
|
|
103
89
|
}
|
|
104
90
|
getFoldingRanges(document) {
|
|
105
91
|
const html = document.html;
|
|
@@ -1,4 +1,4 @@
|
|
|
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';
|
|
1
|
+
import { CodeAction, CodeActionContext, Color, Location, 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 {
|
|
@@ -74,6 +74,9 @@ export interface SemanticTokensProvider {
|
|
|
74
74
|
export interface LinkedEditingRangesProvider {
|
|
75
75
|
getLinkedEditingRanges(document: TextDocument, position: Position): Resolvable<LinkedEditingRanges | null>;
|
|
76
76
|
}
|
|
77
|
+
export interface TypeDefinitionProvider {
|
|
78
|
+
getTypeDefinitions(document: TextDocument, position: Position): Resolvable<Location[] | null>;
|
|
79
|
+
}
|
|
77
80
|
export interface OnWatchFileChangesParam {
|
|
78
81
|
fileName: string;
|
|
79
82
|
changeType: FileChangeType;
|
|
@@ -84,7 +87,7 @@ export interface OnWatchFileChangesProvider {
|
|
|
84
87
|
export interface UpdateNonAstroFile {
|
|
85
88
|
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): void;
|
|
86
89
|
}
|
|
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;
|
|
90
|
+
declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & DefinitionsProvider & TypeDefinitionProvider & FormattingProvider & FoldingRangesProvider & TagCompleteProvider & DocumentColorsProvider & ColorPresentationsProvider & DocumentSymbolsProvider & UpdateImportsProvider & CodeActionsProvider & FindReferencesProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & SelectionRangeProvider & OnWatchFileChangesProvider & LinkedEditingRangesProvider & InlayHintsProvider & UpdateNonAstroFile;
|
|
88
91
|
export declare type LSProvider = ProviderBase;
|
|
89
92
|
export declare type Plugin = Partial<ProviderBase> & {
|
|
90
93
|
__name: string;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { CancellationToken, CodeAction, CodeActionContext, CompletionContext, DefinitionLink, Diagnostic, FoldingRange,
|
|
1
|
+
import { CancellationToken, CodeAction, CodeActionContext, CompletionContext, DefinitionLink, Location, Diagnostic, FoldingRange, Hover, InlayHint, Position, Range, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, 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';
|
|
6
7
|
import { Astro2TSXResult } from './astro2tsx';
|
|
7
8
|
export declare class TypeScriptPlugin implements Plugin {
|
|
8
9
|
__name: string;
|
|
@@ -12,17 +13,16 @@ export declare class TypeScriptPlugin implements Plugin {
|
|
|
12
13
|
private readonly completionProvider;
|
|
13
14
|
private readonly hoverProvider;
|
|
14
15
|
private readonly definitionsProvider;
|
|
16
|
+
private readonly typeDefinitionsProvider;
|
|
15
17
|
private readonly signatureHelpProvider;
|
|
16
18
|
private readonly diagnosticsProvider;
|
|
17
19
|
private readonly documentSymbolsProvider;
|
|
18
20
|
private readonly inlayHintsProvider;
|
|
19
21
|
private readonly semanticTokensProvider;
|
|
20
22
|
private readonly foldingRangesProvider;
|
|
21
|
-
|
|
22
|
-
constructor(docManager: DocumentManager, configManager: ConfigManager, workspaceUris: string[]);
|
|
23
|
+
constructor(configManager: ConfigManager, languageServiceManager: LanguageServiceManager);
|
|
23
24
|
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
|
|
24
25
|
rename(document: AstroDocument, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
|
25
|
-
formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
|
|
26
26
|
getFoldingRanges(document: AstroDocument): Promise<FoldingRange[] | null>;
|
|
27
27
|
getSemanticTokens(document: AstroDocument, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
|
|
28
28
|
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
|
|
@@ -31,6 +31,7 @@ export declare class TypeScriptPlugin implements Plugin {
|
|
|
31
31
|
resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionItemData>, cancellationToken?: CancellationToken): Promise<AppCompletionItem<CompletionItemData>>;
|
|
32
32
|
getInlayHints(document: AstroDocument, range: Range): Promise<InlayHint[]>;
|
|
33
33
|
getDefinitions(document: AstroDocument, position: Position): Promise<DefinitionLink[]>;
|
|
34
|
+
getTypeDefinition(document: AstroDocument, position: Position): Promise<Location[] | null>;
|
|
34
35
|
getDiagnostics(document: AstroDocument, cancellationToken?: CancellationToken): Promise<Diagnostic[]>;
|
|
35
36
|
onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesParam[]): Promise<void>;
|
|
36
37
|
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): Promise<void>;
|
|
@@ -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");
|
|
@@ -18,25 +17,25 @@ const FoldingRangesProvider_1 = require("./features/FoldingRangesProvider");
|
|
|
18
17
|
const CodeActionsProvider_1 = require("./features/CodeActionsProvider");
|
|
19
18
|
const DefinitionsProvider_1 = require("./features/DefinitionsProvider");
|
|
20
19
|
const InlayHintsProvider_1 = require("./features/InlayHintsProvider");
|
|
21
|
-
const FormattingProvider_1 = require("./features/FormattingProvider");
|
|
22
20
|
const astro2tsx_1 = __importDefault(require("./astro2tsx"));
|
|
23
21
|
const utils_2 = require("./snapshots/utils");
|
|
22
|
+
const TypeDefinitionsProvider_1 = require("./features/TypeDefinitionsProvider");
|
|
24
23
|
class TypeScriptPlugin {
|
|
25
|
-
constructor(
|
|
24
|
+
constructor(configManager, languageServiceManager) {
|
|
26
25
|
this.__name = 'typescript';
|
|
27
26
|
this.configManager = configManager;
|
|
28
|
-
this.languageServiceManager =
|
|
27
|
+
this.languageServiceManager = languageServiceManager;
|
|
29
28
|
this.codeActionsProvider = new CodeActionsProvider_1.CodeActionsProviderImpl(this.languageServiceManager, this.configManager);
|
|
30
29
|
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager, this.configManager);
|
|
31
30
|
this.hoverProvider = new HoverProvider_1.HoverProviderImpl(this.languageServiceManager);
|
|
32
31
|
this.definitionsProvider = new DefinitionsProvider_1.DefinitionsProviderImpl(this.languageServiceManager);
|
|
32
|
+
this.typeDefinitionsProvider = new TypeDefinitionsProvider_1.TypeDefinitionsProviderImpl(this.languageServiceManager);
|
|
33
33
|
this.signatureHelpProvider = new SignatureHelpProvider_1.SignatureHelpProviderImpl(this.languageServiceManager);
|
|
34
34
|
this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
|
|
35
35
|
this.documentSymbolsProvider = new DocumentSymbolsProvider_1.DocumentSymbolsProviderImpl(this.languageServiceManager);
|
|
36
36
|
this.semanticTokensProvider = new SemanticTokenProvider_1.SemanticTokensProviderImpl(this.languageServiceManager);
|
|
37
37
|
this.inlayHintsProvider = new InlayHintsProvider_1.InlayHintsProviderImpl(this.languageServiceManager, this.configManager);
|
|
38
38
|
this.foldingRangesProvider = new FoldingRangesProvider_1.FoldingRangesProviderImpl(this.languageServiceManager);
|
|
39
|
-
this.formattingProvider = new FormattingProvider_1.FormattingProviderImpl(this.languageServiceManager, this.configManager);
|
|
40
39
|
}
|
|
41
40
|
async doHover(document, position) {
|
|
42
41
|
if (!(await this.featureEnabled(document, 'hover'))) {
|
|
@@ -67,9 +66,6 @@ class TypeScriptPlugin {
|
|
|
67
66
|
});
|
|
68
67
|
return edit;
|
|
69
68
|
}
|
|
70
|
-
async formatDocument(document, options) {
|
|
71
|
-
return this.formattingProvider.formatDocument(document, options);
|
|
72
|
-
}
|
|
73
69
|
async getFoldingRanges(document) {
|
|
74
70
|
return this.foldingRangesProvider.getFoldingRanges(document);
|
|
75
71
|
}
|
|
@@ -108,6 +104,9 @@ class TypeScriptPlugin {
|
|
|
108
104
|
async getDefinitions(document, position) {
|
|
109
105
|
return this.definitionsProvider.getDefinitions(document, position);
|
|
110
106
|
}
|
|
107
|
+
async getTypeDefinition(document, position) {
|
|
108
|
+
return this.typeDefinitionsProvider.getTypeDefinitions(document, position);
|
|
109
|
+
}
|
|
111
110
|
async getDiagnostics(document, cancellationToken) {
|
|
112
111
|
if (!(await this.featureEnabled(document, 'diagnostics'))) {
|
|
113
112
|
return [];
|
|
@@ -4,10 +4,24 @@ const os_1 = require("os");
|
|
|
4
4
|
const parseAstro_1 = require("../../core/documents/parseAstro");
|
|
5
5
|
function addProps(content, className) {
|
|
6
6
|
let defaultExportType = 'Record<string, any>';
|
|
7
|
+
let shouldAddGlobal = false;
|
|
8
|
+
let astroGlobal = "type AstroGlobal = import('astro').AstroGlobal";
|
|
9
|
+
const astroGlobalConstDef = `
|
|
10
|
+
/**
|
|
11
|
+
* Astro global available in all contexts in .astro files
|
|
12
|
+
*
|
|
13
|
+
* [Astro documentation](https://docs.astro.build/reference/api-reference/#astro-global)
|
|
14
|
+
*/
|
|
15
|
+
declare const Astro: Readonly<AstroGlobal>;
|
|
16
|
+
`;
|
|
7
17
|
if (/(interface|type) Props/.test(content)) {
|
|
8
18
|
defaultExportType = 'Props';
|
|
19
|
+
shouldAddGlobal = true;
|
|
20
|
+
astroGlobal += ' & { props: Props }';
|
|
9
21
|
}
|
|
10
|
-
return os_1.EOL +
|
|
22
|
+
return (os_1.EOL +
|
|
23
|
+
(shouldAddGlobal ? astroGlobal + os_1.EOL + astroGlobalConstDef : '') +
|
|
24
|
+
`export default function ${className}__AstroComponent_(_props: ${defaultExportType}): any {}`);
|
|
11
25
|
}
|
|
12
26
|
function escapeTemplateLiteralContent(content) {
|
|
13
27
|
return content.replace(/`/g, '\\`');
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Position, Location } from 'vscode-languageserver-protocol';
|
|
2
|
+
import { AstroDocument } from '../../../core/documents';
|
|
3
|
+
import { TypeDefinitionProvider } from '../../interfaces';
|
|
4
|
+
import { LanguageServiceManager } from '../LanguageServiceManager';
|
|
5
|
+
export declare class TypeDefinitionsProviderImpl implements TypeDefinitionProvider {
|
|
6
|
+
private languageServiceManager;
|
|
7
|
+
constructor(languageServiceManager: LanguageServiceManager);
|
|
8
|
+
getTypeDefinitions(document: AstroDocument, position: Position): Promise<Location[]>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TypeDefinitionsProviderImpl = void 0;
|
|
4
|
+
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
|
|
5
|
+
const documents_1 = require("../../../core/documents");
|
|
6
|
+
const utils_1 = require("../../../utils");
|
|
7
|
+
const utils_2 = require("../utils");
|
|
8
|
+
const utils_3 = require("./utils");
|
|
9
|
+
class TypeDefinitionsProviderImpl {
|
|
10
|
+
constructor(languageServiceManager) {
|
|
11
|
+
this.languageServiceManager = languageServiceManager;
|
|
12
|
+
}
|
|
13
|
+
async getTypeDefinitions(document, position) {
|
|
14
|
+
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
15
|
+
const mainFragment = await tsDoc.createFragment();
|
|
16
|
+
const fragmentOffset = mainFragment.offsetAt(mainFragment.getGeneratedPosition(position));
|
|
17
|
+
const tsFilePath = (0, utils_2.toVirtualAstroFilePath)(tsDoc.filePath);
|
|
18
|
+
const html = document.html;
|
|
19
|
+
const offset = document.offsetAt(position);
|
|
20
|
+
const node = html.findNodeAt(offset);
|
|
21
|
+
let typeDefs;
|
|
22
|
+
if (node.tag === 'script') {
|
|
23
|
+
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node, position);
|
|
24
|
+
typeDefs = lang.getTypeDefinitionAtPosition(scriptFilePath, scriptOffset);
|
|
25
|
+
if (typeDefs) {
|
|
26
|
+
typeDefs = typeDefs.map((def) => {
|
|
27
|
+
const isInSameFile = def.fileName === scriptFilePath;
|
|
28
|
+
def.fileName = isInSameFile ? tsFilePath : def.fileName;
|
|
29
|
+
if (isInSameFile) {
|
|
30
|
+
def.textSpan.start = mainFragment.offsetAt(scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(def.textSpan.start)));
|
|
31
|
+
}
|
|
32
|
+
return def;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
typeDefs = lang.getTypeDefinitionAtPosition(tsFilePath, fragmentOffset);
|
|
38
|
+
}
|
|
39
|
+
const docs = new utils_3.SnapshotFragmentMap(this.languageServiceManager);
|
|
40
|
+
docs.set(tsFilePath, { fragment: mainFragment, snapshot: tsDoc });
|
|
41
|
+
if (!typeDefs) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
const result = await Promise.all(typeDefs.map(async (typeDef) => {
|
|
45
|
+
const { fragment } = await docs.retrieve(typeDef.fileName);
|
|
46
|
+
const fileName = (0, utils_2.ensureRealFilePath)(typeDef.fileName);
|
|
47
|
+
const range = (0, documents_1.mapRangeToOriginal)(fragment, (0, utils_2.convertRange)(fragment, typeDef.textSpan));
|
|
48
|
+
if (range.start.line >= 0 && range.end.line >= 0) {
|
|
49
|
+
return vscode_languageserver_protocol_1.Location.create((0, utils_1.pathToUrl)(fileName), range);
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
return result.filter(utils_1.isNotNullOrUndefined);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.TypeDefinitionsProviderImpl = TypeDefinitionsProviderImpl;
|
|
@@ -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
|
|
@@ -81,9 +81,8 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
|
|
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
83
|
const scriptFileNames = [];
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
scriptFileNames.push(...['./env.d.ts', './astro-jsx.d.ts'].map((f) => typescript_1.default.sys.resolvePath((0, path_1.resolve)(astroDir, f))));
|
|
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))));
|
|
87
86
|
}
|
|
88
87
|
let languageServerDirectory;
|
|
89
88
|
try {
|
|
@@ -92,14 +91,13 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
|
|
92
91
|
catch (e) {
|
|
93
92
|
languageServerDirectory = __dirname;
|
|
94
93
|
}
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
|
99
98
|
) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
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");
|
|
103
101
|
}
|
|
104
102
|
if (allowArbitraryAttrs) {
|
|
105
103
|
const arbitraryAttrsDTS = typescript_1.default.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, '../types/arbitrary-attrs.d.ts'));
|