@prisma/language-server
Version:
Prisma Language Server
239 lines • 11.2 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.startServer = startServer;
const vscode_languageserver_1 = require("vscode-languageserver");
const node_1 = require("vscode-languageserver/node");
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
const MessageHandler = __importStar(require("./lib/MessageHandler"));
const internals_1 = require("./lib/prisma-schema-wasm/internals");
const Schema_1 = require("./lib/Schema");
const packageJson = require('../package.json'); // eslint-disable-line
function getConnection(options) {
let connection = options?.connection;
if (!connection) {
connection = process.argv.includes('--stdio')
? (0, node_1.createConnection)(process.stdin, process.stdout)
: (0, node_1.createConnection)(new node_1.IPCMessageReader(process), new node_1.IPCMessageWriter(process));
}
return connection;
}
let hasCodeActionLiteralsCapability = false;
let hasConfigurationCapability = false;
/**
* Starts the language server.
*
* @param options Options to customize behavior
*/
function startServer(options) {
// Source code: https://github.com/microsoft/vscode-languageserver-node/blob/main/server/src/common/server.ts#L1044
const connection = getConnection(options);
console.log = connection.console.log.bind(connection.console);
console.error = connection.console.error.bind(connection.console);
const documents = new vscode_languageserver_1.TextDocuments(vscode_languageserver_textdocument_1.TextDocument);
connection.onInitialize((params) => {
// Logging first...
connection.console.info(`Default version of Prisma 'prisma-schema-wasm': ${(0, internals_1.getVersion)()}`);
connection.console.info(
// eslint-disable-next-line
`Extension name ${packageJson.name} with version ${packageJson.version}`);
const prismaEnginesVersion = (0, internals_1.getEnginesVersion)();
connection.console.info(`Prisma Engines version: ${prismaEnginesVersion}`);
const prismaCliVersion = (0, internals_1.getCliVersion)();
connection.console.info(`Prisma CLI version: ${prismaCliVersion}`);
// ... and then capabilities of the language server
const capabilities = params.capabilities;
hasCodeActionLiteralsCapability = Boolean(capabilities?.textDocument?.codeAction?.codeActionLiteralSupport);
hasConfigurationCapability = Boolean(capabilities?.workspace?.configuration);
const result = {
capabilities: {
definitionProvider: true,
documentFormattingProvider: true,
completionProvider: {
resolveProvider: true,
triggerCharacters: ['@', '"', '.'],
},
hoverProvider: true,
renameProvider: true,
documentSymbolProvider: true,
referencesProvider: true,
},
};
if (hasCodeActionLiteralsCapability) {
result.capabilities.codeActionProvider = {
codeActionKinds: [vscode_languageserver_1.CodeActionKind.QuickFix],
};
}
return result;
});
connection.onInitialized(() => {
if (hasConfigurationCapability) {
// Register for all configuration changes.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
connection.client.register(vscode_languageserver_1.DidChangeConfigurationNotification.type, undefined);
}
});
// The global settings, used when the `workspace/configuration` request is not supported by the client or is not set by the user.
// This does not apply to VS Code, as this client supports this setting.
// const defaultSettings: LSSettings = {}
// let globalSettings: LSSettings = defaultSettings // eslint-disable-line
// Cache the settings of all open documents
const documentSettings = new Map();
connection.onDidChangeConfiguration((_change) => {
connection.console.info('Configuration changed.');
if (hasConfigurationCapability) {
// Reset all cached document settings
documentSettings.clear();
}
else {
// globalSettings = <LSSettings>(change.settings.prisma || defaultSettings) // eslint-disable-line @typescript-eslint/no-unsafe-member-access
}
// Revalidate all open prisma schemas
documents.all().forEach(validateTextDocument); // eslint-disable-line @typescript-eslint/no-misused-promises
});
// Only keep settings for open documents
documents.onDidClose((e) => {
documentSettings.delete(e.document.uri);
});
function getDocumentSettings(resource) {
if (!hasConfigurationCapability) {
connection.console.info(`hasConfigurationCapability === false. Defaults will be used.`);
return Promise.resolve({});
}
let result = documentSettings.get(resource);
if (!result) {
result = connection.workspace.getConfiguration({
scopeUri: resource,
section: 'prisma',
});
documentSettings.set(resource, result);
}
return result;
}
// Note: VS Code strips newline characters from the message
function showErrorToast(errorMessage) {
connection.window.showErrorMessage(errorMessage);
}
async function validateTextDocument(textDocument) {
const settings = await getDocumentSettings(textDocument.uri);
if (settings.enableDiagnostics === false) {
await connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] });
return;
}
const schema = await Schema_1.PrismaSchema.load({ currentDocument: textDocument, allDocuments: documents.all() });
const diagnostics = MessageHandler.handleDiagnosticsRequest(schema, showErrorToast);
for (const [uri, fileDiagnostics] of diagnostics.entries()) {
await connection.sendDiagnostics({ uri, diagnostics: fileDiagnostics });
}
}
documents.onDidChangeContent(async (change) => {
await validateTextDocument(change.document);
});
function getDocument(uri) {
return documents.get(uri);
}
connection.onDefinition(async (params) => {
const doc = getDocument(params.textDocument.uri);
if (doc) {
const schema = await Schema_1.PrismaSchema.load({ currentDocument: doc, allDocuments: documents.all() });
return MessageHandler.handleDefinitionRequest(schema, doc, params);
}
});
connection.onCompletion(async (params) => {
const doc = getDocument(params.textDocument.uri);
if (doc) {
const schema = await Schema_1.PrismaSchema.load({ currentDocument: doc, allDocuments: documents.all() });
return MessageHandler.handleCompletionRequest(schema, doc, params, showErrorToast);
}
});
connection.onReferences(async (params) => {
const doc = getDocument(params.textDocument.uri);
if (doc) {
const schema = await Schema_1.PrismaSchema.load({ currentDocument: doc, allDocuments: documents.all() });
return MessageHandler.handleReferencesRequest(schema, params, showErrorToast);
}
});
// This handler resolves additional information for the item selected in the completion list.
connection.onCompletionResolve((completionItem) => {
return MessageHandler.handleCompletionResolveRequest(completionItem);
});
// Unused now
// TODO remove or experiment new file watcher
connection.onDidChangeWatchedFiles(() => {
// Monitored files have changed in VS Code
connection.console.log(`Types have changed. Sending request to restart TS Language Server.`);
// Restart TS Language Server
void connection.sendNotification('prisma/didChangeWatchedFiles', {});
});
connection.onHover(async (params) => {
const doc = getDocument(params.textDocument.uri);
if (doc) {
const schema = await Schema_1.PrismaSchema.load({ currentDocument: doc, allDocuments: documents.all() });
return MessageHandler.handleHoverRequest(schema, doc, params, showErrorToast);
}
});
connection.onDocumentFormatting(async (params) => {
const doc = getDocument(params.textDocument.uri);
if (doc) {
const schema = await Schema_1.PrismaSchema.load({ currentDocument: doc, allDocuments: documents.all() });
return MessageHandler.handleDocumentFormatting(schema, doc, params, showErrorToast);
}
});
connection.onCodeAction(async (params) => {
const doc = getDocument(params.textDocument.uri);
if (doc) {
const schema = await Schema_1.PrismaSchema.load({ currentDocument: doc, allDocuments: documents.all() });
return MessageHandler.handleCodeActions(schema, doc, params, showErrorToast);
}
});
connection.onRenameRequest(async (params) => {
const doc = getDocument(params.textDocument.uri);
if (doc) {
const schema = await Schema_1.PrismaSchema.load({ currentDocument: doc, allDocuments: documents.all() });
return MessageHandler.handleRenameRequest(schema, doc, params);
}
});
connection.onDocumentSymbol((params) => {
const doc = getDocument(params.textDocument.uri);
if (doc) {
return MessageHandler.handleDocumentSymbol(params, doc);
}
});
// Make the text document manager listen on the connection
// for open, change and close text document events
documents.listen(connection);
connection.listen();
}
//# sourceMappingURL=server.js.map