@astrojs/language-server 0.15.0 → 0.17.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/check.js +1 -2
  3. package/dist/core/config/ConfigManager.d.ts +20 -16
  4. package/dist/core/config/ConfigManager.js +112 -46
  5. package/dist/core/config/interfaces.d.ts +0 -52
  6. package/dist/core/documents/AstroDocument.d.ts +1 -0
  7. package/dist/core/documents/AstroDocument.js +1 -0
  8. package/dist/core/documents/DocumentMapper.d.ts +2 -0
  9. package/dist/core/documents/DocumentMapper.js +9 -9
  10. package/dist/core/documents/parseAstro.js +1 -1
  11. package/dist/core/documents/utils.d.ts +1 -0
  12. package/dist/core/documents/utils.js +19 -5
  13. package/dist/plugins/PluginHost.d.ts +2 -1
  14. package/dist/plugins/PluginHost.js +8 -6
  15. package/dist/plugins/astro/AstroPlugin.d.ts +1 -6
  16. package/dist/plugins/astro/AstroPlugin.js +1 -83
  17. package/dist/plugins/astro/features/CompletionsProvider.d.ts +4 -5
  18. package/dist/plugins/astro/features/CompletionsProvider.js +49 -59
  19. package/dist/plugins/css/CSSPlugin.d.ts +5 -5
  20. package/dist/plugins/css/CSSPlugin.js +41 -20
  21. package/dist/plugins/html/HTMLPlugin.d.ts +4 -4
  22. package/dist/plugins/html/HTMLPlugin.js +20 -16
  23. package/dist/plugins/html/features/astro-attributes.js +44 -27
  24. package/dist/plugins/typescript/LanguageServiceManager.js +1 -1
  25. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +5 -4
  26. package/dist/plugins/typescript/TypeScriptPlugin.js +30 -108
  27. package/dist/plugins/typescript/astro-sys.js +3 -5
  28. package/dist/plugins/typescript/astro2tsx.js +1 -2
  29. package/dist/plugins/typescript/features/CodeActionsProvider.d.ts +16 -0
  30. package/dist/plugins/typescript/features/CodeActionsProvider.js +206 -0
  31. package/dist/plugins/typescript/features/CompletionsProvider.d.ts +5 -2
  32. package/dist/plugins/typescript/features/CompletionsProvider.js +116 -68
  33. package/dist/plugins/typescript/features/DefinitionsProvider.d.ts +9 -0
  34. package/dist/plugins/typescript/features/DefinitionsProvider.js +57 -0
  35. package/dist/plugins/typescript/features/DiagnosticsProvider.js +60 -18
  36. package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +3 -4
  37. package/dist/plugins/typescript/features/FoldingRangesProvider.js +13 -6
  38. package/dist/plugins/typescript/features/HoverProvider.js +14 -1
  39. package/dist/plugins/typescript/features/SemanticTokenProvider.js +1 -1
  40. package/dist/plugins/typescript/features/SignatureHelpProvider.js +11 -3
  41. package/dist/plugins/typescript/features/utils.d.ts +2 -0
  42. package/dist/plugins/typescript/features/utils.js +19 -3
  43. package/dist/plugins/typescript/language-service.js +23 -6
  44. package/dist/plugins/typescript/module-loader.js +1 -1
  45. package/dist/plugins/typescript/previewer.js +1 -1
  46. package/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts +22 -2
  47. package/dist/plugins/typescript/snapshots/DocumentSnapshot.js +48 -1
  48. package/dist/plugins/typescript/snapshots/SnapshotManager.js +2 -1
  49. package/dist/plugins/typescript/snapshots/utils.js +3 -6
  50. package/dist/plugins/typescript/utils.d.ts +12 -1
  51. package/dist/plugins/typescript/utils.js +29 -1
  52. package/dist/server.js +43 -14
  53. package/dist/utils.d.ts +4 -0
  54. package/dist/utils.js +16 -3
  55. package/package.json +2 -2
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ensureRealFilePath = exports.ensureRealAstroFilePath = exports.toRealAstroFilePath = exports.toVirtualFilePath = exports.toVirtualAstroFilePath = exports.isVirtualFilePath = exports.isVirtualSvelteFilePath = exports.isVirtualVueFilePath = exports.isVirtualAstroFilePath = exports.isFrameworkFilePath = exports.isAstroFilePath = exports.isVirtualFrameworkFilePath = exports.getFrameworkFromFilePath = exports.removeAstroComponentSuffix = exports.ensureFrontmatterInsert = exports.convertToLocationRange = exports.convertRange = exports.mapSeverity = exports.getScriptKindFromFileName = exports.isSubPath = exports.findTsConfigPath = exports.getExtensionFromScriptKind = exports.getCommitCharactersForScriptElement = exports.scriptElementKindToCompletionItemKind = exports.symbolKindFromString = exports.getSemanticTokenLegend = void 0;
6
+ exports.getScriptTagSnapshot = exports.ensureRealFilePath = exports.ensureRealAstroFilePath = exports.toRealAstroFilePath = exports.toVirtualFilePath = exports.toVirtualAstroFilePath = exports.isVirtualFilePath = exports.isVirtualSvelteFilePath = exports.isVirtualVueFilePath = exports.isVirtualAstroFilePath = exports.isFrameworkFilePath = exports.isAstroFilePath = exports.isVirtualFrameworkFilePath = exports.getFrameworkFromFilePath = exports.removeAstroComponentSuffix = exports.checkEndOfFileCodeInsert = exports.ensureFrontmatterInsert = exports.convertToLocationRange = exports.convertRange = exports.mapSeverity = exports.getScriptKindFromFileName = exports.isSubPath = exports.findTsConfigPath = exports.getExtensionFromScriptKind = exports.getCommitCharactersForScriptElement = exports.scriptElementKindToCompletionItemKind = exports.symbolKindFromString = exports.getSemanticTokenLegend = void 0;
7
7
  const typescript_1 = __importDefault(require("typescript"));
8
8
  const path_1 = require("path");
9
9
  const utils_1 = require("../../utils");
@@ -251,6 +251,18 @@ function ensureFrontmatterInsert(resultRange, document) {
251
251
  return resultRange;
252
252
  }
253
253
  exports.ensureFrontmatterInsert = ensureFrontmatterInsert;
254
+ // Some code actions ill insert code at the end of the generated TSX file, so we'll manually
255
+ // redirect it to the end of the frontmatter instead
256
+ function checkEndOfFileCodeInsert(resultRange, document) {
257
+ if (resultRange.start.line > document.lineCount) {
258
+ if (document.astroMeta.frontmatter.state === 'closed') {
259
+ const position = document.positionAt(document.astroMeta.frontmatter.endOffset);
260
+ return vscode_languageserver_1.Range.create(position, position);
261
+ }
262
+ }
263
+ return resultRange;
264
+ }
265
+ exports.checkEndOfFileCodeInsert = checkEndOfFileCodeInsert;
254
266
  function removeAstroComponentSuffix(name) {
255
267
  return name.replace(/(\w+)__AstroComponent_/, '$1');
256
268
  }
@@ -334,3 +346,19 @@ function ensureRealFilePath(filePath) {
334
346
  }
335
347
  }
336
348
  exports.ensureRealFilePath = ensureRealFilePath;
349
+ function getScriptTagSnapshot(snapshot, document, tagInfo, position) {
350
+ const index = document.scriptTags.findIndex((value) => value.container.start == tagInfo.start);
351
+ const scriptFilePath = snapshot.filePath + `.__script${index}.js`;
352
+ const scriptTagSnapshot = snapshot.scriptTagSnapshots[index];
353
+ let offset = 0;
354
+ if (position) {
355
+ offset = scriptTagSnapshot.offsetAt(scriptTagSnapshot.getGeneratedPosition(position));
356
+ }
357
+ return {
358
+ snapshot: scriptTagSnapshot,
359
+ filePath: scriptFilePath,
360
+ index,
361
+ offset,
362
+ };
363
+ }
364
+ exports.getScriptTagSnapshot = getScriptTagSnapshot;
package/dist/server.js CHANGED
@@ -36,16 +36,17 @@ const PluginHost_1 = require("./plugins/PluginHost");
36
36
  const plugins_1 = require("./plugins");
37
37
  const utils_1 = require("./utils");
38
38
  const utils_2 = require("./plugins/typescript/utils");
39
+ const CodeActionsProvider_1 = require("./plugins/typescript/features/CodeActionsProvider");
39
40
  const TagCloseRequest = new vscode.RequestType('html/tag');
40
41
  // Start the language server
41
42
  function startLanguageServer(connection) {
42
43
  // Create our managers
43
- const configManager = new ConfigManager_1.ConfigManager();
44
44
  const documentManager = new DocumentManager_1.DocumentManager();
45
45
  const pluginHost = new PluginHost_1.PluginHost(documentManager);
46
+ const configManager = new ConfigManager_1.ConfigManager(connection);
47
+ let hasConfigurationCapability = false;
46
48
  connection.onInitialize((params) => {
47
- var _a, _b, _c, _d, _e, _f;
48
- const workspaceUris = (_b = (_a = params.workspaceFolders) === null || _a === void 0 ? void 0 : _a.map((folder) => folder.uri.toString())) !== null && _b !== void 0 ? _b : [(_c = params.rootUri) !== null && _c !== void 0 ? _c : ''];
49
+ const workspaceUris = params.workspaceFolders?.map((folder) => folder.uri.toString()) ?? [params.rootUri ?? ''];
49
50
  workspaceUris.forEach((uri) => {
50
51
  uri = (0, utils_1.urlToPath)(uri);
51
52
  const astroVersion = (0, utils_1.getUserAstroVersion)(uri);
@@ -62,9 +63,10 @@ function startLanguageServer(connection) {
62
63
  });
63
64
  }
64
65
  });
66
+ hasConfigurationCapability = !!(params.capabilities.workspace && !!params.capabilities.workspace.configuration);
65
67
  pluginHost.initialize({
66
- filterIncompleteCompletions: !((_d = params.initializationOptions) === null || _d === void 0 ? void 0 : _d.dontFilterIncompleteCompletions),
67
- definitionLinkSupport: !!((_f = (_e = params.capabilities.textDocument) === null || _e === void 0 ? void 0 : _e.definition) === null || _f === void 0 ? void 0 : _f.linkSupport),
68
+ filterIncompleteCompletions: !params.initializationOptions?.dontFilterIncompleteCompletions,
69
+ definitionLinkSupport: !!params.capabilities.textDocument?.definition?.linkSupport,
68
70
  });
69
71
  // Register plugins
70
72
  pluginHost.registerPlugin(new HTMLPlugin_1.HTMLPlugin(configManager));
@@ -74,15 +76,26 @@ function startLanguageServer(connection) {
74
76
  pluginHost.registerPlugin(new AstroPlugin_1.AstroPlugin(documentManager, configManager, workspaceUris));
75
77
  pluginHost.registerPlugin(new plugins_1.TypeScriptPlugin(documentManager, configManager, workspaceUris));
76
78
  }
77
- // Update language-server config with what the user supplied to us at launch
78
- configManager.updateConfig(params.initializationOptions.configuration.astro);
79
- configManager.updateEmmetConfig(params.initializationOptions.configuration.emmet);
80
79
  return {
81
80
  capabilities: {
82
- textDocumentSync: vscode.TextDocumentSyncKind.Incremental,
81
+ textDocumentSync: {
82
+ openClose: true,
83
+ change: vscode.TextDocumentSyncKind.Incremental,
84
+ save: {
85
+ includeText: true,
86
+ },
87
+ },
83
88
  foldingRangeProvider: true,
84
89
  definitionProvider: true,
85
90
  renameProvider: true,
91
+ codeActionProvider: {
92
+ codeActionKinds: [
93
+ vscode_languageserver_1.CodeActionKind.QuickFix,
94
+ vscode_languageserver_1.CodeActionKind.SourceOrganizeImports,
95
+ // VS Code specific
96
+ CodeActionsProvider_1.sortImportKind,
97
+ ],
98
+ },
86
99
  completionProvider: {
87
100
  resolveProvider: true,
88
101
  triggerCharacters: [
@@ -127,10 +140,18 @@ function startLanguageServer(connection) {
127
140
  },
128
141
  };
129
142
  });
130
- // On update of the user configuration of the language-server
131
- connection.onDidChangeConfiguration(({ settings }) => {
132
- configManager.updateConfig(settings.astro);
133
- configManager.updateEmmetConfig(settings.emmet);
143
+ // The params don't matter here because in "pull mode" it's always null, it's intended that when the config is updated
144
+ // you should just reset "your internal cache" and get the config again for relevant documents, weird API design
145
+ connection.onDidChangeConfiguration(async (change) => {
146
+ if (hasConfigurationCapability) {
147
+ configManager.updateConfig();
148
+ documentManager.getAllOpenedByClient().forEach(async (document) => {
149
+ await configManager.getConfig('astro', document[1].uri);
150
+ });
151
+ }
152
+ else {
153
+ configManager.updateGlobalConfig(change.settings.astro || ConfigManager_1.defaultLSConfig);
154
+ }
134
155
  });
135
156
  // Documents
136
157
  connection.onDidOpenTextDocument((params) => {
@@ -157,6 +178,7 @@ function startLanguageServer(connection) {
157
178
  connection.onHover((params) => pluginHost.doHover(params.textDocument, params.position));
158
179
  connection.onDefinition((evt) => pluginHost.getDefinitions(evt.textDocument, evt.position));
159
180
  connection.onFoldingRanges((evt) => pluginHost.getFoldingRanges(evt.textDocument));
181
+ connection.onCodeAction((evt, cancellationToken) => pluginHost.getCodeActions(evt.textDocument, evt.range, evt.context, cancellationToken));
160
182
  connection.onCompletion(async (evt) => {
161
183
  const promise = pluginHost.getCompletions(evt.textDocument, evt.position, evt.context);
162
184
  return promise;
@@ -185,10 +207,17 @@ function startLanguageServer(connection) {
185
207
  updateAllDiagnostics();
186
208
  });
187
209
  documentManager.on('documentChange', (0, utils_1.debounceThrottle)(async (document) => diagnosticsManager.update(document), 1000));
188
- documentManager.on('documentClose', (document) => diagnosticsManager.removeDiagnostics(document));
210
+ documentManager.on('documentClose', (document) => {
211
+ diagnosticsManager.removeDiagnostics(document);
212
+ configManager.removeDocument(document.uri);
213
+ });
189
214
  // Taking off 🚀
190
215
  connection.onInitialized(() => {
191
216
  connection.console.log('Successfully initialized! 🚀');
217
+ // Register for all configuration changes.
218
+ if (hasConfigurationCapability) {
219
+ connection.client.register(vscode_languageserver_1.DidChangeConfigurationNotification.type);
220
+ }
192
221
  });
193
222
  connection.listen();
194
223
  }
package/dist/utils.d.ts CHANGED
@@ -20,6 +20,10 @@ export declare function getLastPartOfPath(path: string): string;
20
20
  * Transform a string into PascalCase
21
21
  */
22
22
  export declare function toPascalCase(string: string): string;
23
+ /**
24
+ * Function to modify each line of a text, preserving the line break style (`\n` or `\r\n`)
25
+ */
26
+ export declare function modifyLines(text: string, replacementFn: (line: string, lineIdx: number) => string): string;
23
27
  /**
24
28
  * Return true if a specific node could be a component.
25
29
  * 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/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getUserAstroVersion = exports.debounceThrottle = exports.debounceSameArg = exports.getRegExpMatches = exports.isBeforeOrEqualToPosition = exports.isInRange = exports.isNotNullOrUndefined = exports.clamp = exports.flatten = exports.isPossibleComponent = exports.toPascalCase = exports.getLastPartOfPath = exports.pathToUrl = exports.urlToPath = exports.normalizePath = exports.normalizeUri = void 0;
3
+ exports.getUserAstroVersion = exports.debounceThrottle = exports.debounceSameArg = exports.getRegExpMatches = exports.isBeforeOrEqualToPosition = exports.isInRange = exports.isNotNullOrUndefined = exports.clamp = exports.flatten = exports.isPossibleComponent = exports.modifyLines = exports.toPascalCase = exports.getLastPartOfPath = exports.pathToUrl = exports.urlToPath = exports.normalizePath = exports.normalizeUri = void 0;
4
4
  const vscode_uri_1 = require("vscode-uri");
5
5
  /** Normalizes a document URI */
6
6
  function normalizeUri(uri) {
@@ -48,13 +48,26 @@ function toPascalCase(string) {
48
48
  .replace(new RegExp(/\w/), (s) => s.toUpperCase());
49
49
  }
50
50
  exports.toPascalCase = toPascalCase;
51
+ /**
52
+ * Function to modify each line of a text, preserving the line break style (`\n` or `\r\n`)
53
+ */
54
+ function modifyLines(text, replacementFn) {
55
+ let idx = 0;
56
+ return text
57
+ .split('\r\n')
58
+ .map((l1) => l1
59
+ .split('\n')
60
+ .map((line) => replacementFn(line, idx++))
61
+ .join('\n'))
62
+ .join('\r\n');
63
+ }
64
+ exports.modifyLines = modifyLines;
51
65
  /**
52
66
  * Return true if a specific node could be a component.
53
67
  * 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
54
68
  */
55
69
  function isPossibleComponent(node) {
56
- var _a, _b;
57
- return !!((_a = node.tag) === null || _a === void 0 ? void 0 : _a[0].match(/[A-Z]/)) || !!((_b = node.tag) === null || _b === void 0 ? void 0 : _b.match(/.+[.][A-Z]/));
70
+ return !!node.tag?.[0].match(/[A-Z]/) || !!node.tag?.match(/.+[.][A-Z]/);
58
71
  }
59
72
  exports.isPossibleComponent = isPossibleComponent;
60
73
  /** Flattens an array */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/language-server",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "author": "withastro",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -19,7 +19,7 @@
19
19
  "test": "cross-env TS_NODE_TRANSPILE_ONLY=true mocha --timeout 20000 --require ts-node/register \"test/**/*.ts\" --exclude \"test/**/*.d.ts\""
20
20
  },
21
21
  "dependencies": {
22
- "@astrojs/svelte-language-integration": "^0.1.3",
22
+ "@astrojs/svelte-language-integration": "^0.1.4",
23
23
  "@vscode/emmet-helper": "^2.8.4",
24
24
  "lodash": "^4.17.21",
25
25
  "source-map": "^0.7.3",