Fix emitting ?.

Use `emit()` for writing `questionDotToken`, leading to properly calling
the emit hooks (which `emitTokenWithComment` doesn't) and printing the
comments.  This fixes #35372 by calling its hooks to set the `.__pos`
and `.__end` fields.

Also, remove `getDotOrQuestionDotToken` which was used only here --
mainly because it seems likely to encourage misusing the
`questionDotToken` again.

Also, fix a bunch of `visitor` -> `tokenVisiton` calls in
`visitorPublic.ts`.
This commit is contained in:
Eli Barzilay 2020-02-25 12:07:01 -05:00
parent 67930fc163
commit 5c8def9a06
10 changed files with 159 additions and 15 deletions

View File

@ -2273,7 +2273,7 @@ namespace ts {
function emitPropertyAccessExpression(node: PropertyAccessExpression) {
const expression = cast(emitExpression(node.expression), isExpression);
const token = getDotOrQuestionDotToken(node);
const token = node.questionDotToken || createNode(SyntaxKind.DotToken, node.expression.end, node.name.pos) as DotToken;
const indentBeforeDot = needsIndentation(node, node.expression, token);
const indentAfterDot = needsIndentation(node, token, node.name);
@ -2289,7 +2289,12 @@ namespace ts {
writePunctuation(".");
}
emitTokenWithComment(token.kind, node.expression.end, writePunctuation, node);
if (node.questionDotToken) {
emit(token);
}
else {
emitTokenWithComment(token.kind, node.expression.end, writePunctuation, node);
}
increaseIndentIf(indentAfterDot, /*writeSpaceIfNotIndenting*/ false);
emit(node.name);
decreaseIndentIf(indentBeforeDot, indentAfterDot);

View File

@ -5052,10 +5052,6 @@ namespace ts {
}
}
export function getDotOrQuestionDotToken(node: PropertyAccessExpression) {
return node.questionDotToken || createNode(SyntaxKind.DotToken, node.expression.end, node.name.pos) as DotToken;
}
export function isNamedImportsOrExports(node: Node): node is NamedImportsOrExports {
return node.kind === SyntaxKind.NamedImports || node.kind === SyntaxKind.NamedExports;
}

View File

@ -459,7 +459,7 @@ namespace ts {
if (node.flags & NodeFlags.OptionalChain) {
return updatePropertyAccessChain(<PropertyAccessChain>node,
visitNode((<PropertyAccessChain>node).expression, visitor, isExpression),
visitNode((<PropertyAccessChain>node).questionDotToken, visitor, isToken),
visitNode((<PropertyAccessChain>node).questionDotToken, tokenVisitor, isToken),
visitNode((<PropertyAccessChain>node).name, visitor, isIdentifier));
}
return updatePropertyAccess(<PropertyAccessExpression>node,
@ -470,7 +470,7 @@ namespace ts {
if (node.flags & NodeFlags.OptionalChain) {
return updateElementAccessChain(<ElementAccessChain>node,
visitNode((<ElementAccessChain>node).expression, visitor, isExpression),
visitNode((<ElementAccessChain>node).questionDotToken, visitor, isToken),
visitNode((<ElementAccessChain>node).questionDotToken, tokenVisitor, isToken),
visitNode((<ElementAccessChain>node).argumentExpression, visitor, isExpression));
}
return updateElementAccess(<ElementAccessExpression>node,
@ -481,7 +481,7 @@ namespace ts {
if (node.flags & NodeFlags.OptionalChain) {
return updateCallChain(<CallChain>node,
visitNode((<CallChain>node).expression, visitor, isExpression),
visitNode((<CallChain>node).questionDotToken, visitor, isToken),
visitNode((<CallChain>node).questionDotToken, tokenVisitor, isToken),
nodesVisitor((<CallChain>node).typeArguments, visitor, isTypeNode),
nodesVisitor((<CallChain>node).arguments, visitor, isExpression));
}
@ -527,7 +527,7 @@ namespace ts {
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameterDeclaration),
visitParameterList((<ArrowFunction>node).parameters, visitor, context, nodesVisitor),
visitNode((<ArrowFunction>node).type, visitor, isTypeNode),
visitNode((<ArrowFunction>node).equalsGreaterThanToken, visitor, isToken),
visitNode((<ArrowFunction>node).equalsGreaterThanToken, tokenVisitor, isToken),
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
case SyntaxKind.DeleteExpression:
@ -558,14 +558,14 @@ namespace ts {
return updateBinary(<BinaryExpression>node,
visitNode((<BinaryExpression>node).left, visitor, isExpression),
visitNode((<BinaryExpression>node).right, visitor, isExpression),
visitNode((<BinaryExpression>node).operatorToken, visitor, isToken));
visitNode((<BinaryExpression>node).operatorToken, tokenVisitor, isToken));
case SyntaxKind.ConditionalExpression:
return updateConditional(<ConditionalExpression>node,
visitNode((<ConditionalExpression>node).condition, visitor, isExpression),
visitNode((<ConditionalExpression>node).questionToken, visitor, isToken),
visitNode((<ConditionalExpression>node).questionToken, tokenVisitor, isToken),
visitNode((<ConditionalExpression>node).whenTrue, visitor, isExpression),
visitNode((<ConditionalExpression>node).colonToken, visitor, isToken),
visitNode((<ConditionalExpression>node).colonToken, tokenVisitor, isToken),
visitNode((<ConditionalExpression>node).whenFalse, visitor, isExpression));
case SyntaxKind.TemplateExpression:
@ -659,7 +659,7 @@ namespace ts {
case SyntaxKind.ForOfStatement:
return updateForOf(<ForOfStatement>node,
visitNode((<ForOfStatement>node).awaitModifier, visitor, isToken),
visitNode((<ForOfStatement>node).awaitModifier, tokenVisitor, isToken),
visitNode((<ForOfStatement>node).initializer, visitor, isForInitializer),
visitNode((<ForOfStatement>node).expression, visitor, isExpression),
visitNode((<ForOfStatement>node).statement, visitor, isStatement, liftToBlock));

View File

@ -966,7 +966,6 @@ namespace ts.textChanges {
function createWriter(newLine: string): TextChangesWriter {
let lastNonTriviaPosition = 0;
const writer = createTextWriter(newLine);
const onEmitNode: PrintHandlers["onEmitNode"] = (hint, node, printCallback) => {
if (node) {

View File

@ -13,6 +13,23 @@
/*1*/Array
// Single-line comment
/*2*/./*3*/toString/*4*/
/* Existing issue: the "2" comments below are duplicated and "3"s are missing */
/*1*/Array/*2*/?./*3*/toString/*4*/
/*1*/Array
/*2*/?./*3*/
// Single-line comment
toString/*4*/
/*1*/Array/*2*/?./*3*/
// Single-line comment
toString/*4*/
/*1*/Array
// Single-line comment
/*2*/?./*3*/toString/*4*/
//// [propertyAccessExpressionInnerComments.js]
@ -27,3 +44,15 @@
/*1*/ Array
// Single-line comment
/*2*/ . /*3*/toString; /*4*/
/* Existing issue: the "2" comments below are duplicated and "3"s are missing */
/*1*/ Array /*2*/ === null || Array /*2*/ === void 0 ? void 0 : Array /*2*/.toString; /*4*/
/*1*/ Array === null || Array === void 0 ? void 0 : Array
/*2*/ .
// Single-line comment
toString; /*4*/
/*1*/ Array /*2*/ === null || Array /*2*/ === void 0 ? void 0 : Array /*2*/.
// Single-line comment
toString; /*4*/
/*1*/ Array === null || Array === void 0 ? void 0 : Array
// Single-line comment
/*2*/ .toString; /*4*/

View File

@ -29,3 +29,35 @@
/*2*/./*3*/toString/*4*/
>toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))
/* Existing issue: the "2" comments below are duplicated and "3"s are missing */
/*1*/Array/*2*/?./*3*/toString/*4*/
>Array/*2*/?./*3*/toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))
/*1*/Array
>Array/*2*/?./*3*/ // Single-line comment toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
/*2*/?./*3*/
// Single-line comment
toString/*4*/
>toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))
/*1*/Array/*2*/?./*3*/
>Array/*2*/?./*3*/ // Single-line comment toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
// Single-line comment
toString/*4*/
>toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))
/*1*/Array
>Array // Single-line comment /*2*/?./*3*/toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
// Single-line comment
/*2*/?./*3*/toString/*4*/
>toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --))

View File

@ -29,3 +29,35 @@
/*2*/./*3*/toString/*4*/
>toString : () => string
/* Existing issue: the "2" comments below are duplicated and "3"s are missing */
/*1*/Array/*2*/?./*3*/toString/*4*/
>Array/*2*/?./*3*/toString : () => string
>Array : ArrayConstructor
>toString : () => string
/*1*/Array
>Array/*2*/?./*3*/ // Single-line comment toString : () => string
>Array : ArrayConstructor
/*2*/?./*3*/
// Single-line comment
toString/*4*/
>toString : () => string
/*1*/Array/*2*/?./*3*/
>Array/*2*/?./*3*/ // Single-line comment toString : () => string
>Array : ArrayConstructor
// Single-line comment
toString/*4*/
>toString : () => string
/*1*/Array
>Array // Single-line comment /*2*/?./*3*/toString : () => string
>Array : ArrayConstructor
// Single-line comment
/*2*/?./*3*/toString/*4*/
>toString : () => string

View File

@ -12,3 +12,20 @@
/*1*/Array
// Single-line comment
/*2*/./*3*/toString/*4*/
/* Existing issue: the "2" comments below are duplicated and "3"s are missing */
/*1*/Array/*2*/?./*3*/toString/*4*/
/*1*/Array
/*2*/?./*3*/
// Single-line comment
toString/*4*/
/*1*/Array/*2*/?./*3*/
// Single-line comment
toString/*4*/
/*1*/Array
// Single-line comment
/*2*/?./*3*/toString/*4*/

View File

@ -0,0 +1,16 @@
/// <reference path='fourslash.ts' />
////function foo(bar: number) {
//// /*a*/bar.toString();/*b*/
////}
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Extract Symbol",
actionName: "constant_scope_0",
actionDescription: "Extract to constant in enclosing scope",
newContent:
`function foo(bar: number) {
const /*RENAME*/newLocal = bar.toString();
}`
});

View File

@ -0,0 +1,18 @@
/// <reference path='fourslash.ts' />
// GH#35372
////function foo(bar?: number) {
//// /*a*/bar?.toString();/*b*/
////}
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Extract Symbol",
actionName: "constant_scope_0",
actionDescription: "Extract to constant in enclosing scope",
newContent:
`function foo(bar?: number) {
const /*RENAME*/newLocal = bar?.toString();
}`
});