Üldine juhend TypeScript'i kompilaatori API kohta, mis hõlmab abstraktseid süntaksipuid (AST), koodianalüüsi, transformatsiooni ja genereerimist rahvusvahelistele arendajatele.
TypeScript'i kompilaatori API: AST manipuleerimise ja koodi transformatsiooni valdamine
TypeScript'i kompilaatori API pakub võimsat liidest TypeScripti ja JavaScripti koodi analüüsimiseks, manipuleerimiseks ja genereerimiseks. Selle keskmes on abstraktne süntaksipuu (AST), mis on teie lähtekoodi struktureeritud esitus. AST-ga töötamise mõistmine avab võimalused täiustatud tööriistade loomiseks, nagu lintersid, koodiformaatorid, staatilised analüsaatorid ja kohandatud koodigeneraatorid.
Mis on TypeScript'i kompilaatori API?
TypeScript'i kompilaatori API on TypeScripti liideste ja funktsioonide kogum, mis paljastab TypeScript'i kompilaatori sisemised toimingud. See võimaldab arendajatel programmiliselt suhelda kompileerimisprotsessiga, minnes kaugemale koodi lihtsast kompileerimisest. Saate seda kasutada selleks, et:
- Analüüsida koodi: Kontrollida koodi struktuuri, tuvastada võimalikke probleeme ja ekstraktida semantilist teavet.
- Transformeerida koodi: Muuta olemasolevat koodi, lisada uusi funktsioone või refaktoreerida koodi automaatselt.
- Genereerida koodi: Luua uus kood nullist lähtudes mallide või muu sisendi põhjal.
See API on oluline keerukate arendustööriistade loomiseks, mis parandavad koodi kvaliteeti, automatiseerivad korduvaid ülesandeid ja suurendavad arendajate produktiivsust.
Abstraktse süntaksipuu (AST) mõistmine
AST on teie koodi struktuuri puutaoline esitus. Iga puu sõlm tähistab süntaktilist konstruktsiooni, näiteks muutuja deklaratsiooni, funktsiooni kutset või juhtimisvoo lauset. TypeScript'i kompilaatori API pakub tööriistu AST-i läbimiseks, selle sõlmede kontrollimiseks ja nende muutmiseks.
Võtame näiteks selle lihtsa TypeScripti koodi:
function greet(name: string): string {
return `Tere, ${name}!`;
}
console.log(greet("Maailm"));
Selle koodi AST esitaks funktsioonideklaratsiooni, tagastuslauset, mallliteraali, console.logi väljakutse ja muid koodi elemente. AST-i visualiseerimine võib olla keeruline, kuid sellised tööriistad nagu AST explorer (astexplorer.net) võivad aidata. Need tööriistad võimaldavad teil sisestada koodi ja näha selle vastavat AST-i kasutajasõbralikul kujul. AST Exploreri kasutamine aitab teil mõista, millist koodistruktuuri te manipuleerite.
Peamised AST-sõlmede tüübid
TypeScript'i kompilaatori API määratleb erinevad AST-sõlmede tüübid, millest igaüks esindab erinevat süntaktilist konstruktsiooni. Siin on mõned levinumad sõlmede tüübid:
- SourceFile: Esindab tervet TypeScripti faili.
- FunctionDeclaration: Esindab funktsiooni definitsiooni.
- VariableDeclaration: Esindab muutuja deklaratsiooni.
- Identifier: Esindab identifikaatorit (nt muutuja nimi, funktsiooni nimi).
- StringLiteral: Esindab stringiliteraali.
- CallExpression: Esindab funktsiooni kutset.
- ReturnStatement: Esindab tagastuslauset.
Igal sõlmetüübil on omadused, mis annavad teavet vastava koodielemendi kohta. Näiteks võib `FunctionDeclaration`-sõlmel olla omadused selle nime, parameetrite, tagastustüübi ja keha kohta.
Kompilaatori API-ga alustamine
Kompilaatori API kasutamise alustamiseks peate installima TypeScripti ja teil peab olema TypeScripti süntaksi põhiteadmised. Siin on lihtne näide, mis näitab, kuidas TypeScripti faili lugeda ja selle AST-i printida:
import * as ts from "typescript";
import * as fs from "fs";
const fileName = "example.ts";
const sourceCode = fs.readFileSync(fileName, "utf8");
const sourceFile = ts.createSourceFile(
fileName,
sourceCode,
ts.ScriptTarget.ES2015, // Target ECMAScript version
true // SetParentNodes: true to retain parent references in the AST
);
function printAST(node: ts.Node, indent = 0) {
const indentStr = " ".repeat(indent);
console.log(`${indentStr}${ts.SyntaxKind[node.kind]}`);
node.forEachChild(child => printAST(child, indent + 1));
}
printAST(sourceFile);
Selgitus:
- Impordi moodulid: Impordib mooduli `typescript` ja mooduli `fs` failisüsteemi toimingute jaoks.
- Loe lähtefail: Loeb TypeScripti faili nimega `example.ts` sisu. Selle toimimiseks peate looma faili `example.ts`.
- Loo SourceFile: Loob objekti `SourceFile`, mis esindab AST-i juurt. Funktsioon `ts.createSourceFile` parsib lähtekoodi ja genereerib AST-i.
- Prindi AST: Määratleb rekursiivse funktsiooni `printAST`, mis läbib AST-i ja prindib iga sõlme liigi.
- Kutsu printAST: Kutsub `printAST`-i, et alustada AST-i printimist juursõlmest `SourceFile`.
Selle koodi käivitamiseks salvestage see failina `.ts` (nt `ast-example.ts`), looge fail `example.ts` mõne TypeScripti koodiga ning seejärel kompileerige ja käivitage kood:
tsc ast-example.ts
node ast-example.js
See prindib teie `example.ts` faili AST-i konsooli. Väljund näitab sõlmede hierarhiat ja nende tüüpe. Näiteks võib see näidata `FunctionDeclaration`, `Identifier`, `Block` ja muid sõlmede tüüpe.
AST-i läbimine
Kompilaatori API pakub mitmeid viise AST-i läbimiseks. Lihtsaim on meetodi `forEachChild` kasutamine, nagu on näidatud eelmises näites. See meetod külastab iga antud sõlme alamsõlme.
Keerulisemate läbimise stsenaariumide korral saate kasutada mustrit `Visitor`. Külastaja on objekt, mis määratleb meetodid, mida tuleb kutsuda konkreetsete sõlmede tüüpide jaoks. See võimaldab teil kohandada läbimise protsessi ja sooritada toiminguid sõlme tüübi põhjal.
import * as ts from "typescript";
import * as fs from "fs";
const fileName = "example.ts";
const sourceCode = fs.readFileSync(fileName, "utf8");
const sourceFile = ts.createSourceFile(
fileName,
sourceCode,
ts.ScriptTarget.ES2015,
true
);
class IdentifierVisitor {
visit(node: ts.Node) {
if (ts.isIdentifier(node)) {
console.log(`Leitud identifikaator: ${node.text}`);
}
ts.forEachChild(node, n => this.visit(n));
}
}
const visitor = new IdentifierVisitor();
visitor.visit(sourceFile);
Selgitus:
- IdentifierVisitor klass: Määratleb klassi `IdentifierVisitor` meetodiga `visit`.
- Visit meetod: Meetod `visit` kontrollib, kas praegune sõlm on `Identifier`. Kui see on nii, siis prindib see identifikaatori teksti. Seejärel kutsub see rekursiivselt `ts.forEachChild`, et külastada alamsõlmi.
- Loo külastaja: Loob eksemplari `IdentifierVisitor`.
- Alusta läbimist: Kutsub meetodi `visit` `SourceFile`-il, et alustada läbimist.
See näide näitab, kuidas leida AST-is kõik identifikaatorid. Saate seda mustrit kohandada, et leida teisi sõlmede tüüpe ja sooritada erinevaid toiminguid.
AST-i transformeerimine
Kompilaatori API tõeline jõud seisneb selle võimes AST-i transformeerida. Saate AST-i muuta, et muuta oma koodi struktuuri ja käitumist. See on koodi refaktoreerimise tööriistade, koodigeneraatorite ja muude täiustatud tööriistade alus.
AST-i transformeerimiseks peate kasutama funktsiooni `ts.transform`. See funktsioon võtab vastu `SourceFile`-i ja loendi funktsioonidest `TransformerFactory`. `TransformerFactory` on funktsioon, mis võtab vastu `TransformationContext`-i ja tagastab funktsiooni `Transformer`. Funktsioon `Transformer` vastutab sõlmede läbimise ja AST-is transformeerimise eest.
Siin on lihtne näide, mis näitab, kuidas TypeScripti faili algusesse kommentaar lisada:
import * as ts from "typescript";
import * as fs from "fs";
const fileName = "example.ts";
const sourceCode = fs.readFileSync(fileName, "utf8");
const sourceFile = ts.createSourceFile(
fileName,
sourceCode,
ts.ScriptTarget.ES2015,
true
);
const transformerFactory: ts.TransformerFactory = context => {
return transformer => {
return node => {
if (ts.isSourceFile(node)) {
// Loo juhtiv kommentaar
const comment = ts.addSyntheticLeadingComment(
node,
ts.SyntaxKind.MultiLineCommentTrivia,
" See fail muudeti automaatselt ",
true // hasTrailingNewLine
);
return node;
}
return node;
};
};
};
const { transformed } = ts.transform(sourceFile, [transformerFactory]);
const printer = ts.createPrinter({
newLine: ts.NewLineKind.LineFeed
});
const result = printer.printFile(transformed[0]);
fs.writeFileSync("example.transformed.ts", result);
Selgitus:
- TransformerFactory: Määratleb funktsiooni `TransformerFactory`, mis tagastab funktsiooni `Transformer`.
- Transformer: Funktsioon `Transformer` kontrollib, kas praegune sõlm on `SourceFile`. Kui see on nii, lisab see sõlmele juhtiva kommentaari, kasutades `ts.addSyntheticLeadingComment`.
- ts.transform: Kutsub `ts.transform`, et rakendada transformatsioon `SourceFile`-ile.
- Printer: Loob objekti `Printer`, et genereerida koodi transformeeritud AST-st.
- Prindi ja kirjuta: Prindib transformeeritud koodi ja kirjutab selle uude faili nimega `example.transformed.ts`.
See näide demonstreerib lihtsat transformatsiooni, kuid saate sama mustrit kasutada keerukamate transformatsioonide sooritamiseks, nagu koodi refaktoreerimine, logimislausete lisamine või dokumentatsiooni genereerimine.
Täpsemad transformatsioonitehnikad
Siin on mõned täpsemad transformatsioonitehnikad, mida saate kompilaatori API-ga kasutada:
- Uute sõlmede loomine: Kasutage funktsioone `ts.createXXX` uute AST-sõlmede loomiseks. Näiteks `ts.createVariableDeclaration` loob uue muutuja deklaratsiooni sõlme.
- Sõlmede asendamine: Asendage olemasolevad sõlmed uute sõlmedega funktsiooni `ts.visitEachChild` abil.
- Sõlmede lisamine: Lisage uusi sõlmi AST-ile funktsioonide `ts.updateXXX` abil. Näiteks `ts.updateBlock` uuendab plokklauset uute lausetega.
- Sõlmede eemaldamine: Eemaldage sõlmed AST-ist, tagastades transformeerimisfunktsioonist `undefined`.
Koodi genereerimine
Pärast AST-i transformeerimist peate sellest koodi genereerima. Kompilaatori API pakub selleks objekti `Printer`. `Printer` võtab vastu AST-i ja genereerib koodi stringiesituse.
Funktsioon `ts.createPrinter` loob objekti `Printer`. Saate printerit konfigureerida erinevate valikutega, näiteks kasutatava uue rea sümboliga ja sellega, kas kommentaare väljastada.
Meetod `printer.printFile` võtab vastu `SourceFile`-i ja tagastab koodi stringiesituse. Seejärel saate selle stringi faili kirjutada.
Kompilaatori API praktilised rakendused
TypeScript'i kompilaatori API-l on tarkvaraarenduses palju praktilisi rakendusi. Siin on mõned näited:
- Lintersid: Looge kohandatud lintersid, et jõustada kodeerimisstandardeid ja tuvastada potentsiaalseid probleeme oma koodis.
- Koodiformaatorid: Looge koodiformaatorid, et oma koodi automaatselt vormindada vastavalt konkreetsele stiilijuhisele.
- Staatilised analüsaatorid: Arendage staatilisi analüsaatoreid, et tuvastada vigu, turvanõrkusi ja jõudluse kitsaskohti oma koodis.
- Koodigeneraatorid: Genereerige koodi mallidest või muust sisendist, automatiseerides korduvaid ülesandeid ja vähendades boilerplaadi koodi. Näiteks genereerides API kliente või andmebaasi skeeme kirjeldusfailist.
- Refaktoreerimistööriistad: Looge refaktoreerimistööriistad, et automaatselt muuta muutujate nimesid, ekstraktida funktsioone või teisaldada koodi failide vahel.
- Rahvusvahelistamise (i18n) automatiseerimine: Ekstraktige automaatselt tõlgitavad stringid oma TypeScripti koodist ja genereerige lokaliseerimisfailid erinevate keelte jaoks. Näiteks võib tööriist skaneerida koodi stringide suhtes, mis on edastatud funktsioonile `translate()` ja lisada need automaatselt tõlkevarafaili.
Näide: lihtsa linteri loomine
Loome lihtsa linteri, mis kontrollib kasutamata muutujaid TypeScripti koodis. See linter tuvastab muutujad, mis on deklareeritud, kuid mida ei kasutata kunagi.
import * as ts from "typescript";
import * as fs from "fs";
const fileName = "example.ts";
const sourceCode = fs.readFileSync(fileName, "utf8");
const sourceFile = ts.createSourceFile(
fileName,
sourceCode,
ts.ScriptTarget.ES2015,
true
);
function findUnusedVariables(sourceFile: ts.SourceFile) {
const usedVariables = new Set();
function visit(node: ts.Node) {
if (ts.isIdentifier(node)) {
usedVariables.add(node.text);
}
ts.forEachChild(node, visit);
}
visit(sourceFile);
const unusedVariables: string[] = [];
function checkVariableDeclaration(node: ts.Node) {
if (ts.isVariableDeclaration(node) && node.name && ts.isIdentifier(node.name)) {
const variableName = node.name.text;
if (!usedVariables.has(variableName)) {
unusedVariables.push(variableName);
}
}
ts.forEachChild(node, checkVariableDeclaration);
}
checkVariableDeclaration(sourceFile);
return unusedVariables;
}
const unusedVariables = findUnusedVariables(sourceFile);
if (unusedVariables.length > 0) {
console.log("Kasutamata muutujad:");
unusedVariables.forEach(variable => console.log(`- ${variable}`));
} else {
console.log("Kasutamata muutujaid ei leitud.");
}
Selgitus:
- findUnusedVariables funktsioon: Määratleb funktsiooni `findUnusedVariables`, mis võtab sisendina `SourceFile`.
- usedVariables set: Loob `Set`-i, et salvestada kasutatud muutujate nimed.
- visit funktsioon: Määratleb rekursiivse funktsiooni `visit`, mis läbib AST-i ja lisab kõigi identifikaatorite nimed `usedVariables` set-i.
- checkVariableDeclaration funktsioon: Määratleb rekursiivse funktsiooni `checkVariableDeclaration`, mis kontrollib, kas muutuja deklaratsioon on kasutamata. Kui see on nii, lisab see muutuja nime `unusedVariables` massiivi.
- Tagasta unusedVariables: Tagastab massiivi, mis sisaldab kasutamata muutujate nimesid.
- Väljund: Prindib kasutamata muutujad konsooli.
See näide demonstreerib lihtsat linterit. Saate seda laiendada, et kontrollida muid kodeerimisstandardeid ja tuvastada muid võimalikke probleeme oma koodis. Näiteks võiksite kontrollida kasutamata importide, liiga keerukate funktsioonide või potentsiaalsete turvanõrkuste olemasolu. Oluline on mõista, kuidas AST-i läbida ja tuvastada konkreetsed sõlmede tüübid, millest olete huvitatud.
Parimad tavad ja kaalutlused
- Mõistke AST-i: Investeerige aega AST-i struktuuri mõistmisse. Kasutage tööriistu, nagu AST explorer, et visualiseerida oma koodi AST-i.
- Kasutage tüübikaitseid: Kasutage tüübikaitseid (`ts.isXXX`), et tagada õigete sõlmede tüüpidega töötamine.
- Arvestage jõudlusega: AST-i transformatsioonid võivad olla arvutuslikult kallid. Optimeerige oma koodi, et minimeerida külastatavate ja transformeeritavate sõlmede arvu.
- Käsitsege vigu: Käsitsege vigu elegantselt. Kompilaatori API võib visata erandeid, kui proovite AST-il sooritada kehtetuid toiminguid.
- Testige põhjalikult: Testige oma transformatsioone põhjalikult, et veenduda, et need annavad soovitud tulemused ega too sisse uusi vigu.
- Kasutage olemasolevaid teeke: Kaaluge olemasolevate teekide kasutamist, mis pakuvad kõrgema taseme abstraktsioone kompilaatori API kohal. Need teegid võivad lihtsustada levinud ülesandeid ja vähendada kirjutatava koodi hulka. Näited hõlmavad `ts-morph` ja `typescript-eslint`.
Järeldus
TypeScript'i kompilaatori API on võimas tööriist täiustatud arendustööriistade loomiseks. Mõistes, kuidas AST-ga töötada, saate luua lintersid, koodiformaatoreid, staatilisi analüsaatoreid ja muid tööriistu, mis parandavad koodi kvaliteeti, automatiseerivad korduvaid ülesandeid ja suurendavad arendajate produktiivsust. Kuigi API võib olla keeruline, on selle valdamise eelised märkimisväärsed. See põhjalik juhend annab aluse kompilaatori API tõhusaks uurimiseks ja kasutamiseks oma projektides. Pidage meeles, et kasutage selliseid tööriistu nagu AST Explorer, käsitsege hoolikalt sõlmede tüüpe ja testige oma transformatsioone põhjalikult. Harjutamise ja pühendumusega saate avada TypeScript'i kompilaatori API kogu potentsiaali ja luua uuenduslikke lahendusi tarkvaraarenduse maastikule.
Edasine uurimine:
- TypeScript'i kompilaatori API dokumentatsioon: [https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API)
- AST Explorer: [https://astexplorer.net/](https://astexplorer.net/)
- ts-morph teek: [https://ts-morph.com/](https://ts-morph.com/)
- typescript-eslint: [https://typescript-eslint.io/](https://typescript-eslint.io/)