@astrojs/language-server 0.20.3 → 0.22.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 (35) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +1 -2
  3. package/dist/check.js +4 -1
  4. package/dist/core/config/ConfigManager.d.ts +1 -2
  5. package/dist/core/config/ConfigManager.js +0 -7
  6. package/dist/importPackage.d.ts +4 -1
  7. package/dist/importPackage.js +22 -9
  8. package/dist/plugins/PluginHost.d.ts +1 -0
  9. package/dist/plugins/PluginHost.js +4 -0
  10. package/dist/plugins/astro/AstroPlugin.d.ts +5 -3
  11. package/dist/plugins/astro/AstroPlugin.js +35 -3
  12. package/dist/plugins/css/language-service.d.ts +1 -1
  13. package/dist/plugins/html/HTMLPlugin.d.ts +1 -2
  14. package/dist/plugins/html/HTMLPlugin.js +0 -18
  15. package/dist/plugins/interfaces.d.ts +5 -2
  16. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +8 -5
  17. package/dist/plugins/typescript/TypeScriptPlugin.js +12 -8
  18. package/dist/plugins/typescript/astro2tsx.d.ts +1 -2
  19. package/dist/plugins/typescript/astro2tsx.js +0 -4
  20. package/dist/plugins/typescript/features/DiagnosticsProvider.js +0 -5
  21. package/dist/plugins/typescript/features/FoldingRangesProvider.js +1 -1
  22. package/dist/plugins/typescript/features/TypeDefinitionsProvider.d.ts +9 -0
  23. package/dist/plugins/typescript/features/TypeDefinitionsProvider.js +55 -0
  24. package/dist/plugins/typescript/language-service.js +12 -38
  25. package/dist/plugins/typescript/snapshots/utils.d.ts +1 -0
  26. package/dist/plugins/typescript/snapshots/utils.js +2 -1
  27. package/dist/server.js +22 -5
  28. package/dist/utils.d.ts +9 -7
  29. package/dist/utils.js +25 -16
  30. package/package.json +4 -1
  31. package/types/README.md +5 -0
  32. package/types/astro-jsx.d.ts +854 -477
  33. package/types/env.d.ts +22 -0
  34. package/dist/plugins/typescript/features/FormattingProvider.d.ts +0 -11
  35. package/dist/plugins/typescript/features/FormattingProvider.js +0 -132
@@ -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 astroVersion = (0, utils_1.getUserAstroVersion)(workspacePath);
75
+ const astroInstall = (0, utils_1.getAstroInstall)([tsconfigRoot, workspacePath]);
76
76
  const config = (await docContext.configManager.getConfig('astro.typescript', workspacePath)) ?? {};
77
77
  const allowArbitraryAttrs = config.allowArbitraryAttributes ?? false;
78
78
  // `raw` here represent the tsconfig merged with any extended config
@@ -80,6 +80,10 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
80
80
  let projectVersion = 0;
81
81
  const snapshotManager = new SnapshotManager_1.SnapshotManager(docContext.globalSnapshotManager, files, fullConfig, tsconfigRoot || process.cwd());
82
82
  const astroModuleLoader = (0, module_loader_1.createAstroModuleLoader)(getScriptSnapshot, compilerOptions);
83
+ const scriptFileNames = [];
84
+ if (astroInstall) {
85
+ scriptFileNames.push(...['./env.d.ts', './astro-jsx.d.ts'].map((f) => typescript_1.default.sys.resolvePath((0, path_1.resolve)(astroInstall.path, f))));
86
+ }
83
87
  let languageServerDirectory;
84
88
  try {
85
89
  languageServerDirectory = (0, path_1.dirname)(require.resolve('@astrojs/language-server'));
@@ -87,15 +91,13 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
87
91
  catch (e) {
88
92
  languageServerDirectory = __dirname;
89
93
  }
90
- const scriptFileNames = [];
91
- // Before Astro 1.0, JSX definitions were inside of the language-server instead of inside Astro
92
- // TODO: Remove this and astro-jsx.d.ts in types when we consider having support for Astro < 1.0 unnecessary
93
- if ((astroVersion.major === 0 || astroVersion.full === '1.0.0-beta.0') &&
94
- !astroVersion.full.startsWith('0.0.0-rc-') // 1.0.0's RC is considered to be 0.0.0, so we have to check for it
94
+ // Fallback to internal types when Astro is not installed or the Astro version is too old
95
+ if (!astroInstall ||
96
+ ((astroInstall.version.major === 0 || astroInstall.version.full === '1.0.0-beta.0') &&
97
+ !astroInstall.version.full.startsWith('0.0.0-rc-')) // 1.0.0's RC is considered to be 0.0.0, so we have to check for it
95
98
  ) {
96
- const astroTSXFile = typescript_1.default.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, '../types/astro-jsx.d.ts'));
97
- scriptFileNames.push(astroTSXFile);
98
- console.warn("Version lower than 1.0 detected, using internal types instead of Astro's");
99
+ scriptFileNames.push(...['../types/astro-jsx.d.ts', '../types/env.d.ts'].map((f) => typescript_1.default.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, f))));
100
+ console.warn("Couldn't load types from Astro, using internal types instead");
99
101
  }
100
102
  if (allowArbitraryAttrs) {
101
103
  const arbitraryAttrsDTS = typescript_1.default.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, '../types/arbitrary-attrs.d.ts'));
@@ -221,23 +223,7 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
221
223
  });
222
224
  }
223
225
  function getParsedTSConfig() {
224
- let configJson = (tsconfigPath && typescript_1.default.readConfigFile(tsconfigPath, typescript_1.default.sys.readFile).config) || {
225
- compilerOptions: getDefaultCompilerOptions(astroVersion),
226
- };
227
- // If our user has types in their config but it doesn't include the types needed for Astro, add them to the config
228
- if (configJson.compilerOptions?.types) {
229
- if (!configJson.compilerOptions?.types.includes('astro/env')) {
230
- configJson.compilerOptions.types.push('astro/env');
231
- }
232
- if ((astroVersion.major >= 1 || astroVersion.full.startsWith('0.0.0-rc-')) &&
233
- astroVersion.full !== '1.0.0-beta.0' &&
234
- !configJson.compilerOptions?.types.includes('astro/astro-jsx')) {
235
- configJson.compilerOptions.types.push('astro/astro-jsx');
236
- }
237
- }
238
- else {
239
- configJson.compilerOptions = Object.assign(getDefaultCompilerOptions(astroVersion), configJson.compilerOptions);
240
- }
226
+ let configJson = (tsconfigPath && typescript_1.default.readConfigFile(tsconfigPath, typescript_1.default.sys.readFile).config) || {};
241
227
  // Delete include so that .astro files don't get mistakenly excluded by the user
242
228
  delete configJson.include;
243
229
  // If the user supplied exclude, let's use theirs otherwise, use ours
@@ -273,18 +259,6 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
273
259
  };
274
260
  }
275
261
  }
276
- /**
277
- * Default compiler configuration used when the user doesn't have any
278
- */
279
- function getDefaultCompilerOptions(astroVersion) {
280
- const types = ['astro/env'];
281
- if ((astroVersion.major >= 1 && astroVersion.full !== '1.0.0-beta.0') || astroVersion.full.startsWith('0.0.0-rc-')) {
282
- types.push('astro/astro-jsx');
283
- }
284
- return {
285
- types: types,
286
- };
287
- }
288
262
  function getDefaultExclude() {
289
263
  return ['dist', 'node_modules'];
290
264
  }
@@ -26,3 +26,4 @@ export declare function createFromTSFilePath(filePath: string): TypeScriptDocume
26
26
  */
27
27
  export declare function createFromAstroFilePath(filePath: string, createDocument: (filePath: string, text: string) => AstroDocument): AstroSnapshot;
28
28
  export declare function createFromFrameworkFilePath(filePath: string, framework: FrameworkExt): TypeScriptDocumentSnapshot;
29
+ export declare function classNameFromFilename(filename: string): string;
@@ -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.createFromFrameworkFilePath = exports.createFromAstroFilePath = exports.createFromTSFilePath = exports.createFromNonAstroFilePath = exports.createFromFilePath = exports.createFromDocument = void 0;
6
+ exports.classNameFromFilename = exports.createFromFrameworkFilePath = exports.createFromAstroFilePath = exports.createFromTSFilePath = exports.createFromNonAstroFilePath = exports.createFromFilePath = exports.createFromDocument = void 0;
7
7
  const typescript_1 = __importDefault(require("typescript"));
8
8
  const astro2tsx_1 = __importDefault(require("../astro2tsx"));
9
9
  const vscode_uri_1 = require("vscode-uri");
@@ -106,3 +106,4 @@ function classNameFromFilename(filename) {
106
106
  const finalName = firstValidCharIdx === -1 ? `A${inPascalCase}` : inPascalCase;
107
107
  return finalName;
108
108
  }
109
+ exports.classNameFromFilename = classNameFromFilename;
package/dist/server.js CHANGED
@@ -37,6 +37,7 @@ const plugins_1 = require("./plugins");
37
37
  const utils_1 = require("./utils");
38
38
  const utils_2 = require("./plugins/typescript/utils");
39
39
  const CodeActionsProvider_1 = require("./plugins/typescript/features/CodeActionsProvider");
40
+ const LanguageServiceManager_1 = require("./plugins/typescript/LanguageServiceManager");
40
41
  const TagCloseRequest = new vscode.RequestType('html/tag');
41
42
  // Start the language server
42
43
  function startLanguageServer(connection) {
@@ -44,8 +45,10 @@ function startLanguageServer(connection) {
44
45
  const documentManager = new DocumentManager_1.DocumentManager();
45
46
  const pluginHost = new PluginHost_1.PluginHost(documentManager);
46
47
  const configManager = new ConfigManager_1.ConfigManager(connection);
48
+ let typescriptPlugin = undefined;
47
49
  let hasConfigurationCapability = false;
48
50
  connection.onInitialize((params) => {
51
+ const environment = params.initializationOptions?.environment ?? 'node';
49
52
  const workspaceUris = params.workspaceFolders?.map((folder) => folder.uri.toString()) ?? [params.rootUri ?? ''];
50
53
  workspaceUris.forEach((uri) => {
51
54
  uri = (0, utils_1.urlToPath)(uri);
@@ -54,8 +57,8 @@ function startLanguageServer(connection) {
54
57
  if (!(0, utils_1.isAstroWorkspace)(uri) && uri !== '/' && uri !== '') {
55
58
  return;
56
59
  }
57
- const astroVersion = (0, utils_1.getUserAstroVersion)(uri);
58
- if (astroVersion.exist === false) {
60
+ const astroInstall = (0, utils_1.getAstroInstall)([uri]);
61
+ if (!astroInstall) {
59
62
  connection.sendNotification(vscode_languageserver_1.ShowMessageNotification.type, {
60
63
  message: `Couldn't find Astro in workspace "${uri}". Experience might be degraded. For the best experience, please make sure Astro is installed and then restart the language server`,
61
64
  type: vscode_languageserver_1.MessageType.Warning,
@@ -71,9 +74,11 @@ function startLanguageServer(connection) {
71
74
  pluginHost.registerPlugin(new HTMLPlugin_1.HTMLPlugin(configManager));
72
75
  pluginHost.registerPlugin(new CSSPlugin_1.CSSPlugin(configManager));
73
76
  // We don't currently support running the TypeScript and Astro plugin in the browser
74
- if (params.initializationOptions.environment !== 'browser') {
75
- pluginHost.registerPlugin(new AstroPlugin_1.AstroPlugin(documentManager, configManager, workspaceUris));
76
- pluginHost.registerPlugin(new plugins_1.TypeScriptPlugin(documentManager, configManager, workspaceUris));
77
+ if (environment === 'node') {
78
+ const languageServiceManager = new LanguageServiceManager_1.LanguageServiceManager(documentManager, workspaceUris.map(utils_1.normalizeUri), configManager);
79
+ typescriptPlugin = new plugins_1.TypeScriptPlugin(configManager, languageServiceManager);
80
+ pluginHost.registerPlugin(new AstroPlugin_1.AstroPlugin(configManager, languageServiceManager));
81
+ pluginHost.registerPlugin(typescriptPlugin);
77
82
  }
78
83
  return {
79
84
  capabilities: {
@@ -86,6 +91,7 @@ function startLanguageServer(connection) {
86
91
  },
87
92
  foldingRangeProvider: true,
88
93
  definitionProvider: true,
94
+ typeDefinitionProvider: true,
89
95
  renameProvider: true,
90
96
  documentFormattingProvider: true,
91
97
  codeActionProvider: {
@@ -180,6 +186,7 @@ function startLanguageServer(connection) {
180
186
  // Features
181
187
  connection.onHover((params) => pluginHost.doHover(params.textDocument, params.position));
182
188
  connection.onDefinition((evt) => pluginHost.getDefinitions(evt.textDocument, evt.position));
189
+ connection.onTypeDefinition((evt) => pluginHost.getTypeDefinition(evt.textDocument, evt.position));
183
190
  connection.onFoldingRanges((evt) => pluginHost.getFoldingRanges(evt.textDocument));
184
191
  connection.onCodeAction((evt, cancellationToken) => pluginHost.getCodeActions(evt.textDocument, evt.range, evt.context, cancellationToken));
185
192
  connection.onCompletion(async (evt) => {
@@ -212,6 +219,16 @@ function startLanguageServer(connection) {
212
219
  }
213
220
  updateAllDiagnostics();
214
221
  });
222
+ connection.onRequest('$/getTSXOutput', async (uri) => {
223
+ const doc = documentManager.get(uri);
224
+ if (!doc) {
225
+ return undefined;
226
+ }
227
+ if (doc) {
228
+ const tsxOutput = typescriptPlugin.getTSXForDocument(doc);
229
+ return tsxOutput.code;
230
+ }
231
+ });
215
232
  documentManager.on('documentChange', (0, utils_1.debounceThrottle)(async (document) => diagnosticsManager.update(document), 1000));
216
233
  documentManager.on('documentClose', (document) => {
217
234
  diagnosticsManager.removeDiagnostics(document);
package/dist/utils.d.ts CHANGED
@@ -69,11 +69,13 @@ export declare function debounceThrottle<T extends (...args: any) => void>(fn: T
69
69
  * Try to determine if a workspace could be an Astro project based on the content of `package.json`
70
70
  */
71
71
  export declare function isAstroWorkspace(workspacePath: string): boolean;
72
- export interface AstroVersion {
73
- full: string;
74
- major: number;
75
- minor: number;
76
- patch: number;
77
- exist: boolean;
72
+ export interface AstroInstall {
73
+ path: string;
74
+ version: {
75
+ full: string;
76
+ major: number;
77
+ minor: number;
78
+ patch: number;
79
+ };
78
80
  }
79
- export declare function getUserAstroVersion(basePath: string): AstroVersion;
81
+ export declare function getAstroInstall(basePaths: string[]): AstroInstall | undefined;
package/dist/utils.js CHANGED
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getUserAstroVersion = exports.isAstroWorkspace = exports.debounceThrottle = exports.debounceSameArg = exports.getRegExpMatches = exports.regexLastIndexOf = exports.isBeforeOrEqualToPosition = exports.isInRange = exports.isNotNullOrUndefined = exports.clamp = exports.modifyLines = exports.toPascalCase = exports.mergeDeep = exports.get = exports.getLastPartOfPath = exports.pathToUrl = exports.urlToPath = exports.normalizePath = exports.normalizeUri = void 0;
3
+ exports.getAstroInstall = exports.isAstroWorkspace = exports.debounceThrottle = exports.debounceSameArg = exports.getRegExpMatches = exports.regexLastIndexOf = exports.isBeforeOrEqualToPosition = exports.isInRange = exports.isNotNullOrUndefined = exports.clamp = exports.modifyLines = exports.toPascalCase = exports.mergeDeep = exports.get = exports.getLastPartOfPath = exports.pathToUrl = exports.urlToPath = exports.normalizePath = exports.normalizeUri = void 0;
4
4
  const vscode_uri_1 = require("vscode-uri");
5
+ const importPackage_1 = require("./importPackage");
5
6
  /** Normalizes a document URI */
6
7
  function normalizeUri(uri) {
7
8
  return vscode_uri_1.URI.parse(uri).toString();
@@ -214,23 +215,29 @@ function isAstroWorkspace(workspacePath) {
214
215
  return false;
215
216
  }
216
217
  exports.isAstroWorkspace = isAstroWorkspace;
217
- function getUserAstroVersion(basePath) {
218
- let version = '0.0.0';
219
- let exist = true;
218
+ function getAstroInstall(basePaths) {
219
+ let path;
220
+ let version;
220
221
  try {
221
- const astroPackageJson = require.resolve('astro/package.json', { paths: [basePath] });
222
- version = require(astroPackageJson).version;
222
+ path = (0, importPackage_1.getPackagePath)('astro', basePaths);
223
+ if (!path) {
224
+ throw Error;
225
+ }
226
+ version = require(path + '/package.json').version;
223
227
  }
224
228
  catch {
225
229
  // If we couldn't find it inside the workspace's node_modules, it might means we're in the monorepo
226
230
  try {
227
- const monorepoPackageJson = require.resolve('./packages/astro/package.json', { paths: [basePath] });
228
- version = require(monorepoPackageJson).version;
231
+ path = (0, importPackage_1.getPackagePath)('./packages/astro', basePaths);
232
+ if (!path) {
233
+ throw Error;
234
+ }
235
+ version = require(path + '/package.json').version;
229
236
  }
230
237
  catch (e) {
231
238
  // If we still couldn't find it, it probably just doesn't exist
232
- exist = false;
233
- console.error(`${basePath} seems to be an Astro project, but we couldn't find Astro or Astro is not installed`);
239
+ console.error(`${basePaths[0]} seems to be an Astro project, but we couldn't find Astro or Astro is not installed`);
240
+ return undefined;
234
241
  }
235
242
  }
236
243
  let [major, minor, patch] = version.split('.');
@@ -239,11 +246,13 @@ function getUserAstroVersion(basePath) {
239
246
  patch = patchParts[0];
240
247
  }
241
248
  return {
242
- full: version,
243
- major: Number(major),
244
- minor: Number(minor),
245
- patch: Number(patch),
246
- exist,
249
+ path,
250
+ version: {
251
+ full: version,
252
+ major: Number(major),
253
+ minor: Number(minor),
254
+ patch: Number(patch),
255
+ },
247
256
  };
248
257
  }
249
- exports.getUserAstroVersion = getUserAstroVersion;
258
+ exports.getAstroInstall = getAstroInstall;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/language-server",
3
- "version": "0.20.3",
3
+ "version": "0.22.0",
4
4
  "author": "withastro",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -20,6 +20,8 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@vscode/emmet-helper": "^2.8.4",
23
+ "prettier": "^2.7.1",
24
+ "prettier-plugin-astro": "^0.5.0",
23
25
  "source-map": "^0.7.3",
24
26
  "typescript": "~4.6.4",
25
27
  "vscode-css-languageservice": "^6.0.1",
@@ -35,6 +37,7 @@
35
37
  "@astrojs/vue": "^0.5.0",
36
38
  "@types/chai": "^4.3.0",
37
39
  "@types/mocha": "^9.1.0",
40
+ "@types/prettier": "^2.7.0",
38
41
  "@types/sinon": "^10.0.11",
39
42
  "astro": "^1.0.0-beta.72",
40
43
  "astro-scripts": "0.0.1",
@@ -0,0 +1,5 @@
1
+ # Types
2
+
3
+ **Heads up!** `env.d.ts` and `astro-jsx.d.ts` in this folder are only used as fallback by the language server whenever we're not able to load the real types from the user's project. The types here should be in line with the types from Astro, but only loosely as not being able to load the real types from the user's project is an uncommon situation and some things are not necessarily possible without relying on Astro's internals
4
+
5
+ As such, if you're making a PR to fix/improve something related to types, you should probably make a PR to [Astro itself](https://github.com/withastro/astro), not this project!