Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/sveltejs/language-tools i…
Browse files Browse the repository at this point in the history
…nto semantic-doc-highlight
  • Loading branch information
jasonlyu123 committed Nov 30, 2024
2 parents 8971042 + 89cc22b commit fd68cc8
Show file tree
Hide file tree
Showing 140 changed files with 2,666 additions and 872 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
cache: pnpm

# Get projects set up
Expand All @@ -31,7 +31,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
cache: pnpm

# Lets us use one-liner JSON manipulations the package.json files
Expand All @@ -56,7 +56,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
cache: pnpm

# Get projects set up
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/DeployExtensionsProd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
registry-url: "https://registry.npmjs.org"
cache: pnpm

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/DeploySvelte2tsxProd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
registry-url: "https://registry.npmjs.org"
cache: pnpm

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/DeploySvelteCheckProd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
registry-url: "https://registry.npmjs.org"
cache: pnpm

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/DeploySvelteLanguageServerProd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
registry-url: "https://registry.npmjs.org"
cache: pnpm

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/DeployTypescriptPluginProd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
registry-url: "https://registry.npmjs.org"
cache: pnpm

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"lint": "prettier --check ."
},
"dependencies": {
"typescript": "^5.5.2"
"typescript": "~5.6.3"
},
"devDependencies": {
"cross-env": "^7.0.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/language-server/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dist/
.vscode/
node_modules/
!test/plugins/typescript/features/diagnostics/fixtures/exports-map-svelte/node_modules/
!test/plugins/typescript/features/diagnostics/fixtures/exports-map-svelte/node_modules/package
4 changes: 4 additions & 0 deletions packages/language-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ Enable code actions for Svelte. _Default_: `true`

Enable selection range for Svelte. _Default_: `true`

##### `svelte.plugin.svelte.runesLegacyModeCodeLens.enable`

Whether or not to show a code lens at the top of Svelte files indicating if they are in runes mode or legacy mode. Only visible in Svelte 5 projects. _Default_: `true`

##### `svelte.plugin.svelte.defaultScriptLanguage`

The default language to use when generating new script tags in Svelte. _Default_: `none`
Expand Down
8 changes: 5 additions & 3 deletions packages/language-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
},
"devDependencies": {
"@types/estree": "^0.0.42",
"@types/globrex": "^0.1.4",
"@types/lodash": "^4.14.116",
"@types/mocha": "^9.1.0",
"@types/node": "^18.0.0",
Expand All @@ -55,13 +56,14 @@
"chokidar": "^4.0.1",
"estree-walker": "^2.0.1",
"fdir": "^6.2.0",
"globrex": "^0.1.2",
"lodash": "^4.17.21",
"prettier": "~3.3.3",
"prettier-plugin-svelte": "^3.2.6",
"prettier-plugin-svelte": "^3.3.0",
"svelte": "^4.2.19",
"svelte2tsx": "workspace:~",
"typescript": "^5.5.2",
"typescript-auto-import-cache": "^0.3.3",
"typescript": "~5.6.3",
"typescript-auto-import-cache": "^0.3.5",
"vscode-css-languageservice": "~6.3.0",
"vscode-html-languageservice": "~5.3.0",
"vscode-languageserver": "9.0.1",
Expand Down
25 changes: 14 additions & 11 deletions packages/language-server/src/lib/FallbackWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from 'vscode-languageserver';
import { pathToUrl } from '../utils';
import { fileURLToPath } from 'url';
import { Stats } from 'fs';

type DidChangeHandler = (para: DidChangeWatchedFilesParams) => void;

Expand All @@ -20,18 +21,20 @@ export class FallbackWatcher {

private undeliveredFileEvents: FileEvent[] = [];

constructor(recursivePatterns: string, workspacePaths: string[]) {
constructor(watchExtensions: string[], workspacePaths: string[]) {
const gitOrNodeModules = /\.git|node_modules/;
this.watcher = watch(
workspacePaths.map((workspacePath) => join(workspacePath, recursivePatterns)),
{
ignored: gitOrNodeModules,
// typescript would scan the project files on init.
// We only need to know what got updated.
ignoreInitial: true,
ignorePermissionErrors: true
}
);
const ignoredExtensions = (fileName: string, stats?: Stats) => {
return (
stats?.isFile() === true && !watchExtensions.some((ext) => fileName.endsWith(ext))
);
};
this.watcher = watch(workspacePaths, {
ignored: [gitOrNodeModules, ignoredExtensions],
// typescript would scan the project files on init.
// We only need to know what got updated.
ignoreInitial: true,
ignorePermissionErrors: true
});

this.watcher
.on('add', (path) => this.onFSEvent(path, FileChangeType.Created))
Expand Down
43 changes: 41 additions & 2 deletions packages/language-server/src/ls-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const defaultLSConfig: LSConfig = {
hover: { enable: true },
codeActions: { enable: true },
selectionRange: { enable: true },
runesLegacyModeCodeLens: { enable: true },
defaultScriptLanguage: 'none'
}
};
Expand Down Expand Up @@ -188,6 +189,7 @@ export interface LSSvelteConfig {
selectionRange: {
enable: boolean;
};
runesLegacyModeCodeLens: { enable: boolean };
defaultScriptLanguage: 'none' | 'ts';
}

Expand Down Expand Up @@ -221,6 +223,20 @@ export interface TsUserPreferencesConfig {
includePackageJsonAutoImports?: ts.UserPreferences['includePackageJsonAutoImports'];

preferTypeOnlyAutoImports?: ts.UserPreferences['preferTypeOnlyAutoImports'];

autoImportSpecifierExcludeRegexes?: string[];

organizeImports?: TsOrganizeImportPreferencesConfig;
}

interface TsOrganizeImportPreferencesConfig {
accentCollation: ts.UserPreferences['organizeImportsAccentCollation'];
caseFirst: ts.UserPreferences['organizeImportsCaseFirst'] | 'default';
caseSensitivity: ts.UserPreferences['organizeImportsIgnoreCase'];
collation: ts.UserPreferences['organizeImportsCollation'];
locale: ts.UserPreferences['organizeImportsLocale'];
numericCollation: ts.UserPreferences['organizeImportsNumericCollation'];
typeOrder: ts.UserPreferences['organizeImportsTypeOrder'] | 'auto';
}

/**
Expand Down Expand Up @@ -473,11 +489,34 @@ export class LSConfigManager {
includeInlayPropertyDeclarationTypeHints: inlayHints?.propertyDeclarationTypes?.enabled,
includeInlayVariableTypeHintsWhenTypeMatchesName:
inlayHints?.variableTypes?.suppressWhenTypeMatchesName === false,

interactiveInlayHints: true
interactiveInlayHints: true,

autoImportSpecifierExcludeRegexes:
config.preferences?.autoImportSpecifierExcludeRegexes,

organizeImportsAccentCollation: config.preferences?.organizeImports?.accentCollation,
organizeImportsCollation: config.preferences?.organizeImports?.collation,
organizeImportsCaseFirst: this.withDefaultAsUndefined(
config.preferences?.organizeImports?.caseFirst,
'default'
),
organizeImportsIgnoreCase: this.withDefaultAsUndefined(
config.preferences?.organizeImports?.caseSensitivity,
'auto'
),
organizeImportsLocale: config.preferences?.organizeImports?.locale,
organizeImportsNumericCollation: config.preferences?.organizeImports?.numericCollation,
organizeImportsTypeOrder: this.withDefaultAsUndefined(
config.preferences?.organizeImports?.typeOrder,
'auto'
)
};
}

private withDefaultAsUndefined<T, O extends T>(value: T, def: O): Exclude<T, O> | undefined {
return value === def ? undefined : (value as Exclude<T, O>);
}

getTsUserPreferences(
lang: TsUserConfigLang,
normalizedWorkspacePath: string | null
Expand Down
26 changes: 23 additions & 3 deletions packages/language-server/src/plugins/PluginHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,22 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
});
}

let itemDefaults: CompletionList['itemDefaults'];
if (completions.length === 1) {
itemDefaults = completions[0]?.result.itemDefaults;
} else {
// don't apply items default to the result of other plugins
for (const completion of completions) {
const itemDefaults = completion.result.itemDefaults;
if (!itemDefaults) {
continue;
}
completion.result.items.forEach((item) => {
item.commitCharacters ??= itemDefaults.commitCharacters;
});
}
}

let flattenedCompletions = flatten(
completions.map((completion) => completion.result.items)
);
Expand All @@ -195,7 +211,10 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
);
}

return CompletionList.create(flattenedCompletions, isIncomplete);
const result = CompletionList.create(flattenedCompletions, isIncomplete);
result.itemDefaults = itemDefaults;

return result;
}

async resolveCompletion(
Expand Down Expand Up @@ -615,12 +634,13 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
throw new Error('Cannot call methods on an unopened document');
}

return await this.execute<CodeLens[]>(
const result = await this.execute<CodeLens[]>(
'getCodeLens',
[document],
ExecuteMode.FirstNonNull,
ExecuteMode.Collect,
'smart'
);
return flatten(result.filter(Boolean));
}

async getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[]> {
Expand Down
7 changes: 6 additions & 1 deletion packages/language-server/src/plugins/css/CSSPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import { getDocumentContext } from '../documentContext';
import { FoldingRange, FoldingRangeKind } from 'vscode-languageserver-types';
import { indentBasedFoldingRangeForTag } from '../../lib/foldingRange/indentFolding';
import { wordHighlightForTag } from '../../lib/documentHighlight/wordHighlight';
import { isNotNullOrUndefined, urlToPath } from '../../utils';

// https://github.com/microsoft/vscode/blob/c6f507deeb99925e713271b1048f21dbaab4bd54/extensions/css/language-configuration.json#L34
const wordPattern = /(#?-?\d*\.\d\w*%?)|(::?[\w-]*(?=[^,{;]*[,{]))|(([@#.!])?[\w-?]+%?|[@#!.])/g;
Expand All @@ -75,7 +76,7 @@ export class CSSPlugin
private cssLanguageServices: CSSLanguageServices;
private workspaceFolders: WorkspaceFolder[];
private triggerCharacters = ['.', ':', '-', '/'];
private globalVars = new GlobalVars();
private globalVars: GlobalVars;

constructor(
docManager: DocumentManager,
Expand All @@ -87,6 +88,10 @@ export class CSSPlugin
this.workspaceFolders = workspaceFolders;
this.configManager = configManager;
this.updateConfigs();
const workspacePaths = workspaceFolders
.map((folder) => urlToPath(folder.uri))
.filter(isNotNullOrUndefined);
this.globalVars = new GlobalVars(workspacePaths);

this.globalVars.watchFiles(this.configManager.get('css.globals'));
this.configManager.onChange((config) => {
Expand Down
51 changes: 47 additions & 4 deletions packages/language-server/src/plugins/css/global-vars.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { watch, FSWatcher } from 'chokidar';
import { FSWatcher, watch } from 'chokidar';
import { readFile } from 'fs';
import { isNotNullOrUndefined, flatten } from '../../utils';
import globrex from 'globrex';
import { join } from 'path';
import { flatten, isNotNullOrUndefined, normalizePath } from '../../utils';

const varRegex = /^\s*(--\w+.*?):\s*?([^;]*)/;

Expand All @@ -12,26 +14,67 @@ export interface GlobalVar {

export class GlobalVars {
private fsWatcher?: FSWatcher;
private watchedFiles: string | undefined;
private globalVars = new Map<string, GlobalVar[]>();
private readonly workspaceRoot: string[];

constructor(workspaceRoot: string[]) {
this.workspaceRoot = workspaceRoot;
}

watchFiles(filesToWatch: string): void {
if (!filesToWatch) {
if (!filesToWatch || this.watchedFiles === filesToWatch) {
return;
}

this.watchedFiles = filesToWatch;
if (this.fsWatcher) {
this.fsWatcher.close();
this.globalVars.clear();
}

this.fsWatcher = watch(filesToWatch.split(','))
const paths = new Set<string>();
const includePatterns = new Set<string>();

for (const root of this.workspaceRoot) {
for (const filePath of filesToWatch.split(',')) {
if (!filePath.includes('*')) {
paths.add(filePath);
continue;
}

const normalizedPath = normalizePath(join(root, filePath));
includePatterns.add(normalizedPath);
const pathSegments = normalizedPath.split('**');
let directory = pathSegments[0] || '.';
paths.add(directory);
}
}

this.fsWatcher = watch(Array.from(paths), {
ignored: this.createIgnoreMatcher(includePatterns)
})
.addListener('add', (file) => this.updateForFile(file))
.addListener('change', (file) => {
this.updateForFile(file);
})
.addListener('unlink', (file) => this.globalVars.delete(file));
}

private createIgnoreMatcher(includePatterns: Set<string>) {
if (includePatterns.size === 0) {
return undefined;
}

const regexList = Array.from(includePatterns).map(
(pattern) => globrex(pattern, { globstar: true }).regex
);

return (path: string) => {
return !regexList.some((regex) => regex.test(path));
};
}

private updateForFile(filename: string) {
// Inside a small timeout because it seems chikidar is "too fast"
// and reading the file will then return empty content
Expand Down
Loading

0 comments on commit fd68cc8

Please sign in to comment.