Skip to content

Commit

Permalink
feat(language-server): simplify asFileName result if possible
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Jul 2, 2024
1 parent 6fca81f commit 8ada673
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 19 deletions.
46 changes: 29 additions & 17 deletions packages/language-server/lib/project/typescriptProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,22 @@ export function createTypeScriptProject(
}>
) {
let server: LanguageServer;
let uriConverter: ReturnType<typeof createUriConverter>;

const { asFileName, asUri } = createUriConverter();
const configProjects = createUriMap<Promise<TypeScriptProjectLS>>();
const inferredProjects = createUriMap<Promise<TypeScriptProjectLS>>();
const rootTsConfigs = new Set<string>();
const searchedDirs = new Set<string>();
const projects: LanguageServerProject = {
setup(_server) {
uriConverter = createUriConverter([..._server.workspaceFolders.keys()]);
server = _server;
server.onDidChangeWatchedFiles(({ changes }) => {
const tsConfigChanges = changes.filter(change => rootTsConfigNames.includes(change.uri.substring(change.uri.lastIndexOf('/') + 1)));

for (const change of tsConfigChanges) {
const changeUri = URI.parse(change.uri);
const changeFileName = asFileName(changeUri);
const changeFileName = uriConverter.asFileName(changeUri);
if (change.type === vscode.FileChangeType.Created) {
rootTsConfigs.add(changeFileName);
}
Expand Down Expand Up @@ -88,7 +89,7 @@ export function createTypeScriptProject(

async function findMatchTSConfig(server: LanguageServer, uri: URI) {

const fileName = asFileName(uri);
const fileName = uriConverter.asFileName(uri);

let dir = path.dirname(fileName);

Expand All @@ -99,7 +100,7 @@ export function createTypeScriptProject(
searchedDirs.add(dir);
for (const tsConfigName of rootTsConfigNames) {
const tsconfigPath = path.join(dir, tsConfigName);
if ((await server.fs.stat?.(asUri(tsconfigPath)))?.type === FileType.File) {
if ((await server.fs.stat?.(uriConverter.asUri(tsconfigPath)))?.type === FileType.File) {
rootTsConfigs.add(tsconfigPath);
}
}
Expand Down Expand Up @@ -128,7 +129,7 @@ export function createTypeScriptProject(
}
function findIndirectReferenceTsconfig() {
return findTSConfig(async tsconfig => {
const tsconfigUri = asUri(tsconfig);
const tsconfigUri = uriConverter.asUri(tsconfig);
const project = await configProjects.get(tsconfigUri);
return project?.askedFiles.has(uri) ?? false;
});
Expand All @@ -138,7 +139,7 @@ export function createTypeScriptProject(
const map = createUriMap<boolean>();
const parsedCommandLine = await getParsedCommandLine(tsconfig);
for (const fileName of parsedCommandLine?.fileNames ?? []) {
const uri = asUri(fileName);
const uri = uriConverter.asUri(fileName);
map.set(uri, true);
}
return map.has(uri);
Expand All @@ -149,7 +150,7 @@ export function createTypeScriptProject(
const checked = new Set<string>();

for (const rootTsConfig of [...rootTsConfigs].sort((a, b) => sortTSConfigs(fileName, a, b))) {
const tsconfigUri = asUri(rootTsConfig);
const tsconfigUri = uriConverter.asUri(rootTsConfig);
const project = await configProjects.get(tsconfigUri);
if (project) {

Expand Down Expand Up @@ -186,13 +187,13 @@ export function createTypeScriptProject(
let tsConfigPath = projectReference.path.replace(/\\/g, '/');

// fix https://github.com/johnsoncodehk/volar/issues/712
if ((await server.fs.stat?.(asUri(tsConfigPath)))?.type === FileType.File) {
if ((await server.fs.stat?.(uriConverter.asUri(tsConfigPath)))?.type === FileType.File) {
const newTsConfigPath = path.join(tsConfigPath, 'tsconfig.json');
const newJsConfigPath = path.join(tsConfigPath, 'jsconfig.json');
if ((await server.fs.stat?.(asUri(newTsConfigPath)))?.type === FileType.File) {
if ((await server.fs.stat?.(uriConverter.asUri(newTsConfigPath)))?.type === FileType.File) {
tsConfigPath = newTsConfigPath;
}
else if ((await server.fs.stat?.(asUri(newJsConfigPath)))?.type === FileType.File) {
else if ((await server.fs.stat?.(uriConverter.asUri(newJsConfigPath)))?.type === FileType.File) {
tsConfigPath = newJsConfigPath;
}
}
Expand Down Expand Up @@ -225,7 +226,7 @@ export function createTypeScriptProject(

function getOrCreateConfiguredProject(server: LanguageServer, tsconfig: string) {
tsconfig = tsconfig.replace(/\\/g, '/');
const tsconfigUri = asUri(tsconfig);
const tsconfigUri = uriConverter.asUri(tsconfig);
let projectPromise = configProjects.get(tsconfigUri);
if (!projectPromise) {
const workspaceFolder = getWorkspaceFolder(tsconfigUri, server.workspaceFolders);
Expand All @@ -237,7 +238,7 @@ export function createTypeScriptProject(
server,
serviceEnv,
workspaceFolder,
{ asUri, asFileName },
{ asUri: uriConverter.asUri, asFileName: uriConverter.asFileName },
create
);
configProjects.set(tsconfigUri, projectPromise);
Expand All @@ -258,31 +259,37 @@ export function createTypeScriptProject(
server,
serviceEnv,
workspaceFolder,
{ asUri, asFileName },
{ asUri: uriConverter.asUri, asFileName: uriConverter.asFileName },
create
);
})());
}

const project = await inferredProjects.get(workspaceFolder)!;

project.tryAddFile(asFileName(uri));
project.tryAddFile(uriConverter.asFileName(uri));

return project;
}
}

export function createUriConverter() {
export function createUriConverter(rootFolders: URI[]) {
const encodeds = new Map<string, URI>();
const isFileScheme = rootFolders.every(folder => folder.scheme === 'file');

return {
asFileName,
asUri,
};

function asFileName(parsed: URI) {
if (parsed.scheme === 'file') {
return parsed.fsPath.replace(/\\/g, '/');
if (rootFolders.every(folder => folder.scheme === parsed.scheme && folder.authority === parsed.authority)) {
if (isFileScheme) {
return parsed.fsPath.replace(/\\/g, '/');
}
else {
return parsed.path;
}
}
const encoded = encodeURIComponent(`${parsed.scheme}://${parsed.authority}`);
encodeds.set(encoded, parsed);
Expand Down Expand Up @@ -317,6 +324,11 @@ export function createUriConverter() {
}
}
}
if (!isFileScheme) {
for (const folder of rootFolders) {
return URI.parse(`${folder.scheme}://${folder.authority}${fileName}`);
}
}
return URI.file(fileName);
}
}
Expand Down
21 changes: 19 additions & 2 deletions packages/language-server/tests/uri.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { createUriConverter } from '../lib/project/typescriptProject';
describe('URI', () => {

test('recoverable', () => {

const uriConverter = createUriConverter();
const uriConverter = createUriConverter([URI.parse('file:///')]);
const cases = [
'file:///a/b/c',
'test://test/test.html',
Expand All @@ -21,4 +20,22 @@ describe('URI', () => {
expect(a).toBe(b);
}
});

test('HTTPs', () => {
const uriConverter = createUriConverter([URI.parse('http://a')]);

expect(uriConverter.asFileName(URI.parse('http://a/b'))).toBe('/b');
expect(uriConverter.asFileName(URI.parse('https://a/b'))).toBe('/https%3A%2F%2Fa/b');

expect(uriConverter.asUri('/b').toString()).toBe('http://a/b');
expect(uriConverter.asUri('/c').toString()).toBe('http://a/c');
expect(uriConverter.asUri('/https%3A%2F%2Fa/d').toString()).toBe('https://a/d');
});

test('Empty Root Folders', () => {
const uriConverter = createUriConverter([]);

expect(uriConverter.asFileName(URI.parse('file:///a/b'))).toBe('/a/b');
expect(uriConverter.asUri('/a/b').toString()).toBe('file:///a/b');
});
});

0 comments on commit 8ada673

Please sign in to comment.