问题描述
我尝试将新属性添加到我的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 {
// ...
}
}
我想在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 {
// ...
}
}
在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;
}
}
这是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',ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),undefined
);
// add propertyDeclaration to nodes
// ??
}
Error: Debug Failure. False expression: Node must have a real position for this operation
有什么想法或最佳做法吗?
解决方法
通常,如果使用转换API,它将与food
函数一起使用,然后使用ts.transform
将属性添加到类中。最终转换后的AST之后,您可以使用打印机(factory.updateClassDeclaration
)将其打印为字符串。
也就是说,转换API不是为此目的而设计的,它是将TS代码转换为JS的,因此在修改现有的TypeScript文件方面不是很好。例如,如果您转换AST然后将其打印出来,则会丢失格式信息,并且可能会破坏现有注释。
由于这个原因,我建议改用文本更改API(请参阅ts.createPrinter
)(这是用于快速修复的方法),或更简单地说,只需将属性文本插入字符串中的正确位置即可直。您可以根据周围的节点位置确定要插入的位置。例如:
SourceFile#update
或者,您可能只想使用ts-morph为您处理此问题,因为quite easy会使用它向类中插入属性。