in packages/pyright-internal/src/analyzer/parseTreeUtils.ts [146:455]
export function printExpression(node: ExpressionNode, flags = PrintExpressionFlags.None): string {
switch (node.nodeType) {
case ParseNodeType.Name: {
return node.value;
}
case ParseNodeType.MemberAccess: {
return printExpression(node.leftExpression, flags) + '.' + node.memberName.value;
}
case ParseNodeType.Call: {
return (
printExpression(node.leftExpression, flags) +
'(' +
node.arguments.map((arg) => printArgument(arg, flags)).join(', ') +
')'
);
}
case ParseNodeType.Index: {
return (
printExpression(node.baseExpression, flags) +
'[' +
node.items.map((item) => printArgument(item, flags)).join(', ') +
']' +
(node.trailingComma ? ',' : '')
);
}
case ParseNodeType.UnaryOperation: {
return printOperator(node.operator) + printExpression(node.expression, flags);
}
case ParseNodeType.BinaryOperation: {
const exprStr =
printExpression(node.leftExpression, flags) +
' ' +
printOperator(node.operator) +
' ' +
printExpression(node.rightExpression, flags);
return node.parenthesized ? `(${exprStr})` : exprStr;
}
case ParseNodeType.Number: {
let value = node.value.toString();
// If it's stored as a bigint, strip off the "n".
if (value.endsWith('n')) {
value = value.substring(0, value.length - 1);
}
if (node.isImaginary) {
value += 'j';
}
return value;
}
case ParseNodeType.StringList: {
if (flags & PrintExpressionFlags.ForwardDeclarations && node.typeAnnotation) {
return printExpression(node.typeAnnotation, flags);
} else {
return node.strings
.map((str) => {
return printExpression(str, flags);
})
.join(' ');
}
}
case ParseNodeType.String: {
let exprString = '';
if (node.token.flags & StringTokenFlags.Raw) {
exprString += 'r';
}
if (node.token.flags & StringTokenFlags.Unicode) {
exprString += 'u';
}
if (node.token.flags & StringTokenFlags.Bytes) {
exprString += 'b';
}
if (node.token.flags & StringTokenFlags.Format) {
exprString += 'f';
}
if (node.token.flags & StringTokenFlags.Triplicate) {
if (node.token.flags & StringTokenFlags.SingleQuote) {
exprString += `'''${node.token.escapedValue}'''`;
} else {
exprString += `"""${node.token.escapedValue}"""`;
}
} else {
if (node.token.flags & StringTokenFlags.SingleQuote) {
exprString += `'${node.token.escapedValue}'`;
} else {
exprString += `"${node.token.escapedValue}"`;
}
}
return exprString;
}
case ParseNodeType.Assignment: {
return printExpression(node.leftExpression, flags) + ' = ' + printExpression(node.rightExpression, flags);
}
case ParseNodeType.AssignmentExpression: {
return printExpression(node.name, flags) + ' := ' + printExpression(node.rightExpression, flags);
}
case ParseNodeType.TypeAnnotation: {
return printExpression(node.valueExpression, flags) + ': ' + printExpression(node.typeAnnotation, flags);
}
case ParseNodeType.AugmentedAssignment: {
return (
printExpression(node.leftExpression, flags) +
' ' +
printOperator(node.operator) +
' ' +
printExpression(node.rightExpression, flags)
);
}
case ParseNodeType.Await: {
return 'await ' + printExpression(node.expression, flags);
}
case ParseNodeType.Ternary: {
return (
printExpression(node.ifExpression, flags) +
' if ' +
printExpression(node.testExpression, flags) +
' else ' +
printExpression(node.elseExpression, flags)
);
}
case ParseNodeType.List: {
const expressions = node.entries.map((expr) => {
return printExpression(expr, flags);
});
return `[${expressions.join(', ')}]`;
}
case ParseNodeType.Unpack: {
return '*' + printExpression(node.expression, flags);
}
case ParseNodeType.Tuple: {
const expressions = node.expressions.map((expr) => {
return printExpression(expr, flags);
});
if (expressions.length === 1) {
return `(${expressions[0]}, )`;
}
return `(${expressions.join(', ')})`;
}
case ParseNodeType.Yield: {
if (node.expression) {
return 'yield ' + printExpression(node.expression, flags);
} else {
return 'yield';
}
}
case ParseNodeType.YieldFrom: {
return 'yield from ' + printExpression(node.expression, flags);
}
case ParseNodeType.Ellipsis: {
return '...';
}
case ParseNodeType.ListComprehension: {
let listStr = '<ListExpression>';
if (isExpressionNode(node.expression)) {
listStr = printExpression(node.expression as ExpressionNode, flags);
} else if (node.expression.nodeType === ParseNodeType.DictionaryKeyEntry) {
const keyStr = printExpression(node.expression.keyExpression, flags);
const valueStr = printExpression(node.expression.valueExpression, flags);
listStr = `${keyStr}: ${valueStr}`;
}
listStr =
listStr +
' ' +
node.comprehensions
.map((expr) => {
if (expr.nodeType === ParseNodeType.ListComprehensionFor) {
return (
`${expr.isAsync ? 'async ' : ''}for ` +
printExpression(expr.targetExpression, flags) +
` in ${printExpression(expr.iterableExpression, flags)}`
);
} else {
return `if ${printExpression(expr.testExpression, flags)}`;
}
})
.join(' ');
return node.isParenthesized ? `(${listStr}})` : listStr;
}
case ParseNodeType.Slice: {
let result = '';
if (node.startValue) {
result += printExpression(node.startValue, flags);
}
if (node.endValue) {
result += ': ' + printExpression(node.endValue, flags);
}
if (node.stepValue) {
result += ': ' + printExpression(node.stepValue, flags);
}
return result;
}
case ParseNodeType.Lambda: {
return (
'lambda ' +
node.parameters
.map((param) => {
let paramStr = '';
if (param.category === ParameterCategory.VarArgList) {
paramStr += '*';
} else if (param.category === ParameterCategory.VarArgDictionary) {
paramStr += '**';
}
if (param.name) {
paramStr += param.name.value;
}
if (param.defaultValue) {
paramStr += ' = ' + printExpression(param.defaultValue, flags);
}
return paramStr;
})
.join(', ') +
': ' +
printExpression(node.expression, flags)
);
}
case ParseNodeType.Constant: {
if (node.constType === KeywordType.True) {
return 'True';
} else if (node.constType === KeywordType.False) {
return 'False';
} else if (node.constType === KeywordType.Debug) {
return '__debug__';
} else if (node.constType === KeywordType.None) {
return 'None';
}
break;
}
case ParseNodeType.Dictionary: {
const dictContents = `${node.entries.map((entry) => {
if (entry.nodeType === ParseNodeType.DictionaryKeyEntry) {
return (
`${printExpression(entry.keyExpression, flags)}: ` +
`${printExpression(entry.valueExpression, flags)}`
);
} else {
return printExpression(entry, flags);
}
})}`;
if (dictContents) {
return `{ ${dictContents} }`;
}
return '{}';
}
case ParseNodeType.DictionaryExpandEntry: {
return `**${printExpression(node.expandExpression, flags)}`;
}
case ParseNodeType.Set: {
return node.entries.map((entry) => printExpression(entry, flags)).join(', ');
}
case ParseNodeType.ArrowCallable: {
const paramsText = node.parameters.map((param) => {
let prefix = '';
if (param.category === ParameterCategory.VarArgList) {
prefix = '*';
} else if (param.category === ParameterCategory.VarArgDictionary) {
prefix = '**';
}
const typeText = printExpression(param.typeAnnotation);
return `${prefix}${typeText}`;
});
const optionalAsync = node.isAsync ? 'async ' : '';
return `${optionalAsync}(${paramsText.join(', ')}) -> ${printExpression(node.returnTypeAnnotation)}`;
}
}