如何在 typescript-transformer 函数中正确转换 'this' 关键字?
How can I properly transform the 'this' keyword in a typescript-transformer function?
我创建了一个遍历 AST 并更改数组调用的打字稿转换器
myArr.push(el)
到 Array.prototype.push.call(myArr, args)
除了数组在 class:
中使用 this
关键字的情况外,这适用于所有情况
this.myArr.push(el)
转换为 Array.prototype.push.call(this.myArr, args)
而正确的转换应该是:
this.myArr.push(el)
至 Array.prototype.push.call(_this.myArr, args)
(_this
已经由 ts-loader 插件创建)
我怎样才能做到这一点?
这是我的变压器的代码:
function getType(type) {
if (type && type.symbol && type.symbol.name) {
return type.symbol.name;
} else if (
type &&
type.literalType &&
type.literalType.symbol &&
type.literalType.symbol.name
) {
return type.literalType.symbol.name;
}
return null;
}
exports.__esModule = true;
const { ClassificationTypeNames } = require("typescript");
var ts = require("typescript");
var transformer = function (typechecker) {
return function (context) {
var visitor = function (node) {
// 1. First check: chained expression
// if it's array.filter().join().map() then I want to change only the first part
// meaning
// if property access is a call expression - ignore and dont change
if (
ts.isCallExpression(node) &&
ts.isPropertyAccessExpression(node.expression) &&
ts.isCallExpression(node.expression.expression)
) {
return ts.visitEachChild(node, visitor, context);
}
if (
ts.isCallExpression(node) &&
ts.isPropertyAccessExpression(node.expression)
) {
const type = typechecker.getTypeAtLocation(node.expression.expression);
const typeNameS = getType(type);
if (typeNameS === "Array") {
const methodName = node.expression.name.getText();
const callArgs = node.arguments;
const identifier = node.expression.expression.getText();
return ts.createCall(
ts.createPropertyAccess(
ts.createPropertyAccess(
ts.createPropertyAccess(
ts.createIdentifier("Array"),
ts.createIdentifier("prototype")
),
ts.createIdentifier(methodName)
),
ts.createIdentifier("call")
),
undefined,
[ts.createIdentifier(identifier), ...callArgs]
);
}
}
return ts.visitEachChild(node, visitor, context);
};
return function (node) {
return ts.visitNode(node, visitor);
};
};
};
发现错误。
我正在获取标识符并手动创建它。
const identifier = node.expression.expression.getText();
然后
ts.createIdentifier(identifier)
构造新节点的正确方法是将node.expression.expression
直接传递给构造调用。
return ts.createCall(
ts.createPropertyAccess(
ts.createPropertyAccess(
ts.createPropertyAccess(
ts.createIdentifier("Array"),
ts.createIdentifier("prototype")
),
ts.createIdentifier(methodName)
),
ts.createIdentifier("call")
),
undefined,
[node.expression.expression, ...callArgs]
);
这样 typescript 引擎就知道如何正确构建 _this
和 this
引用。
我创建了一个遍历 AST 并更改数组调用的打字稿转换器
myArr.push(el)
到 Array.prototype.push.call(myArr, args)
除了数组在 class:
中使用this
关键字的情况外,这适用于所有情况
this.myArr.push(el)
转换为 Array.prototype.push.call(this.myArr, args)
而正确的转换应该是:
this.myArr.push(el)
至 Array.prototype.push.call(_this.myArr, args)
(_this
已经由 ts-loader 插件创建)
我怎样才能做到这一点?
这是我的变压器的代码:
function getType(type) {
if (type && type.symbol && type.symbol.name) {
return type.symbol.name;
} else if (
type &&
type.literalType &&
type.literalType.symbol &&
type.literalType.symbol.name
) {
return type.literalType.symbol.name;
}
return null;
}
exports.__esModule = true;
const { ClassificationTypeNames } = require("typescript");
var ts = require("typescript");
var transformer = function (typechecker) {
return function (context) {
var visitor = function (node) {
// 1. First check: chained expression
// if it's array.filter().join().map() then I want to change only the first part
// meaning
// if property access is a call expression - ignore and dont change
if (
ts.isCallExpression(node) &&
ts.isPropertyAccessExpression(node.expression) &&
ts.isCallExpression(node.expression.expression)
) {
return ts.visitEachChild(node, visitor, context);
}
if (
ts.isCallExpression(node) &&
ts.isPropertyAccessExpression(node.expression)
) {
const type = typechecker.getTypeAtLocation(node.expression.expression);
const typeNameS = getType(type);
if (typeNameS === "Array") {
const methodName = node.expression.name.getText();
const callArgs = node.arguments;
const identifier = node.expression.expression.getText();
return ts.createCall(
ts.createPropertyAccess(
ts.createPropertyAccess(
ts.createPropertyAccess(
ts.createIdentifier("Array"),
ts.createIdentifier("prototype")
),
ts.createIdentifier(methodName)
),
ts.createIdentifier("call")
),
undefined,
[ts.createIdentifier(identifier), ...callArgs]
);
}
}
return ts.visitEachChild(node, visitor, context);
};
return function (node) {
return ts.visitNode(node, visitor);
};
};
};
发现错误。
我正在获取标识符并手动创建它。
const identifier = node.expression.expression.getText();
然后
ts.createIdentifier(identifier)
构造新节点的正确方法是将node.expression.expression
直接传递给构造调用。
return ts.createCall(
ts.createPropertyAccess(
ts.createPropertyAccess(
ts.createPropertyAccess(
ts.createIdentifier("Array"),
ts.createIdentifier("prototype")
),
ts.createIdentifier(methodName)
),
ts.createIdentifier("call")
),
undefined,
[node.expression.expression, ...callArgs]
);
这样 typescript 引擎就知道如何正确构建 _this
和 this
引用。