我尝试将新属性添加到我的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 {
// ...
}
}
我想在name
属性行之后添加一个新属性color_code: string;
。看起来像这样:
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 {
// ...
}
}
在我的原理图规则函数中,我尝试过这个,但我被卡住了:
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;
}
}
这里是updateModelFields()
函数:
export function updateModelFields(file: string, nodes: ts.Node[], options: Schema) {
// find field definitions
let propertyNodes: ts.Node[] = nodes.filter(n => n.kind === ts.SyntaxKind.PropertyDeclaration) || [];
// create new property declaration
const propertyDeclaration = ts.factory.createPropertyDeclaration(
undefined,
undefined,
'color_code',
undefined,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
undefined
);
// add propertyDeclaration to nodes
// ??
}
我尝试了几种方法来添加新的属性声明,但总是失败。
当我尝试添加splice()
功能时,它说:
Error: Debug Failure. False expression: Node must have a real position for this operation
有什么想法或最佳实践吗?
通常,如果使用转换API,则这将与ts.transform
函数一起使用,然后使用factory.updateClassDeclaration
将属性添加到类中。一旦获得了最终转换的AST,就可以使用打印机(ts.createPrinter
(将其打印为字符串。
也就是说,转换API并不是为这个目的而设计的——它的目的是将TS代码转换为JS-and,因此它不适合修改现有的TypeScript文件。例如,如果您转换AST然后将其打印出来,您将丢失格式信息,并且它可能会践踏现有的注释。
出于这个原因,我建议使用文本更改API(请参见SourceFile#update
(——这是用于快速修复的方法——或者更简单地说,直接将属性文本插入字符串中的正确位置。您可以根据周围节点的位置来确定插入位置。例如:
const classDec = sourceFile.statements.find(ts.isClassDeclaration)!;
const nameProp = classDec.members
.find(c => ts.isPropertyDeclaration(c) && c.name.getText(sourceFile) === "name")!;
// Assumes that the name property node does not have any trailing comments...
// You can use ts.getTrailingCommentRanges to figure that out and use
// the last comment end position instead of `nameProp.end`
sourceText = sourceText.substring(0, nameProp.end)
+ "n color_code: string;"
+ sourceText.substring(nameProp.end);
或者,你可能只想使用ts变形来处理这个问题,因为使用它可以很容易地将属性插入到类中