Skip to content

feat: extend typescript help signatures with mongodb items VSCODE-403 #509

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

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 7 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
519 changes: 264 additions & 255 deletions package-lock.json

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"reformat": "prettier --write ."
},
"engines": {
"vscode": "^1.76.2",
"vscode": "^1.77.0",
"node": "^16.16.0",
"npm": "^8.15.1"
},
Expand Down Expand Up @@ -959,10 +959,10 @@
}
},
"dependencies": {
"@babel/parser": "^7.21.3",
"@babel/traverse": "^7.21.3",
"@fortawesome/fontawesome-svg-core": "^6.3.0",
"@fortawesome/free-solid-svg-icons": "^6.3.0",
"@babel/parser": "^7.21.4",
"@babel/traverse": "^7.21.4",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@iconify-icons/codicon": "^1.2.23",
"@iconify/react": "^1.1.4",
Expand All @@ -974,13 +974,13 @@
"@mongosh/service-provider-server": "^1.8.0",
"@mongosh/shell-api": "^1.8.0",
"analytics-node": "^6.2.0",
"bson": "^5.1.0",
"bson": "^5.2.0",
"bson-transpilers": "^2.0.3",
"classnames": "^2.3.2",
"debug": "^4.3.4",
"dotenv": "^16.0.3",
"micromatch": "^4.0.5",
"mongodb": "^5.1.0",
"mongodb": "^5.2.0",
"mongodb-build-info": "^1.5.0",
"mongodb-cloud-info": "^1.1.3",
"mongodb-connection-string-url": "^2.6.0",
Expand Down Expand Up @@ -1012,14 +1012,14 @@
"@types/micromatch": "^4.0.2",
"@types/mkdirp": "^2.0.0",
"@types/mocha": "^8.2.3",
"@types/node": "^14.18.40",
"@types/react": "^17.0.53",
"@types/node": "^14.18.42",
"@types/react": "^17.0.56",
"@types/react-dom": "^17.0.19",
"@types/sinon": "^9.0.11",
"@types/uuid": "^8.3.4",
"@types/vscode": "^1.76.0",
"@typescript-eslint/eslint-plugin": "^5.56.0",
"@typescript-eslint/parser": "^5.56.0",
"@types/vscode": "^1.77.0",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"@vscode/test-electron": "^2.3.0",
"@vscode/vsce": "^2.18.0",
"@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
Expand All @@ -1034,9 +1034,9 @@
"css-loader": "^3.6.0",
"depcheck": "^1.4.3",
"download": "^8.0.0",
"electron": "^23.2.0",
"electron": "^23.2.2",
"enzyme": "^3.11.0",
"eslint": "^8.36.0",
"eslint": "^8.37.0",
"eslint-config-mongodb-js": "^5.0.3",
"eslint-plugin-mocha": "^10.1.0",
"execa": "^1.0.0",
Expand Down Expand Up @@ -1068,7 +1068,7 @@
"ts-loader": "^9.4.2",
"ts-node": "^10.9.1",
"typescript": "^4.9.5",
"webpack": "^5.76.3",
"webpack": "^5.78.0",
"webpack-cli": "^4.10.0",
"xvfb-maybe": "^0.2.1",
"yargs-parser": "^20.2.9"
Expand Down
2 changes: 1 addition & 1 deletion scripts/check-vsix-size.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const vsixFileName = path.resolve(
);
const size = fs.statSync(vsixFileName).size;

const maxSize = 7 * 1000000; // 7 MB
const maxSize = 9 * 1000000; // 9 MB

if (size >= maxSize) {
throw new Error(
Expand Down
66 changes: 57 additions & 9 deletions src/language/mongoDBService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
InsertTextFormat,
MarkupKind,
DiagnosticSeverity,
SignatureHelpContext,
} from 'vscode-languageserver/node';
import type {
CancellationToken,
Expand Down Expand Up @@ -399,7 +400,7 @@ export default class MongoDBService {
getExportToLanguageMode(
params: PlaygroundTextAndSelection
): ExportToLanguageMode {
const state = this._visitor.parseAST(params);
const state = this._visitor.parseASTForExportToLanguage(params);

if (state.isArraySelection) {
return ExportToLanguageMode.AGGREGATION;
Expand All @@ -420,7 +421,7 @@ export default class MongoDBService {
params: PlaygroundTextAndSelection
): ExportToLanguageNamespace {
try {
const state = this._visitor.parseAST(params);
const state = this._visitor.parseASTForNamespace(params);
return {
databaseName: state.databaseName,
collectionName: state.collectionName,
Expand Down Expand Up @@ -802,13 +803,10 @@ export default class MongoDBService {
position: { line: number; character: number }
): Promise<CompletionItem[]> {
this._connection.console.log(
`LS current symbol position: ${util.inspect(position)}`
`Provide completion items for a position: ${util.inspect(position)}`
);

const state = this._visitor.parseASTWithPlaceholder(
textFromEditor,
position
);
const state = this._visitor.parseASTForCompletion(textFromEditor, position);
this._connection.console.log(
`VISITOR completion state: ${util.inspect(state)}`
);
Expand Down Expand Up @@ -842,12 +840,62 @@ export default class MongoDBService {
}
}

this._connection.console.log('VISITOR no completion');
this._connection.console.log('VISITOR found no mongodb completion');
return [];
}

/**
* Parse code from a playground to identify
* where the cursor is and show mongodb method signature help items.
*/
provideSignatureHelp(
textFromEditor: string,
position: { line: number; character: number },
context?: SignatureHelpContext
) {
this._connection.console.log(
`Provide signature help for a position: ${util.inspect(position)}`
);

const state = this._visitor.parseASTWForSignatureHelp(
textFromEditor,
position
);
this._connection.console.log(
`VISITOR signature help state: ${util.inspect(state)}`
);

if (state.isFind) {
return {
activeSignatureHelp: context?.activeSignatureHelp,
signatures: [
{
label: 'Collection.find(query, projection, options) : Cursor',
documentation: 'Selects documents in a collection or view.',
parameters: [],
},
],
};
}

if (state.isAggregation) {
return {
activeSignatureHelp: context?.activeSignatureHelp,
signatures: [
{
label: 'Collection.aggregate(pipeline, options) : Cursor',
documentation:
'Calculates aggregate values for the data in a collection or a view.',
parameters: [],
},
],
};
}

this._connection.console.log('VISITOR found no mongodb signature help');
}

// Highlight the usage of commands that only works inside interactive session.
// eslint-disable-next-line complexity
provideDiagnostics(textFromEditor: string) {
const lines = textFromEditor.split(/\r?\n/g);
const diagnostics: Diagnostic[] = [];
Expand Down
41 changes: 38 additions & 3 deletions src/language/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ import {
RequestType,
TextDocumentSyncKind,
Connection,
SignatureHelpParams,
} from 'vscode-languageserver/node';
import { TextDocument } from 'vscode-languageserver-textdocument';

import MongoDBService from './mongoDBService';
import TypeScriptService from './tsLanguageService';

import { ServerCommands } from './serverCommands';
import {
PlaygroundEvaluateParams,
Expand All @@ -30,6 +33,9 @@ const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
// MongoDB Playground Service Manager.
const mongoDBService = new MongoDBService(connection);

// TypeScript language service.
const typeScriptService = new TypeScriptService(connection);

let hasConfigurationCapability = false;
// let hasWorkspaceFolderCapability = false;
// let hasDiagnosticRelatedInformationCapability = false;
Expand Down Expand Up @@ -66,6 +72,10 @@ connection.onInitialize((params: InitializeParams) => {
resolveProvider: true,
triggerCharacters: ['.'],
},
signatureHelpProvider: {
resolveProvider: true,
triggerCharacters: [','],
},
// documentFormattingProvider: true,
// documentRangeFormattingProvider: true,
// codeLensProvider: {
Expand Down Expand Up @@ -118,8 +128,6 @@ connection.onDidChangeConfiguration((/* change */) => {

// Only keep settings for open documents.
documents.onDidClose((e) => {
// connection.console.log(`documents.onDidClose: ${JSON.stringify(e)}`);

documentSettings.delete(e.document.uri);
});

Expand Down Expand Up @@ -160,6 +168,7 @@ connection.onRequest(
}
);

// Pass the extension path to the MongoDB service.
connection.onRequest(ServerCommands.SET_EXTENSION_PATH, (extensionPath) => {
return mongoDBService.setExtensionPath(extensionPath);
});
Expand All @@ -183,21 +192,23 @@ connection.onRequest(
}
);

// Identify if the playground selection is an array or object.
connection.onRequest(
ServerCommands.GET_EXPORT_TO_LANGUAGE_MODE,
(params: PlaygroundTextAndSelection) => {
return mongoDBService.getExportToLanguageMode(params);
}
);

// Find the current namespace for a playground selection.
connection.onRequest(
ServerCommands.GET_NAMESPACE_FOR_SELECTION,
(params: PlaygroundTextAndSelection) => {
return mongoDBService.getNamespaceForSelection(params);
}
);

// This handler provides the list of the completion items.
// Provide MongoDB completion items.
connection.onCompletion((params: TextDocumentPositionParams) => {
const textFromEditor = documents.get(params.textDocument.uri)?.getText();

Expand All @@ -223,6 +234,28 @@ connection.onCompletionResolve((item: CompletionItem): CompletionItem => {
return item;
});

// Provide MongoDB or TypeScript help signatures.
connection.onSignatureHelp((params: SignatureHelpParams) => {
const document = documents.get(params.textDocument.uri);

if (!document) {
return;
}

const textFromEditor = document.getText() || '';
const mongodbSignatures = mongoDBService.provideSignatureHelp(
textFromEditor,
params.position,
params.context
);

if (mongodbSignatures) {
return mongodbSignatures;
}

return typeScriptService.doSignatureHelp(document, params.position);
});

connection.onRequest('textDocument/rangeFormatting', (event) => {
// connection.console.log(
// `textDocument/rangeFormatting: ${JSON.stringify({ event })}`
Expand Down Expand Up @@ -258,6 +291,7 @@ connection.onDidOpenTextDocument((/* params */) => {
// params.textDocument.text the initial full content of the document.
// connection.console.log(`${params.textDocument.uri} opened.`);
});

connection.onDidChangeTextDocument((/* params */) => {
// The content of a text document did change in VSCode.
// params.textDocument.uri uniquely identifies the document.
Expand All @@ -268,6 +302,7 @@ connection.onDidChangeTextDocument((/* params */) => {
// )}`
// );
});

connection.onDidCloseTextDocument((/* params */) => {
// A text document got closed in VSCode.
// params.textDocument.uri uniquely identifies the document.
Expand Down
Loading