UNPKG

plaxtony

Version:

Static code analysis of SC2 Galaxy Script

226 lines 8.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Store = exports.S2WorkspaceWatcher = exports.WorkspaceWatcher = exports.IndexedDocument = exports.openSourceFilesInLocation = exports.createTextDocumentFromUri = exports.readDocumentFile = exports.createTextDocumentFromFs = exports.createTextDocument = void 0; const parser_1 = require("../compiler/parser"); const s2meta_1 = require("./s2meta"); const binder_1 = require("../compiler/binder"); const archive_1 = require("../sc2mod/archive"); const lsp = require("vscode-languageserver"); const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument"); const path = require("path"); const fs = require("fs-extra"); const glob = require("fast-glob"); const vscode_uri_1 = require("vscode-uri"); const checker_1 = require("../compiler/checker"); function createTextDocument(uri, text) { return vscode_languageserver_textdocument_1.TextDocument.create(uri, 'galaxy', 0, text); } exports.createTextDocument = createTextDocument; function createTextDocumentFromFs(filepath) { filepath = path.resolve(filepath); return createTextDocument(vscode_uri_1.default.file(filepath).toString(), fs.readFileSync(filepath, 'utf8')); } exports.createTextDocumentFromFs = createTextDocumentFromFs; async function readDocumentFile(fsPath) { return createTextDocument(vscode_uri_1.default.file(fsPath).toString(), await fs.readFile(fsPath, 'utf8')); } exports.readDocumentFile = readDocumentFile; function createTextDocumentFromUri(uri) { return createTextDocument(uri, fs.readFileSync(vscode_uri_1.default.parse(uri).fsPath, 'utf8')); } exports.createTextDocumentFromUri = createTextDocumentFromUri; async function* openSourceFilesInLocation(...srcFolders) { const workspaceFolders = await Promise.all(srcFolders.map(async (folder) => { return { folder, galaxyFiles: await glob('**/*.galaxy', { cwd: folder, absolute: true, caseSensitiveMatch: false, onlyFiles: true, objectMode: false, }) }; })); for (const wsFolder of workspaceFolders) { for (const wsFile of wsFolder.galaxyFiles) { yield await readDocumentFile(wsFile); } } } exports.openSourceFilesInLocation = openSourceFilesInLocation; class IndexedDocument { } exports.IndexedDocument = IndexedDocument; class WorkspaceWatcher { constructor(...folders) { this._onDidOpen = new lsp.Emitter(); this.folders = folders; } get onDidOpen() { return this._onDidOpen.event; } } exports.WorkspaceWatcher = WorkspaceWatcher; class S2WorkspaceWatcher extends WorkspaceWatcher { constructor(workspacePath, modSources) { super(workspacePath); this.modSources = []; this.modSources = modSources; this._onDidOpenS2Workspace = new lsp.Emitter(); } get onDidOpenS2Archive() { return this._onDidOpenS2Workspace.event; } async watch() { const rootArchive = new archive_1.SC2Archive(path.basename(this.folders[0]), this.folders[0]); const workspace = await archive_1.openArchiveWorkspace(rootArchive, this.modSources); for (const modArchive of workspace.dependencies) { for (const extSrc of await modArchive.findFiles('**/*.galaxy')) { this._onDidOpen.fire({ document: createTextDocumentFromFs(path.join(modArchive.directory, extSrc)) }); } } for (const extSrc of await rootArchive.findFiles('**/*.galaxy')) { this._onDidOpen.fire({ document: createTextDocumentFromFs(path.join(rootArchive.directory, extSrc)) }); } this._onDidOpenS2Workspace.fire({ src: this.folders[0], workspace: workspace, }); } } exports.S2WorkspaceWatcher = S2WorkspaceWatcher; class Store { constructor(opts = {}) { this.documents = new Map(); this.qualifiedDocuments = new Map(); this.openDocuments = new Set(); this.parser = opts.parser ? opts.parser : new parser_1.Parser(); } clear() { for (const key of this.documents.keys()) { if (this.openDocuments.has(key)) continue; this.removeDocument(key); } this.s2workspace = void 0; this.s2metadata = void 0; } removeQualifiedDocument(qsFile) { const qDocMap = this.qualifiedDocuments.get(qsFile.s2meta.docName.toLowerCase()); if (qDocMap) { qDocMap.delete(qsFile.fileName); if (!qDocMap.size) { this.qualifiedDocuments.delete(qsFile.s2meta.docName.toLowerCase()); } } } requalifyFile(qsFile) { if (qsFile.s2meta) { this.removeQualifiedDocument(qsFile); } const fsPath = vscode_uri_1.default.parse(qsFile.fileName).fsPath; let s2file; if (this.s2workspace) { s2file = this.s2workspace.resolvePath(fsPath); } else if (this.rootPath) { const commonBase = fsPath.toLowerCase().startsWith(this.rootPath.toLowerCase() + path.sep); if (commonBase) { const relativePath = fsPath.substring(this.rootPath.length + 1).toLowerCase(); s2file = { fsPath: fsPath, relativePath: relativePath, archiveRelpath: relativePath, priority: 0, }; } } if (s2file) { qsFile.s2meta = { file: s2file, docName: s2file.relativePath.replace(/\.galaxy$/, ''), }; let qDocMap = this.qualifiedDocuments.get(qsFile.s2meta.docName.toLowerCase()); if (!qDocMap) { qDocMap = new Map(); this.qualifiedDocuments.set(qsFile.s2meta.docName.toLowerCase(), qDocMap); } if (qDocMap.size > 1) { const tmpDocs = Array.from(qDocMap).sort((a, b) => a[1].s2meta.file.priority - b[1].s2meta.file.priority); qDocMap.clear(); for (const [k, v] of tmpDocs) { qDocMap.set(k, v); } } qDocMap.set(qsFile.fileName, qsFile); } else { qsFile.s2meta = void 0; } } removeDocument(documentUri) { const currSorceFile = this.documents.get(documentUri); if (!currSorceFile) return; binder_1.unbindSourceFile(currSorceFile, this); if (currSorceFile.s2meta) { this.removeQualifiedDocument(currSorceFile); } this.documents.delete(documentUri); } updateDocument(document, check = false) { if (this.documents.has(document.uri)) { const currSorceFile = this.documents.get(document.uri); if (document.getText().length === currSorceFile.text.length && document.getText().valueOf() === currSorceFile.text.valueOf()) { return; } this.removeDocument(document.uri); } const sourceFile = this.parser.parseFile(document.uri, document.getText()); this.documents.set(document.uri, sourceFile); this.requalifyFile(sourceFile); if (check) { const checker = new checker_1.TypeChecker(this); sourceFile.additionalSyntacticDiagnostics = checker.checkSourceFile(sourceFile, true); } else { binder_1.bindSourceFile(sourceFile, this); } } async updateS2Workspace(workspace) { this.s2workspace = workspace; this.qualifiedDocuments.clear(); for (const qsFile of this.documents.values()) { this.requalifyFile(qsFile); } } async rebuildS2Metadata(metadataCfg = { loadLevel: 'Default', localization: 'enUS', }, dataCatalogConfig = { enabled: true, }) { this.s2metadata = new s2meta_1.S2WorkspaceMetadata(this.s2workspace, metadataCfg, dataCatalogConfig); await this.s2metadata.build(); } isUriInWorkspace(documentUri) { const qsFile = this.documents.get(documentUri); if (qsFile && qsFile.s2meta) return true; const fsPath = vscode_uri_1.default.parse(documentUri).fsPath; const s2file = this.s2workspace.resolvePath(fsPath); if (s2file) return true; return false; } resolveGlobalSymbol(name) { for (const doc of this.documents.values()) { if (doc.symbol.members.has(name)) { return doc.symbol.members.get(name); } } } } exports.Store = Store; //# sourceMappingURL=store.js.map