试着写了一个ts server plugin

This commit is contained in:
pqcqaq 2024-11-01 13:33:25 +08:00
parent 18800d1b43
commit 716f8b6da3
3 changed files with 93 additions and 0 deletions

View File

@ -75,6 +75,10 @@ async function main() {
'src/extension.ts',
'src/utils/analyzeWorker.ts',
// 'src/server/xmlLanguageServer.ts',
// 所有src/typescript下面的文件
...(
await fs.readdir('src/typescript')
).map((file) => `src/typescript/${file}`),
],
bundle: true,
format: 'cjs',

View File

@ -0,0 +1,23 @@
import path from 'path';
import * as vscode from 'vscode';
export const activate = (context: vscode.ExtensionContext) => {
const pluginPath = path.join(
context.extensionPath,
'utils',
'trigger-checker-plugin.js'
);
// 注册 TypeScript 语言特性提供者
// context.subscriptions.push(
// vscode.languages.registerTypeScriptServerPlugin({
// languageIds: ['typescript', 'typescriptreact'],
// pluginPath,
// enableForWorkspaceTypeScriptVersions: true,
// })
// );
console.log('Await Checker Plugin has been activated!');
};
export function deactivate() {}

View File

@ -0,0 +1,66 @@
import * as ts from 'typescript/lib/tsserverlibrary';
function isPromiseType(typeChecker: ts.TypeChecker, type: ts.Type): boolean {
if (type.isUnion()) {
return type.types.some(t => isPromiseType(typeChecker, t));
}
const symbol = type.getSymbol();
if (symbol && symbol.name === 'Promise') {
return true;
}
const baseTypes = type.getBaseTypes();
return baseTypes ? baseTypes.some(t => isPromiseType(typeChecker, t)) : false;
}
function init(modules: { typescript: typeof ts }) {
const ts = modules.typescript;
function create(info: ts.server.PluginCreateInfo) {
const proxy: ts.LanguageService = Object.create(null);
for (let k of Object.keys(info.languageService) as Array<keyof ts.LanguageService>) {
const x = info.languageService[k] as Function;
proxy[k] = (...args: any[]) => x.apply(info.languageService, args);
}
proxy.getSemanticDiagnostics = (fileName) => {
const prior = info.languageService.getSemanticDiagnostics(fileName);
const sourceFile = info.languageService.getProgram()?.getSourceFile(fileName);
if (sourceFile) {
const typeChecker = info.languageService.getProgram()?.getTypeChecker();
ts.forEachChild(sourceFile, function checkNode(node) {
if (ts.isCallExpression(node)) {
const signature = typeChecker?.getResolvedSignature(node);
const returnType = signature?.getReturnType();
if (returnType && typeChecker && isPromiseType(typeChecker, returnType)) {
if (!ts.isAwaitExpression(node.parent)) {
prior.push({
file: sourceFile,
start: node.getStart(),
length: node.getWidth(),
messageText: "This function returns a Promise and should be awaited.",
category: ts.DiagnosticCategory.Warning,
code: 9999,
});
}
}
}
ts.forEachChild(node, checkNode);
});
}
return prior;
};
return proxy;
}
return { create };
}
export = init;