Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nxls): get project targets for the language server #1330

Merged
merged 11 commits into from
Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@
"sourceTag": "*",
"onlyDependOnLibsWithTags": ["*"]
},
{
"sourceTag": "type:vscode",
"onlyDependOnLibsWithTags": ["type:shared", "type:vscode"]
},
{
"sourceTag": "type:lsp",
"onlyDependOnLibsWithTags": ["type:lsp", "type:shared-utils"],
"onlyDependOnLibsWithTags": ["type:lsp", "type:shared"],
"bannedExternalImports": ["vscode"]
},
{
"sourceTag": "type:shared",
"onlyDependOnLibsWithTags": ["type:shared"],
"bannedExternalImports": ["vscode"]
}
]
Expand Down
18 changes: 14 additions & 4 deletions apps/nxls/esbuild.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
require('esbuild')
.build({
(async () => {
let esbuild = require('esbuild');

let result = await esbuild.build({
entryPoints: ['./apps/nxls/src/main.ts'],
bundle: true,
minify: true,
platform: 'node',
mainFields: ['module', 'main'],
outfile: './dist/apps/vscode/nxls/main.js',
})
.catch(() => process.exit(1));
metafile: true,
});

let text = await esbuild.analyzeMetafile(result.metafile, {
verbose: true,
});

// Comment out to analyze the build
// await require('fs/promises').writeFile('./dep.txt', text);
})();
100 changes: 57 additions & 43 deletions apps/nxls/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@ import {
import { getCompletionItems } from '@nx-console/language-server/capabilities/code-completion';
import { getDocumentLinks } from '@nx-console/language-server/capabilities/document-links';
import {
configureJsonLanguageService,
getJsonLanguageService,
getLanguageModelCache,
getSchemaRequestService,
lspLogger,
mergeArrays,
setLspLogger,
} from '@nx-console/language-server/utils';
import {
ClientCapabilities,
CompletionList,
getLanguageService,
TextDocument,
} from 'vscode-json-languageservice';
import { nxWorkspace } from '@nx-console/workspace';
import { CompletionList, TextDocument } from 'vscode-json-languageservice';
import {
createConnection,
InitializeResult,
ProposedFeatures,
ResponseError,
TextDocuments,
TextDocumentSyncKind,
} from 'vscode-languageserver/node';
Expand All @@ -38,12 +39,6 @@ const workspaceContext = {

const connection = createConnection(ProposedFeatures.all);

let languageService = getLanguageService({
workspaceContext,
contributions: [],
clientCapabilities: ClientCapabilities.LATEST,
});

// Create a text document manager.
const documents = new TextDocuments(TextDocument);

Expand All @@ -52,15 +47,9 @@ const documents = new TextDocuments(TextDocument);
documents.listen(connection);

connection.onInitialize(async (params) => {
const { workspacePath, projects } = params.initializationOptions ?? {};

languageService = getLanguageService({
schemaRequestService: getSchemaRequestService(['file']),
workspaceContext,
contributions: [],
clientCapabilities: params.capabilities,
});
setLspLogger(connection);

const { workspacePath, projects } = params.initializationOptions ?? {};
try {
WORKING_PATH =
workspacePath ??
Expand All @@ -74,22 +63,31 @@ connection.onInitialize(async (params) => {
const collections = await getExecutors(WORKING_PATH, projects, false);
const workspaceSchema = getWorkspaceJsonSchema(collections);
const projectSchema = getProjectJsonSchema(collections);
languageService.configure({
schemas: [
{
uri: 'nx://schemas/workspace',
fileMatch: ['**/workspace.json', '**/angular.json'],
schema: workspaceSchema,
},
{
uri: 'nx://schemas/project',
fileMatch: ['**/project.json'],
schema: projectSchema,
},
],
});

configureJsonLanguageService(
{
schemaRequestService: getSchemaRequestService(['file']),
workspaceContext,
contributions: [],
clientCapabilities: params.capabilities,
},
{
schemas: [
{
uri: 'nx://schemas/workspace',
fileMatch: ['**/workspace.json', '**/angular.json'],
schema: workspaceSchema,
},
{
uri: 'nx://schemas/project',
fileMatch: ['**/project.json'],
schema: projectSchema,
},
],
}
);
} catch (e) {
connection.console.log('Unable to get Nx info: ' + e.toString());
lspLogger.log('Unable to get Nx info: ' + e.toString());
}

const result: InitializeResult = {
Expand Down Expand Up @@ -119,13 +117,15 @@ connection.onCompletion(async (completionParams) => {
const { jsonAst, document } = getJsonDocument(changedDocument);

const completionResults =
(await languageService.doComplete(
(await getJsonLanguageService().doComplete(
document,
completionParams.position,
jsonAst
)) ?? CompletionList.create([]);

const schemas = await languageService.getMatchingSchemas(document, jsonAst);
const schemas =
(await getJsonLanguageService().getMatchingSchemas(document, jsonAst)) ??
[];

const pathItems = await getCompletionItems(
WORKING_PATH,
Expand All @@ -147,7 +147,11 @@ connection.onHover(async (hoverParams) => {
}

const { jsonAst, document } = getJsonDocument(hoverDocument);
return languageService.doHover(document, hoverParams.position, jsonAst);
return getJsonLanguageService().doHover(
document,
hoverParams.position,
jsonAst
);
});

connection.onDocumentLinks(async (params) => {
Expand All @@ -158,14 +162,14 @@ connection.onDocumentLinks(async (params) => {
}

const { jsonAst, document } = getJsonDocument(linkDocument);
const schemas = await languageService.getMatchingSchemas(document, jsonAst);
const schemas =
(await getJsonLanguageService().getMatchingSchemas(document, jsonAst)) ??
[];

return getDocumentLinks(WORKING_PATH, jsonAst, document, schemas);
});

const jsonDocumentMapper = getLanguageModelCache(10, 60, (document) =>
languageService.parseJSONDocument(document)
);
const jsonDocumentMapper = getLanguageModelCache();

documents.onDidClose((e) => {
jsonDocumentMapper.onDocumentRemoved(e.document);
Expand All @@ -175,8 +179,18 @@ connection.onShutdown(() => {
jsonDocumentMapper.dispose();
});

connection.onRequest('nx/workspace', async () => {
if (!WORKING_PATH) {
return new ResponseError(1000, 'Unable to get Nx info: no workspace path');
}

const workspace = await nxWorkspace(WORKING_PATH, lspLogger);

return workspace.workspace.projects;
});

function getJsonDocument(document: TextDocument) {
return jsonDocumentMapper.get(document);
return jsonDocumentMapper.retrieve(document);
}

connection.listen();
5 changes: 3 additions & 2 deletions apps/vscode/src/commands/refresh-workspace.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getWorkspacePath, outputLogger } from '@nx-console/vscode/utils';
import { debounceTime, Subject } from 'rxjs';
import { commands } from 'vscode';

Expand All @@ -6,8 +7,8 @@ export const REFRESH_WORKSPACE = 'nxConsole.refreshWorkspace';
const refresh = new Subject();

refresh.pipe(debounceTime(150)).subscribe(async () => {
const { nxWorkspace } = await import('@nx-console/vscode/nx-workspace');
await nxWorkspace(true);
const { nxWorkspace } = await import('@nx-console/workspace');
await nxWorkspace(getWorkspacePath(), outputLogger, true);
commands.executeCommand('nxConsole.refreshNxProjectsTree');
commands.executeCommand('nxConsole.refreshRunTargetTree');
commands.executeCommand('nx.graph.refresh');
Expand Down
25 changes: 13 additions & 12 deletions apps/vscode/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,7 @@ import {
workspace,
} from 'vscode';

import {
checkIsNxWorkspace,
getOutputChannel,
getTelemetry,
initTelemetry,
teardownTelemetry,
watchFile,
} from '@nx-console/utils';
import { checkIsNxWorkspace } from '@nx-console/utils';
import {
GlobalConfigurationStore,
WorkspaceConfigurationStore,
Expand All @@ -42,6 +35,14 @@ import {
registerCliTaskCommands,
registerNxCommands,
} from '@nx-console/vscode/tasks';
import {
getOutputChannel,
getTelemetry,
initTelemetry,
outputLogger,
teardownTelemetry,
watchFile,
} from '@nx-console/vscode/utils';
import { revealWebViewPanel } from '@nx-console/vscode/webview';
import { environment } from './environments/environment';

Expand Down Expand Up @@ -288,9 +289,9 @@ async function setWorkspace(workspacePath: string) {
}

async function setApplicationAndLibraryContext(workspacePath: string) {
const { nxWorkspace } = await import('@nx-console/vscode/nx-workspace');
const { nxWorkspace } = await import('@nx-console/workspace');

const { workspaceLayout } = await nxWorkspace();
const { workspaceLayout } = await nxWorkspace(workspacePath, outputLogger);

commands.executeCommand('setContext', 'nxAppsDir', [
join(workspacePath, workspaceLayout.appsDir),
Expand Down Expand Up @@ -334,9 +335,9 @@ async function registerWorkspaceFileWatcher(
workspaceFileWatcher.dispose();
}

const { nxWorkspace } = await import('@nx-console/vscode/nx-workspace');
const { nxWorkspace } = await import('@nx-console/workspace');

const { workspaceLayout } = await nxWorkspace();
const { workspaceLayout } = await nxWorkspace(workspacePath, outputLogger);
const workspacePackageDirs = new Set<string>();
workspacePackageDirs.add(workspaceLayout.appsDir);
workspacePackageDirs.add(workspaceLayout.libsDir);
Expand Down
2 changes: 1 addition & 1 deletion libs/collections/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
}
}
},
"tags": ["type:shared-utils"]
"tags": ["type:shared"]
}
2 changes: 1 addition & 1 deletion libs/file-system/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
}
}
},
"tags": ["type:shared-utils"]
"tags": ["type:shared"]
}
1 change: 1 addition & 0 deletions libs/file-system/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export { readAndCacheJsonFile } from './lib/cache-json';
export { clearJsonCache } from './lib/cache-json';
export { readAndParseJson } from './lib/cache-json';
export { listFiles } from './lib/list-files';
export { readFile } from './lib/read-file';
9 changes: 9 additions & 0 deletions libs/file-system/src/lib/read-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { crossFs } from './cache-json';

export async function readFile(filePath: string): Promise<string> {
try {
return crossFs.readFilePromise(filePath, 'utf8');
} catch {
return '';
}
}
2 changes: 1 addition & 1 deletion libs/json-schema/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@
}
}
},
"tags": ["type:shared-utils"]
"tags": ["type:shared"]
}
2 changes: 1 addition & 1 deletion libs/json-schema/src/lib/completion-type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { hasKey } from '@nx-console/utils';
import { JSONSchema } from 'vscode-json-languageservice';
import { hasKey } from '@nx-console/utils/shared';

export const X_COMPLETION_TYPE = 'x-completion-type' as const;
export const X_COMPLETION_GLOB = 'x-completion-glob' as const;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
ASTNode,
CompletionItem,
CompletionItemKind,
TextDocument,
} from 'vscode-json-languageservice';

export function createCompletionPathItem(
label: string,
path: string,
node: ASTNode,
document: TextDocument,
kind: CompletionItemKind
): CompletionItem {
const startPosition = document.positionAt(node.offset);
const endPosition = document.positionAt(node.offset + node.length);
label = `"${label}"`;
return {
label,
kind,
insertText: label,
insertTextFormat: 2,
textEdit: {
newText: label,
range: {
start: startPosition,
end: endPosition,
},
},
detail: path,
};
}
Loading