UNPKG

@icare-jp/vue-type-check

Version:

a type checker for typescript written Vue components

165 lines (164 loc) 8.26 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.check = void 0; const path = __importStar(require("path")); const vscode_languageserver_1 = require("vscode-languageserver"); const interpolationMode_1 = require("vue-language-server/dist/modes/template/interpolationMode"); const javascript_1 = require("vue-language-server/dist/modes/script/javascript"); const serviceHost_1 = require("vue-language-server/dist/services/typescriptService/serviceHost"); const languageModelCache_1 = require("vue-language-server/dist/embeddedSupport/languageModelCache"); const embeddedSupport_1 = require("vue-language-server/dist/embeddedSupport/embeddedSupport"); const typescript_1 = __importDefault(require("typescript")); const progress_1 = __importDefault(require("progress")); const print_1 = require("./print"); const file_util_1 = require("./file-util"); const dep_graph_1 = require("./dep-graph"); let validLanguages = ["vue"]; function check(options) { return __awaiter(this, void 0, void 0, function* () { const { workspace, onlyTemplate = false, onlyTypeScript = false, targets = [], excludeDir, configPath, } = options; if (onlyTypeScript) { validLanguages = ["ts", "tsx", "vue"]; } const srcDir = options.srcDir || options.workspace; const excludeDirs = typeof excludeDir === "string" ? [excludeDir] : excludeDir; const docs = yield traverse(srcDir, onlyTypeScript, targets, excludeDirs, configPath); yield getDiagnostics({ docs, workspace, onlyTemplate }); }); } exports.check = check; function traverse(root, onlyTypeScript, targets, excludeDirs, configPath) { return __awaiter(this, void 0, void 0, function* () { let targetFiles = targets.length > 0 ? file_util_1.globSync(dep_graph_1.collectDependencies(targets, configPath) .map((t) => path.resolve(process.cwd(), t)) .filter((t) => validLanguages.map((e) => `.${e}`).includes(path.extname(t)))) : file_util_1.globSync(path.join(root, onlyTypeScript ? `**/*.{${validLanguages.join(",")}}` : "**/*.vue")); if (excludeDirs) { const filterTargets = excludeDirs.map((dir) => path.resolve(dir)).join("|"); targetFiles = targetFiles.filter((targetFile) => !new RegExp(`^(?:${filterTargets}).*$`).test(targetFile)); } let files = yield Promise.all(targetFiles.map((absFilePath) => __awaiter(this, void 0, void 0, function* () { const src = yield file_util_1.readFile(absFilePath); return { absFilePath, fileExt: file_util_1.extractTargetFileExtension(absFilePath), src, }; }))); if (onlyTypeScript) { files = files.filter(({ src, fileExt }) => { if (fileExt !== "vue" || !hasScriptTag(src)) { return true; } return isTs(src) || isImportOtherTs(src); }); } const docs = files.map(({ absFilePath, src, fileExt }) => vscode_languageserver_1.TextDocument.create(`file://${absFilePath}`, fileExt, 0, src)); return docs; }); } function getDiagnostics({ docs, workspace, onlyTemplate }) { return __awaiter(this, void 0, void 0, function* () { const documentRegions = languageModelCache_1.getLanguageModelCache(10, 60, (document) => embeddedSupport_1.getVueDocumentRegions(document)); const scriptRegionDocuments = languageModelCache_1.getLanguageModelCache(10, 60, (document) => { const vueDocument = documentRegions.refreshAndGet(document); return vueDocument.getSingleTypeDocument("script"); }); let hasError = false; try { const serviceHost = serviceHost_1.getServiceHost(typescript_1.default, workspace, scriptRegionDocuments); const vueMode = new interpolationMode_1.VueInterpolationMode(typescript_1.default, serviceHost); const scriptMode = yield javascript_1.getJavascriptMode(serviceHost, scriptRegionDocuments, workspace); const bar = new progress_1.default("checking [:bar] :current/:total", { total: docs.length, width: 20, clear: true, }); for (const doc of docs) { const vueTplResults = vueMode.doValidation(doc); let scriptResults = []; if (!onlyTemplate && scriptMode.doValidation) { scriptResults = scriptMode.doValidation(doc); } const results = vueTplResults.concat(scriptResults); if (results.length) { hasError = true; for (const result of results) { const total = doc.lineCount; const lines = print_1.getLines({ start: result.range.start.line, end: result.range.end.line, total, }); print_1.printError(`Error in ${doc.uri}`); print_1.printMessage(`${result.range.start.line}:${result.range.start.character} ${result.message}`); for (const line of lines) { const code = doc .getText({ start: { line, character: 0 }, end: { line, character: Infinity }, }) .replace(/\n$/, ""); const isError = line === result.range.start.line; print_1.printLog(print_1.formatLine({ number: line, code, isError })); if (isError) { print_1.printLog(print_1.formatCursor(result.range)); } } } } bar.tick(); } } catch (error) { hasError = true; console.error(error); } finally { documentRegions.dispose(); scriptRegionDocuments.dispose(); process.exit(hasError ? 1 : 0); } }); } function hasScriptTag(src) { return /.*\<script.*\>/.test(src); } function isTs(src) { return /.*\<script.*lang="tsx?".*\>/.test(src); } function isImportOtherTs(src) { return /.*\<script.*src=".*".*\>/.test(src); }