@astrojs/language-server 0.28.3 → 0.29.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 (41) hide show
  1. package/dist/core/documents/DocumentMapper.d.ts +13 -7
  2. package/dist/core/documents/DocumentMapper.js +30 -12
  3. package/dist/core/worker/TSXService.d.ts +7 -0
  4. package/dist/core/worker/TSXService.js +12 -0
  5. package/dist/core/worker/TSXWorker.d.ts +1 -0
  6. package/dist/core/worker/TSXWorker.js +9 -0
  7. package/dist/plugins/astro/AstroPlugin.d.ts +3 -2
  8. package/dist/plugins/astro/AstroPlugin.js +5 -1
  9. package/dist/plugins/astro/features/CompletionsProvider.d.ts +2 -2
  10. package/dist/plugins/astro/features/DiagnosticsProvider.d.ts +10 -0
  11. package/dist/plugins/astro/features/DiagnosticsProvider.js +23 -0
  12. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +2 -2
  13. package/dist/plugins/typescript/TypeScriptPlugin.js +8 -10
  14. package/dist/plugins/typescript/astro2tsx.d.ts +2 -4
  15. package/dist/plugins/typescript/astro2tsx.js +4 -91
  16. package/dist/plugins/typescript/features/CodeActionsProvider.js +18 -9
  17. package/dist/plugins/typescript/features/CompletionsProvider.d.ts +2 -2
  18. package/dist/plugins/typescript/features/CompletionsProvider.js +15 -15
  19. package/dist/plugins/typescript/features/DefinitionsProvider.d.ts +1 -1
  20. package/dist/plugins/typescript/features/DefinitionsProvider.js +13 -11
  21. package/dist/plugins/typescript/features/DiagnosticsProvider.d.ts +0 -1
  22. package/dist/plugins/typescript/features/DiagnosticsProvider.js +8 -24
  23. package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +4 -7
  24. package/dist/plugins/typescript/features/FileReferencesProvider.js +4 -5
  25. package/dist/plugins/typescript/features/FoldingRangesProvider.js +6 -2
  26. package/dist/plugins/typescript/features/HoverProvider.js +4 -5
  27. package/dist/plugins/typescript/features/ImplementationsProvider.js +10 -8
  28. package/dist/plugins/typescript/features/InlayHintsProvider.js +3 -4
  29. package/dist/plugins/typescript/features/ReferencesProvider.js +9 -8
  30. package/dist/plugins/typescript/features/SemanticTokenProvider.js +8 -9
  31. package/dist/plugins/typescript/features/SignatureHelpProvider.js +1 -2
  32. package/dist/plugins/typescript/features/TypeDefinitionsProvider.js +7 -7
  33. package/dist/plugins/typescript/features/utils.d.ts +5 -16
  34. package/dist/plugins/typescript/features/utils.js +11 -18
  35. package/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts +30 -45
  36. package/dist/plugins/typescript/snapshots/DocumentSnapshot.js +50 -43
  37. package/dist/plugins/typescript/snapshots/SnapshotManager.js +0 -4
  38. package/dist/plugins/typescript/snapshots/utils.js +3 -2
  39. package/dist/plugins/typescript/utils.d.ts +2 -2
  40. package/dist/utils.js +3 -2
  41. package/package.json +5 -3
@@ -1,5 +1,7 @@
1
- import type { SourceMapConsumer } from 'source-map';
1
+ import { TraceMap } from '@jridgewell/trace-mapping';
2
+ import type ts from 'typescript';
2
3
  import { CodeAction, ColorPresentation, CompletionItem, Diagnostic, FoldingRange, Hover, InsertReplaceEdit, LocationLink, Position, Range, SelectionRange, SymbolInformation, TextDocumentEdit, TextEdit } from 'vscode-languageserver';
4
+ import { DocumentSnapshot, ScriptTagDocumentSnapshot } from '../../plugins/typescript/snapshots/DocumentSnapshot';
3
5
  import { TagInformation } from './utils';
4
6
  export interface DocumentMapper {
5
7
  /**
@@ -56,18 +58,21 @@ export declare class FragmentMapper implements DocumentMapper {
56
58
  getURL(): string;
57
59
  }
58
60
  export declare class SourceMapDocumentMapper implements DocumentMapper {
59
- protected consumer: SourceMapConsumer;
61
+ protected traceMap: TraceMap;
60
62
  protected sourceUri: string;
61
63
  private parent?;
62
- constructor(consumer: SourceMapConsumer, sourceUri: string, parent?: DocumentMapper | undefined);
64
+ constructor(traceMap: TraceMap, sourceUri: string, parent?: DocumentMapper | undefined);
63
65
  getOriginalPosition(generatedPosition: Position): Position;
64
66
  getGeneratedPosition(originalPosition: Position): Position;
65
67
  isInGenerated(position: Position): boolean;
66
68
  getURL(): string;
67
- /**
68
- * Needs to be called when source mapper is no longer needed in order to prevent memory leaks.
69
- */
70
- destroy(): void;
69
+ }
70
+ export declare class ConsumerDocumentMapper extends SourceMapDocumentMapper {
71
+ private nrPrependesLines;
72
+ constructor(traceMap: TraceMap, sourceUri: string, nrPrependesLines: number);
73
+ getOriginalPosition(generatedPosition: Position): Position;
74
+ getGeneratedPosition(originalPosition: Position): Position;
75
+ isInGenerated(): boolean;
71
76
  }
72
77
  export declare function mapRangeToOriginal(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, range: Range): Range;
73
78
  export declare function mapRangeToGenerated(fragment: DocumentMapper, range: Range): Range;
@@ -84,5 +89,6 @@ export declare function mapSymbolInformationToOriginal(fragment: Pick<DocumentMa
84
89
  export declare function mapLocationLinkToOriginal(fragment: DocumentMapper, def: LocationLink): LocationLink;
85
90
  export declare function mapTextDocumentEditToOriginal(fragment: DocumentMapper, edit: TextDocumentEdit): TextDocumentEdit;
86
91
  export declare function mapCodeActionToOriginal(fragment: DocumentMapper, codeAction: CodeAction): CodeAction;
92
+ export declare function mapScriptSpanStartToSnapshot(span: ts.TextSpan, scriptTagSnapshot: ScriptTagDocumentSnapshot, tsSnapshot: DocumentSnapshot): number;
87
93
  export declare function mapFoldingRangeToParent(fragment: DocumentMapper, foldingRange: FoldingRange): FoldingRange;
88
94
  export declare function mapSelectionRangeToParent(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, selectionRange: SelectionRange): SelectionRange;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapSelectionRangeToParent = exports.mapFoldingRangeToParent = exports.mapCodeActionToOriginal = exports.mapTextDocumentEditToOriginal = exports.mapLocationLinkToOriginal = exports.mapSymbolInformationToOriginal = exports.mapColorPresentationToOriginal = exports.mapDiagnosticToGenerated = exports.mapEditToOriginal = exports.mapInsertReplaceEditToOriginal = exports.mapObjWithRangeToOriginal = exports.mapHoverToParent = exports.mapCompletionItemToOriginal = exports.mapRangeToGenerated = exports.mapRangeToOriginal = exports.SourceMapDocumentMapper = exports.FragmentMapper = exports.IdentityMapper = void 0;
3
+ exports.mapSelectionRangeToParent = exports.mapFoldingRangeToParent = exports.mapScriptSpanStartToSnapshot = exports.mapCodeActionToOriginal = exports.mapTextDocumentEditToOriginal = exports.mapLocationLinkToOriginal = exports.mapSymbolInformationToOriginal = exports.mapColorPresentationToOriginal = exports.mapDiagnosticToGenerated = exports.mapEditToOriginal = exports.mapInsertReplaceEditToOriginal = exports.mapObjWithRangeToOriginal = exports.mapHoverToParent = exports.mapCompletionItemToOriginal = exports.mapRangeToGenerated = exports.mapRangeToOriginal = exports.ConsumerDocumentMapper = exports.SourceMapDocumentMapper = exports.FragmentMapper = exports.IdentityMapper = void 0;
4
+ const trace_mapping_1 = require("@jridgewell/trace-mapping");
4
5
  const vscode_languageserver_1 = require("vscode-languageserver");
5
6
  const utils_1 = require("./utils");
6
7
  /**
@@ -69,8 +70,8 @@ class FragmentMapper {
69
70
  }
70
71
  exports.FragmentMapper = FragmentMapper;
71
72
  class SourceMapDocumentMapper {
72
- constructor(consumer, sourceUri, parent) {
73
- this.consumer = consumer;
73
+ constructor(traceMap, sourceUri, parent) {
74
+ this.traceMap = traceMap;
74
75
  this.sourceUri = sourceUri;
75
76
  this.parent = parent;
76
77
  }
@@ -81,7 +82,7 @@ class SourceMapDocumentMapper {
81
82
  if (generatedPosition.line < 0) {
82
83
  return { line: -1, character: -1 };
83
84
  }
84
- const mapped = this.consumer.originalPositionFor({
85
+ const mapped = (0, trace_mapping_1.originalPositionFor)(this.traceMap, {
85
86
  line: generatedPosition.line + 1,
86
87
  column: generatedPosition.character,
87
88
  });
@@ -101,7 +102,7 @@ class SourceMapDocumentMapper {
101
102
  if (this.parent) {
102
103
  originalPosition = this.parent.getGeneratedPosition(originalPosition);
103
104
  }
104
- const mapped = this.consumer.generatedPositionFor({
105
+ const mapped = (0, trace_mapping_1.generatedPositionFor)(this.traceMap, {
105
106
  line: originalPosition.line + 1,
106
107
  column: originalPosition.character,
107
108
  source: this.sourceUri,
@@ -128,15 +129,27 @@ class SourceMapDocumentMapper {
128
129
  getURL() {
129
130
  return this.sourceUri;
130
131
  }
131
- /**
132
- * Needs to be called when source mapper is no longer needed in order to prevent memory leaks.
133
- */
134
- destroy() {
135
- this.parent?.destroy?.();
136
- this.consumer.destroy();
137
- }
138
132
  }
139
133
  exports.SourceMapDocumentMapper = SourceMapDocumentMapper;
134
+ class ConsumerDocumentMapper extends SourceMapDocumentMapper {
135
+ constructor(traceMap, sourceUri, nrPrependesLines) {
136
+ super(traceMap, sourceUri);
137
+ this.nrPrependesLines = nrPrependesLines;
138
+ }
139
+ getOriginalPosition(generatedPosition) {
140
+ return super.getOriginalPosition(vscode_languageserver_1.Position.create(generatedPosition.line - this.nrPrependesLines, generatedPosition.character));
141
+ }
142
+ getGeneratedPosition(originalPosition) {
143
+ const result = super.getGeneratedPosition(originalPosition);
144
+ result.line += this.nrPrependesLines;
145
+ return result;
146
+ }
147
+ isInGenerated() {
148
+ // always return true and map outliers case by case
149
+ return true;
150
+ }
151
+ }
152
+ exports.ConsumerDocumentMapper = ConsumerDocumentMapper;
140
153
  function mapRangeToOriginal(fragment, range) {
141
154
  // DON'T use Range.create here! Positions might not be mapped
142
155
  // and therefore return negative numbers, which makes Range.create throw.
@@ -232,6 +245,11 @@ function mapCodeActionToOriginal(fragment, codeAction) {
232
245
  }, codeAction.kind);
233
246
  }
234
247
  exports.mapCodeActionToOriginal = mapCodeActionToOriginal;
248
+ function mapScriptSpanStartToSnapshot(span, scriptTagSnapshot, tsSnapshot) {
249
+ const originalPosition = scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(span.start));
250
+ return tsSnapshot.offsetAt(tsSnapshot.getGeneratedPosition(originalPosition));
251
+ }
252
+ exports.mapScriptSpanStartToSnapshot = mapScriptSpanStartToSnapshot;
235
253
  function mapFoldingRangeToParent(fragment, foldingRange) {
236
254
  // Despite FoldingRange asking for a start and end line and a start and end character, FoldingRanges
237
255
  // don't use the Range type, instead asking for 4 number. Not sure why, but it's not convenient
@@ -0,0 +1,7 @@
1
+ import type { TSXResult } from '@astrojs/compiler/shared/types';
2
+ /**
3
+ * Parse code by `@astrojs/compiler`
4
+ */
5
+ export declare function convertToTSX(source: string, options: {
6
+ sourcefile: string;
7
+ }): TSXResult;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertToTSX = void 0;
4
+ const synckit_1 = require("synckit");
5
+ const convertToTSXSync = (0, synckit_1.createSyncFn)(require.resolve('./TSXWorker'));
6
+ /**
7
+ * Parse code by `@astrojs/compiler`
8
+ */
9
+ function convertToTSX(source, options) {
10
+ return convertToTSXSync(source, options);
11
+ }
12
+ exports.convertToTSX = convertToTSX;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const synckit_1 = require("synckit");
4
+ const dynamicImport = new Function('m', 'return import(m)');
5
+ (0, synckit_1.runAsWorker)(async (source, options) => {
6
+ const { convertToTSX } = await dynamicImport('@astrojs/compiler');
7
+ const result = convertToTSX(source, options);
8
+ return result;
9
+ });
@@ -1,4 +1,4 @@
1
- import { CompletionContext, FoldingRange, FormattingOptions, Position, TextEdit } from 'vscode-languageserver';
1
+ import { CompletionContext, Diagnostic, FoldingRange, FormattingOptions, Position, TextEdit } from 'vscode-languageserver';
2
2
  import type { ConfigManager } from '../../core/config';
3
3
  import type { AstroDocument } from '../../core/documents';
4
4
  import type { AppCompletionList, Plugin } from '../interfaces';
@@ -7,10 +7,11 @@ export declare class AstroPlugin implements Plugin {
7
7
  __name: string;
8
8
  private configManager;
9
9
  private readonly languageServiceManager;
10
- private readonly ts;
11
10
  private readonly completionProvider;
11
+ private readonly diagnosticsProvider;
12
12
  constructor(configManager: ConfigManager, languageServiceManager: LanguageServiceManager);
13
13
  getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
14
+ getDiagnostics(document: AstroDocument): Promise<Diagnostic[]>;
14
15
  formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
15
16
  getFoldingRanges(document: AstroDocument): FoldingRange[];
16
17
  }
@@ -4,18 +4,22 @@ exports.AstroPlugin = void 0;
4
4
  const vscode_languageserver_1 = require("vscode-languageserver");
5
5
  const importPackage_1 = require("../../importPackage");
6
6
  const CompletionsProvider_1 = require("./features/CompletionsProvider");
7
+ const DiagnosticsProvider_1 = require("./features/DiagnosticsProvider");
7
8
  class AstroPlugin {
8
9
  constructor(configManager, languageServiceManager) {
9
10
  this.__name = 'astro';
10
11
  this.configManager = configManager;
11
12
  this.languageServiceManager = languageServiceManager;
12
- this.ts = languageServiceManager.docContext.ts;
13
13
  this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager);
14
+ this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
14
15
  }
15
16
  async getCompletions(document, position, completionContext) {
16
17
  const completions = this.completionProvider.getCompletions(document, position, completionContext);
17
18
  return completions;
18
19
  }
20
+ async getDiagnostics(document) {
21
+ return await this.diagnosticsProvider.getDiagnostics(document);
22
+ }
19
23
  async formatDocument(document, options) {
20
24
  const filePath = document.getFilePath();
21
25
  if (!filePath) {
@@ -1,13 +1,13 @@
1
1
  import { CompletionContext, Position } from 'vscode-languageserver';
2
2
  import type { AstroDocument } from '../../../core/documents';
3
3
  import type { AppCompletionList, CompletionsProvider } from '../../interfaces';
4
- import type { LanguageServiceManager as TypeScriptLanguageServiceManager } from '../../typescript/LanguageServiceManager';
4
+ import type { LanguageServiceManager } from '../../typescript/LanguageServiceManager';
5
5
  export declare class CompletionsProviderImpl implements CompletionsProvider {
6
6
  private readonly languageServiceManager;
7
7
  private readonly ts;
8
8
  private lastCompletion;
9
9
  directivesHTMLLang: import("vscode-html-languageservice").LanguageService;
10
- constructor(languageServiceManager: TypeScriptLanguageServiceManager);
10
+ constructor(languageServiceManager: LanguageServiceManager);
11
11
  getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
12
12
  private getComponentScriptCompletion;
13
13
  private getPropCompletionsAndFilePath;
@@ -0,0 +1,10 @@
1
+ import { Diagnostic } from 'vscode-languageserver-types';
2
+ import { AstroDocument } from '../../../core/documents';
3
+ import { DiagnosticsProvider } from '../../interfaces';
4
+ import { LanguageServiceManager } from '../../typescript/LanguageServiceManager';
5
+ export declare class DiagnosticsProviderImpl implements DiagnosticsProvider {
6
+ private languageServiceManager;
7
+ constructor(languageServiceManager: LanguageServiceManager);
8
+ getDiagnostics(document: AstroDocument): Promise<Diagnostic[]>;
9
+ private compilerMessageToDiagnostic;
10
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DiagnosticsProviderImpl = void 0;
4
+ const vscode_languageserver_types_1 = require("vscode-languageserver-types");
5
+ class DiagnosticsProviderImpl {
6
+ constructor(languageServiceManager) {
7
+ this.languageServiceManager = languageServiceManager;
8
+ }
9
+ async getDiagnostics(document) {
10
+ const { tsDoc } = (await this.languageServiceManager.getLSAndTSDoc(document));
11
+ return tsDoc.compilerDiagnostics.map(this.compilerMessageToDiagnostic);
12
+ }
13
+ compilerMessageToDiagnostic(message) {
14
+ return {
15
+ message: message.text + '\n\n' + message.hint,
16
+ range: vscode_languageserver_types_1.Range.create(message.location.line - 1, message.location.column - 1, message.location.line, message.location.length),
17
+ code: message.code,
18
+ severity: message.severity,
19
+ source: 'astro',
20
+ };
21
+ }
22
+ }
23
+ exports.DiagnosticsProviderImpl = DiagnosticsProviderImpl;
@@ -1,8 +1,8 @@
1
+ import type { TSXResult } from '@astrojs/compiler/shared/types';
1
2
  import { CancellationToken, CodeAction, CodeActionContext, CompletionContext, DefinitionLink, Diagnostic, FoldingRange, Hover, InlayHint, Location, Position, Range, ReferenceContext, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
2
3
  import type { ConfigManager } from '../../core/config';
3
4
  import type { AstroDocument } from '../../core/documents';
4
5
  import type { AppCompletionItem, AppCompletionList, OnWatchFileChangesParam, Plugin } from '../interfaces';
5
- import { Astro2TSXResult } from './astro2tsx';
6
6
  import { CompletionItemData } from './features/CompletionsProvider';
7
7
  import type { LanguageServiceManager } from './LanguageServiceManager';
8
8
  export declare class TypeScriptPlugin implements Plugin {
@@ -43,7 +43,7 @@ export declare class TypeScriptPlugin implements Plugin {
43
43
  onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesParam[]): Promise<void>;
44
44
  updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[], text?: string): Promise<void>;
45
45
  getSignatureHelp(document: AstroDocument, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
46
- getTSXForDocument(document: AstroDocument): Astro2TSXResult;
46
+ getTSXForDocument(document: AstroDocument): TSXResult;
47
47
  /**
48
48
  * @internal Public for tests only
49
49
  */
@@ -20,8 +20,7 @@ const ReferencesProvider_1 = require("./features/ReferencesProvider");
20
20
  const SemanticTokenProvider_1 = require("./features/SemanticTokenProvider");
21
21
  const SignatureHelpProvider_1 = require("./features/SignatureHelpProvider");
22
22
  const TypeDefinitionsProvider_1 = require("./features/TypeDefinitionsProvider");
23
- const utils_1 = require("./snapshots/utils");
24
- const utils_2 = require("./utils");
23
+ const utils_1 = require("./utils");
25
24
  class TypeScriptPlugin {
26
25
  constructor(configManager, languageServiceManager) {
27
26
  this.__name = 'typescript';
@@ -51,8 +50,7 @@ class TypeScriptPlugin {
51
50
  }
52
51
  async rename(document, position, newName) {
53
52
  const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
54
- const fragment = await tsDoc.createFragment();
55
- const offset = fragment.offsetAt(fragment.getGeneratedPosition(position));
53
+ const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
56
54
  let renames = lang.findRenameLocations(tsDoc.filePath, offset, false, false, true);
57
55
  if (!renames) {
58
56
  return null;
@@ -61,13 +59,13 @@ class TypeScriptPlugin {
61
59
  changes: {},
62
60
  };
63
61
  renames.forEach((rename) => {
64
- const filePath = (0, utils_2.ensureRealFilePath)(rename.fileName);
62
+ const filePath = (0, utils_1.ensureRealFilePath)(rename.fileName);
65
63
  if (!(filePath in edit.changes)) {
66
64
  edit.changes[filePath] = [];
67
65
  }
68
66
  edit.changes[filePath].push({
69
67
  newText: newName,
70
- range: (0, utils_2.convertToLocationRange)(fragment, rename.textSpan),
68
+ range: (0, utils_1.convertToLocationRange)(tsDoc, rename.textSpan),
71
69
  });
72
70
  });
73
71
  return edit;
@@ -131,8 +129,8 @@ class TypeScriptPlugin {
131
129
  async onWatchFileChanges(onWatchFileChangesParas) {
132
130
  let doneUpdateProjectFiles = false;
133
131
  for (const { fileName, changeType } of onWatchFileChangesParas) {
134
- const scriptKind = (0, utils_2.getScriptKindFromFileName)(fileName, this.ts);
135
- if (scriptKind === this.ts.ScriptKind.Unknown && !(0, utils_2.isFrameworkFilePath)(fileName) && !(0, utils_2.isAstroFilePath)(fileName)) {
132
+ const scriptKind = (0, utils_1.getScriptKindFromFileName)(fileName, this.ts);
133
+ if (scriptKind === this.ts.ScriptKind.Unknown && !(0, utils_1.isFrameworkFilePath)(fileName) && !(0, utils_1.isAstroFilePath)(fileName)) {
136
134
  continue;
137
135
  }
138
136
  if (changeType === vscode_languageserver_1.FileChangeType.Created && !doneUpdateProjectFiles) {
@@ -142,7 +140,7 @@ class TypeScriptPlugin {
142
140
  else if (changeType === vscode_languageserver_1.FileChangeType.Deleted) {
143
141
  await this.languageServiceManager.deleteSnapshot(fileName);
144
142
  }
145
- else if (!(0, utils_2.isAstroFilePath)(fileName)) {
143
+ else if (!(0, utils_1.isAstroFilePath)(fileName)) {
146
144
  // Content updates for Astro files are handled through the documentManager and the 'documentChange' event
147
145
  await this.languageServiceManager.updateExistingNonAstroFile(fileName);
148
146
  }
@@ -155,7 +153,7 @@ class TypeScriptPlugin {
155
153
  return this.signatureHelpProvider.getSignatureHelp(document, position, context, cancellationToken);
156
154
  }
157
155
  getTSXForDocument(document) {
158
- return (0, astro2tsx_1.default)(document.getText(), (0, utils_1.classNameFromFilename)(document.getURL()));
156
+ return (0, astro2tsx_1.default)(document.getText(), document.getURL());
159
157
  }
160
158
  /**
161
159
  * @internal Public for tests only
@@ -1,4 +1,2 @@
1
- export interface Astro2TSXResult {
2
- code: string;
3
- }
4
- export default function (content: string, className: string): Astro2TSXResult;
1
+ import { TSXResult } from '@astrojs/compiler/shared/types';
2
+ export default function (content: string, fileName: string): TSXResult;
@@ -1,95 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const parseAstro_1 = require("../../core/documents/parseAstro");
4
- function addProps(content, className) {
5
- let defaultExportType = 'Record<string, any>';
6
- let shouldAddGlobal = false;
7
- let astroGlobal = "type AstroGlobal = import('astro').AstroGlobal";
8
- const astroGlobalConstDef = `
9
- /**
10
- * Astro global available in all contexts in .astro files
11
- *
12
- * [Astro documentation](https://docs.astro.build/reference/api-reference/#astro-global)
13
- */
14
- declare const Astro: Readonly<AstroGlobal>;
15
- `;
16
- if (/(interface|type) Props/.test(content)) {
17
- defaultExportType = 'Props';
18
- shouldAddGlobal = true;
19
- astroGlobal += ' & { props: Props }';
20
- }
21
- return ('\n' +
22
- (shouldAddGlobal ? astroGlobal + '\n' + astroGlobalConstDef : '') +
23
- `export default function ${className}__AstroComponent_(_props: ${defaultExportType}): any {}`);
24
- }
25
- function escapeTemplateLiteralContent(content) {
26
- return content.replace(/`/g, '\\`');
27
- }
28
- function default_1(content, className) {
29
- let result = {
30
- code: '',
31
- };
32
- const astroDocument = (0, parseAstro_1.parseAstro)(content);
33
- // Frontmatter replacements
34
- let frontMatterRaw = '';
35
- if (astroDocument.frontmatter.state === 'closed') {
36
- frontMatterRaw = content
37
- .substring(astroDocument.frontmatter.startOffset ?? 0, (astroDocument.frontmatter.endOffset ?? 0) + 3)
38
- // Handle case where semicolons is not used in the frontmatter section
39
- // We need to add something before the semi-colon or TypeScript won't be able to do completions
40
- .replace(/((?!^)(?<!;)\n)(---)/g, (_whole, start, _dashes) => {
41
- return start + '"";';
42
- })
43
- // Replace frontmatter marks with comments
44
- .replace(/---/g, '///');
45
- }
46
- // Content replacement
47
- const htmlBegin = astroDocument.frontmatter.endOffset ? astroDocument.frontmatter.endOffset + 3 : 0;
48
- let htmlRaw = content
49
- .substring(htmlBegin)
50
- // Turn comments into JS comments
51
- .replace(/<\s*!--([^-->]*)(.*?)-->/gs, (whole) => {
52
- return `{/*${whole}*/}`;
53
- })
54
- // Turn styles tags into internal strings
55
- .replace(/<\s*style([^>]*)>(.*?)<\s*\/\s*style>/gs, (_whole, attrs, children) => {
56
- return `<style${attrs}>{\`${escapeTemplateLiteralContent(children)}\`}</style>`;
57
- })
58
- // Turn scripts into function calls
59
- .replace(/<\s*script([^\/>]*)>(.*?)<\s*\/\s*script>/gs, (_whole, attrs, children, offset) => {
60
- return `<script${attrs}>{()=>{${children}}}</script>`;
61
- })
62
- // Close void elements
63
- .replace(/<(\s*(meta|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)([^>]*))>/g, (whole, inner) => {
64
- if (whole.endsWith('/>'))
65
- return whole;
66
- return `<${inner} />`;
67
- })
68
- // Replace `@` prefixed attributes with `_` prefix
69
- .replace(/<([$A-Z_a-z][^\s\/>]*)([^\/>]*)>/g, (whole, tag, attrs) => {
70
- if (attrs.includes('@')) {
71
- return `<${tag}${attrs.replace(
72
- // the following regular expression captures:
73
- // $1. any character that may appear before an attribute name (https://html.spec.whatwg.org/#before-attribute-name-state)
74
- // then, one `@` at sign, then:
75
- // $2. any characters that may appear in an attribute name (https://html.spec.whatwg.org/#attribute-name-state)
76
- // then, looking ahead any one character that may not appear in an attribute name, or the end
77
- /([\f\n\r\t "'])@([^\f\n\r\t /=>"'<]+)(?=[\f\n\r\t /=>"'<]|$)/g, '$1_$2')}>`;
78
- }
79
- else {
80
- return whole;
81
- }
82
- })
83
- // Fix doctypes
84
- .replace(/<!(doctype html)>/gi, (_whole, main) => {
85
- return `<${main.toLowerCase()}/>`;
86
- });
87
- result.code =
88
- frontMatterRaw +
89
- htmlRaw +
90
- '\n' +
91
- // Add TypeScript definitions
92
- addProps(frontMatterRaw, className);
93
- return result;
3
+ const TSXService_1 = require("../../core/worker/TSXService");
4
+ function default_1(content, fileName) {
5
+ const tsx = (0, TSXService_1.convertToTSX)(content, { sourcefile: fileName });
6
+ return tsx;
94
7
  }
95
8
  exports.default = default_1;
@@ -17,7 +17,6 @@ class CodeActionsProviderImpl {
17
17
  }
18
18
  async getCodeActions(document, range, context, cancellationToken) {
19
19
  const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
20
- const fragment = await tsDoc.createFragment();
21
20
  const tsPreferences = await this.configManager.getTSPreferences(document);
22
21
  const formatOptions = await this.configManager.getTSFormatConfig(document);
23
22
  let result = [];
@@ -59,8 +58,8 @@ class CodeActionsProviderImpl {
59
58
  isInsideScript = true;
60
59
  }
61
60
  else {
62
- const start = fragment.offsetAt(fragment.getGeneratedPosition(range.start));
63
- const end = fragment.offsetAt(fragment.getGeneratedPosition(range.end));
61
+ const start = tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.start));
62
+ const end = tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.end));
64
63
  codeFixes = errorCodes.includes(2304)
65
64
  ? this.getComponentQuickFix(start, end, lang, tsDoc.filePath, formatOptions, tsPreferences)
66
65
  : undefined;
@@ -75,12 +74,12 @@ class CodeActionsProviderImpl {
75
74
  function codeFixToCodeAction(codeFix, diagnostics, kind, isInsideScript, ts) {
76
75
  const documentChanges = codeFix.changes.map((change) => {
77
76
  return vscode_languageserver_types_1.TextDocumentEdit.create(vscode_languageserver_types_1.OptionalVersionedTextDocumentIdentifier.create(document.getURL(), null), change.textChanges.map((edit) => {
78
- let originalRange = (0, documents_1.mapRangeToOriginal)(fragment, (0, utils_2.convertRange)(fragment, edit.span));
77
+ let originalRange = (0, documents_1.mapRangeToOriginal)(tsDoc, (0, utils_2.convertRange)(tsDoc, edit.span));
79
78
  // Inside scripts, we don't need to restrain the insertion of code inside a specific zone as it will be
80
79
  // restricted to the area of the script tag by default
81
80
  if (!isInsideScript) {
82
81
  if (codeFix.fixName === 'import') {
83
- return (0, CompletionsProvider_1.codeActionChangeToTextEdit)(document, fragment, false, edit, ts);
82
+ return (0, CompletionsProvider_1.codeActionChangeToTextEdit)(document, tsDoc, false, edit, ts);
84
83
  }
85
84
  if (codeFix.fixName === 'fixMissingFunctionDeclaration') {
86
85
  originalRange = (0, utils_2.checkEndOfFileCodeInsert)(originalRange, document);
@@ -108,7 +107,7 @@ class CodeActionsProviderImpl {
108
107
  function mapScriptTagFixToOriginal(changes, scriptTagSnapshot) {
109
108
  return changes.map((change) => {
110
109
  change.textChanges.map((edit) => {
111
- edit.span.start = fragment.offsetAt(scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(edit.span.start)));
110
+ edit.span.start = (0, documents_1.mapScriptSpanStartToSnapshot)(edit.span, scriptTagSnapshot, tsDoc);
112
111
  return edit;
113
112
  });
114
113
  return change;
@@ -145,7 +144,6 @@ class CodeActionsProviderImpl {
145
144
  async organizeSortImports(document, skipDestructiveCodeActions = false, cancellationToken) {
146
145
  const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
147
146
  const filePath = tsDoc.filePath;
148
- const fragment = await tsDoc.createFragment();
149
147
  if (cancellationToken?.isCancellationRequested) {
150
148
  return [];
151
149
  }
@@ -160,7 +158,13 @@ class CodeActionsProviderImpl {
160
158
  edit.fileName = tsDoc.filePath;
161
159
  edit.textChanges = edit.textChanges
162
160
  .map((change) => {
163
- change.span.start = fragment.offsetAt(scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(change.span.start)));
161
+ change.span.start = (0, documents_1.mapScriptSpanStartToSnapshot)(change.span, scriptTagSnapshot, tsDoc);
162
+ // If the result ending position is unmapped, it usually means the ending position has a newline
163
+ // inside the virtual part of the script tag, so let's just make it a character shorter
164
+ const range = (0, documents_1.mapRangeToOriginal)(tsDoc, (0, utils_2.convertRange)(tsDoc, change.span));
165
+ if (range.end.character === 0 && range.end.line === 0) {
166
+ change.span.length -= 1;
167
+ }
164
168
  return change;
165
169
  })
166
170
  // Since our last line is a (virtual) export, organize imports will try to rewrite it, so let's only take
@@ -175,7 +179,12 @@ class CodeActionsProviderImpl {
175
179
  });
176
180
  const documentChanges = changes.map((change) => {
177
181
  return vscode_languageserver_types_1.TextDocumentEdit.create(vscode_languageserver_types_1.OptionalVersionedTextDocumentIdentifier.create(document.url, null), change.textChanges.map((edit) => {
178
- const range = (0, documents_1.mapRangeToOriginal)(fragment, (0, utils_2.convertRange)(fragment, edit.span));
182
+ const range = (0, documents_1.mapRangeToOriginal)(tsDoc, (0, utils_2.convertRange)(tsDoc, edit.span));
183
+ if (document.offsetAt(range.start) < (document.astroMeta.content.firstNonWhitespaceOffset ?? 0)) {
184
+ if (document.offsetAt(range.end) > document.astroMeta.frontmatter.endOffset) {
185
+ range.end = document.positionAt(document.astroMeta.frontmatter.endOffset);
186
+ }
187
+ }
179
188
  return vscode_languageserver_types_1.TextEdit.replace(range, this.fixIndentationOfImports(edit.newText, range, document));
180
189
  }));
181
190
  });
@@ -4,7 +4,7 @@ import type { ConfigManager } from '../../../core/config';
4
4
  import { AstroDocument } from '../../../core/documents';
5
5
  import type { AppCompletionItem, AppCompletionList, CompletionsProvider } from '../../interfaces';
6
6
  import type { LanguageServiceManager } from '../LanguageServiceManager';
7
- import type { AstroSnapshotFragment } from '../snapshots/DocumentSnapshot';
7
+ import type { DocumentSnapshot } from '../snapshots/DocumentSnapshot';
8
8
  export interface CompletionItemData extends TextDocumentIdentifier {
9
9
  filePath: string;
10
10
  offset: number;
@@ -34,4 +34,4 @@ export declare class CompletionsProviderImpl implements CompletionsProvider<Comp
34
34
  private isAstroComponentImport;
35
35
  private isValidCompletion;
36
36
  }
37
- export declare function codeActionChangeToTextEdit(document: AstroDocument, fragment: AstroSnapshotFragment, isInsideScriptTag: boolean, change: ts.TextChange, ts: typeof import('typescript/lib/tsserverlibrary')): TextEdit;
37
+ export declare function codeActionChangeToTextEdit(document: AstroDocument, snapshot: DocumentSnapshot, isInsideScriptTag: boolean, change: ts.TextChange, ts: typeof import('typescript/lib/tsserverlibrary')): TextEdit;