@astrojs/language-server 0.19.0 → 0.19.3

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 CHANGED
@@ -1,5 +1,31 @@
1
1
  # @astrojs/language-server
2
2
 
3
+ ## 0.19.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 49ff4ef: Fixed more bugs where nonexistent server settings would result in a crash
8
+ - 14cbf05: Fix frontmatter completion not working when three dashes were already present
9
+
10
+ ## 0.19.2
11
+
12
+ ### Patch Changes
13
+
14
+ - 7de4967: Add better error messages for Vue and Svelte components with syntax errors
15
+ - Updated dependencies [7de4967]
16
+ - @astrojs/svelte-language-integration@0.1.6
17
+ - @astrojs/vue-language-integration@0.1.1
18
+
19
+ ## 0.19.1
20
+
21
+ ### Patch Changes
22
+
23
+ - 729dff5: Add support for giving linked editing ranges
24
+ - 05a48c2: Fix some TypeScript diagnostics not showing up in certain cases
25
+ - fe2d26b: Add support for showing Svelte components documentation on hover
26
+ - Updated dependencies [fe2d26b]
27
+ - @astrojs/svelte-language-integration@0.1.5
28
+
3
29
  ## 0.19.0
4
30
 
5
31
  ### Minor Changes
@@ -142,8 +142,15 @@ class ConfigManager {
142
142
  * Return true if a plugin and an optional feature is enabled
143
143
  */
144
144
  async isEnabled(document, plugin, feature) {
145
- const config = await this.getConfig('astro', document.uri);
146
- return feature ? config[plugin].enabled && config[plugin][feature].enabled : config[plugin].enabled;
145
+ const config = (await this.getConfig('astro', document.uri)) ?? {};
146
+ if (config[plugin]) {
147
+ let res = config[plugin].enabled;
148
+ if (feature && config[plugin][feature]) {
149
+ res = res && config[plugin][feature].enabled;
150
+ }
151
+ return res;
152
+ }
153
+ return false;
147
154
  }
148
155
  /**
149
156
  * Updating the global config should only be done in cases where the client doesn't support `workspace/configuration`
@@ -1,4 +1,4 @@
1
- import { CancellationToken, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, Location, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, TextDocumentIdentifier, WorkspaceEdit, SymbolInformation, SemanticTokens, CodeActionContext, CodeAction, InlayHint, FormattingOptions, TextEdit } from 'vscode-languageserver';
1
+ import { CancellationToken, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, Location, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, TextDocumentIdentifier, WorkspaceEdit, SymbolInformation, SemanticTokens, CodeActionContext, CodeAction, InlayHint, FormattingOptions, TextEdit, LinkedEditingRanges } from 'vscode-languageserver';
2
2
  import type { AppCompletionItem, Plugin } from './interfaces';
3
3
  import { DocumentManager } from '../core/documents/DocumentManager';
4
4
  interface PluginHostConfig {
@@ -22,6 +22,7 @@ export declare class PluginHost {
22
22
  getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[] | null>;
23
23
  getDocumentSymbols(textDocument: TextDocumentIdentifier, cancellationToken: CancellationToken): Promise<SymbolInformation[]>;
24
24
  getSemanticTokens(textDocument: TextDocumentIdentifier, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
25
+ getLinkedEditingRanges(textDocument: TextDocumentIdentifier, position: Position): Promise<LinkedEditingRanges | null>;
25
26
  getDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<DefinitionLink[] | Location[]>;
26
27
  rename(textDocument: TextDocumentIdentifier, position: Position, newName: string): Promise<WorkspaceEdit | null>;
27
28
  getDocumentColors(textDocument: TextDocumentIdentifier): Promise<ColorInformation[]>;
@@ -94,6 +94,10 @@ class PluginHost {
94
94
  const document = this.getDocument(textDocument.uri);
95
95
  return await this.execute('getSemanticTokens', [document, range, cancellationToken], ExecuteMode.FirstNonNull);
96
96
  }
97
+ async getLinkedEditingRanges(textDocument, position) {
98
+ const document = this.getDocument(textDocument.uri);
99
+ return await this.execute('getLinkedEditingRanges', [document, position], ExecuteMode.FirstNonNull);
100
+ }
97
101
  async getDefinitions(textDocument, position) {
98
102
  const document = this.getDocument(textDocument.uri);
99
103
  const definitions = (0, lodash_1.flatten)(await this.execute('getDefinitions', [document, position], ExecuteMode.Collect));
@@ -23,15 +23,16 @@ class CompletionsProviderImpl {
23
23
  }
24
24
  async getCompletions(document, position, completionContext) {
25
25
  let items = [];
26
- if (completionContext?.triggerCharacter === '-') {
26
+ const html = document.html;
27
+ const offset = document.offsetAt(position);
28
+ const node = html.findNodeAt(offset);
29
+ const insideExpression = (0, utils_1.isInsideExpression)(document.getText(), node.start, offset);
30
+ if (completionContext?.triggerCharacter === '-' && node.parent === undefined && !insideExpression) {
27
31
  const frontmatter = this.getComponentScriptCompletion(document, position);
28
32
  if (frontmatter)
29
33
  items.push(frontmatter);
30
34
  }
31
- const html = document.html;
32
- const offset = document.offsetAt(position);
33
- const node = html.findNodeAt(offset);
34
- if ((0, utils_1.isInComponentStartTag)(html, offset) && !(0, utils_1.isInsideExpression)(document.getText(), node.start, offset)) {
35
+ if ((0, utils_1.isInComponentStartTag)(html, offset) && !insideExpression) {
35
36
  const { completions: props, componentFilePath } = await this.getPropCompletionsAndFilePath(document, position, completionContext);
36
37
  if (props.length) {
37
38
  items.push(...props);
@@ -50,7 +51,7 @@ class CompletionsProviderImpl {
50
51
  label: '---',
51
52
  sortText: '\0',
52
53
  preselect: true,
53
- detail: 'Component script',
54
+ detail: 'Create component script block',
54
55
  insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
55
56
  commitCharacters: [],
56
57
  };
@@ -65,11 +66,18 @@ class CompletionsProviderImpl {
65
66
  };
66
67
  }
67
68
  if (document.astroMeta.frontmatter.state === 'open') {
69
+ let insertText = '---';
70
+ // If the current line is a full component script starter/ender, the user expects a full frontmatter
71
+ // completion and not just a completion for "---" on the same line (which result in, well, nothing)
72
+ if (prefix === '---') {
73
+ insertText = '---\n$0\n---';
74
+ }
68
75
  return {
69
76
  ...base,
70
- insertText: '---',
77
+ insertText,
78
+ detail: insertText === '---' ? 'Close component script block' : 'Create component script block',
71
79
  textEdit: prefix.match(/^\s*\-+/)
72
- ? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, '---')
80
+ ? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, insertText)
73
81
  : undefined,
74
82
  };
75
83
  }
@@ -1,4 +1,4 @@
1
- import { CompletionList, Position, TextEdit, FoldingRange, Hover, SymbolInformation, FormattingOptions } from 'vscode-languageserver';
1
+ import { CompletionList, Position, TextEdit, FoldingRange, Hover, SymbolInformation, FormattingOptions, 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';
@@ -17,6 +17,7 @@ export declare class HTMLPlugin implements Plugin {
17
17
  getCompletions(document: AstroDocument, position: Position): Promise<CompletionList | null>;
18
18
  formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
19
19
  getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
20
+ getLinkedEditingRanges(document: AstroDocument, position: Position): LinkedEditingRanges | null;
20
21
  doTagComplete(document: AstroDocument, position: Position): Promise<string | null>;
21
22
  getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
22
23
  /**
@@ -63,8 +63,8 @@ class HTMLPlugin {
63
63
  items: [],
64
64
  };
65
65
  const emmetConfig = await this.configManager.getEmmetConfig(document);
66
- const extensionConfig = await this.configManager.getConfig('astro', document.uri);
67
- if (extensionConfig.html.completions.emmet) {
66
+ const extensionConfig = (await this.configManager.getConfig('astro', document.uri)) ?? {};
67
+ if (extensionConfig?.html?.completions?.emmet) {
68
68
  this.lang.setCompletionParticipants([
69
69
  {
70
70
  onHtmlContent: () => (emmetResults = (0, emmet_helper_1.doComplete)(document, position, 'html', emmetConfig) || emmetResults),
@@ -105,6 +105,17 @@ class HTMLPlugin {
105
105
  }
106
106
  return this.lang.getFoldingRanges(document);
107
107
  }
108
+ getLinkedEditingRanges(document, position) {
109
+ const html = document.html;
110
+ if (!html) {
111
+ return null;
112
+ }
113
+ const ranges = this.lang.findLinkedEditingRanges(document, position, html);
114
+ if (!ranges) {
115
+ return null;
116
+ }
117
+ return { ranges };
118
+ }
108
119
  async doTagComplete(document, position) {
109
120
  if (!(await this.featureEnabled(document, 'tagComplete'))) {
110
121
  return null;
@@ -3,6 +3,18 @@ import { Diagnostic } from 'vscode-languageserver-types';
3
3
  import { AstroDocument } from '../../../core/documents';
4
4
  import { DiagnosticsProvider } from '../../interfaces';
5
5
  import { LanguageServiceManager } from '../LanguageServiceManager';
6
+ export declare enum DiagnosticCodes {
7
+ SPREAD_EXPECTED = 1005,
8
+ DUPLICATED_JSX_ATTRIBUTES = 17001,
9
+ MUST_HAVE_PARENT_ELEMENT = 2657,
10
+ CANNOT_IMPORT_TS_EXT = 2691,
11
+ CANT_RETURN_OUTSIDE_FUNC = 1108,
12
+ ISOLATED_MODULE_COMPILE_ERR = 1208,
13
+ TYPE_NOT_ASSIGNABLE = 2322,
14
+ JSX_NO_CLOSING_TAG = 17008,
15
+ NO_DECL_IMPLICIT_ANY_TYPE = 7016,
16
+ JSX_ELEMENT_NO_CALL = 2604
17
+ }
6
18
  export declare class DiagnosticsProviderImpl implements DiagnosticsProvider {
7
19
  private readonly languageServiceManager;
8
20
  constructor(languageServiceManager: LanguageServiceManager);
@@ -3,11 +3,26 @@ 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.DiagnosticsProviderImpl = void 0;
6
+ exports.DiagnosticsProviderImpl = exports.DiagnosticCodes = void 0;
7
7
  const typescript_1 = __importDefault(require("typescript"));
8
8
  const vscode_languageserver_types_1 = require("vscode-languageserver-types");
9
9
  const documents_1 = require("../../../core/documents");
10
10
  const utils_1 = require("../utils");
11
+ // List of codes:
12
+ // https://github.com/Microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
13
+ var DiagnosticCodes;
14
+ (function (DiagnosticCodes) {
15
+ DiagnosticCodes[DiagnosticCodes["SPREAD_EXPECTED"] = 1005] = "SPREAD_EXPECTED";
16
+ DiagnosticCodes[DiagnosticCodes["DUPLICATED_JSX_ATTRIBUTES"] = 17001] = "DUPLICATED_JSX_ATTRIBUTES";
17
+ DiagnosticCodes[DiagnosticCodes["MUST_HAVE_PARENT_ELEMENT"] = 2657] = "MUST_HAVE_PARENT_ELEMENT";
18
+ DiagnosticCodes[DiagnosticCodes["CANNOT_IMPORT_TS_EXT"] = 2691] = "CANNOT_IMPORT_TS_EXT";
19
+ DiagnosticCodes[DiagnosticCodes["CANT_RETURN_OUTSIDE_FUNC"] = 1108] = "CANT_RETURN_OUTSIDE_FUNC";
20
+ DiagnosticCodes[DiagnosticCodes["ISOLATED_MODULE_COMPILE_ERR"] = 1208] = "ISOLATED_MODULE_COMPILE_ERR";
21
+ DiagnosticCodes[DiagnosticCodes["TYPE_NOT_ASSIGNABLE"] = 2322] = "TYPE_NOT_ASSIGNABLE";
22
+ DiagnosticCodes[DiagnosticCodes["JSX_NO_CLOSING_TAG"] = 17008] = "JSX_NO_CLOSING_TAG";
23
+ DiagnosticCodes[DiagnosticCodes["NO_DECL_IMPLICIT_ANY_TYPE"] = 7016] = "NO_DECL_IMPLICIT_ANY_TYPE";
24
+ DiagnosticCodes[DiagnosticCodes["JSX_ELEMENT_NO_CALL"] = 2604] = "JSX_ELEMENT_NO_CALL";
25
+ })(DiagnosticCodes = exports.DiagnosticCodes || (exports.DiagnosticCodes = {}));
11
26
  class DiagnosticsProviderImpl {
12
27
  constructor(languageServiceManager) {
13
28
  this.languageServiceManager = languageServiceManager;
@@ -39,17 +54,15 @@ class DiagnosticsProviderImpl {
39
54
  code: diagnostic.code,
40
55
  tags: getDiagnosticTag(diagnostic),
41
56
  }))
57
+ .filter(isNoCantEndWithTS)
42
58
  .map(mapRange(scriptTagSnapshot, document));
43
59
  scriptDiagnostics.push(...scriptDiagnostic);
44
60
  });
45
61
  const { script: scriptBoundaries } = this.getTagBoundaries(lang, filePath);
46
- const syntaxDiagnostics = lang.getSyntacticDiagnostics(filePath);
47
- const suggestionDiagnostics = lang.getSuggestionDiagnostics(filePath);
48
- const semanticDiagnostics = lang.getSemanticDiagnostics(filePath);
49
62
  const diagnostics = [
50
- ...syntaxDiagnostics,
51
- ...suggestionDiagnostics,
52
- ...semanticDiagnostics,
63
+ ...lang.getSyntacticDiagnostics(filePath),
64
+ ...lang.getSuggestionDiagnostics(filePath),
65
+ ...lang.getSemanticDiagnostics(filePath),
53
66
  ].filter((diag) => {
54
67
  return isNoWithinBoundary(scriptBoundaries, diag);
55
68
  });
@@ -67,14 +80,15 @@ class DiagnosticsProviderImpl {
67
80
  ...scriptDiagnostics,
68
81
  ]
69
82
  .filter((diag) => {
70
- return (hasNoNegativeLines(diag) &&
71
- isNoJSXImplicitRuntimeWarning(diag) &&
83
+ return (
84
+ // Make sure the diagnostic is inside the document and not in generated code
85
+ diag.range.start.line <= document.lineCount &&
86
+ hasNoNegativeLines(diag) &&
72
87
  isNoJSXMustHaveOneParent(diag) &&
73
- isNoCantEndWithTS(diag) &&
74
- isNoSpreadExpected(diag) &&
75
- isNoCantResolveJSONModule(diag) &&
88
+ isNoSpreadExpected(diag, document) &&
76
89
  isNoCantReturnOutsideFunction(diag) &&
77
90
  isNoIsolatedModuleError(diag) &&
91
+ isNoImportImplicitAnyType(diag) &&
78
92
  isNoJsxCannotHaveMultipleAttrsError(diag));
79
93
  })
80
94
  .map(enhanceIfNecessary);
@@ -113,30 +127,39 @@ class DiagnosticsProviderImpl {
113
127
  }
114
128
  }
115
129
  exports.DiagnosticsProviderImpl = DiagnosticsProviderImpl;
116
- function getDiagnosticTag(diagnostic) {
117
- const tags = [];
118
- if (diagnostic.reportsUnnecessary) {
119
- tags.push(vscode_languageserver_types_1.DiagnosticTag.Unnecessary);
130
+ function isWithinBoundaries(boundaries, start) {
131
+ for (let [bstart, bend] of boundaries) {
132
+ if (start > bstart && start < bend) {
133
+ return true;
134
+ }
120
135
  }
121
- if (diagnostic.reportsDeprecated) {
122
- tags.push(vscode_languageserver_types_1.DiagnosticTag.Deprecated);
136
+ return false;
137
+ }
138
+ function diagnosticIsWithinBoundaries(sourceFile, boundaries, diagnostic) {
139
+ if ('start' in diagnostic) {
140
+ if (diagnostic.start == null)
141
+ return false;
142
+ return isWithinBoundaries(boundaries, diagnostic.start);
123
143
  }
124
- return tags;
144
+ if (!sourceFile)
145
+ return false;
146
+ let startRange = diagnostic.range.start;
147
+ let pos = typescript_1.default.getPositionOfLineAndCharacter(sourceFile, startRange.line, startRange.character);
148
+ return isWithinBoundaries(boundaries, pos);
149
+ }
150
+ function isNoWithinBoundary(boundaries, diagnostic) {
151
+ return !diagnosticIsWithinBoundaries(undefined, boundaries, diagnostic);
125
152
  }
126
153
  function mapRange(fragment, _document) {
127
154
  return (diagnostic) => {
128
155
  let range = (0, documents_1.mapRangeToOriginal)(fragment, diagnostic.range);
129
- if (range.start.line < 0) {
130
- // Could be a props error?
131
- // From svelte
132
- }
133
156
  return { ...diagnostic, range };
134
157
  };
135
158
  }
136
159
  /**
137
160
  * In some rare cases mapping of diagnostics does not work and produces negative lines.
138
161
  * We filter out these diagnostics with negative lines because else the LSP
139
- * apparently has a hickup and does not show any diagnostics at all.
162
+ * apparently has a hiccup and does not show any diagnostics at all.
140
163
  */
141
164
  function hasNoNegativeLines(diagnostic) {
142
165
  return diagnostic.range.start.line >= 0 && diagnostic.range.end.line >= 0;
@@ -145,56 +168,68 @@ function hasNoNegativeLines(diagnostic) {
145
168
  * Astro allows multiple attributes to have the same name
146
169
  */
147
170
  function isNoJsxCannotHaveMultipleAttrsError(diagnostic) {
148
- return diagnostic.code !== 17001;
171
+ return diagnostic.code !== DiagnosticCodes.DUPLICATED_JSX_ATTRIBUTES;
149
172
  }
150
173
  /** Astro allows component with multiple root elements */
151
174
  function isNoJSXMustHaveOneParent(diagnostic) {
152
- return diagnostic.code !== 2657;
175
+ return diagnostic.code !== DiagnosticCodes.MUST_HAVE_PARENT_ELEMENT;
153
176
  }
154
- /** Astro allows `.ts` ending for imports, unlike TypeScript */
155
- function isNoCantEndWithTS(diagnostic) {
156
- return diagnostic.code !== 2691;
177
+ function isNoImportImplicitAnyType(diagnostic) {
178
+ return diagnostic.code !== DiagnosticCodes.NO_DECL_IMPLICIT_ANY_TYPE;
157
179
  }
158
- function isNoSpreadExpected(diagnostic) {
159
- return diagnostic.code !== 1005;
180
+ /**
181
+ * When using the shorthand syntax for props TSX expects you to use the spread operator
182
+ * Since the shorthand syntax works differently in Astro and this is not required, hide this message
183
+ * However, the error code used here is quite generic, as such we need to make we only ignore in valid cases
184
+ */
185
+ function isNoSpreadExpected(diagnostic, document) {
186
+ if (diagnostic.code === DiagnosticCodes.SPREAD_EXPECTED &&
187
+ diagnostic.message.includes('...') &&
188
+ document.offsetAt(diagnostic.range.start) > (document.astroMeta.frontmatter.endOffset ?? 0)) {
189
+ return false;
190
+ }
191
+ return true;
160
192
  }
161
- function isNoJSXImplicitRuntimeWarning(diagnostic) {
162
- return diagnostic.code !== 7016 && diagnostic.code !== 2792;
193
+ /** Inside script tags, Astro currently require the `.ts` file extension for imports */
194
+ function isNoCantEndWithTS(diagnostic) {
195
+ return diagnostic.code !== DiagnosticCodes.CANNOT_IMPORT_TS_EXT;
163
196
  }
164
197
  /**
165
198
  * Ignore "Can't return outside of function body"
166
- * This is technically a valid diagnostic, but due to how we format our TSX, the frontmatter is at top-level so we have
167
- * to ignore this. It wasn't a problem before because users didn't need to return things but they can now with SSR
199
+ * Since the frontmatter is at the top level, users trying to return a Response for SSR mode run into this
168
200
  */
169
201
  function isNoCantReturnOutsideFunction(diagnostic) {
170
- return diagnostic.code !== 1108;
171
- }
172
- /**
173
- * Astro allows users to import JSON modules
174
- */
175
- function isNoCantResolveJSONModule(diagnostic) {
176
- return diagnostic.code !== 2732;
202
+ return diagnostic.code !== DiagnosticCodes.CANT_RETURN_OUTSIDE_FUNC;
177
203
  }
178
204
  /**
179
205
  * When the content of the file is invalid and can't be parsed properly for TSX generation, TS will show an error about
180
206
  * how the current module can't be compiled under --isolatedModule, this is confusing to users so let's ignore this
181
207
  */
182
208
  function isNoIsolatedModuleError(diagnostic) {
183
- return diagnostic.code !== 1208;
209
+ return diagnostic.code !== DiagnosticCodes.ISOLATED_MODULE_COMPILE_ERR;
184
210
  }
185
211
  /**
186
212
  * Some diagnostics have JSX-specific nomenclature or unclear description. Enhance them for more clarity.
187
213
  */
188
214
  function enhanceIfNecessary(diagnostic) {
189
215
  // JSX element has no closing tag. JSX -> HTML
190
- if (diagnostic.code === 17008) {
216
+ if (diagnostic.code === DiagnosticCodes.JSX_NO_CLOSING_TAG) {
191
217
  return {
192
218
  ...diagnostic,
193
219
  message: diagnostic.message.replace('JSX', 'HTML'),
194
220
  };
195
221
  }
222
+ // JSX Element can't be constructed or called. This happens on syntax errors / invalid components
223
+ if (diagnostic.code === DiagnosticCodes.JSX_ELEMENT_NO_CALL) {
224
+ return {
225
+ ...diagnostic,
226
+ message: diagnostic.message
227
+ .replace('JSX element type', 'Component')
228
+ .replace('does not have any construct or call signatures.', 'is not a valid component.\n\nIf this is a Svelte or Vue component, it might have a syntax error that makes it impossible to parse.'),
229
+ };
230
+ }
196
231
  // For the rare case where an user might try to put a client directive on something that is not a component
197
- if (diagnostic.code === 2322) {
232
+ if (diagnostic.code === DiagnosticCodes.TYPE_NOT_ASSIGNABLE) {
198
233
  if (diagnostic.message.includes("Property 'client:") && diagnostic.message.includes("to type 'HTMLProps")) {
199
234
  return {
200
235
  ...diagnostic,
@@ -202,28 +237,23 @@ function enhanceIfNecessary(diagnostic) {
202
237
  };
203
238
  }
204
239
  }
240
+ // An import path cannot end with '.ts(x)' consider importing with no extension
241
+ // TODO: Remove this when https://github.com/withastro/astro/issues/3415 is fixed
242
+ if (diagnostic.code === DiagnosticCodes.CANNOT_IMPORT_TS_EXT) {
243
+ return {
244
+ ...diagnostic,
245
+ message: diagnostic.message.replace(/\.jsx?/, ''),
246
+ };
247
+ }
205
248
  return diagnostic;
206
249
  }
207
- function isWithinBoundaries(boundaries, start) {
208
- for (let [bstart, bend] of boundaries) {
209
- if (start > bstart && start < bend) {
210
- return true;
211
- }
250
+ function getDiagnosticTag(diagnostic) {
251
+ const tags = [];
252
+ if (diagnostic.reportsUnnecessary) {
253
+ tags.push(vscode_languageserver_types_1.DiagnosticTag.Unnecessary);
212
254
  }
213
- return false;
214
- }
215
- function diagnosticIsWithinBoundaries(sourceFile, boundaries, diagnostic) {
216
- if ('start' in diagnostic) {
217
- if (diagnostic.start == null)
218
- return false;
219
- return isWithinBoundaries(boundaries, diagnostic.start);
255
+ if (diagnostic.reportsDeprecated) {
256
+ tags.push(vscode_languageserver_types_1.DiagnosticTag.Deprecated);
220
257
  }
221
- if (!sourceFile)
222
- return false;
223
- let startRange = diagnostic.range.start;
224
- let pos = typescript_1.default.getPositionOfLineAndCharacter(sourceFile, startRange.line, startRange.character);
225
- return isWithinBoundaries(boundaries, pos);
226
- }
227
- function isNoWithinBoundary(boundaries, diagnostic) {
228
- return !diagnosticIsWithinBoundaries(undefined, boundaries, diagnostic);
258
+ return tags;
229
259
  }
@@ -224,6 +224,7 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
224
224
  const forcedCompilerOptions = {
225
225
  noEmit: true,
226
226
  declaration: false,
227
+ resolveJsonModule: true,
227
228
  allowNonTsExtensions: true,
228
229
  allowJs: true,
229
230
  jsx: typescript_1.default.JsxEmit.Preserve,
package/dist/server.js CHANGED
@@ -129,6 +129,7 @@ function startLanguageServer(connection) {
129
129
  colorProvider: true,
130
130
  hoverProvider: true,
131
131
  documentSymbolProvider: true,
132
+ linkedEditingRangeProvider: true,
132
133
  semanticTokensProvider: {
133
134
  legend: (0, utils_2.getSemanticTokenLegend)(),
134
135
  range: true,
@@ -195,6 +196,7 @@ function startLanguageServer(connection) {
195
196
  connection.onDocumentSymbol((params, cancellationToken) => pluginHost.getDocumentSymbols(params.textDocument, cancellationToken));
196
197
  connection.onRequest(vscode_languageserver_1.SemanticTokensRequest.type, (evt, cancellationToken) => pluginHost.getSemanticTokens(evt.textDocument, undefined, cancellationToken));
197
198
  connection.onRequest(vscode_languageserver_1.SemanticTokensRangeRequest.type, (evt, cancellationToken) => pluginHost.getSemanticTokens(evt.textDocument, evt.range, cancellationToken));
199
+ connection.onRequest(vscode_languageserver_1.LinkedEditingRangeRequest.type, async (evt) => await pluginHost.getLinkedEditingRanges(evt.textDocument, evt.position));
198
200
  connection.onDocumentFormatting((params) => pluginHost.formatDocument(params.textDocument, params.options));
199
201
  connection.onDocumentColor((params) => pluginHost.getDocumentColors(params.textDocument));
200
202
  connection.onColorPresentation((params) => pluginHost.getColorPresentations(params.textDocument, params.range, params.color));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/language-server",
3
- "version": "0.19.0",
3
+ "version": "0.19.3",
4
4
  "author": "withastro",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -19,8 +19,8 @@
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/vue-language-integration": "^0.1.0",
23
- "@astrojs/svelte-language-integration": "^0.1.4",
22
+ "@astrojs/vue-language-integration": "^0.1.1",
23
+ "@astrojs/svelte-language-integration": "^0.1.6",
24
24
  "@vscode/emmet-helper": "^2.8.4",
25
25
  "lodash": "^4.17.21",
26
26
  "source-map": "^0.7.3",