@prisma/language-server
Version:
Prisma Language Server
152 lines • 5.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PrismaSchema = exports.SchemaDocument = void 0;
exports.loadConfig = loadConfig;
const schema_files_loader_1 = require("@prisma/schema-files-loader");
const config_1 = require("@prisma/config");
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
const vscode_uri_1 = require("vscode-uri");
const ast_1 = require("./ast");
class SchemaDocument {
constructor(textDocument) {
this.textDocument = textDocument;
this.lines = [];
for (let i = 0; i < textDocument.lineCount; i++) {
const line = (0, ast_1.getCurrentLine)(textDocument, i);
this.lines.push({
document: this,
lineIndex: i,
untrimmedText: line,
text: line.trim(),
});
}
}
get uri() {
return this.textDocument.uri;
}
get content() {
return this.textDocument.getText();
}
positionAt(offset) {
return this.textDocument.positionAt(offset);
}
getLineContent(lineIndex) {
return this.lines[lineIndex].text;
}
}
exports.SchemaDocument = SchemaDocument;
/**
* Will try to load the prisma config file from the given path, default path or create a default config.
*/
async function loadConfig(configRoot) {
const { config, error, resolvedPath } = await (0, config_1.loadConfigFromFile)({ configRoot });
if (error) {
switch (error._tag) {
case 'ConfigFileNotFound':
throw new Error(`Config file not found at "${resolvedPath}"`);
case 'ConfigFileSyntaxError':
throw new Error(`Failed to parse config file at "${resolvedPath}"`);
case 'ConfigLoadError':
throw new Error(`Failed to import config file as TypeScript from "${resolvedPath}". Error: ${error.error.message}`);
case 'UnknownError':
throw new Error(`Unknown error during config file loading: ${error.error.message}`);
default:
throw new Error(`Unhandled error '${JSON.stringify(error)}' in 'loadConfigFromFile'.`);
}
}
return config;
}
async function loadSchemaDocumentsFromPath(fsPath, allDocuments) {
// `loadRelatedSchemaFiles` locates and returns either a single schema files, or a set of related schema files.
const schemaFiles = await (0, schema_files_loader_1.loadRelatedSchemaFiles)(fsPath, createFilesResolver(allDocuments));
const documents = schemaFiles.map(([filePath, content]) => {
return new SchemaDocument(vscode_languageserver_textdocument_1.TextDocument.create(vscode_uri_1.URI.file(filePath).toString(), 'prisma', 1, content));
});
return documents;
}
class PrismaSchema {
// TODO: remove, use `PrismaSchema.load` directly
static singleFile(textDocument) {
return new PrismaSchema([new SchemaDocument(textDocument)]);
}
static async load(input, configRoot) {
let config;
try {
config = await loadConfig(configRoot);
}
catch (error) {
console.debug('Failed to load Prisma config file', error);
console.log('Continuing without Prisma config file');
}
let schemaDocs;
if (Array.isArray(input)) {
schemaDocs = input;
}
else {
const fsPath = config?.schema ?? vscode_uri_1.URI.parse(input.currentDocument.uri).fsPath;
schemaDocs = await loadSchemaDocumentsFromPath(fsPath, input.allDocuments);
}
return new PrismaSchema(schemaDocs, config);
}
constructor(documents, config) {
this.documents = documents;
this.config = config;
}
*iterLines() {
for (const doc of this.documents) {
for (const line of doc.lines) {
yield line;
}
}
}
linesAsArray() {
return Array.from(this.iterLines());
}
findDocByUri(fileUri) {
return this.documents.find((doc) => doc.uri === fileUri);
}
findWithRegex(regexp) {
for (const doc of this.documents) {
regexp.lastIndex = 0;
const match = regexp.exec(doc.content);
if (match) {
return { match, documentUri: doc.uri };
}
}
return undefined;
}
/**
*
* @returns array of (uri, content) tuples. Expected input for prisma-schema-wasm
*/
toTuples() {
return this.documents.map((doc) => [doc.uri, doc.content]);
}
toJSON() {
return this.toTuples();
}
}
exports.PrismaSchema = PrismaSchema;
function createFilesResolver(allDocuments) {
const options = {
// Technically, macos and Windows can use case-sensitive file systems
// too, however, VSCode does not support this at the moment, so there is
// no meaningful way for us to support them in extension
// See:
// - https://github.com/microsoft/vscode/issues/123660
// - https://github.com/microsoft/vscode/issues/94307
// - https://github.com/microsoft/vscode/blob/c06c555b481aaac4afd51d6fc7691d7658949651/src/vs/platform/files/node/diskFileSystemProvider.ts#L81
caseSensitive: process.platform === 'linux',
};
return new schema_files_loader_1.CompositeFilesResolver(createInMemoryResolver(allDocuments, options), schema_files_loader_1.realFsResolver, options);
}
function createInMemoryResolver(allDocuments, options) {
const resolver = new schema_files_loader_1.InMemoryFilesResolver(options);
for (const doc of allDocuments) {
const filePath = vscode_uri_1.URI.parse(doc.uri).fsPath;
const content = doc.getText();
resolver.addFile(filePath, content);
}
return resolver;
}
//# sourceMappingURL=Schema.js.map