net*_*djw 2 typescript typescript-compiler-api
我尝试向我的文件添加新属性awesome.model.ts。
原来的内容是这样的:
import { TagInterface, TagUIFieldsInterface } from './tag.interface';
export class Tag implements TagInterface {
readonly api_endpoint = '/tag';
id: ID;
name: string;
fields: FieldContainerInterface<TagUIFieldsInterface> = {
// ...
};
init(data?: any): TagInterface {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
我想在属性行color_code: string;之后添加一个新属性。name看起来像这样:
import { TagInterface, TagUIFieldsInterface } from './tag.interface';
export class Tag implements TagInterface {
readonly api_endpoint = '/tag';
id: ID;
name: string;
color_code: string;
fields: FieldContainerInterface<TagUIFieldsInterface> = {
// ...
};
init(data?: any): TagInterface {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
在我的 Schematics 规则函数中,我尝试了这个,但我被困住了:
export function model(_options: Schema, _fields?: Field[]): Rule {
return (tree: Tree, _context: SchematicContext) => {
// ...
if (tree.exists(file)) {
// read the file content and convert it to ts.Node[]
const text = tree.read(file) ?? '';
let sourceText = text.toString('utf-8');
const sourceFile = ts.createSourceFile(file, sourceText, ts.ScriptTarget.Latest, true);
const nodes = getSourceNodes(sourceFile);
updateModelFields(file, nodes, _options);
return;
}
}
Run Code Online (Sandbox Code Playgroud)
这是updateModelFields()函数:
export function model(_options: Schema, _fields?: Field[]): Rule {
return (tree: Tree, _context: SchematicContext) => {
// ...
if (tree.exists(file)) {
// read the file content and convert it to ts.Node[]
const text = tree.read(file) ?? '';
let sourceText = text.toString('utf-8');
const sourceFile = ts.createSourceFile(file, sourceText, ts.ScriptTarget.Latest, true);
const nodes = getSourceNodes(sourceFile);
updateModelFields(file, nodes, _options);
return;
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试了多种方法来添加新的属性声明,但总是失败。
当我尝试添加splice()功能时,它说:
Error: Debug Failure. False expression: Node must have a real position for this operation
Run Code Online (Sandbox Code Playgroud)
有什么想法或最佳实践吗?
一般来说,如果使用转换 API,这将与ts.transform函数一起使用,然后用于factory.updateClassDeclaration将属性添加到类中。获得最终转换后的 AST 后,您可以使用打印机 ( ts.createPrinter) 将其打印为字符串。
也就是说,转换 API 并不是为此目的而设计的\xe2\x80\x94,它的目的是将 TS 代码转换为 JS\xe2\x80\x94,因此它不适合修改现有的 TypeScript 文件。例如,如果您转换 AST 然后将其打印出来,您将丢失格式信息,并且可能会破坏现有注释。
\n因此,我建议改用文本更改 API(请参阅SourceFile#update)\xe2\x80\x94,这是用于快速修复的\xe2\x80\x94,或者更简单地将属性文本插入到字符串中的正确位置直接地。您可以根据周围的节点位置来确定插入位置。例如:
const classDec = sourceFile.statements.find(ts.isClassDeclaration)!;\nconst nameProp = classDec.members\n\xc2\xa0 \xc2\xa0 .find(c => ts.isPropertyDeclaration(c) && c.name.getText(sourceFile) === "name")!;\n\n// Assumes that the name property node does not have any trailing comments...\n// You can use ts.getTrailingCommentRanges to figure that out and use\n// the last comment end position instead of `nameProp.end`\nsourceText = sourceText.substring(0, nameProp.end)\n\xc2\xa0 \xc2\xa0 + "\\n \xc2\xa0color_code: string;"\n\xc2\xa0 \xc2\xa0 + sourceText.substring(nameProp.end);\nRun Code Online (Sandbox Code Playgroud)\n或者,您可能只想使用ts-morph来为您处理这个问题,因为使用它可以很容易地将属性插入到类中。
\n| 归档时间: |
|
| 查看次数: |
1813 次 |
| 最近记录: |