Я использую API-интерфейс компилятора Typescript (ts.transform, ts.updateFunctionDeclaration) для вставки дополнительных операторов в начало функций в существующих исходных файлах. Это отлично работает, за исключением того, что когда я печатаю преобразованный код (с помощью ts.Printer), первый комментарий в исходном источнике излучается над моими введенными операторами. Как я могу этого предотвратить?
Я пробовал различные способы построения новых узлов, возвращаемых трансформатором, но ничего не меняет результат. Вот мой полный код, я выполняю его с помощью Node.
import * as ts from 'typescript';
const sourceLines = [
"// The list of properties exposed by this script to the user",
"var properties = {'speed': 20};",
"",
"function tick(deltaTime)",
"{",
" var currentDeltaTime = deltaTime;",
"}"
];
var sourceCode = sourceLines.join('\n');
const sourceFile = ts.createSourceFile("originalSource.js", sourceCode, ts.ScriptTarget.Latest, true);
const additionalSource: ts.SourceFile = ts.createSourceFile(
'ownerCheck.js', "var variableToAdd = 5;", ts.ScriptTarget.ES5, false, ts.ScriptKind.JS
);
const transformer = <T extends ts.Node>(context: ts.TransformationContext) =>
(rootNode: T) => {
function visit(node: ts.Node): ts.Node {
if (ts.isFunctionDeclaration(node)) {
var functionDeclaration = <ts.FunctionDeclaration>node;
var functionName: ts.Identifier = functionDeclaration.name;
var updatedFunction = ts.updateFunctionDeclaration(
functionDeclaration,
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ functionDeclaration.asteriskToken,
/*functionName*/ functionName,
/*typeParameters*/ undefined,
/*parameters*/ functionDeclaration.parameters,
/*returnType*/ undefined,
/*body*/ ts.createBlock(ts.createNodeArray([].concat(additionalSource.statements, functionDeclaration.body.statements), false))
);
return updatedFunction;
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
const result = ts.transform(
sourceFile, [transformer]
);
const transformedNodes = result.transformed[0];
const printer: ts.Printer = ts.createPrinter({
newLine: ts.NewLineKind.LineFeed,
removeComments: false
});
console.log(printer.printNode(ts.EmitHint.SourceFile, transformedNodes, sourceFile));
Выход:
// The list of properties exposed by this script to the user
var properties = { 'speed': 20 };
function tick(deltaTime) {
// The list of properties exposed by this script to the user
var variableToAdd = 5;
var currentDeltaTime = deltaTime;
}
Я ожидал бы, что вывод будет включать дополнительные операторы без повторного комментария перед ними.
Обновление: добавление этой функции:
stripRanges(additionalSource);
function stripRanges(node: ts.Node) {
node.pos = -1;
node.end = -1;
ts.forEachChild(node, stripRanges);
}
удаление диапазонов узлов в additionalSource
узлах технически работает, но удаляет все переводы строки в выводе после этих узлов, что приводит к следующему выводу:
// The list of properties exposed by this script to the user
var properties = { 'speed': 20 };
function tick(deltaTime) { var variableToAdd = 5; var currentDeltaTime = deltaTime; }
Обновление 2: изменение вызова ts.createBlock () на true, чтобы для multiLine было установлено значение true, исправлено следующее:
ts.createBlock(
ts.createNodeArray(
[].concat(
additionalSource.statements,
functionDeclaration.body.statements),
false), /*has trailing comma*/
true) /*multiLine*/