From 2ef3e0f617e58545b623bbfbcec7e7935c37f2e3 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 2 Aug 2019 13:03:20 +0800 Subject: [PATCH 01/26] migrate nullish coalescing commit --- src/compiler/binder.ts | 10 +- src/compiler/checker.ts | 9 +- src/compiler/factory.ts | 4 + src/compiler/parser.ts | 1 + src/compiler/scanner.ts | 4 + src/compiler/transformers/esnext.ts | 33 ++++ src/compiler/types.ts | 2 + src/compiler/utilities.ts | 1 + .../reference/nullishCoalescingOperator1.js | 60 ++++++ .../nullishCoalescingOperator1.symbols | 125 +++++++++++++ .../nullishCoalescingOperator1.types | 172 ++++++++++++++++++ .../reference/nullishCoalescingOperator2.js | 33 ++++ .../nullishCoalescingOperator2.symbols | 65 +++++++ .../nullishCoalescingOperator2.types | 94 ++++++++++ .../nullishCoalescingOperator1.ts | 42 +++++ .../nullishCoalescingOperator2.ts | 22 +++ 16 files changed, 672 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperator1.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator1.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator1.types create mode 100644 tests/baselines/reference/nullishCoalescingOperator2.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator2.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator2.types create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator1.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator2.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 660b19a587276..54d43c0a7639e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -934,7 +934,8 @@ namespace ts { else { return node.kind === SyntaxKind.BinaryExpression && ( (node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || - (node).operatorToken.kind === SyntaxKind.BarBarToken); + (node).operatorToken.kind === SyntaxKind.BarBarToken || + (node).operatorToken.kind === SyntaxKind.QuestionQuestionToken); } } } @@ -1367,7 +1368,7 @@ namespace ts { function bindBinaryExpressionFlow(node: BinaryExpression) { const operator = node.operatorToken.kind; - if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) { + if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { if (isTopLevelLogicalExpression(node)) { const postExpressionLabel = createBranchLabel(); bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); @@ -3147,7 +3148,10 @@ namespace ts { const operatorTokenKind = node.operatorToken.kind; const leftKind = node.left.kind; - if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { + if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) { + transformFlags |= TransformFlags.AssertESNext; + } + else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { // Destructuring object assignments with are ES2015 syntax // and possibly ES2018 if they contain rest transformFlags |= TransformFlags.AssertES2018 | TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a4ad3af7d9a35..7679cb14167bf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11524,7 +11524,7 @@ namespace ts { return isContextSensitive((node).whenTrue) || isContextSensitive((node).whenFalse); case SyntaxKind.BinaryExpression: - return (node).operatorToken.kind === SyntaxKind.BarBarToken && + return ((node).operatorToken.kind === SyntaxKind.BarBarToken || (node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) && (isContextSensitive((node).left) || isContextSensitive((node).right)); case SyntaxKind.PropertyAssignment: return isContextSensitive((node).initializer); @@ -18477,6 +18477,7 @@ namespace ts { } return contextSensitive === true ? getTypeOfExpression(left) : contextSensitive; case SyntaxKind.BarBarToken: + case SyntaxKind.QuestionQuestionToken: // When an || expression has a contextual type, the operands are contextually typed by that type, except // when that type originates in a binding pattern, the right operand is contextually typed by the type of // the left operand. When an || expression has no contextual type, the right operand is contextually typed @@ -23761,7 +23762,7 @@ namespace ts { return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode, right.kind === SyntaxKind.ThisKeyword); } let leftType: Type; - if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) { + if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { leftType = checkTruthinessExpression(left, checkMode); } else { @@ -23917,6 +23918,10 @@ namespace ts { return getTypeFacts(leftType) & TypeFacts.Falsy ? getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) : leftType; + case SyntaxKind.QuestionQuestionToken: + return getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ? + getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) : + leftType; case SyntaxKind.EqualsToken: const declKind = isBinaryExpression(left.parent) ? getAssignmentDeclarationKind(left.parent) : AssignmentDeclarationKind.None; checkAssignmentDeclaration(declKind, rightType); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index f67ec39b0a47e..c1740b53118a9 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -3044,6 +3044,10 @@ namespace ts { return createBinary(left, SyntaxKind.BarBarToken, right); } + export function createNullishCoalescing(left: Expression, right: Expression) { + return createBinary(left, SyntaxKind.QuestionQuestionToken, right); + } + export function createLogicalNot(operand: Expression) { return createPrefix(SyntaxKind.ExclamationToken, operand); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c38e4f67fe287..d770b2db2b854 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4659,6 +4659,7 @@ namespace ts { case SyntaxKind.ExclamationEqualsEqualsToken: // foo !== case SyntaxKind.AmpersandAmpersandToken: // foo && case SyntaxKind.BarBarToken: // foo || + case SyntaxKind.QuestionQuestionToken: // foo ?? case SyntaxKind.CaretToken: // foo ^ case SyntaxKind.AmpersandToken: // foo & case SyntaxKind.BarToken: // foo | diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 36ac8adfa9053..2d335c9cb98e6 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -182,6 +182,7 @@ namespace ts { "&&": SyntaxKind.AmpersandAmpersandToken, "||": SyntaxKind.BarBarToken, "?": SyntaxKind.QuestionToken, + "??": SyntaxKind.QuestionQuestionToken, ":": SyntaxKind.ColonToken, "=": SyntaxKind.EqualsToken, "+=": SyntaxKind.PlusEqualsToken, @@ -1778,6 +1779,9 @@ namespace ts { pos++; return token = SyntaxKind.GreaterThanToken; case CharacterCodes.question: + if (text.charCodeAt(pos + 1) === CharacterCodes.question) { + return pos += 2, token = SyntaxKind.QuestionQuestionToken; + } pos++; return token = SyntaxKind.QuestionToken; case CharacterCodes.openBracket: diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 80debb46f8a04..ea6d3882be437 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -16,9 +16,42 @@ namespace ts { return node; } switch (node.kind) { + case SyntaxKind.BinaryExpression: + if ((node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) { + return transformNullishCoalescingExpression(node); + } + // falls through default: return visitEachChild(node, visitor, context); } } + + function createNotUndefinedCondition(node: Expression) { + return isIdentifier(node) && !isGeneratedIdentifier(node) + ? createStrictInequality(createTypeOf(node), createLiteral("undefined")) + : createStrictInequality(node, createVoidZero()); + } + + function createNotNullCondition(node: Expression) { + return createStrictInequality(node, createNull()); + } + + function transformNullishCoalescingExpression(node: BinaryExpression) { + const expressions: Expression[] = []; + let left = visitNode(node.left, visitor, isExpression); + if (!isIdentifier(left)) { + const temp = createTempVariable(/*recordTempVariable*/ undefined); + expressions.push(createAssignment(temp, left)); + left = temp; + } + expressions.push( + createConditional( + createLogicalAnd( + createNotUndefinedCondition(left), + createNotNullCondition(left)), + left, + visitNode(node.right, visitor, isExpression))); + return inlineExpressions(expressions); + } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 845c63b707bc8..ef389b3860fd7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -181,6 +181,7 @@ namespace ts { QuestionToken, ColonToken, AtToken, + QuestionQuestionToken, /** Only the JSDoc scanner produces BacktickToken. The normal scanner produces NoSubstitutionTemplateLiteral and related kinds. */ BacktickToken, // Assignments @@ -1497,6 +1498,7 @@ namespace ts { export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken + | SyntaxKind.QuestionQuestionToken ; // see: https://tc39.github.io/ecma262/#prod-LogicalANDExpression diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 0e2488a02331c..6017bc6096162 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2988,6 +2988,7 @@ namespace ts { export function getBinaryOperatorPrecedence(kind: SyntaxKind): number { switch (kind) { + case SyntaxKind.QuestionQuestionToken: case SyntaxKind.BarBarToken: return 5; case SyntaxKind.AmpersandAmpersandToken: diff --git a/tests/baselines/reference/nullishCoalescingOperator1.js b/tests/baselines/reference/nullishCoalescingOperator1.js new file mode 100644 index 0000000000000..f94f87acc3a8f --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator1.js @@ -0,0 +1,60 @@ +//// [nullishCoalescingOperator1.ts] +declare const a1: string | undefined | null +declare const a2: string | undefined | null +declare const a3: string | undefined | null +declare const a4: string | undefined | null + +declare const b1: number | undefined | null +declare const b2: number | undefined | null +declare const b3: number | undefined | null +declare const b4: number | undefined | null + +declare const c1: boolean | undefined | null +declare const c2: boolean | undefined | null +declare const c3: boolean | undefined | null +declare const c4: boolean | undefined | null + +interface I { a: string } +declare const d1: I | undefined | null +declare const d2: I | undefined | null +declare const d3: I | undefined | null +declare const d4: I | undefined | null + +const aa1 = a1 ?? 'whatever'; +const aa2 = a2 ?? 'whatever'; +const aa3 = a3 ?? 'whatever'; +const aa4 = a4 ?? 'whatever'; + +const bb1 = b1 ?? 1; +const bb2 = b2 ?? 1; +const bb3 = b3 ?? 1; +const bb4 = b4 ?? 1; + +const cc1 = c1 ?? true; +const cc2 = c2 ?? true; +const cc3 = c3 ?? true; +const cc4 = c4 ?? true; + +const dd1 = d1 ?? {b: 1}; +const dd2 = d2 ?? {b: 1}; +const dd3 = d3 ?? {b: 1}; +const dd4 = d4 ?? {b: 1}; + +//// [nullishCoalescingOperator1.js] +"use strict"; +var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever'; +var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever'; +var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever'; +var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever'; +var bb1 = typeof b1 !== "undefined" && b1 !== null ? b1 : 1; +var bb2 = typeof b2 !== "undefined" && b2 !== null ? b2 : 1; +var bb3 = typeof b3 !== "undefined" && b3 !== null ? b3 : 1; +var bb4 = typeof b4 !== "undefined" && b4 !== null ? b4 : 1; +var cc1 = typeof c1 !== "undefined" && c1 !== null ? c1 : true; +var cc2 = typeof c2 !== "undefined" && c2 !== null ? c2 : true; +var cc3 = typeof c3 !== "undefined" && c3 !== null ? c3 : true; +var cc4 = typeof c4 !== "undefined" && c4 !== null ? c4 : true; +var dd1 = typeof d1 !== "undefined" && d1 !== null ? d1 : { b: 1 }; +var dd2 = typeof d2 !== "undefined" && d2 !== null ? d2 : { b: 1 }; +var dd3 = typeof d3 !== "undefined" && d3 !== null ? d3 : { b: 1 }; +var dd4 = typeof d4 !== "undefined" && d4 !== null ? d4 : { b: 1 }; diff --git a/tests/baselines/reference/nullishCoalescingOperator1.symbols b/tests/baselines/reference/nullishCoalescingOperator1.symbols new file mode 100644 index 0000000000000..fb95dee5096a6 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator1.symbols @@ -0,0 +1,125 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator1.ts === +declare const a1: string | undefined | null +>a1 : Symbol(a1, Decl(nullishCoalescingOperator1.ts, 0, 13)) + +declare const a2: string | undefined | null +>a2 : Symbol(a2, Decl(nullishCoalescingOperator1.ts, 1, 13)) + +declare const a3: string | undefined | null +>a3 : Symbol(a3, Decl(nullishCoalescingOperator1.ts, 2, 13)) + +declare const a4: string | undefined | null +>a4 : Symbol(a4, Decl(nullishCoalescingOperator1.ts, 3, 13)) + +declare const b1: number | undefined | null +>b1 : Symbol(b1, Decl(nullishCoalescingOperator1.ts, 5, 13)) + +declare const b2: number | undefined | null +>b2 : Symbol(b2, Decl(nullishCoalescingOperator1.ts, 6, 13)) + +declare const b3: number | undefined | null +>b3 : Symbol(b3, Decl(nullishCoalescingOperator1.ts, 7, 13)) + +declare const b4: number | undefined | null +>b4 : Symbol(b4, Decl(nullishCoalescingOperator1.ts, 8, 13)) + +declare const c1: boolean | undefined | null +>c1 : Symbol(c1, Decl(nullishCoalescingOperator1.ts, 10, 13)) + +declare const c2: boolean | undefined | null +>c2 : Symbol(c2, Decl(nullishCoalescingOperator1.ts, 11, 13)) + +declare const c3: boolean | undefined | null +>c3 : Symbol(c3, Decl(nullishCoalescingOperator1.ts, 12, 13)) + +declare const c4: boolean | undefined | null +>c4 : Symbol(c4, Decl(nullishCoalescingOperator1.ts, 13, 13)) + +interface I { a: string } +>I : Symbol(I, Decl(nullishCoalescingOperator1.ts, 13, 44)) +>a : Symbol(I.a, Decl(nullishCoalescingOperator1.ts, 15, 13)) + +declare const d1: I | undefined | null +>d1 : Symbol(d1, Decl(nullishCoalescingOperator1.ts, 16, 13)) +>I : Symbol(I, Decl(nullishCoalescingOperator1.ts, 13, 44)) + +declare const d2: I | undefined | null +>d2 : Symbol(d2, Decl(nullishCoalescingOperator1.ts, 17, 13)) +>I : Symbol(I, Decl(nullishCoalescingOperator1.ts, 13, 44)) + +declare const d3: I | undefined | null +>d3 : Symbol(d3, Decl(nullishCoalescingOperator1.ts, 18, 13)) +>I : Symbol(I, Decl(nullishCoalescingOperator1.ts, 13, 44)) + +declare const d4: I | undefined | null +>d4 : Symbol(d4, Decl(nullishCoalescingOperator1.ts, 19, 13)) +>I : Symbol(I, Decl(nullishCoalescingOperator1.ts, 13, 44)) + +const aa1 = a1 ?? 'whatever'; +>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator1.ts, 21, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator1.ts, 0, 13)) + +const aa2 = a2 ?? 'whatever'; +>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator1.ts, 22, 5)) +>a2 : Symbol(a2, Decl(nullishCoalescingOperator1.ts, 1, 13)) + +const aa3 = a3 ?? 'whatever'; +>aa3 : Symbol(aa3, Decl(nullishCoalescingOperator1.ts, 23, 5)) +>a3 : Symbol(a3, Decl(nullishCoalescingOperator1.ts, 2, 13)) + +const aa4 = a4 ?? 'whatever'; +>aa4 : Symbol(aa4, Decl(nullishCoalescingOperator1.ts, 24, 5)) +>a4 : Symbol(a4, Decl(nullishCoalescingOperator1.ts, 3, 13)) + +const bb1 = b1 ?? 1; +>bb1 : Symbol(bb1, Decl(nullishCoalescingOperator1.ts, 26, 5)) +>b1 : Symbol(b1, Decl(nullishCoalescingOperator1.ts, 5, 13)) + +const bb2 = b2 ?? 1; +>bb2 : Symbol(bb2, Decl(nullishCoalescingOperator1.ts, 27, 5)) +>b2 : Symbol(b2, Decl(nullishCoalescingOperator1.ts, 6, 13)) + +const bb3 = b3 ?? 1; +>bb3 : Symbol(bb3, Decl(nullishCoalescingOperator1.ts, 28, 5)) +>b3 : Symbol(b3, Decl(nullishCoalescingOperator1.ts, 7, 13)) + +const bb4 = b4 ?? 1; +>bb4 : Symbol(bb4, Decl(nullishCoalescingOperator1.ts, 29, 5)) +>b4 : Symbol(b4, Decl(nullishCoalescingOperator1.ts, 8, 13)) + +const cc1 = c1 ?? true; +>cc1 : Symbol(cc1, Decl(nullishCoalescingOperator1.ts, 31, 5)) +>c1 : Symbol(c1, Decl(nullishCoalescingOperator1.ts, 10, 13)) + +const cc2 = c2 ?? true; +>cc2 : Symbol(cc2, Decl(nullishCoalescingOperator1.ts, 32, 5)) +>c2 : Symbol(c2, Decl(nullishCoalescingOperator1.ts, 11, 13)) + +const cc3 = c3 ?? true; +>cc3 : Symbol(cc3, Decl(nullishCoalescingOperator1.ts, 33, 5)) +>c3 : Symbol(c3, Decl(nullishCoalescingOperator1.ts, 12, 13)) + +const cc4 = c4 ?? true; +>cc4 : Symbol(cc4, Decl(nullishCoalescingOperator1.ts, 34, 5)) +>c4 : Symbol(c4, Decl(nullishCoalescingOperator1.ts, 13, 13)) + +const dd1 = d1 ?? {b: 1}; +>dd1 : Symbol(dd1, Decl(nullishCoalescingOperator1.ts, 36, 5)) +>d1 : Symbol(d1, Decl(nullishCoalescingOperator1.ts, 16, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator1.ts, 36, 19)) + +const dd2 = d2 ?? {b: 1}; +>dd2 : Symbol(dd2, Decl(nullishCoalescingOperator1.ts, 37, 5)) +>d2 : Symbol(d2, Decl(nullishCoalescingOperator1.ts, 17, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator1.ts, 37, 19)) + +const dd3 = d3 ?? {b: 1}; +>dd3 : Symbol(dd3, Decl(nullishCoalescingOperator1.ts, 38, 5)) +>d3 : Symbol(d3, Decl(nullishCoalescingOperator1.ts, 18, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator1.ts, 38, 19)) + +const dd4 = d4 ?? {b: 1}; +>dd4 : Symbol(dd4, Decl(nullishCoalescingOperator1.ts, 39, 5)) +>d4 : Symbol(d4, Decl(nullishCoalescingOperator1.ts, 19, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator1.ts, 39, 19)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator1.types b/tests/baselines/reference/nullishCoalescingOperator1.types new file mode 100644 index 0000000000000..0e800540ee8b3 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator1.types @@ -0,0 +1,172 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator1.ts === +declare const a1: string | undefined | null +>a1 : string | null | undefined +>null : null + +declare const a2: string | undefined | null +>a2 : string | null | undefined +>null : null + +declare const a3: string | undefined | null +>a3 : string | null | undefined +>null : null + +declare const a4: string | undefined | null +>a4 : string | null | undefined +>null : null + +declare const b1: number | undefined | null +>b1 : number | null | undefined +>null : null + +declare const b2: number | undefined | null +>b2 : number | null | undefined +>null : null + +declare const b3: number | undefined | null +>b3 : number | null | undefined +>null : null + +declare const b4: number | undefined | null +>b4 : number | null | undefined +>null : null + +declare const c1: boolean | undefined | null +>c1 : boolean | null | undefined +>null : null + +declare const c2: boolean | undefined | null +>c2 : boolean | null | undefined +>null : null + +declare const c3: boolean | undefined | null +>c3 : boolean | null | undefined +>null : null + +declare const c4: boolean | undefined | null +>c4 : boolean | null | undefined +>null : null + +interface I { a: string } +>a : string + +declare const d1: I | undefined | null +>d1 : I | null | undefined +>null : null + +declare const d2: I | undefined | null +>d2 : I | null | undefined +>null : null + +declare const d3: I | undefined | null +>d3 : I | null | undefined +>null : null + +declare const d4: I | undefined | null +>d4 : I | null | undefined +>null : null + +const aa1 = a1 ?? 'whatever'; +>aa1 : string +>a1 ?? 'whatever' : string +>a1 : string | null | undefined +>'whatever' : "whatever" + +const aa2 = a2 ?? 'whatever'; +>aa2 : string +>a2 ?? 'whatever' : string +>a2 : string | null | undefined +>'whatever' : "whatever" + +const aa3 = a3 ?? 'whatever'; +>aa3 : string +>a3 ?? 'whatever' : string +>a3 : string | null | undefined +>'whatever' : "whatever" + +const aa4 = a4 ?? 'whatever'; +>aa4 : string +>a4 ?? 'whatever' : string +>a4 : string | null | undefined +>'whatever' : "whatever" + +const bb1 = b1 ?? 1; +>bb1 : number +>b1 ?? 1 : number +>b1 : number | null | undefined +>1 : 1 + +const bb2 = b2 ?? 1; +>bb2 : number +>b2 ?? 1 : number +>b2 : number | null | undefined +>1 : 1 + +const bb3 = b3 ?? 1; +>bb3 : number +>b3 ?? 1 : number +>b3 : number | null | undefined +>1 : 1 + +const bb4 = b4 ?? 1; +>bb4 : number +>b4 ?? 1 : number +>b4 : number | null | undefined +>1 : 1 + +const cc1 = c1 ?? true; +>cc1 : boolean +>c1 ?? true : boolean +>c1 : boolean | null | undefined +>true : true + +const cc2 = c2 ?? true; +>cc2 : boolean +>c2 ?? true : boolean +>c2 : boolean | null | undefined +>true : true + +const cc3 = c3 ?? true; +>cc3 : boolean +>c3 ?? true : boolean +>c3 : boolean | null | undefined +>true : true + +const cc4 = c4 ?? true; +>cc4 : boolean +>c4 ?? true : boolean +>c4 : boolean | null | undefined +>true : true + +const dd1 = d1 ?? {b: 1}; +>dd1 : I | { b: number; } +>d1 ?? {b: 1} : I | { b: number; } +>d1 : I | null | undefined +>{b: 1} : { b: number; } +>b : number +>1 : 1 + +const dd2 = d2 ?? {b: 1}; +>dd2 : I | { b: number; } +>d2 ?? {b: 1} : I | { b: number; } +>d2 : I | null | undefined +>{b: 1} : { b: number; } +>b : number +>1 : 1 + +const dd3 = d3 ?? {b: 1}; +>dd3 : I | { b: number; } +>d3 ?? {b: 1} : I | { b: number; } +>d3 : I | null | undefined +>{b: 1} : { b: number; } +>b : number +>1 : 1 + +const dd4 = d4 ?? {b: 1}; +>dd4 : I | { b: number; } +>d4 ?? {b: 1} : I | { b: number; } +>d4 : I | null | undefined +>{b: 1} : { b: number; } +>b : number +>1 : 1 + diff --git a/tests/baselines/reference/nullishCoalescingOperator2.js b/tests/baselines/reference/nullishCoalescingOperator2.js new file mode 100644 index 0000000000000..133eb55d8b542 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator2.js @@ -0,0 +1,33 @@ +//// [nullishCoalescingOperator2.ts] +declare const a1: 'literal' | undefined | null +declare const a2: '' | undefined | null +declare const a3: 1 | undefined | null +declare const a4: 0 | undefined | null +declare const a5: true | undefined | null +declare const a6: false | undefined | null +declare const a7: unknown | null +declare const a8: never | null +declare const a9: any | null + + +const aa1 = a1 ?? 'whatever' +const aa2 = a2 ?? 'whatever' +const aa3 = a3 ?? 'whatever' +const aa4 = a4 ?? 'whatever' +const aa5 = a5 ?? 'whatever' +const aa6 = a6 ?? 'whatever' +const aa7 = a7 ?? 'whatever' +const aa8 = a8 ?? 'whatever' +const aa9 = a9 ?? 'whatever' + +//// [nullishCoalescingOperator2.js] +"use strict"; +var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever'; +var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever'; +var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever'; +var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever'; +var aa5 = typeof a5 !== "undefined" && a5 !== null ? a5 : 'whatever'; +var aa6 = typeof a6 !== "undefined" && a6 !== null ? a6 : 'whatever'; +var aa7 = typeof a7 !== "undefined" && a7 !== null ? a7 : 'whatever'; +var aa8 = typeof a8 !== "undefined" && a8 !== null ? a8 : 'whatever'; +var aa9 = typeof a9 !== "undefined" && a9 !== null ? a9 : 'whatever'; diff --git a/tests/baselines/reference/nullishCoalescingOperator2.symbols b/tests/baselines/reference/nullishCoalescingOperator2.symbols new file mode 100644 index 0000000000000..d712165683405 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator2.symbols @@ -0,0 +1,65 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator2.ts === +declare const a1: 'literal' | undefined | null +>a1 : Symbol(a1, Decl(nullishCoalescingOperator2.ts, 0, 13)) + +declare const a2: '' | undefined | null +>a2 : Symbol(a2, Decl(nullishCoalescingOperator2.ts, 1, 13)) + +declare const a3: 1 | undefined | null +>a3 : Symbol(a3, Decl(nullishCoalescingOperator2.ts, 2, 13)) + +declare const a4: 0 | undefined | null +>a4 : Symbol(a4, Decl(nullishCoalescingOperator2.ts, 3, 13)) + +declare const a5: true | undefined | null +>a5 : Symbol(a5, Decl(nullishCoalescingOperator2.ts, 4, 13)) + +declare const a6: false | undefined | null +>a6 : Symbol(a6, Decl(nullishCoalescingOperator2.ts, 5, 13)) + +declare const a7: unknown | null +>a7 : Symbol(a7, Decl(nullishCoalescingOperator2.ts, 6, 13)) + +declare const a8: never | null +>a8 : Symbol(a8, Decl(nullishCoalescingOperator2.ts, 7, 13)) + +declare const a9: any | null +>a9 : Symbol(a9, Decl(nullishCoalescingOperator2.ts, 8, 13)) + + +const aa1 = a1 ?? 'whatever' +>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator2.ts, 11, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator2.ts, 0, 13)) + +const aa2 = a2 ?? 'whatever' +>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator2.ts, 12, 5)) +>a2 : Symbol(a2, Decl(nullishCoalescingOperator2.ts, 1, 13)) + +const aa3 = a3 ?? 'whatever' +>aa3 : Symbol(aa3, Decl(nullishCoalescingOperator2.ts, 13, 5)) +>a3 : Symbol(a3, Decl(nullishCoalescingOperator2.ts, 2, 13)) + +const aa4 = a4 ?? 'whatever' +>aa4 : Symbol(aa4, Decl(nullishCoalescingOperator2.ts, 14, 5)) +>a4 : Symbol(a4, Decl(nullishCoalescingOperator2.ts, 3, 13)) + +const aa5 = a5 ?? 'whatever' +>aa5 : Symbol(aa5, Decl(nullishCoalescingOperator2.ts, 15, 5)) +>a5 : Symbol(a5, Decl(nullishCoalescingOperator2.ts, 4, 13)) + +const aa6 = a6 ?? 'whatever' +>aa6 : Symbol(aa6, Decl(nullishCoalescingOperator2.ts, 16, 5)) +>a6 : Symbol(a6, Decl(nullishCoalescingOperator2.ts, 5, 13)) + +const aa7 = a7 ?? 'whatever' +>aa7 : Symbol(aa7, Decl(nullishCoalescingOperator2.ts, 17, 5)) +>a7 : Symbol(a7, Decl(nullishCoalescingOperator2.ts, 6, 13)) + +const aa8 = a8 ?? 'whatever' +>aa8 : Symbol(aa8, Decl(nullishCoalescingOperator2.ts, 18, 5)) +>a8 : Symbol(a8, Decl(nullishCoalescingOperator2.ts, 7, 13)) + +const aa9 = a9 ?? 'whatever' +>aa9 : Symbol(aa9, Decl(nullishCoalescingOperator2.ts, 19, 5)) +>a9 : Symbol(a9, Decl(nullishCoalescingOperator2.ts, 8, 13)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator2.types b/tests/baselines/reference/nullishCoalescingOperator2.types new file mode 100644 index 0000000000000..dd1e31c4038c4 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator2.types @@ -0,0 +1,94 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator2.ts === +declare const a1: 'literal' | undefined | null +>a1 : "literal" | null | undefined +>null : null + +declare const a2: '' | undefined | null +>a2 : "" | null | undefined +>null : null + +declare const a3: 1 | undefined | null +>a3 : 1 | null | undefined +>null : null + +declare const a4: 0 | undefined | null +>a4 : 0 | null | undefined +>null : null + +declare const a5: true | undefined | null +>a5 : true | null | undefined +>true : true +>null : null + +declare const a6: false | undefined | null +>a6 : false | null | undefined +>false : false +>null : null + +declare const a7: unknown | null +>a7 : unknown +>null : null + +declare const a8: never | null +>a8 : null +>null : null + +declare const a9: any | null +>a9 : any +>null : null + + +const aa1 = a1 ?? 'whatever' +>aa1 : "literal" | "whatever" +>a1 ?? 'whatever' : "literal" | "whatever" +>a1 : "literal" | null | undefined +>'whatever' : "whatever" + +const aa2 = a2 ?? 'whatever' +>aa2 : "" | "whatever" +>a2 ?? 'whatever' : "" | "whatever" +>a2 : "" | null | undefined +>'whatever' : "whatever" + +const aa3 = a3 ?? 'whatever' +>aa3 : 1 | "whatever" +>a3 ?? 'whatever' : 1 | "whatever" +>a3 : 1 | null | undefined +>'whatever' : "whatever" + +const aa4 = a4 ?? 'whatever' +>aa4 : 0 | "whatever" +>a4 ?? 'whatever' : 0 | "whatever" +>a4 : 0 | null | undefined +>'whatever' : "whatever" + +const aa5 = a5 ?? 'whatever' +>aa5 : true | "whatever" +>a5 ?? 'whatever' : true | "whatever" +>a5 : true | null | undefined +>'whatever' : "whatever" + +const aa6 = a6 ?? 'whatever' +>aa6 : false | "whatever" +>a6 ?? 'whatever' : false | "whatever" +>a6 : false | null | undefined +>'whatever' : "whatever" + +const aa7 = a7 ?? 'whatever' +>aa7 : unknown +>a7 ?? 'whatever' : unknown +>a7 : unknown +>'whatever' : "whatever" + +const aa8 = a8 ?? 'whatever' +>aa8 : "whatever" +>a8 ?? 'whatever' : "whatever" +>a8 : null +>'whatever' : "whatever" + +const aa9 = a9 ?? 'whatever' +>aa9 : any +>a9 ?? 'whatever' : any +>a9 : any +>'whatever' : "whatever" + diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator1.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator1.ts new file mode 100644 index 0000000000000..80f0c64e7d94d --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator1.ts @@ -0,0 +1,42 @@ +// @strict: true + +declare const a1: string | undefined | null +declare const a2: string | undefined | null +declare const a3: string | undefined | null +declare const a4: string | undefined | null + +declare const b1: number | undefined | null +declare const b2: number | undefined | null +declare const b3: number | undefined | null +declare const b4: number | undefined | null + +declare const c1: boolean | undefined | null +declare const c2: boolean | undefined | null +declare const c3: boolean | undefined | null +declare const c4: boolean | undefined | null + +interface I { a: string } +declare const d1: I | undefined | null +declare const d2: I | undefined | null +declare const d3: I | undefined | null +declare const d4: I | undefined | null + +const aa1 = a1 ?? 'whatever'; +const aa2 = a2 ?? 'whatever'; +const aa3 = a3 ?? 'whatever'; +const aa4 = a4 ?? 'whatever'; + +const bb1 = b1 ?? 1; +const bb2 = b2 ?? 1; +const bb3 = b3 ?? 1; +const bb4 = b4 ?? 1; + +const cc1 = c1 ?? true; +const cc2 = c2 ?? true; +const cc3 = c3 ?? true; +const cc4 = c4 ?? true; + +const dd1 = d1 ?? {b: 1}; +const dd2 = d2 ?? {b: 1}; +const dd3 = d3 ?? {b: 1}; +const dd4 = d4 ?? {b: 1}; \ No newline at end of file diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator2.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator2.ts new file mode 100644 index 0000000000000..5d5761aeec534 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator2.ts @@ -0,0 +1,22 @@ +// @strict: true + +declare const a1: 'literal' | undefined | null +declare const a2: '' | undefined | null +declare const a3: 1 | undefined | null +declare const a4: 0 | undefined | null +declare const a5: true | undefined | null +declare const a6: false | undefined | null +declare const a7: unknown | null +declare const a8: never | null +declare const a9: any | null + + +const aa1 = a1 ?? 'whatever' +const aa2 = a2 ?? 'whatever' +const aa3 = a3 ?? 'whatever' +const aa4 = a4 ?? 'whatever' +const aa5 = a5 ?? 'whatever' +const aa6 = a6 ?? 'whatever' +const aa7 = a7 ?? 'whatever' +const aa8 = a8 ?? 'whatever' +const aa9 = a9 ?? 'whatever' \ No newline at end of file From 91a04ed5c92288739e4607c8601768d3e9cef4d6 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 14 Aug 2019 17:08:30 +0800 Subject: [PATCH 02/26] add more test case --- src/compiler/binder.ts | 1 + .../reference/nullishCoalescingOperator3.js | 15 +++ .../nullishCoalescingOperator3.symbols | 29 ++++++ .../nullishCoalescingOperator3.types | 44 +++++++++ .../nullishCoalescingOperator_esnext.js | 36 +++++++ .../nullishCoalescingOperator_esnext.symbols | 67 +++++++++++++ .../nullishCoalescingOperator_esnext.types | 96 +++++++++++++++++++ .../nullishCoalescingOperator_not_strict.js | 32 +++++++ ...llishCoalescingOperator_not_strict.symbols | 65 +++++++++++++ ...nullishCoalescingOperator_not_strict.types | 94 ++++++++++++++++++ .../nullishCoalescingOperator3.ts | 12 +++ .../nullishCoalescingOperator_esnext.ts | 23 +++++ .../nullishCoalescingOperator_not_strict.ts | 22 +++++ 13 files changed, 536 insertions(+) create mode 100644 tests/baselines/reference/nullishCoalescingOperator3.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator3.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator3.types create mode 100644 tests/baselines/reference/nullishCoalescingOperator_esnext.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator_esnext.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator_esnext.types create mode 100644 tests/baselines/reference/nullishCoalescingOperator_not_strict.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator_not_strict.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator_not_strict.types create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_not_strict.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 54d43c0a7639e..93e5e236fc497 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1366,6 +1366,7 @@ namespace ts { } } + // TODO(rbuckton): Determine how to hook ?? into flow typing function bindBinaryExpressionFlow(node: BinaryExpression) { const operator = node.operatorToken.kind; if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { diff --git a/tests/baselines/reference/nullishCoalescingOperator3.js b/tests/baselines/reference/nullishCoalescingOperator3.js new file mode 100644 index 0000000000000..00c6ac5073292 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator3.js @@ -0,0 +1,15 @@ +//// [nullishCoalescingOperator3.ts] +declare const a1: 'literal' | undefined | null +declare const a2: '' | undefined | null +declare const a3: 1 | undefined | null +declare const a4: 0 | undefined | null +declare const a5: true | undefined | null +declare const a6: false | undefined | null + + +const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' + + +//// [nullishCoalescingOperator3.js] +"use strict"; +var aa1 = (_a = (_b = (_c = (_d = (_e = typeof a1 !== "undefined" && a1 !== null ? a1 : a2, _e !== void 0 && _e !== null ? _e : a3), _d !== void 0 && _d !== null ? _d : a4), _c !== void 0 && _c !== null ? _c : a5), _b !== void 0 && _b !== null ? _b : a6), _a !== void 0 && _a !== null ? _a : 'whatever'); diff --git a/tests/baselines/reference/nullishCoalescingOperator3.symbols b/tests/baselines/reference/nullishCoalescingOperator3.symbols new file mode 100644 index 0000000000000..5f9e5a7c3a549 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator3.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts === +declare const a1: 'literal' | undefined | null +>a1 : Symbol(a1, Decl(nullishCoalescingOperator3.ts, 0, 13)) + +declare const a2: '' | undefined | null +>a2 : Symbol(a2, Decl(nullishCoalescingOperator3.ts, 1, 13)) + +declare const a3: 1 | undefined | null +>a3 : Symbol(a3, Decl(nullishCoalescingOperator3.ts, 2, 13)) + +declare const a4: 0 | undefined | null +>a4 : Symbol(a4, Decl(nullishCoalescingOperator3.ts, 3, 13)) + +declare const a5: true | undefined | null +>a5 : Symbol(a5, Decl(nullishCoalescingOperator3.ts, 4, 13)) + +declare const a6: false | undefined | null +>a6 : Symbol(a6, Decl(nullishCoalescingOperator3.ts, 5, 13)) + + +const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' +>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator3.ts, 8, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator3.ts, 0, 13)) +>a2 : Symbol(a2, Decl(nullishCoalescingOperator3.ts, 1, 13)) +>a3 : Symbol(a3, Decl(nullishCoalescingOperator3.ts, 2, 13)) +>a4 : Symbol(a4, Decl(nullishCoalescingOperator3.ts, 3, 13)) +>a5 : Symbol(a5, Decl(nullishCoalescingOperator3.ts, 4, 13)) +>a6 : Symbol(a6, Decl(nullishCoalescingOperator3.ts, 5, 13)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator3.types b/tests/baselines/reference/nullishCoalescingOperator3.types new file mode 100644 index 0000000000000..3f725c8c772a2 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator3.types @@ -0,0 +1,44 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts === +declare const a1: 'literal' | undefined | null +>a1 : "literal" | null | undefined +>null : null + +declare const a2: '' | undefined | null +>a2 : "" | null | undefined +>null : null + +declare const a3: 1 | undefined | null +>a3 : 1 | null | undefined +>null : null + +declare const a4: 0 | undefined | null +>a4 : 0 | null | undefined +>null : null + +declare const a5: true | undefined | null +>a5 : true | null | undefined +>true : true +>null : null + +declare const a6: false | undefined | null +>a6 : false | null | undefined +>false : false +>null : null + + +const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' +>aa1 : boolean | "" | 0 | "literal" | 1 | "whatever" +>a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' : boolean | "" | 0 | "literal" | 1 | "whatever" +>a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 : boolean | "" | 0 | "literal" | 1 | null | undefined +>a1 ?? a2 ?? a3 ?? a4 ?? a5 : true | "" | 0 | "literal" | 1 | null | undefined +>a1 ?? a2 ?? a3 ?? a4 : "" | 0 | "literal" | 1 | null | undefined +>a1 ?? a2 ?? a3 : "" | "literal" | 1 | null | undefined +>a1 ?? a2 : "" | "literal" | null | undefined +>a1 : "literal" | null | undefined +>a2 : "" | null | undefined +>a3 : 1 | null | undefined +>a4 : 0 | null | undefined +>a5 : true | null | undefined +>a6 : false | null | undefined +>'whatever' : "whatever" + diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.js b/tests/baselines/reference/nullishCoalescingOperator_esnext.js new file mode 100644 index 0000000000000..a97dfebaeac80 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.js @@ -0,0 +1,36 @@ +//// [nullishCoalescingOperator_esnext.ts] +// target: esnext + +declare const a1: 'literal' | undefined | null +declare const a2: '' | undefined | null +declare const a3: 1 | undefined | null +declare const a4: 0 | undefined | null +declare const a5: true | undefined | null +declare const a6: false | undefined | null +declare const a7: unknown | null +declare const a8: never | null +declare const a9: any | null + + +const aa1 = a1 ?? 'whatever' +const aa2 = a2 ?? 'whatever' +const aa3 = a3 ?? 'whatever' +const aa4 = a4 ?? 'whatever' +const aa5 = a5 ?? 'whatever' +const aa6 = a6 ?? 'whatever' +const aa7 = a7 ?? 'whatever' +const aa8 = a8 ?? 'whatever' +const aa9 = a9 ?? 'whatever' + +//// [nullishCoalescingOperator_esnext.js] +"use strict"; +// target: esnext +var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever'; +var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever'; +var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever'; +var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever'; +var aa5 = typeof a5 !== "undefined" && a5 !== null ? a5 : 'whatever'; +var aa6 = typeof a6 !== "undefined" && a6 !== null ? a6 : 'whatever'; +var aa7 = typeof a7 !== "undefined" && a7 !== null ? a7 : 'whatever'; +var aa8 = typeof a8 !== "undefined" && a8 !== null ? a8 : 'whatever'; +var aa9 = typeof a9 !== "undefined" && a9 !== null ? a9 : 'whatever'; diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols b/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols new file mode 100644 index 0000000000000..3891363868f24 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols @@ -0,0 +1,67 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts === +// target: esnext + +declare const a1: 'literal' | undefined | null +>a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 2, 13)) + +declare const a2: '' | undefined | null +>a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 3, 13)) + +declare const a3: 1 | undefined | null +>a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 4, 13)) + +declare const a4: 0 | undefined | null +>a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 5, 13)) + +declare const a5: true | undefined | null +>a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 6, 13)) + +declare const a6: false | undefined | null +>a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 7, 13)) + +declare const a7: unknown | null +>a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) + +declare const a8: never | null +>a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 9, 13)) + +declare const a9: any | null +>a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 10, 13)) + + +const aa1 = a1 ?? 'whatever' +>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator_esnext.ts, 13, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 2, 13)) + +const aa2 = a2 ?? 'whatever' +>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator_esnext.ts, 14, 5)) +>a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 3, 13)) + +const aa3 = a3 ?? 'whatever' +>aa3 : Symbol(aa3, Decl(nullishCoalescingOperator_esnext.ts, 15, 5)) +>a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 4, 13)) + +const aa4 = a4 ?? 'whatever' +>aa4 : Symbol(aa4, Decl(nullishCoalescingOperator_esnext.ts, 16, 5)) +>a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 5, 13)) + +const aa5 = a5 ?? 'whatever' +>aa5 : Symbol(aa5, Decl(nullishCoalescingOperator_esnext.ts, 17, 5)) +>a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 6, 13)) + +const aa6 = a6 ?? 'whatever' +>aa6 : Symbol(aa6, Decl(nullishCoalescingOperator_esnext.ts, 18, 5)) +>a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 7, 13)) + +const aa7 = a7 ?? 'whatever' +>aa7 : Symbol(aa7, Decl(nullishCoalescingOperator_esnext.ts, 19, 5)) +>a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) + +const aa8 = a8 ?? 'whatever' +>aa8 : Symbol(aa8, Decl(nullishCoalescingOperator_esnext.ts, 20, 5)) +>a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 9, 13)) + +const aa9 = a9 ?? 'whatever' +>aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_esnext.ts, 21, 5)) +>a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 10, 13)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.types b/tests/baselines/reference/nullishCoalescingOperator_esnext.types new file mode 100644 index 0000000000000..f3355fdd7c314 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.types @@ -0,0 +1,96 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts === +// target: esnext + +declare const a1: 'literal' | undefined | null +>a1 : "literal" | null | undefined +>null : null + +declare const a2: '' | undefined | null +>a2 : "" | null | undefined +>null : null + +declare const a3: 1 | undefined | null +>a3 : 1 | null | undefined +>null : null + +declare const a4: 0 | undefined | null +>a4 : 0 | null | undefined +>null : null + +declare const a5: true | undefined | null +>a5 : true | null | undefined +>true : true +>null : null + +declare const a6: false | undefined | null +>a6 : false | null | undefined +>false : false +>null : null + +declare const a7: unknown | null +>a7 : unknown +>null : null + +declare const a8: never | null +>a8 : null +>null : null + +declare const a9: any | null +>a9 : any +>null : null + + +const aa1 = a1 ?? 'whatever' +>aa1 : "literal" | "whatever" +>a1 ?? 'whatever' : "literal" | "whatever" +>a1 : "literal" | null | undefined +>'whatever' : "whatever" + +const aa2 = a2 ?? 'whatever' +>aa2 : "" | "whatever" +>a2 ?? 'whatever' : "" | "whatever" +>a2 : "" | null | undefined +>'whatever' : "whatever" + +const aa3 = a3 ?? 'whatever' +>aa3 : 1 | "whatever" +>a3 ?? 'whatever' : 1 | "whatever" +>a3 : 1 | null | undefined +>'whatever' : "whatever" + +const aa4 = a4 ?? 'whatever' +>aa4 : 0 | "whatever" +>a4 ?? 'whatever' : 0 | "whatever" +>a4 : 0 | null | undefined +>'whatever' : "whatever" + +const aa5 = a5 ?? 'whatever' +>aa5 : true | "whatever" +>a5 ?? 'whatever' : true | "whatever" +>a5 : true | null | undefined +>'whatever' : "whatever" + +const aa6 = a6 ?? 'whatever' +>aa6 : false | "whatever" +>a6 ?? 'whatever' : false | "whatever" +>a6 : false | null | undefined +>'whatever' : "whatever" + +const aa7 = a7 ?? 'whatever' +>aa7 : unknown +>a7 ?? 'whatever' : unknown +>a7 : unknown +>'whatever' : "whatever" + +const aa8 = a8 ?? 'whatever' +>aa8 : "whatever" +>a8 ?? 'whatever' : "whatever" +>a8 : null +>'whatever' : "whatever" + +const aa9 = a9 ?? 'whatever' +>aa9 : any +>a9 ?? 'whatever' : any +>a9 : any +>'whatever' : "whatever" + diff --git a/tests/baselines/reference/nullishCoalescingOperator_not_strict.js b/tests/baselines/reference/nullishCoalescingOperator_not_strict.js new file mode 100644 index 0000000000000..fd6c6e9ab374c --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator_not_strict.js @@ -0,0 +1,32 @@ +//// [nullishCoalescingOperator_not_strict.ts] +declare const a1: 'literal' | undefined | null +declare const a2: '' | undefined | null +declare const a3: 1 | undefined | null +declare const a4: 0 | undefined | null +declare const a5: true | undefined | null +declare const a6: false | undefined | null +declare const a7: unknown | null +declare const a8: never | null +declare const a9: any | null + + +const aa1 = a1 ?? 'whatever' +const aa2 = a2 ?? 'whatever' +const aa3 = a3 ?? 'whatever' +const aa4 = a4 ?? 'whatever' +const aa5 = a5 ?? 'whatever' +const aa6 = a6 ?? 'whatever' +const aa7 = a7 ?? 'whatever' +const aa8 = a8 ?? 'whatever' +const aa9 = a9 ?? 'whatever' + +//// [nullishCoalescingOperator_not_strict.js] +var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever'; +var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever'; +var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever'; +var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever'; +var aa5 = typeof a5 !== "undefined" && a5 !== null ? a5 : 'whatever'; +var aa6 = typeof a6 !== "undefined" && a6 !== null ? a6 : 'whatever'; +var aa7 = typeof a7 !== "undefined" && a7 !== null ? a7 : 'whatever'; +var aa8 = typeof a8 !== "undefined" && a8 !== null ? a8 : 'whatever'; +var aa9 = typeof a9 !== "undefined" && a9 !== null ? a9 : 'whatever'; diff --git a/tests/baselines/reference/nullishCoalescingOperator_not_strict.symbols b/tests/baselines/reference/nullishCoalescingOperator_not_strict.symbols new file mode 100644 index 0000000000000..76f098e1c2abc --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator_not_strict.symbols @@ -0,0 +1,65 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_not_strict.ts === +declare const a1: 'literal' | undefined | null +>a1 : Symbol(a1, Decl(nullishCoalescingOperator_not_strict.ts, 0, 13)) + +declare const a2: '' | undefined | null +>a2 : Symbol(a2, Decl(nullishCoalescingOperator_not_strict.ts, 1, 13)) + +declare const a3: 1 | undefined | null +>a3 : Symbol(a3, Decl(nullishCoalescingOperator_not_strict.ts, 2, 13)) + +declare const a4: 0 | undefined | null +>a4 : Symbol(a4, Decl(nullishCoalescingOperator_not_strict.ts, 3, 13)) + +declare const a5: true | undefined | null +>a5 : Symbol(a5, Decl(nullishCoalescingOperator_not_strict.ts, 4, 13)) + +declare const a6: false | undefined | null +>a6 : Symbol(a6, Decl(nullishCoalescingOperator_not_strict.ts, 5, 13)) + +declare const a7: unknown | null +>a7 : Symbol(a7, Decl(nullishCoalescingOperator_not_strict.ts, 6, 13)) + +declare const a8: never | null +>a8 : Symbol(a8, Decl(nullishCoalescingOperator_not_strict.ts, 7, 13)) + +declare const a9: any | null +>a9 : Symbol(a9, Decl(nullishCoalescingOperator_not_strict.ts, 8, 13)) + + +const aa1 = a1 ?? 'whatever' +>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator_not_strict.ts, 11, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator_not_strict.ts, 0, 13)) + +const aa2 = a2 ?? 'whatever' +>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator_not_strict.ts, 12, 5)) +>a2 : Symbol(a2, Decl(nullishCoalescingOperator_not_strict.ts, 1, 13)) + +const aa3 = a3 ?? 'whatever' +>aa3 : Symbol(aa3, Decl(nullishCoalescingOperator_not_strict.ts, 13, 5)) +>a3 : Symbol(a3, Decl(nullishCoalescingOperator_not_strict.ts, 2, 13)) + +const aa4 = a4 ?? 'whatever' +>aa4 : Symbol(aa4, Decl(nullishCoalescingOperator_not_strict.ts, 14, 5)) +>a4 : Symbol(a4, Decl(nullishCoalescingOperator_not_strict.ts, 3, 13)) + +const aa5 = a5 ?? 'whatever' +>aa5 : Symbol(aa5, Decl(nullishCoalescingOperator_not_strict.ts, 15, 5)) +>a5 : Symbol(a5, Decl(nullishCoalescingOperator_not_strict.ts, 4, 13)) + +const aa6 = a6 ?? 'whatever' +>aa6 : Symbol(aa6, Decl(nullishCoalescingOperator_not_strict.ts, 16, 5)) +>a6 : Symbol(a6, Decl(nullishCoalescingOperator_not_strict.ts, 5, 13)) + +const aa7 = a7 ?? 'whatever' +>aa7 : Symbol(aa7, Decl(nullishCoalescingOperator_not_strict.ts, 17, 5)) +>a7 : Symbol(a7, Decl(nullishCoalescingOperator_not_strict.ts, 6, 13)) + +const aa8 = a8 ?? 'whatever' +>aa8 : Symbol(aa8, Decl(nullishCoalescingOperator_not_strict.ts, 18, 5)) +>a8 : Symbol(a8, Decl(nullishCoalescingOperator_not_strict.ts, 7, 13)) + +const aa9 = a9 ?? 'whatever' +>aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_not_strict.ts, 19, 5)) +>a9 : Symbol(a9, Decl(nullishCoalescingOperator_not_strict.ts, 8, 13)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator_not_strict.types b/tests/baselines/reference/nullishCoalescingOperator_not_strict.types new file mode 100644 index 0000000000000..adfdce759dce5 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator_not_strict.types @@ -0,0 +1,94 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_not_strict.ts === +declare const a1: 'literal' | undefined | null +>a1 : "literal" +>null : null + +declare const a2: '' | undefined | null +>a2 : "" +>null : null + +declare const a3: 1 | undefined | null +>a3 : 1 +>null : null + +declare const a4: 0 | undefined | null +>a4 : 0 +>null : null + +declare const a5: true | undefined | null +>a5 : true +>true : true +>null : null + +declare const a6: false | undefined | null +>a6 : false +>false : false +>null : null + +declare const a7: unknown | null +>a7 : unknown +>null : null + +declare const a8: never | null +>a8 : null +>null : null + +declare const a9: any | null +>a9 : any +>null : null + + +const aa1 = a1 ?? 'whatever' +>aa1 : "literal" | "whatever" +>a1 ?? 'whatever' : "literal" | "whatever" +>a1 : "literal" +>'whatever' : "whatever" + +const aa2 = a2 ?? 'whatever' +>aa2 : "" | "whatever" +>a2 ?? 'whatever' : "" | "whatever" +>a2 : "" +>'whatever' : "whatever" + +const aa3 = a3 ?? 'whatever' +>aa3 : 1 | "whatever" +>a3 ?? 'whatever' : 1 | "whatever" +>a3 : 1 +>'whatever' : "whatever" + +const aa4 = a4 ?? 'whatever' +>aa4 : 0 | "whatever" +>a4 ?? 'whatever' : 0 | "whatever" +>a4 : 0 +>'whatever' : "whatever" + +const aa5 = a5 ?? 'whatever' +>aa5 : true | "whatever" +>a5 ?? 'whatever' : true | "whatever" +>a5 : true +>'whatever' : "whatever" + +const aa6 = a6 ?? 'whatever' +>aa6 : false | "whatever" +>a6 ?? 'whatever' : false | "whatever" +>a6 : false +>'whatever' : "whatever" + +const aa7 = a7 ?? 'whatever' +>aa7 : unknown +>a7 ?? 'whatever' : unknown +>a7 : unknown +>'whatever' : "whatever" + +const aa8 = a8 ?? 'whatever' +>aa8 : "whatever" +>a8 ?? 'whatever' : "whatever" +>a8 : null +>'whatever' : "whatever" + +const aa9 = a9 ?? 'whatever' +>aa9 : any +>a9 ?? 'whatever' : any +>a9 : any +>'whatever' : "whatever" + diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts new file mode 100644 index 0000000000000..92a48599f5bd6 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts @@ -0,0 +1,12 @@ +// @strict: true + +declare const a1: 'literal' | undefined | null +declare const a2: '' | undefined | null +declare const a3: 1 | undefined | null +declare const a4: 0 | undefined | null +declare const a5: true | undefined | null +declare const a6: false | undefined | null + + +const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' +const aa2 = a1 ?? a1.toString() \ No newline at end of file diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts new file mode 100644 index 0000000000000..23bbd669ee99a --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts @@ -0,0 +1,23 @@ +// @strict: true +// target: esnext + +declare const a1: 'literal' | undefined | null +declare const a2: '' | undefined | null +declare const a3: 1 | undefined | null +declare const a4: 0 | undefined | null +declare const a5: true | undefined | null +declare const a6: false | undefined | null +declare const a7: unknown | null +declare const a8: never | null +declare const a9: any | null + + +const aa1 = a1 ?? 'whatever' +const aa2 = a2 ?? 'whatever' +const aa3 = a3 ?? 'whatever' +const aa4 = a4 ?? 'whatever' +const aa5 = a5 ?? 'whatever' +const aa6 = a6 ?? 'whatever' +const aa7 = a7 ?? 'whatever' +const aa8 = a8 ?? 'whatever' +const aa9 = a9 ?? 'whatever' \ No newline at end of file diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_not_strict.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_not_strict.ts new file mode 100644 index 0000000000000..d05e1c6541eb6 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_not_strict.ts @@ -0,0 +1,22 @@ +// @strict: false + +declare const a1: 'literal' | undefined | null +declare const a2: '' | undefined | null +declare const a3: 1 | undefined | null +declare const a4: 0 | undefined | null +declare const a5: true | undefined | null +declare const a6: false | undefined | null +declare const a7: unknown | null +declare const a8: never | null +declare const a9: any | null + + +const aa1 = a1 ?? 'whatever' +const aa2 = a2 ?? 'whatever' +const aa3 = a3 ?? 'whatever' +const aa4 = a4 ?? 'whatever' +const aa5 = a5 ?? 'whatever' +const aa6 = a6 ?? 'whatever' +const aa7 = a7 ?? 'whatever' +const aa8 = a8 ?? 'whatever' +const aa9 = a9 ?? 'whatever' \ No newline at end of file From ba39ae848a523dd9defc8c22c0705b23c98e269c Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 14 Aug 2019 17:23:58 +0800 Subject: [PATCH 03/26] add branch type check test --- .../reference/nullishCoalescingOperator3.js | 12 +++++----- .../nullishCoalescingOperator4.errors.txt | 13 +++++++++++ .../reference/nullishCoalescingOperator4.js | 10 ++++++++ .../nullishCoalescingOperator4.symbols | 14 +++++++++++ .../nullishCoalescingOperator4.types | 23 +++++++++++++++++++ .../nullishCoalescingOperator3.ts | 1 - .../nullishCoalescingOperator4.ts | 5 ++++ 7 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperator4.errors.txt create mode 100644 tests/baselines/reference/nullishCoalescingOperator4.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator4.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator4.types create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts diff --git a/tests/baselines/reference/nullishCoalescingOperator3.js b/tests/baselines/reference/nullishCoalescingOperator3.js index 00c6ac5073292..8138a9b64389d 100644 --- a/tests/baselines/reference/nullishCoalescingOperator3.js +++ b/tests/baselines/reference/nullishCoalescingOperator3.js @@ -1,4 +1,4 @@ -//// [nullishCoalescingOperator3.ts] +//// [nullishCoalescingOperator3.ts] declare const a1: 'literal' | undefined | null declare const a2: '' | undefined | null declare const a3: 1 | undefined | null @@ -8,8 +8,8 @@ declare const a6: false | undefined | null const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' - - -//// [nullishCoalescingOperator3.js] -"use strict"; -var aa1 = (_a = (_b = (_c = (_d = (_e = typeof a1 !== "undefined" && a1 !== null ? a1 : a2, _e !== void 0 && _e !== null ? _e : a3), _d !== void 0 && _d !== null ? _d : a4), _c !== void 0 && _c !== null ? _c : a5), _b !== void 0 && _b !== null ? _b : a6), _a !== void 0 && _a !== null ? _a : 'whatever'); + + +//// [nullishCoalescingOperator3.js] +"use strict"; +var aa1 = (_a = (_b = (_c = (_d = (_e = typeof a1 !== "undefined" && a1 !== null ? a1 : a2, _e !== void 0 && _e !== null ? _e : a3), _d !== void 0 && _d !== null ? _d : a4), _c !== void 0 && _c !== null ? _c : a5), _b !== void 0 && _b !== null ? _b : a6), _a !== void 0 && _a !== null ? _a : 'whatever'); diff --git a/tests/baselines/reference/nullishCoalescingOperator4.errors.txt b/tests/baselines/reference/nullishCoalescingOperator4.errors.txt new file mode 100644 index 0000000000000..ba8ad2e7ac7c3 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator4.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts(2,19): error TS2533: Object is possibly 'null' or 'undefined'. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts(3,19): error TS2533: Object is possibly 'null' or 'undefined'. + + +==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts (2 errors) ==== + declare const a1: 'literal' | undefined | null + const aa1 = a1 ?? a1.toLowerCase() + ~~ +!!! error TS2533: Object is possibly 'null' or 'undefined'. + const aa2 = a1 || a1.toLocaleUpperCase() + ~~ +!!! error TS2533: Object is possibly 'null' or 'undefined'. + \ No newline at end of file diff --git a/tests/baselines/reference/nullishCoalescingOperator4.js b/tests/baselines/reference/nullishCoalescingOperator4.js new file mode 100644 index 0000000000000..d69f04a4681fd --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator4.js @@ -0,0 +1,10 @@ +//// [nullishCoalescingOperator4.ts] +declare const a1: 'literal' | undefined | null +const aa1 = a1 ?? a1.toLowerCase() +const aa2 = a1 || a1.toLocaleUpperCase() + + +//// [nullishCoalescingOperator4.js] +"use strict"; +var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : a1.toLowerCase(); +var aa2 = a1 || a1.toLocaleUpperCase(); diff --git a/tests/baselines/reference/nullishCoalescingOperator4.symbols b/tests/baselines/reference/nullishCoalescingOperator4.symbols new file mode 100644 index 0000000000000..ec83f771d04a7 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator4.symbols @@ -0,0 +1,14 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts === +declare const a1: 'literal' | undefined | null +>a1 : Symbol(a1, Decl(nullishCoalescingOperator4.ts, 0, 13)) + +const aa1 = a1 ?? a1.toLowerCase() +>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator4.ts, 1, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator4.ts, 0, 13)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator4.ts, 0, 13)) + +const aa2 = a1 || a1.toLocaleUpperCase() +>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator4.ts, 2, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator4.ts, 0, 13)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator4.ts, 0, 13)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator4.types b/tests/baselines/reference/nullishCoalescingOperator4.types new file mode 100644 index 0000000000000..8ac9111c009a2 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator4.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts === +declare const a1: 'literal' | undefined | null +>a1 : "literal" | null | undefined +>null : null + +const aa1 = a1 ?? a1.toLowerCase() +>aa1 : any +>a1 ?? a1.toLowerCase() : any +>a1 : "literal" | null | undefined +>a1.toLowerCase() : any +>a1.toLowerCase : any +>a1 : null | undefined +>toLowerCase : any + +const aa2 = a1 || a1.toLocaleUpperCase() +>aa2 : any +>a1 || a1.toLocaleUpperCase() : any +>a1 : "literal" | null | undefined +>a1.toLocaleUpperCase() : any +>a1.toLocaleUpperCase : any +>a1 : null | undefined +>toLocaleUpperCase : any + diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts index 92a48599f5bd6..288b7cec4fb70 100644 --- a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts @@ -9,4 +9,3 @@ declare const a6: false | undefined | null const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' -const aa2 = a1 ?? a1.toString() \ No newline at end of file diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts new file mode 100644 index 0000000000000..96109d8ad1cd1 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator4.ts @@ -0,0 +1,5 @@ +// @strict: true + +declare const a1: 'literal' | undefined | null +const aa1 = a1 ?? a1.toLowerCase() +const aa2 = a1 || a1.toLocaleUpperCase() From 079d00256fc64686dd567045b96efccff56dcd07 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 14 Aug 2019 17:46:11 +0800 Subject: [PATCH 04/26] add more tests --- .../reference/nullishCoalescingOperator5.js | 68 +++++++++++ .../nullishCoalescingOperator5.symbols | 82 +++++++++++++ .../nullishCoalescingOperator5.types | 114 ++++++++++++++++++ .../reference/nullishCoalescingOperator6.js | 9 ++ .../nullishCoalescingOperator6.symbols | 7 ++ .../nullishCoalescingOperator6.types | 9 ++ .../reference/nullishCoalescingOperator7.js | 22 ++++ .../nullishCoalescingOperator7.symbols | 34 ++++++ .../nullishCoalescingOperator7.types | 58 +++++++++ .../nullishCoalescingOperator_esnext.js | 21 ++-- .../nullishCoalescingOperator_esnext.symbols | 56 +++++---- .../nullishCoalescingOperator_esnext.types | 2 - .../nullishCoalescingOperator5.ts | 41 +++++++ .../nullishCoalescingOperator6.ts | 3 + .../nullishCoalescingOperator7.ts | 13 ++ .../nullishCoalescingOperator_esnext.ts | 2 +- 16 files changed, 497 insertions(+), 44 deletions(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperator5.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator5.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator5.types create mode 100644 tests/baselines/reference/nullishCoalescingOperator6.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator6.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator6.types create mode 100644 tests/baselines/reference/nullishCoalescingOperator7.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator7.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator7.types create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator6.ts create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator7.ts diff --git a/tests/baselines/reference/nullishCoalescingOperator5.js b/tests/baselines/reference/nullishCoalescingOperator5.js new file mode 100644 index 0000000000000..71da6e53ad551 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator5.js @@ -0,0 +1,68 @@ +//// [nullishCoalescingOperator5.ts] +declare const a: string | undefined +declare const b: string | undefined +declare const c: string | undefined + +// should be a syntax error +a ?? b || c; + +// should be a syntax error +a || b ?? c; + +// should be a syntax error +a ?? b && c; + +// should be a syntax error +a && b ?? c; + +// Valid according to spec +a ?? (b || c); + +// Valid according to spec +(a ?? b) || c; + +// Valid according to spec +(a || b) ?? c; + +// Valid according to spec +a || (b ?? c); + +// Valid according to spec +a ?? (b && c); + +// Valid according to spec +(a ?? b) && c; + +// Valid according to spec +(a && b) ?? c; + +// Valid according to spec +a && (b ?? c); + + +//// [nullishCoalescingOperator5.js] +"use strict"; +// should be a syntax error +(typeof a !== "undefined" && a !== null ? a : b) || c; +// should be a syntax error +_a = a || b, _a !== void 0 && _a !== null ? _a : c; +// should be a syntax error +typeof a !== "undefined" && a !== null ? a : b && c; +// should be a syntax error +_b = a && b, _b !== void 0 && _b !== null ? _b : c; +// Valid according to spec +typeof a !== "undefined" && a !== null ? a : (b || c); +// Valid according to spec +(typeof a !== "undefined" && a !== null ? a : b) || c; +// Valid according to spec +_c = (a || b), _c !== void 0 && _c !== null ? _c : c; +// Valid according to spec +a || (typeof b !== "undefined" && b !== null ? b : c); +// Valid according to spec +typeof a !== "undefined" && a !== null ? a : (b && c); +// Valid according to spec +(typeof a !== "undefined" && a !== null ? a : b) && c; +// Valid according to spec +_d = (a && b), _d !== void 0 && _d !== null ? _d : c; +// Valid according to spec +a && (typeof b !== "undefined" && b !== null ? b : c); diff --git a/tests/baselines/reference/nullishCoalescingOperator5.symbols b/tests/baselines/reference/nullishCoalescingOperator5.symbols new file mode 100644 index 0000000000000..d073c91fbc503 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator5.symbols @@ -0,0 +1,82 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts === +declare const a: string | undefined +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) + +declare const b: string | undefined +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) + +declare const c: string | undefined +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// should be a syntax error +a ?? b || c; +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// should be a syntax error +a || b ?? c; +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// should be a syntax error +a ?? b && c; +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// should be a syntax error +a && b ?? c; +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// Valid according to spec +a ?? (b || c); +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// Valid according to spec +(a ?? b) || c; +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// Valid according to spec +(a || b) ?? c; +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// Valid according to spec +a || (b ?? c); +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// Valid according to spec +a ?? (b && c); +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// Valid according to spec +(a ?? b) && c; +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// Valid according to spec +(a && b) ?? c; +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + +// Valid according to spec +a && (b ?? c); +>a : Symbol(a, Decl(nullishCoalescingOperator5.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator5.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator5.ts, 2, 13)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator5.types b/tests/baselines/reference/nullishCoalescingOperator5.types new file mode 100644 index 0000000000000..badb71e76344a --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator5.types @@ -0,0 +1,114 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts === +declare const a: string | undefined +>a : string | undefined + +declare const b: string | undefined +>b : string | undefined + +declare const c: string | undefined +>c : string | undefined + +// should be a syntax error +a ?? b || c; +>a ?? b || c : string | undefined +>a ?? b : string | undefined +>a : string | undefined +>b : string | undefined +>c : string | undefined + +// should be a syntax error +a || b ?? c; +>a || b ?? c : string | undefined +>a || b : string | undefined +>a : string | undefined +>b : string | undefined +>c : string | undefined + +// should be a syntax error +a ?? b && c; +>a ?? b && c : string | undefined +>a : string | undefined +>b && c : string | undefined +>b : string | undefined +>c : string | undefined + +// should be a syntax error +a && b ?? c; +>a && b ?? c : string | undefined +>a && b : string | undefined +>a : string | undefined +>b : string | undefined +>c : string | undefined + +// Valid according to spec +a ?? (b || c); +>a ?? (b || c) : string | undefined +>a : string | undefined +>(b || c) : string | undefined +>b || c : string | undefined +>b : string | undefined +>c : string | undefined + +// Valid according to spec +(a ?? b) || c; +>(a ?? b) || c : string | undefined +>(a ?? b) : string | undefined +>a ?? b : string | undefined +>a : string | undefined +>b : string | undefined +>c : string | undefined + +// Valid according to spec +(a || b) ?? c; +>(a || b) ?? c : string | undefined +>(a || b) : string | undefined +>a || b : string | undefined +>a : string | undefined +>b : string | undefined +>c : string | undefined + +// Valid according to spec +a || (b ?? c); +>a || (b ?? c) : string | undefined +>a : string | undefined +>(b ?? c) : string | undefined +>b ?? c : string | undefined +>b : string | undefined +>c : string | undefined + +// Valid according to spec +a ?? (b && c); +>a ?? (b && c) : string | undefined +>a : string | undefined +>(b && c) : string | undefined +>b && c : string | undefined +>b : string | undefined +>c : string | undefined + +// Valid according to spec +(a ?? b) && c; +>(a ?? b) && c : string | undefined +>(a ?? b) : string | undefined +>a ?? b : string | undefined +>a : string | undefined +>b : string | undefined +>c : string | undefined + +// Valid according to spec +(a && b) ?? c; +>(a && b) ?? c : string | undefined +>(a && b) : string | undefined +>a && b : string | undefined +>a : string | undefined +>b : string | undefined +>c : string | undefined + +// Valid according to spec +a && (b ?? c); +>a && (b ?? c) : string | undefined +>a : string | undefined +>(b ?? c) : string | undefined +>b ?? c : string | undefined +>b : string | undefined +>c : string | undefined + diff --git a/tests/baselines/reference/nullishCoalescingOperator6.js b/tests/baselines/reference/nullishCoalescingOperator6.js new file mode 100644 index 0000000000000..4ba0fddbf8a7a --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator6.js @@ -0,0 +1,9 @@ +//// [nullishCoalescingOperator6.ts] +function foo(foo: string, bar = foo ?? "bar") { } + + +//// [nullishCoalescingOperator6.js] +"use strict"; +function foo(foo, bar) { + if (bar === void 0) { bar = typeof foo !== "undefined" && foo !== null ? foo : "bar"; } +} diff --git a/tests/baselines/reference/nullishCoalescingOperator6.symbols b/tests/baselines/reference/nullishCoalescingOperator6.symbols new file mode 100644 index 0000000000000..41ec5d1c28c0f --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator6.symbols @@ -0,0 +1,7 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator6.ts === +function foo(foo: string, bar = foo ?? "bar") { } +>foo : Symbol(foo, Decl(nullishCoalescingOperator6.ts, 0, 0)) +>foo : Symbol(foo, Decl(nullishCoalescingOperator6.ts, 0, 13)) +>bar : Symbol(bar, Decl(nullishCoalescingOperator6.ts, 0, 25)) +>foo : Symbol(foo, Decl(nullishCoalescingOperator6.ts, 0, 13)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator6.types b/tests/baselines/reference/nullishCoalescingOperator6.types new file mode 100644 index 0000000000000..8bc738ab5fe42 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator6.types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator6.ts === +function foo(foo: string, bar = foo ?? "bar") { } +>foo : (foo: string, bar?: string) => void +>foo : string +>bar : string +>foo ?? "bar" : string +>foo : string +>"bar" : "bar" + diff --git a/tests/baselines/reference/nullishCoalescingOperator7.js b/tests/baselines/reference/nullishCoalescingOperator7.js new file mode 100644 index 0000000000000..bc10e7a5bdbfc --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator7.js @@ -0,0 +1,22 @@ +//// [nullishCoalescingOperator7.ts] +declare const a: string | undefined; +declare const b: string | undefined; +declare const c: string | undefined; + +const foo1 = a ? 1 : 2; +const foo2 = a ?? 'foo' ? 1 : 2; +const foo3 = a ?? 'foo' ? (b ?? 'bar') : (c ?? 'baz'); + +function f () { + const foo4 = a ?? 'foo' ? b ?? 'bar' : c ?? 'baz'; +} + + +//// [nullishCoalescingOperator7.js] +"use strict"; +var foo1 = a ? 1 : 2; +var foo2 = typeof a !== "undefined" && a !== null ? a : 'foo' ? 1 : 2; +var foo3 = typeof a !== "undefined" && a !== null ? a : 'foo' ? (typeof b !== "undefined" && b !== null ? b : 'bar') : (typeof c !== "undefined" && c !== null ? c : 'baz'); +function f() { + var foo4 = typeof a !== "undefined" && a !== null ? a : 'foo' ? typeof b !== "undefined" && b !== null ? b : 'bar' : typeof c !== "undefined" && c !== null ? c : 'baz'; +} diff --git a/tests/baselines/reference/nullishCoalescingOperator7.symbols b/tests/baselines/reference/nullishCoalescingOperator7.symbols new file mode 100644 index 0000000000000..89fc9aaec3f03 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator7.symbols @@ -0,0 +1,34 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator7.ts === +declare const a: string | undefined; +>a : Symbol(a, Decl(nullishCoalescingOperator7.ts, 0, 13)) + +declare const b: string | undefined; +>b : Symbol(b, Decl(nullishCoalescingOperator7.ts, 1, 13)) + +declare const c: string | undefined; +>c : Symbol(c, Decl(nullishCoalescingOperator7.ts, 2, 13)) + +const foo1 = a ? 1 : 2; +>foo1 : Symbol(foo1, Decl(nullishCoalescingOperator7.ts, 4, 5)) +>a : Symbol(a, Decl(nullishCoalescingOperator7.ts, 0, 13)) + +const foo2 = a ?? 'foo' ? 1 : 2; +>foo2 : Symbol(foo2, Decl(nullishCoalescingOperator7.ts, 5, 5)) +>a : Symbol(a, Decl(nullishCoalescingOperator7.ts, 0, 13)) + +const foo3 = a ?? 'foo' ? (b ?? 'bar') : (c ?? 'baz'); +>foo3 : Symbol(foo3, Decl(nullishCoalescingOperator7.ts, 6, 5)) +>a : Symbol(a, Decl(nullishCoalescingOperator7.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator7.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator7.ts, 2, 13)) + +function f () { +>f : Symbol(f, Decl(nullishCoalescingOperator7.ts, 6, 54)) + + const foo4 = a ?? 'foo' ? b ?? 'bar' : c ?? 'baz'; +>foo4 : Symbol(foo4, Decl(nullishCoalescingOperator7.ts, 9, 9)) +>a : Symbol(a, Decl(nullishCoalescingOperator7.ts, 0, 13)) +>b : Symbol(b, Decl(nullishCoalescingOperator7.ts, 1, 13)) +>c : Symbol(c, Decl(nullishCoalescingOperator7.ts, 2, 13)) +} + diff --git a/tests/baselines/reference/nullishCoalescingOperator7.types b/tests/baselines/reference/nullishCoalescingOperator7.types new file mode 100644 index 0000000000000..a465779625dfd --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator7.types @@ -0,0 +1,58 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator7.ts === +declare const a: string | undefined; +>a : string | undefined + +declare const b: string | undefined; +>b : string | undefined + +declare const c: string | undefined; +>c : string | undefined + +const foo1 = a ? 1 : 2; +>foo1 : 1 | 2 +>a ? 1 : 2 : 1 | 2 +>a : string | undefined +>1 : 1 +>2 : 2 + +const foo2 = a ?? 'foo' ? 1 : 2; +>foo2 : 1 | 2 +>a ?? 'foo' ? 1 : 2 : 1 | 2 +>a ?? 'foo' : string +>a : string | undefined +>'foo' : "foo" +>1 : 1 +>2 : 2 + +const foo3 = a ?? 'foo' ? (b ?? 'bar') : (c ?? 'baz'); +>foo3 : string +>a ?? 'foo' ? (b ?? 'bar') : (c ?? 'baz') : string +>a ?? 'foo' : string +>a : string | undefined +>'foo' : "foo" +>(b ?? 'bar') : string +>b ?? 'bar' : string +>b : string | undefined +>'bar' : "bar" +>(c ?? 'baz') : string +>c ?? 'baz' : string +>c : string | undefined +>'baz' : "baz" + +function f () { +>f : () => void + + const foo4 = a ?? 'foo' ? b ?? 'bar' : c ?? 'baz'; +>foo4 : string +>a ?? 'foo' ? b ?? 'bar' : c ?? 'baz' : string +>a ?? 'foo' : string +>a : string | undefined +>'foo' : "foo" +>b ?? 'bar' : string +>b : string | undefined +>'bar' : "bar" +>c ?? 'baz' : string +>c : string | undefined +>'baz' : "baz" +} + diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.js b/tests/baselines/reference/nullishCoalescingOperator_esnext.js index a97dfebaeac80..0593e7bb211b0 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.js +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.js @@ -1,6 +1,4 @@ //// [nullishCoalescingOperator_esnext.ts] -// target: esnext - declare const a1: 'literal' | undefined | null declare const a2: '' | undefined | null declare const a3: 1 | undefined | null @@ -24,13 +22,12 @@ const aa9 = a9 ?? 'whatever' //// [nullishCoalescingOperator_esnext.js] "use strict"; -// target: esnext -var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever'; -var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever'; -var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever'; -var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever'; -var aa5 = typeof a5 !== "undefined" && a5 !== null ? a5 : 'whatever'; -var aa6 = typeof a6 !== "undefined" && a6 !== null ? a6 : 'whatever'; -var aa7 = typeof a7 !== "undefined" && a7 !== null ? a7 : 'whatever'; -var aa8 = typeof a8 !== "undefined" && a8 !== null ? a8 : 'whatever'; -var aa9 = typeof a9 !== "undefined" && a9 !== null ? a9 : 'whatever'; +const aa1 = a1 ?? 'whatever'; +const aa2 = a2 ?? 'whatever'; +const aa3 = a3 ?? 'whatever'; +const aa4 = a4 ?? 'whatever'; +const aa5 = a5 ?? 'whatever'; +const aa6 = a6 ?? 'whatever'; +const aa7 = a7 ?? 'whatever'; +const aa8 = a8 ?? 'whatever'; +const aa9 = a9 ?? 'whatever'; diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols b/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols index 3891363868f24..d5829609552d8 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols @@ -1,67 +1,65 @@ === tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts === -// target: esnext - declare const a1: 'literal' | undefined | null ->a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 2, 13)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 0, 13)) declare const a2: '' | undefined | null ->a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 3, 13)) +>a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 1, 13)) declare const a3: 1 | undefined | null ->a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 4, 13)) +>a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 2, 13)) declare const a4: 0 | undefined | null ->a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 5, 13)) +>a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 3, 13)) declare const a5: true | undefined | null ->a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 6, 13)) +>a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 4, 13)) declare const a6: false | undefined | null ->a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 7, 13)) +>a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 5, 13)) declare const a7: unknown | null ->a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) +>a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 6, 13)) declare const a8: never | null ->a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 9, 13)) +>a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 7, 13)) declare const a9: any | null ->a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 10, 13)) +>a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) const aa1 = a1 ?? 'whatever' ->aa1 : Symbol(aa1, Decl(nullishCoalescingOperator_esnext.ts, 13, 5)) ->a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 2, 13)) +>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator_esnext.ts, 11, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 0, 13)) const aa2 = a2 ?? 'whatever' ->aa2 : Symbol(aa2, Decl(nullishCoalescingOperator_esnext.ts, 14, 5)) ->a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 3, 13)) +>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator_esnext.ts, 12, 5)) +>a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 1, 13)) const aa3 = a3 ?? 'whatever' ->aa3 : Symbol(aa3, Decl(nullishCoalescingOperator_esnext.ts, 15, 5)) ->a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 4, 13)) +>aa3 : Symbol(aa3, Decl(nullishCoalescingOperator_esnext.ts, 13, 5)) +>a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 2, 13)) const aa4 = a4 ?? 'whatever' ->aa4 : Symbol(aa4, Decl(nullishCoalescingOperator_esnext.ts, 16, 5)) ->a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 5, 13)) +>aa4 : Symbol(aa4, Decl(nullishCoalescingOperator_esnext.ts, 14, 5)) +>a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 3, 13)) const aa5 = a5 ?? 'whatever' ->aa5 : Symbol(aa5, Decl(nullishCoalescingOperator_esnext.ts, 17, 5)) ->a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 6, 13)) +>aa5 : Symbol(aa5, Decl(nullishCoalescingOperator_esnext.ts, 15, 5)) +>a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 4, 13)) const aa6 = a6 ?? 'whatever' ->aa6 : Symbol(aa6, Decl(nullishCoalescingOperator_esnext.ts, 18, 5)) ->a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 7, 13)) +>aa6 : Symbol(aa6, Decl(nullishCoalescingOperator_esnext.ts, 16, 5)) +>a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 5, 13)) const aa7 = a7 ?? 'whatever' ->aa7 : Symbol(aa7, Decl(nullishCoalescingOperator_esnext.ts, 19, 5)) ->a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) +>aa7 : Symbol(aa7, Decl(nullishCoalescingOperator_esnext.ts, 17, 5)) +>a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 6, 13)) const aa8 = a8 ?? 'whatever' ->aa8 : Symbol(aa8, Decl(nullishCoalescingOperator_esnext.ts, 20, 5)) ->a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 9, 13)) +>aa8 : Symbol(aa8, Decl(nullishCoalescingOperator_esnext.ts, 18, 5)) +>a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 7, 13)) const aa9 = a9 ?? 'whatever' ->aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_esnext.ts, 21, 5)) ->a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 10, 13)) +>aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_esnext.ts, 19, 5)) +>a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.types b/tests/baselines/reference/nullishCoalescingOperator_esnext.types index f3355fdd7c314..6ee6cf167444a 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.types +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.types @@ -1,6 +1,4 @@ === tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts === -// target: esnext - declare const a1: 'literal' | undefined | null >a1 : "literal" | null | undefined >null : null diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts new file mode 100644 index 0000000000000..d1c68e0dd7775 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts @@ -0,0 +1,41 @@ +// @strict: true + +declare const a: string | undefined +declare const b: string | undefined +declare const c: string | undefined + +// should be a syntax error +a ?? b || c; + +// should be a syntax error +a || b ?? c; + +// should be a syntax error +a ?? b && c; + +// should be a syntax error +a && b ?? c; + +// Valid according to spec +a ?? (b || c); + +// Valid according to spec +(a ?? b) || c; + +// Valid according to spec +(a || b) ?? c; + +// Valid according to spec +a || (b ?? c); + +// Valid according to spec +a ?? (b && c); + +// Valid according to spec +(a ?? b) && c; + +// Valid according to spec +(a && b) ?? c; + +// Valid according to spec +a && (b ?? c); diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator6.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator6.ts new file mode 100644 index 0000000000000..01db04f4ab269 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator6.ts @@ -0,0 +1,3 @@ +// @strict: true + +function foo(foo: string, bar = foo ?? "bar") { } diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator7.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator7.ts new file mode 100644 index 0000000000000..0390e8ec480e4 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator7.ts @@ -0,0 +1,13 @@ +// @strict: true + +declare const a: string | undefined; +declare const b: string | undefined; +declare const c: string | undefined; + +const foo1 = a ? 1 : 2; +const foo2 = a ?? 'foo' ? 1 : 2; +const foo3 = a ?? 'foo' ? (b ?? 'bar') : (c ?? 'baz'); + +function f () { + const foo4 = a ?? 'foo' ? b ?? 'bar' : c ?? 'baz'; +} diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts index 23bbd669ee99a..5713107859b3d 100644 --- a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts @@ -1,5 +1,5 @@ // @strict: true -// target: esnext +// @target: esnext declare const a1: 'literal' | undefined | null declare const a2: '' | undefined | null From 3822fde4fecbab458079ae75644eccc1047cced1 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 14 Aug 2019 17:55:15 +0800 Subject: [PATCH 05/26] fix nullish precedence --- src/compiler/utilities.ts | 1 + tests/baselines/reference/nullishCoalescingOperator5.js | 2 +- tests/baselines/reference/nullishCoalescingOperator5.types | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6017bc6096162..445ca85faee37 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2989,6 +2989,7 @@ namespace ts { export function getBinaryOperatorPrecedence(kind: SyntaxKind): number { switch (kind) { case SyntaxKind.QuestionQuestionToken: + return 4; case SyntaxKind.BarBarToken: return 5; case SyntaxKind.AmpersandAmpersandToken: diff --git a/tests/baselines/reference/nullishCoalescingOperator5.js b/tests/baselines/reference/nullishCoalescingOperator5.js index 71da6e53ad551..46d7cc624b341 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.js +++ b/tests/baselines/reference/nullishCoalescingOperator5.js @@ -43,7 +43,7 @@ a && (b ?? c); //// [nullishCoalescingOperator5.js] "use strict"; // should be a syntax error -(typeof a !== "undefined" && a !== null ? a : b) || c; +typeof a !== "undefined" && a !== null ? a : b || c; // should be a syntax error _a = a || b, _a !== void 0 && _a !== null ? _a : c; // should be a syntax error diff --git a/tests/baselines/reference/nullishCoalescingOperator5.types b/tests/baselines/reference/nullishCoalescingOperator5.types index badb71e76344a..bbf526d774339 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.types +++ b/tests/baselines/reference/nullishCoalescingOperator5.types @@ -11,8 +11,8 @@ declare const c: string | undefined // should be a syntax error a ?? b || c; >a ?? b || c : string | undefined ->a ?? b : string | undefined >a : string | undefined +>b || c : string | undefined >b : string | undefined >c : string | undefined From f67e524b8e49f74012e83547602cc953c390d181 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 14 Aug 2019 17:59:14 +0800 Subject: [PATCH 06/26] update public api --- .../reference/api/tsserverlibrary.d.ts | 564 +++++++++--------- tests/baselines/reference/api/typescript.d.ts | 564 +++++++++--------- 2 files changed, 566 insertions(+), 562 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index cbab57b0644e8..507fdb757a13f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -135,283 +135,284 @@ declare namespace ts { QuestionToken = 56, ColonToken = 57, AtToken = 58, + QuestionQuestionToken = 59, /** Only the JSDoc scanner produces BacktickToken. The normal scanner produces NoSubstitutionTemplateLiteral and related kinds. */ - BacktickToken = 59, - EqualsToken = 60, - PlusEqualsToken = 61, - MinusEqualsToken = 62, - AsteriskEqualsToken = 63, - AsteriskAsteriskEqualsToken = 64, - SlashEqualsToken = 65, - PercentEqualsToken = 66, - LessThanLessThanEqualsToken = 67, - GreaterThanGreaterThanEqualsToken = 68, - GreaterThanGreaterThanGreaterThanEqualsToken = 69, - AmpersandEqualsToken = 70, - BarEqualsToken = 71, - CaretEqualsToken = 72, - Identifier = 73, - BreakKeyword = 74, - CaseKeyword = 75, - CatchKeyword = 76, - ClassKeyword = 77, - ConstKeyword = 78, - ContinueKeyword = 79, - DebuggerKeyword = 80, - DefaultKeyword = 81, - DeleteKeyword = 82, - DoKeyword = 83, - ElseKeyword = 84, - EnumKeyword = 85, - ExportKeyword = 86, - ExtendsKeyword = 87, - FalseKeyword = 88, - FinallyKeyword = 89, - ForKeyword = 90, - FunctionKeyword = 91, - IfKeyword = 92, - ImportKeyword = 93, - InKeyword = 94, - InstanceOfKeyword = 95, - NewKeyword = 96, - NullKeyword = 97, - ReturnKeyword = 98, - SuperKeyword = 99, - SwitchKeyword = 100, - ThisKeyword = 101, - ThrowKeyword = 102, - TrueKeyword = 103, - TryKeyword = 104, - TypeOfKeyword = 105, - VarKeyword = 106, - VoidKeyword = 107, - WhileKeyword = 108, - WithKeyword = 109, - ImplementsKeyword = 110, - InterfaceKeyword = 111, - LetKeyword = 112, - PackageKeyword = 113, - PrivateKeyword = 114, - ProtectedKeyword = 115, - PublicKeyword = 116, - StaticKeyword = 117, - YieldKeyword = 118, - AbstractKeyword = 119, - AsKeyword = 120, - AnyKeyword = 121, - AsyncKeyword = 122, - AwaitKeyword = 123, - BooleanKeyword = 124, - ConstructorKeyword = 125, - DeclareKeyword = 126, - GetKeyword = 127, - InferKeyword = 128, - IsKeyword = 129, - KeyOfKeyword = 130, - ModuleKeyword = 131, - NamespaceKeyword = 132, - NeverKeyword = 133, - ReadonlyKeyword = 134, - RequireKeyword = 135, - NumberKeyword = 136, - ObjectKeyword = 137, - SetKeyword = 138, - StringKeyword = 139, - SymbolKeyword = 140, - TypeKeyword = 141, - UndefinedKeyword = 142, - UniqueKeyword = 143, - UnknownKeyword = 144, - FromKeyword = 145, - GlobalKeyword = 146, - BigIntKeyword = 147, - OfKeyword = 148, - QualifiedName = 149, - ComputedPropertyName = 150, - TypeParameter = 151, - Parameter = 152, - Decorator = 153, - PropertySignature = 154, - PropertyDeclaration = 155, - MethodSignature = 156, - MethodDeclaration = 157, - Constructor = 158, - GetAccessor = 159, - SetAccessor = 160, - CallSignature = 161, - ConstructSignature = 162, - IndexSignature = 163, - TypePredicate = 164, - TypeReference = 165, - FunctionType = 166, - ConstructorType = 167, - TypeQuery = 168, - TypeLiteral = 169, - ArrayType = 170, - TupleType = 171, - OptionalType = 172, - RestType = 173, - UnionType = 174, - IntersectionType = 175, - ConditionalType = 176, - InferType = 177, - ParenthesizedType = 178, - ThisType = 179, - TypeOperator = 180, - IndexedAccessType = 181, - MappedType = 182, - LiteralType = 183, - ImportType = 184, - ObjectBindingPattern = 185, - ArrayBindingPattern = 186, - BindingElement = 187, - ArrayLiteralExpression = 188, - ObjectLiteralExpression = 189, - PropertyAccessExpression = 190, - ElementAccessExpression = 191, - CallExpression = 192, - NewExpression = 193, - TaggedTemplateExpression = 194, - TypeAssertionExpression = 195, - ParenthesizedExpression = 196, - FunctionExpression = 197, - ArrowFunction = 198, - DeleteExpression = 199, - TypeOfExpression = 200, - VoidExpression = 201, - AwaitExpression = 202, - PrefixUnaryExpression = 203, - PostfixUnaryExpression = 204, - BinaryExpression = 205, - ConditionalExpression = 206, - TemplateExpression = 207, - YieldExpression = 208, - SpreadElement = 209, - ClassExpression = 210, - OmittedExpression = 211, - ExpressionWithTypeArguments = 212, - AsExpression = 213, - NonNullExpression = 214, - MetaProperty = 215, - SyntheticExpression = 216, - TemplateSpan = 217, - SemicolonClassElement = 218, - Block = 219, - VariableStatement = 220, - EmptyStatement = 221, - ExpressionStatement = 222, - IfStatement = 223, - DoStatement = 224, - WhileStatement = 225, - ForStatement = 226, - ForInStatement = 227, - ForOfStatement = 228, - ContinueStatement = 229, - BreakStatement = 230, - ReturnStatement = 231, - WithStatement = 232, - SwitchStatement = 233, - LabeledStatement = 234, - ThrowStatement = 235, - TryStatement = 236, - DebuggerStatement = 237, - VariableDeclaration = 238, - VariableDeclarationList = 239, - FunctionDeclaration = 240, - ClassDeclaration = 241, - InterfaceDeclaration = 242, - TypeAliasDeclaration = 243, - EnumDeclaration = 244, - ModuleDeclaration = 245, - ModuleBlock = 246, - CaseBlock = 247, - NamespaceExportDeclaration = 248, - ImportEqualsDeclaration = 249, - ImportDeclaration = 250, - ImportClause = 251, - NamespaceImport = 252, - NamedImports = 253, - ImportSpecifier = 254, - ExportAssignment = 255, - ExportDeclaration = 256, - NamedExports = 257, - ExportSpecifier = 258, - MissingDeclaration = 259, - ExternalModuleReference = 260, - JsxElement = 261, - JsxSelfClosingElement = 262, - JsxOpeningElement = 263, - JsxClosingElement = 264, - JsxFragment = 265, - JsxOpeningFragment = 266, - JsxClosingFragment = 267, - JsxAttribute = 268, - JsxAttributes = 269, - JsxSpreadAttribute = 270, - JsxExpression = 271, - CaseClause = 272, - DefaultClause = 273, - HeritageClause = 274, - CatchClause = 275, - PropertyAssignment = 276, - ShorthandPropertyAssignment = 277, - SpreadAssignment = 278, - EnumMember = 279, - UnparsedPrologue = 280, - UnparsedPrepend = 281, - UnparsedText = 282, - UnparsedInternalText = 283, - UnparsedSyntheticReference = 284, - SourceFile = 285, - Bundle = 286, - UnparsedSource = 287, - InputFiles = 288, - JSDocTypeExpression = 289, - JSDocAllType = 290, - JSDocUnknownType = 291, - JSDocNullableType = 292, - JSDocNonNullableType = 293, - JSDocOptionalType = 294, - JSDocFunctionType = 295, - JSDocVariadicType = 296, - JSDocComment = 297, - JSDocTypeLiteral = 298, - JSDocSignature = 299, - JSDocTag = 300, - JSDocAugmentsTag = 301, - JSDocClassTag = 302, - JSDocCallbackTag = 303, - JSDocEnumTag = 304, - JSDocParameterTag = 305, - JSDocReturnTag = 306, - JSDocThisTag = 307, - JSDocTypeTag = 308, - JSDocTemplateTag = 309, - JSDocTypedefTag = 310, - JSDocPropertyTag = 311, - SyntaxList = 312, - NotEmittedStatement = 313, - PartiallyEmittedExpression = 314, - CommaListExpression = 315, - MergeDeclarationMarker = 316, - EndOfDeclarationMarker = 317, - Count = 318, - FirstAssignment = 60, - LastAssignment = 72, - FirstCompoundAssignment = 61, - LastCompoundAssignment = 72, - FirstReservedWord = 74, - LastReservedWord = 109, - FirstKeyword = 74, - LastKeyword = 148, - FirstFutureReservedWord = 110, - LastFutureReservedWord = 118, - FirstTypeNode = 164, - LastTypeNode = 184, + BacktickToken = 60, + EqualsToken = 61, + PlusEqualsToken = 62, + MinusEqualsToken = 63, + AsteriskEqualsToken = 64, + AsteriskAsteriskEqualsToken = 65, + SlashEqualsToken = 66, + PercentEqualsToken = 67, + LessThanLessThanEqualsToken = 68, + GreaterThanGreaterThanEqualsToken = 69, + GreaterThanGreaterThanGreaterThanEqualsToken = 70, + AmpersandEqualsToken = 71, + BarEqualsToken = 72, + CaretEqualsToken = 73, + Identifier = 74, + BreakKeyword = 75, + CaseKeyword = 76, + CatchKeyword = 77, + ClassKeyword = 78, + ConstKeyword = 79, + ContinueKeyword = 80, + DebuggerKeyword = 81, + DefaultKeyword = 82, + DeleteKeyword = 83, + DoKeyword = 84, + ElseKeyword = 85, + EnumKeyword = 86, + ExportKeyword = 87, + ExtendsKeyword = 88, + FalseKeyword = 89, + FinallyKeyword = 90, + ForKeyword = 91, + FunctionKeyword = 92, + IfKeyword = 93, + ImportKeyword = 94, + InKeyword = 95, + InstanceOfKeyword = 96, + NewKeyword = 97, + NullKeyword = 98, + ReturnKeyword = 99, + SuperKeyword = 100, + SwitchKeyword = 101, + ThisKeyword = 102, + ThrowKeyword = 103, + TrueKeyword = 104, + TryKeyword = 105, + TypeOfKeyword = 106, + VarKeyword = 107, + VoidKeyword = 108, + WhileKeyword = 109, + WithKeyword = 110, + ImplementsKeyword = 111, + InterfaceKeyword = 112, + LetKeyword = 113, + PackageKeyword = 114, + PrivateKeyword = 115, + ProtectedKeyword = 116, + PublicKeyword = 117, + StaticKeyword = 118, + YieldKeyword = 119, + AbstractKeyword = 120, + AsKeyword = 121, + AnyKeyword = 122, + AsyncKeyword = 123, + AwaitKeyword = 124, + BooleanKeyword = 125, + ConstructorKeyword = 126, + DeclareKeyword = 127, + GetKeyword = 128, + InferKeyword = 129, + IsKeyword = 130, + KeyOfKeyword = 131, + ModuleKeyword = 132, + NamespaceKeyword = 133, + NeverKeyword = 134, + ReadonlyKeyword = 135, + RequireKeyword = 136, + NumberKeyword = 137, + ObjectKeyword = 138, + SetKeyword = 139, + StringKeyword = 140, + SymbolKeyword = 141, + TypeKeyword = 142, + UndefinedKeyword = 143, + UniqueKeyword = 144, + UnknownKeyword = 145, + FromKeyword = 146, + GlobalKeyword = 147, + BigIntKeyword = 148, + OfKeyword = 149, + QualifiedName = 150, + ComputedPropertyName = 151, + TypeParameter = 152, + Parameter = 153, + Decorator = 154, + PropertySignature = 155, + PropertyDeclaration = 156, + MethodSignature = 157, + MethodDeclaration = 158, + Constructor = 159, + GetAccessor = 160, + SetAccessor = 161, + CallSignature = 162, + ConstructSignature = 163, + IndexSignature = 164, + TypePredicate = 165, + TypeReference = 166, + FunctionType = 167, + ConstructorType = 168, + TypeQuery = 169, + TypeLiteral = 170, + ArrayType = 171, + TupleType = 172, + OptionalType = 173, + RestType = 174, + UnionType = 175, + IntersectionType = 176, + ConditionalType = 177, + InferType = 178, + ParenthesizedType = 179, + ThisType = 180, + TypeOperator = 181, + IndexedAccessType = 182, + MappedType = 183, + LiteralType = 184, + ImportType = 185, + ObjectBindingPattern = 186, + ArrayBindingPattern = 187, + BindingElement = 188, + ArrayLiteralExpression = 189, + ObjectLiteralExpression = 190, + PropertyAccessExpression = 191, + ElementAccessExpression = 192, + CallExpression = 193, + NewExpression = 194, + TaggedTemplateExpression = 195, + TypeAssertionExpression = 196, + ParenthesizedExpression = 197, + FunctionExpression = 198, + ArrowFunction = 199, + DeleteExpression = 200, + TypeOfExpression = 201, + VoidExpression = 202, + AwaitExpression = 203, + PrefixUnaryExpression = 204, + PostfixUnaryExpression = 205, + BinaryExpression = 206, + ConditionalExpression = 207, + TemplateExpression = 208, + YieldExpression = 209, + SpreadElement = 210, + ClassExpression = 211, + OmittedExpression = 212, + ExpressionWithTypeArguments = 213, + AsExpression = 214, + NonNullExpression = 215, + MetaProperty = 216, + SyntheticExpression = 217, + TemplateSpan = 218, + SemicolonClassElement = 219, + Block = 220, + VariableStatement = 221, + EmptyStatement = 222, + ExpressionStatement = 223, + IfStatement = 224, + DoStatement = 225, + WhileStatement = 226, + ForStatement = 227, + ForInStatement = 228, + ForOfStatement = 229, + ContinueStatement = 230, + BreakStatement = 231, + ReturnStatement = 232, + WithStatement = 233, + SwitchStatement = 234, + LabeledStatement = 235, + ThrowStatement = 236, + TryStatement = 237, + DebuggerStatement = 238, + VariableDeclaration = 239, + VariableDeclarationList = 240, + FunctionDeclaration = 241, + ClassDeclaration = 242, + InterfaceDeclaration = 243, + TypeAliasDeclaration = 244, + EnumDeclaration = 245, + ModuleDeclaration = 246, + ModuleBlock = 247, + CaseBlock = 248, + NamespaceExportDeclaration = 249, + ImportEqualsDeclaration = 250, + ImportDeclaration = 251, + ImportClause = 252, + NamespaceImport = 253, + NamedImports = 254, + ImportSpecifier = 255, + ExportAssignment = 256, + ExportDeclaration = 257, + NamedExports = 258, + ExportSpecifier = 259, + MissingDeclaration = 260, + ExternalModuleReference = 261, + JsxElement = 262, + JsxSelfClosingElement = 263, + JsxOpeningElement = 264, + JsxClosingElement = 265, + JsxFragment = 266, + JsxOpeningFragment = 267, + JsxClosingFragment = 268, + JsxAttribute = 269, + JsxAttributes = 270, + JsxSpreadAttribute = 271, + JsxExpression = 272, + CaseClause = 273, + DefaultClause = 274, + HeritageClause = 275, + CatchClause = 276, + PropertyAssignment = 277, + ShorthandPropertyAssignment = 278, + SpreadAssignment = 279, + EnumMember = 280, + UnparsedPrologue = 281, + UnparsedPrepend = 282, + UnparsedText = 283, + UnparsedInternalText = 284, + UnparsedSyntheticReference = 285, + SourceFile = 286, + Bundle = 287, + UnparsedSource = 288, + InputFiles = 289, + JSDocTypeExpression = 290, + JSDocAllType = 291, + JSDocUnknownType = 292, + JSDocNullableType = 293, + JSDocNonNullableType = 294, + JSDocOptionalType = 295, + JSDocFunctionType = 296, + JSDocVariadicType = 297, + JSDocComment = 298, + JSDocTypeLiteral = 299, + JSDocSignature = 300, + JSDocTag = 301, + JSDocAugmentsTag = 302, + JSDocClassTag = 303, + JSDocCallbackTag = 304, + JSDocEnumTag = 305, + JSDocParameterTag = 306, + JSDocReturnTag = 307, + JSDocThisTag = 308, + JSDocTypeTag = 309, + JSDocTemplateTag = 310, + JSDocTypedefTag = 311, + JSDocPropertyTag = 312, + SyntaxList = 313, + NotEmittedStatement = 314, + PartiallyEmittedExpression = 315, + CommaListExpression = 316, + MergeDeclarationMarker = 317, + EndOfDeclarationMarker = 318, + Count = 319, + FirstAssignment = 61, + LastAssignment = 73, + FirstCompoundAssignment = 62, + LastCompoundAssignment = 73, + FirstReservedWord = 75, + LastReservedWord = 110, + FirstKeyword = 75, + LastKeyword = 149, + FirstFutureReservedWord = 111, + LastFutureReservedWord = 119, + FirstTypeNode = 165, + LastTypeNode = 185, FirstPunctuation = 18, - LastPunctuation = 72, + LastPunctuation = 73, FirstToken = 0, - LastToken = 148, + LastToken = 149, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -419,12 +420,12 @@ declare namespace ts { FirstTemplateToken = 14, LastTemplateToken = 17, FirstBinaryOperator = 28, - LastBinaryOperator = 72, - FirstNode = 149, - FirstJSDocNode = 289, - LastJSDocNode = 311, - FirstJSDocTagNode = 300, - LastJSDocTagNode = 311, + LastBinaryOperator = 73, + FirstNode = 150, + FirstJSDocNode = 290, + LastJSDocNode = 312, + FirstJSDocTagNode = 301, + LastJSDocTagNode = 312, } enum NodeFlags { None = 0, @@ -937,7 +938,7 @@ declare namespace ts { type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; - type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken; + type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken; type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; @@ -4095,6 +4096,7 @@ declare namespace ts { function createPostfixIncrement(operand: Expression): PostfixUnaryExpression; function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; function createLogicalOr(left: Expression, right: Expression): BinaryExpression; + function createNullishCoalescing(left: Expression, right: Expression): BinaryExpression; function createLogicalNot(operand: Expression): PrefixUnaryExpression; function createVoidZero(): VoidExpression; function createExportDefault(expression: Expression): ExportAssignment; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index fd254a2fe5074..c54d9d4538cc3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -135,283 +135,284 @@ declare namespace ts { QuestionToken = 56, ColonToken = 57, AtToken = 58, + QuestionQuestionToken = 59, /** Only the JSDoc scanner produces BacktickToken. The normal scanner produces NoSubstitutionTemplateLiteral and related kinds. */ - BacktickToken = 59, - EqualsToken = 60, - PlusEqualsToken = 61, - MinusEqualsToken = 62, - AsteriskEqualsToken = 63, - AsteriskAsteriskEqualsToken = 64, - SlashEqualsToken = 65, - PercentEqualsToken = 66, - LessThanLessThanEqualsToken = 67, - GreaterThanGreaterThanEqualsToken = 68, - GreaterThanGreaterThanGreaterThanEqualsToken = 69, - AmpersandEqualsToken = 70, - BarEqualsToken = 71, - CaretEqualsToken = 72, - Identifier = 73, - BreakKeyword = 74, - CaseKeyword = 75, - CatchKeyword = 76, - ClassKeyword = 77, - ConstKeyword = 78, - ContinueKeyword = 79, - DebuggerKeyword = 80, - DefaultKeyword = 81, - DeleteKeyword = 82, - DoKeyword = 83, - ElseKeyword = 84, - EnumKeyword = 85, - ExportKeyword = 86, - ExtendsKeyword = 87, - FalseKeyword = 88, - FinallyKeyword = 89, - ForKeyword = 90, - FunctionKeyword = 91, - IfKeyword = 92, - ImportKeyword = 93, - InKeyword = 94, - InstanceOfKeyword = 95, - NewKeyword = 96, - NullKeyword = 97, - ReturnKeyword = 98, - SuperKeyword = 99, - SwitchKeyword = 100, - ThisKeyword = 101, - ThrowKeyword = 102, - TrueKeyword = 103, - TryKeyword = 104, - TypeOfKeyword = 105, - VarKeyword = 106, - VoidKeyword = 107, - WhileKeyword = 108, - WithKeyword = 109, - ImplementsKeyword = 110, - InterfaceKeyword = 111, - LetKeyword = 112, - PackageKeyword = 113, - PrivateKeyword = 114, - ProtectedKeyword = 115, - PublicKeyword = 116, - StaticKeyword = 117, - YieldKeyword = 118, - AbstractKeyword = 119, - AsKeyword = 120, - AnyKeyword = 121, - AsyncKeyword = 122, - AwaitKeyword = 123, - BooleanKeyword = 124, - ConstructorKeyword = 125, - DeclareKeyword = 126, - GetKeyword = 127, - InferKeyword = 128, - IsKeyword = 129, - KeyOfKeyword = 130, - ModuleKeyword = 131, - NamespaceKeyword = 132, - NeverKeyword = 133, - ReadonlyKeyword = 134, - RequireKeyword = 135, - NumberKeyword = 136, - ObjectKeyword = 137, - SetKeyword = 138, - StringKeyword = 139, - SymbolKeyword = 140, - TypeKeyword = 141, - UndefinedKeyword = 142, - UniqueKeyword = 143, - UnknownKeyword = 144, - FromKeyword = 145, - GlobalKeyword = 146, - BigIntKeyword = 147, - OfKeyword = 148, - QualifiedName = 149, - ComputedPropertyName = 150, - TypeParameter = 151, - Parameter = 152, - Decorator = 153, - PropertySignature = 154, - PropertyDeclaration = 155, - MethodSignature = 156, - MethodDeclaration = 157, - Constructor = 158, - GetAccessor = 159, - SetAccessor = 160, - CallSignature = 161, - ConstructSignature = 162, - IndexSignature = 163, - TypePredicate = 164, - TypeReference = 165, - FunctionType = 166, - ConstructorType = 167, - TypeQuery = 168, - TypeLiteral = 169, - ArrayType = 170, - TupleType = 171, - OptionalType = 172, - RestType = 173, - UnionType = 174, - IntersectionType = 175, - ConditionalType = 176, - InferType = 177, - ParenthesizedType = 178, - ThisType = 179, - TypeOperator = 180, - IndexedAccessType = 181, - MappedType = 182, - LiteralType = 183, - ImportType = 184, - ObjectBindingPattern = 185, - ArrayBindingPattern = 186, - BindingElement = 187, - ArrayLiteralExpression = 188, - ObjectLiteralExpression = 189, - PropertyAccessExpression = 190, - ElementAccessExpression = 191, - CallExpression = 192, - NewExpression = 193, - TaggedTemplateExpression = 194, - TypeAssertionExpression = 195, - ParenthesizedExpression = 196, - FunctionExpression = 197, - ArrowFunction = 198, - DeleteExpression = 199, - TypeOfExpression = 200, - VoidExpression = 201, - AwaitExpression = 202, - PrefixUnaryExpression = 203, - PostfixUnaryExpression = 204, - BinaryExpression = 205, - ConditionalExpression = 206, - TemplateExpression = 207, - YieldExpression = 208, - SpreadElement = 209, - ClassExpression = 210, - OmittedExpression = 211, - ExpressionWithTypeArguments = 212, - AsExpression = 213, - NonNullExpression = 214, - MetaProperty = 215, - SyntheticExpression = 216, - TemplateSpan = 217, - SemicolonClassElement = 218, - Block = 219, - VariableStatement = 220, - EmptyStatement = 221, - ExpressionStatement = 222, - IfStatement = 223, - DoStatement = 224, - WhileStatement = 225, - ForStatement = 226, - ForInStatement = 227, - ForOfStatement = 228, - ContinueStatement = 229, - BreakStatement = 230, - ReturnStatement = 231, - WithStatement = 232, - SwitchStatement = 233, - LabeledStatement = 234, - ThrowStatement = 235, - TryStatement = 236, - DebuggerStatement = 237, - VariableDeclaration = 238, - VariableDeclarationList = 239, - FunctionDeclaration = 240, - ClassDeclaration = 241, - InterfaceDeclaration = 242, - TypeAliasDeclaration = 243, - EnumDeclaration = 244, - ModuleDeclaration = 245, - ModuleBlock = 246, - CaseBlock = 247, - NamespaceExportDeclaration = 248, - ImportEqualsDeclaration = 249, - ImportDeclaration = 250, - ImportClause = 251, - NamespaceImport = 252, - NamedImports = 253, - ImportSpecifier = 254, - ExportAssignment = 255, - ExportDeclaration = 256, - NamedExports = 257, - ExportSpecifier = 258, - MissingDeclaration = 259, - ExternalModuleReference = 260, - JsxElement = 261, - JsxSelfClosingElement = 262, - JsxOpeningElement = 263, - JsxClosingElement = 264, - JsxFragment = 265, - JsxOpeningFragment = 266, - JsxClosingFragment = 267, - JsxAttribute = 268, - JsxAttributes = 269, - JsxSpreadAttribute = 270, - JsxExpression = 271, - CaseClause = 272, - DefaultClause = 273, - HeritageClause = 274, - CatchClause = 275, - PropertyAssignment = 276, - ShorthandPropertyAssignment = 277, - SpreadAssignment = 278, - EnumMember = 279, - UnparsedPrologue = 280, - UnparsedPrepend = 281, - UnparsedText = 282, - UnparsedInternalText = 283, - UnparsedSyntheticReference = 284, - SourceFile = 285, - Bundle = 286, - UnparsedSource = 287, - InputFiles = 288, - JSDocTypeExpression = 289, - JSDocAllType = 290, - JSDocUnknownType = 291, - JSDocNullableType = 292, - JSDocNonNullableType = 293, - JSDocOptionalType = 294, - JSDocFunctionType = 295, - JSDocVariadicType = 296, - JSDocComment = 297, - JSDocTypeLiteral = 298, - JSDocSignature = 299, - JSDocTag = 300, - JSDocAugmentsTag = 301, - JSDocClassTag = 302, - JSDocCallbackTag = 303, - JSDocEnumTag = 304, - JSDocParameterTag = 305, - JSDocReturnTag = 306, - JSDocThisTag = 307, - JSDocTypeTag = 308, - JSDocTemplateTag = 309, - JSDocTypedefTag = 310, - JSDocPropertyTag = 311, - SyntaxList = 312, - NotEmittedStatement = 313, - PartiallyEmittedExpression = 314, - CommaListExpression = 315, - MergeDeclarationMarker = 316, - EndOfDeclarationMarker = 317, - Count = 318, - FirstAssignment = 60, - LastAssignment = 72, - FirstCompoundAssignment = 61, - LastCompoundAssignment = 72, - FirstReservedWord = 74, - LastReservedWord = 109, - FirstKeyword = 74, - LastKeyword = 148, - FirstFutureReservedWord = 110, - LastFutureReservedWord = 118, - FirstTypeNode = 164, - LastTypeNode = 184, + BacktickToken = 60, + EqualsToken = 61, + PlusEqualsToken = 62, + MinusEqualsToken = 63, + AsteriskEqualsToken = 64, + AsteriskAsteriskEqualsToken = 65, + SlashEqualsToken = 66, + PercentEqualsToken = 67, + LessThanLessThanEqualsToken = 68, + GreaterThanGreaterThanEqualsToken = 69, + GreaterThanGreaterThanGreaterThanEqualsToken = 70, + AmpersandEqualsToken = 71, + BarEqualsToken = 72, + CaretEqualsToken = 73, + Identifier = 74, + BreakKeyword = 75, + CaseKeyword = 76, + CatchKeyword = 77, + ClassKeyword = 78, + ConstKeyword = 79, + ContinueKeyword = 80, + DebuggerKeyword = 81, + DefaultKeyword = 82, + DeleteKeyword = 83, + DoKeyword = 84, + ElseKeyword = 85, + EnumKeyword = 86, + ExportKeyword = 87, + ExtendsKeyword = 88, + FalseKeyword = 89, + FinallyKeyword = 90, + ForKeyword = 91, + FunctionKeyword = 92, + IfKeyword = 93, + ImportKeyword = 94, + InKeyword = 95, + InstanceOfKeyword = 96, + NewKeyword = 97, + NullKeyword = 98, + ReturnKeyword = 99, + SuperKeyword = 100, + SwitchKeyword = 101, + ThisKeyword = 102, + ThrowKeyword = 103, + TrueKeyword = 104, + TryKeyword = 105, + TypeOfKeyword = 106, + VarKeyword = 107, + VoidKeyword = 108, + WhileKeyword = 109, + WithKeyword = 110, + ImplementsKeyword = 111, + InterfaceKeyword = 112, + LetKeyword = 113, + PackageKeyword = 114, + PrivateKeyword = 115, + ProtectedKeyword = 116, + PublicKeyword = 117, + StaticKeyword = 118, + YieldKeyword = 119, + AbstractKeyword = 120, + AsKeyword = 121, + AnyKeyword = 122, + AsyncKeyword = 123, + AwaitKeyword = 124, + BooleanKeyword = 125, + ConstructorKeyword = 126, + DeclareKeyword = 127, + GetKeyword = 128, + InferKeyword = 129, + IsKeyword = 130, + KeyOfKeyword = 131, + ModuleKeyword = 132, + NamespaceKeyword = 133, + NeverKeyword = 134, + ReadonlyKeyword = 135, + RequireKeyword = 136, + NumberKeyword = 137, + ObjectKeyword = 138, + SetKeyword = 139, + StringKeyword = 140, + SymbolKeyword = 141, + TypeKeyword = 142, + UndefinedKeyword = 143, + UniqueKeyword = 144, + UnknownKeyword = 145, + FromKeyword = 146, + GlobalKeyword = 147, + BigIntKeyword = 148, + OfKeyword = 149, + QualifiedName = 150, + ComputedPropertyName = 151, + TypeParameter = 152, + Parameter = 153, + Decorator = 154, + PropertySignature = 155, + PropertyDeclaration = 156, + MethodSignature = 157, + MethodDeclaration = 158, + Constructor = 159, + GetAccessor = 160, + SetAccessor = 161, + CallSignature = 162, + ConstructSignature = 163, + IndexSignature = 164, + TypePredicate = 165, + TypeReference = 166, + FunctionType = 167, + ConstructorType = 168, + TypeQuery = 169, + TypeLiteral = 170, + ArrayType = 171, + TupleType = 172, + OptionalType = 173, + RestType = 174, + UnionType = 175, + IntersectionType = 176, + ConditionalType = 177, + InferType = 178, + ParenthesizedType = 179, + ThisType = 180, + TypeOperator = 181, + IndexedAccessType = 182, + MappedType = 183, + LiteralType = 184, + ImportType = 185, + ObjectBindingPattern = 186, + ArrayBindingPattern = 187, + BindingElement = 188, + ArrayLiteralExpression = 189, + ObjectLiteralExpression = 190, + PropertyAccessExpression = 191, + ElementAccessExpression = 192, + CallExpression = 193, + NewExpression = 194, + TaggedTemplateExpression = 195, + TypeAssertionExpression = 196, + ParenthesizedExpression = 197, + FunctionExpression = 198, + ArrowFunction = 199, + DeleteExpression = 200, + TypeOfExpression = 201, + VoidExpression = 202, + AwaitExpression = 203, + PrefixUnaryExpression = 204, + PostfixUnaryExpression = 205, + BinaryExpression = 206, + ConditionalExpression = 207, + TemplateExpression = 208, + YieldExpression = 209, + SpreadElement = 210, + ClassExpression = 211, + OmittedExpression = 212, + ExpressionWithTypeArguments = 213, + AsExpression = 214, + NonNullExpression = 215, + MetaProperty = 216, + SyntheticExpression = 217, + TemplateSpan = 218, + SemicolonClassElement = 219, + Block = 220, + VariableStatement = 221, + EmptyStatement = 222, + ExpressionStatement = 223, + IfStatement = 224, + DoStatement = 225, + WhileStatement = 226, + ForStatement = 227, + ForInStatement = 228, + ForOfStatement = 229, + ContinueStatement = 230, + BreakStatement = 231, + ReturnStatement = 232, + WithStatement = 233, + SwitchStatement = 234, + LabeledStatement = 235, + ThrowStatement = 236, + TryStatement = 237, + DebuggerStatement = 238, + VariableDeclaration = 239, + VariableDeclarationList = 240, + FunctionDeclaration = 241, + ClassDeclaration = 242, + InterfaceDeclaration = 243, + TypeAliasDeclaration = 244, + EnumDeclaration = 245, + ModuleDeclaration = 246, + ModuleBlock = 247, + CaseBlock = 248, + NamespaceExportDeclaration = 249, + ImportEqualsDeclaration = 250, + ImportDeclaration = 251, + ImportClause = 252, + NamespaceImport = 253, + NamedImports = 254, + ImportSpecifier = 255, + ExportAssignment = 256, + ExportDeclaration = 257, + NamedExports = 258, + ExportSpecifier = 259, + MissingDeclaration = 260, + ExternalModuleReference = 261, + JsxElement = 262, + JsxSelfClosingElement = 263, + JsxOpeningElement = 264, + JsxClosingElement = 265, + JsxFragment = 266, + JsxOpeningFragment = 267, + JsxClosingFragment = 268, + JsxAttribute = 269, + JsxAttributes = 270, + JsxSpreadAttribute = 271, + JsxExpression = 272, + CaseClause = 273, + DefaultClause = 274, + HeritageClause = 275, + CatchClause = 276, + PropertyAssignment = 277, + ShorthandPropertyAssignment = 278, + SpreadAssignment = 279, + EnumMember = 280, + UnparsedPrologue = 281, + UnparsedPrepend = 282, + UnparsedText = 283, + UnparsedInternalText = 284, + UnparsedSyntheticReference = 285, + SourceFile = 286, + Bundle = 287, + UnparsedSource = 288, + InputFiles = 289, + JSDocTypeExpression = 290, + JSDocAllType = 291, + JSDocUnknownType = 292, + JSDocNullableType = 293, + JSDocNonNullableType = 294, + JSDocOptionalType = 295, + JSDocFunctionType = 296, + JSDocVariadicType = 297, + JSDocComment = 298, + JSDocTypeLiteral = 299, + JSDocSignature = 300, + JSDocTag = 301, + JSDocAugmentsTag = 302, + JSDocClassTag = 303, + JSDocCallbackTag = 304, + JSDocEnumTag = 305, + JSDocParameterTag = 306, + JSDocReturnTag = 307, + JSDocThisTag = 308, + JSDocTypeTag = 309, + JSDocTemplateTag = 310, + JSDocTypedefTag = 311, + JSDocPropertyTag = 312, + SyntaxList = 313, + NotEmittedStatement = 314, + PartiallyEmittedExpression = 315, + CommaListExpression = 316, + MergeDeclarationMarker = 317, + EndOfDeclarationMarker = 318, + Count = 319, + FirstAssignment = 61, + LastAssignment = 73, + FirstCompoundAssignment = 62, + LastCompoundAssignment = 73, + FirstReservedWord = 75, + LastReservedWord = 110, + FirstKeyword = 75, + LastKeyword = 149, + FirstFutureReservedWord = 111, + LastFutureReservedWord = 119, + FirstTypeNode = 165, + LastTypeNode = 185, FirstPunctuation = 18, - LastPunctuation = 72, + LastPunctuation = 73, FirstToken = 0, - LastToken = 148, + LastToken = 149, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -419,12 +420,12 @@ declare namespace ts { FirstTemplateToken = 14, LastTemplateToken = 17, FirstBinaryOperator = 28, - LastBinaryOperator = 72, - FirstNode = 149, - FirstJSDocNode = 289, - LastJSDocNode = 311, - FirstJSDocTagNode = 300, - LastJSDocTagNode = 311, + LastBinaryOperator = 73, + FirstNode = 150, + FirstJSDocNode = 290, + LastJSDocNode = 312, + FirstJSDocTagNode = 301, + LastJSDocTagNode = 312, } enum NodeFlags { None = 0, @@ -937,7 +938,7 @@ declare namespace ts { type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; - type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken; + type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken; type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; @@ -4095,6 +4096,7 @@ declare namespace ts { function createPostfixIncrement(operand: Expression): PostfixUnaryExpression; function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; function createLogicalOr(left: Expression, right: Expression): BinaryExpression; + function createNullishCoalescing(left: Expression, right: Expression): BinaryExpression; function createLogicalNot(operand: Expression): PrefixUnaryExpression; function createVoidZero(): VoidExpression; function createExportDefault(expression: Expression): ExportAssignment; From 2327b3b4d30899097ecf6f4a78ec68e23704b3d1 Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 15 Aug 2019 13:57:58 +0800 Subject: [PATCH 07/26] add rescan question question token to fix regression --- src/compiler/parser.ts | 4 ++++ src/compiler/scanner.ts | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d770b2db2b854..c7f0b5f905e4c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2953,6 +2953,10 @@ namespace ts { return parseJSDocAllType(/*postfixEquals*/ false); case SyntaxKind.AsteriskEqualsToken: return parseJSDocAllType(/*postfixEquals*/ true); + case SyntaxKind.QuestionQuestionToken: + // If there is '??', consider that is prefix '?' in JSDoc type. + scanner.reScanQuestionQuestionToken(); + // falls through case SyntaxKind.QuestionToken: return parseJSDocUnknownOrNullableType(); case SyntaxKind.FunctionKeyword: diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 2d335c9cb98e6..f9ef4ef90924f 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -32,6 +32,7 @@ namespace ts { scanJsxAttributeValue(): SyntaxKind; reScanJsxToken(): JsxTokenSyntaxKind; reScanLessThanToken(): SyntaxKind; + reScanQuestionQuestionToken(): SyntaxKind; scanJsxToken(): JsxTokenSyntaxKind; scanJsDocToken(): JSDocSyntaxKind; scan(): SyntaxKind; @@ -886,6 +887,7 @@ namespace ts { scanJsxAttributeValue, reScanJsxToken, reScanLessThanToken, + reScanQuestionQuestionToken, scanJsxToken, scanJsDocToken, scan, @@ -1962,6 +1964,12 @@ namespace ts { return token; } + function reScanQuestionQuestionToken(): SyntaxKind { + Debug.assert(token === SyntaxKind.QuestionQuestionToken, "'reScanQuestionQuestionToken' should only be called on a '??'"); + pos = tokenPos + 1; + return token = SyntaxKind.QuestionToken; + } + function scanJsxToken(): JsxTokenSyntaxKind { startPos = tokenPos = pos; From fb0d3c9daef577b2fa2caf263ed299a1337e6dfe Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 15 Aug 2019 14:40:25 +0800 Subject: [PATCH 08/26] update public api baseline --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 507fdb757a13f..9bc886667ef31 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3173,6 +3173,7 @@ declare namespace ts { scanJsxAttributeValue(): SyntaxKind; reScanJsxToken(): JsxTokenSyntaxKind; reScanLessThanToken(): SyntaxKind; + reScanQuestionQuestionToken(): SyntaxKind; scanJsxToken(): JsxTokenSyntaxKind; scanJsDocToken(): JSDocSyntaxKind; scan(): SyntaxKind; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index c54d9d4538cc3..2a04df7b2cf4d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3173,6 +3173,7 @@ declare namespace ts { scanJsxAttributeValue(): SyntaxKind; reScanJsxToken(): JsxTokenSyntaxKind; reScanLessThanToken(): SyntaxKind; + reScanQuestionQuestionToken(): SyntaxKind; scanJsxToken(): JsxTokenSyntaxKind; scanJsDocToken(): JSDocSyntaxKind; scan(): SyntaxKind; From 06149d00143d661fc3111be91a406ac569a8c702 Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Thu, 15 Aug 2019 18:02:29 +0300 Subject: [PATCH 09/26] Added tests that emit for nullish coalescing operator conforming with grammar restrictions when assertions are used. --- .../nullishCoalescingOperator_esnext.js | 31 ++++- .../nullishCoalescingOperator_esnext.symbols | 78 +++++++++++ .../nullishCoalescingOperator_esnext.types | 130 ++++++++++++++++++ .../nullishCoalescingOperator_esnext.ts | 19 ++- 4 files changed, 256 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.js b/tests/baselines/reference/nullishCoalescingOperator_esnext.js index 0593e7bb211b0..d75fea492c6a8 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.js +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.js @@ -18,7 +18,24 @@ const aa5 = a5 ?? 'whatever' const aa6 = a6 ?? 'whatever' const aa7 = a7 ?? 'whatever' const aa8 = a8 ?? 'whatever' -const aa9 = a9 ?? 'whatever' +const aa9 = a9 ?? 'whatever' + + +declare let a: any, b: any, c: any; + +let x1 = (a ?? b as any) || c; +let x2 = c || (a ?? b as any); +let x3 = ((a ?? b) as any) || c; +let x4 = c || ((a ?? b) as any); +let x5 = (a ?? b) as any || c; +let x6 = c || (a ?? b) as any; + +let y1 = (a ?? b as any) && c; +let y2 = c && (a ?? b as any); +let y3 = ((a ?? b) as any) && c; +let y4 = c && ((a ?? b) as any); +let y5 = (a ?? b) as any && c; +let y6 = c && (a ?? b) as any; //// [nullishCoalescingOperator_esnext.js] "use strict"; @@ -31,3 +48,15 @@ const aa6 = a6 ?? 'whatever'; const aa7 = a7 ?? 'whatever'; const aa8 = a8 ?? 'whatever'; const aa9 = a9 ?? 'whatever'; +let x1 = (a ?? b) || c; +let x2 = c || (a ?? b); +let x3 = (a ?? b) || c; +let x4 = c || (a ?? b); +let x5 = (a ?? b) || c; +let x6 = c || (a ?? b); +let y1 = (a ?? b) && c; +let y2 = c && (a ?? b); +let y3 = (a ?? b) && c; +let y4 = c && (a ?? b); +let y5 = (a ?? b) && c; +let y6 = c && (a ?? b); diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols b/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols index d5829609552d8..42c382c9f1037 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols @@ -63,3 +63,81 @@ const aa9 = a9 ?? 'whatever' >aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_esnext.ts, 19, 5)) >a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) + +declare let a: any, b: any, c: any; +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) + +let x1 = (a ?? b as any) || c; +>x1 : Symbol(x1, Decl(nullishCoalescingOperator_esnext.ts, 24, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) + +let x2 = c || (a ?? b as any); +>x2 : Symbol(x2, Decl(nullishCoalescingOperator_esnext.ts, 25, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) + +let x3 = ((a ?? b) as any) || c; +>x3 : Symbol(x3, Decl(nullishCoalescingOperator_esnext.ts, 26, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) + +let x4 = c || ((a ?? b) as any); +>x4 : Symbol(x4, Decl(nullishCoalescingOperator_esnext.ts, 27, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) + +let x5 = (a ?? b) as any || c; +>x5 : Symbol(x5, Decl(nullishCoalescingOperator_esnext.ts, 28, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) + +let x6 = c || (a ?? b) as any; +>x6 : Symbol(x6, Decl(nullishCoalescingOperator_esnext.ts, 29, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) + +let y1 = (a ?? b as any) && c; +>y1 : Symbol(y1, Decl(nullishCoalescingOperator_esnext.ts, 31, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) + +let y2 = c && (a ?? b as any); +>y2 : Symbol(y2, Decl(nullishCoalescingOperator_esnext.ts, 32, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) + +let y3 = ((a ?? b) as any) && c; +>y3 : Symbol(y3, Decl(nullishCoalescingOperator_esnext.ts, 33, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) + +let y4 = c && ((a ?? b) as any); +>y4 : Symbol(y4, Decl(nullishCoalescingOperator_esnext.ts, 34, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) + +let y5 = (a ?? b) as any && c; +>y5 : Symbol(y5, Decl(nullishCoalescingOperator_esnext.ts, 35, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) + +let y6 = c && (a ?? b) as any; +>y6 : Symbol(y6, Decl(nullishCoalescingOperator_esnext.ts, 36, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.types b/tests/baselines/reference/nullishCoalescingOperator_esnext.types index 6ee6cf167444a..3de2d2c6b4d43 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.types +++ b/tests/baselines/reference/nullishCoalescingOperator_esnext.types @@ -92,3 +92,133 @@ const aa9 = a9 ?? 'whatever' >a9 : any >'whatever' : "whatever" + +declare let a: any, b: any, c: any; +>a : any +>b : any +>c : any + +let x1 = (a ?? b as any) || c; +>x1 : any +>(a ?? b as any) || c : any +>(a ?? b as any) : any +>a ?? b as any : any +>a : any +>b as any : any +>b : any +>c : any + +let x2 = c || (a ?? b as any); +>x2 : any +>c || (a ?? b as any) : any +>c : any +>(a ?? b as any) : any +>a ?? b as any : any +>a : any +>b as any : any +>b : any + +let x3 = ((a ?? b) as any) || c; +>x3 : any +>((a ?? b) as any) || c : any +>((a ?? b) as any) : any +>(a ?? b) as any : any +>(a ?? b) : any +>a ?? b : any +>a : any +>b : any +>c : any + +let x4 = c || ((a ?? b) as any); +>x4 : any +>c || ((a ?? b) as any) : any +>c : any +>((a ?? b) as any) : any +>(a ?? b) as any : any +>(a ?? b) : any +>a ?? b : any +>a : any +>b : any + +let x5 = (a ?? b) as any || c; +>x5 : any +>(a ?? b) as any || c : any +>(a ?? b) as any : any +>(a ?? b) : any +>a ?? b : any +>a : any +>b : any +>c : any + +let x6 = c || (a ?? b) as any; +>x6 : any +>c || (a ?? b) as any : any +>c : any +>(a ?? b) as any : any +>(a ?? b) : any +>a ?? b : any +>a : any +>b : any + +let y1 = (a ?? b as any) && c; +>y1 : any +>(a ?? b as any) && c : any +>(a ?? b as any) : any +>a ?? b as any : any +>a : any +>b as any : any +>b : any +>c : any + +let y2 = c && (a ?? b as any); +>y2 : any +>c && (a ?? b as any) : any +>c : any +>(a ?? b as any) : any +>a ?? b as any : any +>a : any +>b as any : any +>b : any + +let y3 = ((a ?? b) as any) && c; +>y3 : any +>((a ?? b) as any) && c : any +>((a ?? b) as any) : any +>(a ?? b) as any : any +>(a ?? b) : any +>a ?? b : any +>a : any +>b : any +>c : any + +let y4 = c && ((a ?? b) as any); +>y4 : any +>c && ((a ?? b) as any) : any +>c : any +>((a ?? b) as any) : any +>(a ?? b) as any : any +>(a ?? b) : any +>a ?? b : any +>a : any +>b : any + +let y5 = (a ?? b) as any && c; +>y5 : any +>(a ?? b) as any && c : any +>(a ?? b) as any : any +>(a ?? b) : any +>a ?? b : any +>a : any +>b : any +>c : any + +let y6 = c && (a ?? b) as any; +>y6 : any +>c && (a ?? b) as any : any +>c : any +>(a ?? b) as any : any +>(a ?? b) : any +>a ?? b : any +>a : any +>b : any + diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts index 5713107859b3d..c718ca189e70d 100644 --- a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts @@ -20,4 +20,21 @@ const aa5 = a5 ?? 'whatever' const aa6 = a6 ?? 'whatever' const aa7 = a7 ?? 'whatever' const aa8 = a8 ?? 'whatever' -const aa9 = a9 ?? 'whatever' \ No newline at end of file +const aa9 = a9 ?? 'whatever' + + +declare let a: any, b: any, c: any; + +let x1 = (a ?? b as any) || c; +let x2 = c || (a ?? b as any); +let x3 = ((a ?? b) as any) || c; +let x4 = c || ((a ?? b) as any); +let x5 = (a ?? b) as any || c; +let x6 = c || (a ?? b) as any; + +let y1 = (a ?? b as any) && c; +let y2 = c && (a ?? b as any); +let y3 = ((a ?? b) as any) && c; +let y4 = c && ((a ?? b) as any); +let y5 = (a ?? b) as any && c; +let y6 = c && (a ?? b) as any; \ No newline at end of file From 3d94652c40aab8c006929ddf55b125812c5d1b36 Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Thu, 15 Aug 2019 18:51:29 +0300 Subject: [PATCH 10/26] Fixed emit to hoist temporary variables (they previously went undeclared). Added tests to ensure calls and property accesses are only called once. --- src/compiler/transformers/esnext.ts | 6 ++- .../reference/nullishCoalescingOperator3.js | 3 +- .../reference/nullishCoalescingOperator5.js | 1 + .../reference/nullishCoalescingOperator8.js | 16 +++++++ .../nullishCoalescingOperator8.symbols | 35 ++++++++++++++ .../nullishCoalescingOperator8.types | 46 +++++++++++++++++++ .../nullishCoalescingOperator8.ts | 8 ++++ 7 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperator8.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator8.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator8.types create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator8.ts diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index ea6d3882be437..f5dacaf1b44b7 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -1,6 +1,10 @@ /*@internal*/ namespace ts { export function transformESNext(context: TransformationContext) { + const { + hoistVariableDeclaration, + } = context; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { @@ -40,7 +44,7 @@ namespace ts { const expressions: Expression[] = []; let left = visitNode(node.left, visitor, isExpression); if (!isIdentifier(left)) { - const temp = createTempVariable(/*recordTempVariable*/ undefined); + const temp = createTempVariable(hoistVariableDeclaration); expressions.push(createAssignment(temp, left)); left = temp; } diff --git a/tests/baselines/reference/nullishCoalescingOperator3.js b/tests/baselines/reference/nullishCoalescingOperator3.js index 8138a9b64389d..8774860e3e1f7 100644 --- a/tests/baselines/reference/nullishCoalescingOperator3.js +++ b/tests/baselines/reference/nullishCoalescingOperator3.js @@ -11,5 +11,6 @@ const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' //// [nullishCoalescingOperator3.js] +var _a, _b, _c, _d, _e; "use strict"; -var aa1 = (_a = (_b = (_c = (_d = (_e = typeof a1 !== "undefined" && a1 !== null ? a1 : a2, _e !== void 0 && _e !== null ? _e : a3), _d !== void 0 && _d !== null ? _d : a4), _c !== void 0 && _c !== null ? _c : a5), _b !== void 0 && _b !== null ? _b : a6), _a !== void 0 && _a !== null ? _a : 'whatever'); +var aa1 = (_e = (_d = (_c = (_b = (_a = typeof a1 !== "undefined" && a1 !== null ? a1 : a2, _a !== void 0 && _a !== null ? _a : a3), _b !== void 0 && _b !== null ? _b : a4), _c !== void 0 && _c !== null ? _c : a5), _d !== void 0 && _d !== null ? _d : a6), _e !== void 0 && _e !== null ? _e : 'whatever'); diff --git a/tests/baselines/reference/nullishCoalescingOperator5.js b/tests/baselines/reference/nullishCoalescingOperator5.js index 46d7cc624b341..f235ea23ffb52 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.js +++ b/tests/baselines/reference/nullishCoalescingOperator5.js @@ -41,6 +41,7 @@ a && (b ?? c); //// [nullishCoalescingOperator5.js] +var _a, _b, _c, _d; "use strict"; // should be a syntax error typeof a !== "undefined" && a !== null ? a : b || c; diff --git a/tests/baselines/reference/nullishCoalescingOperator8.js b/tests/baselines/reference/nullishCoalescingOperator8.js new file mode 100644 index 0000000000000..5c60f1f9dc1e2 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator8.js @@ -0,0 +1,16 @@ +//// [nullishCoalescingOperator8.ts] +declare const a: { p: string | undefined, m(): string | undefined }; +declare const b: { p: string | undefined, m(): string | undefined }; + +const n1 = a.p ?? "default"; +const n2 = a.m() ?? "default"; +const n3 = a.m() ?? b.p ?? b.m() ?? "default";; + + +//// [nullishCoalescingOperator8.js] +var _a, _b, _c, _d, _e; +"use strict"; +var n1 = (_a = a.p, _a !== void 0 && _a !== null ? _a : "default"); +var n2 = (_b = a.m(), _b !== void 0 && _b !== null ? _b : "default"); +var n3 = (_e = (_d = (_c = a.m(), _c !== void 0 && _c !== null ? _c : b.p), _d !== void 0 && _d !== null ? _d : b.m()), _e !== void 0 && _e !== null ? _e : "default"); +; diff --git a/tests/baselines/reference/nullishCoalescingOperator8.symbols b/tests/baselines/reference/nullishCoalescingOperator8.symbols new file mode 100644 index 0000000000000..40d881cb99e51 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator8.symbols @@ -0,0 +1,35 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator8.ts === +declare const a: { p: string | undefined, m(): string | undefined }; +>a : Symbol(a, Decl(nullishCoalescingOperator8.ts, 0, 13)) +>p : Symbol(p, Decl(nullishCoalescingOperator8.ts, 0, 18)) +>m : Symbol(m, Decl(nullishCoalescingOperator8.ts, 0, 41)) + +declare const b: { p: string | undefined, m(): string | undefined }; +>b : Symbol(b, Decl(nullishCoalescingOperator8.ts, 1, 13)) +>p : Symbol(p, Decl(nullishCoalescingOperator8.ts, 1, 18)) +>m : Symbol(m, Decl(nullishCoalescingOperator8.ts, 1, 41)) + +const n1 = a.p ?? "default"; +>n1 : Symbol(n1, Decl(nullishCoalescingOperator8.ts, 3, 5)) +>a.p : Symbol(p, Decl(nullishCoalescingOperator8.ts, 0, 18)) +>a : Symbol(a, Decl(nullishCoalescingOperator8.ts, 0, 13)) +>p : Symbol(p, Decl(nullishCoalescingOperator8.ts, 0, 18)) + +const n2 = a.m() ?? "default"; +>n2 : Symbol(n2, Decl(nullishCoalescingOperator8.ts, 4, 5)) +>a.m : Symbol(m, Decl(nullishCoalescingOperator8.ts, 0, 41)) +>a : Symbol(a, Decl(nullishCoalescingOperator8.ts, 0, 13)) +>m : Symbol(m, Decl(nullishCoalescingOperator8.ts, 0, 41)) + +const n3 = a.m() ?? b.p ?? b.m() ?? "default";; +>n3 : Symbol(n3, Decl(nullishCoalescingOperator8.ts, 5, 5)) +>a.m : Symbol(m, Decl(nullishCoalescingOperator8.ts, 0, 41)) +>a : Symbol(a, Decl(nullishCoalescingOperator8.ts, 0, 13)) +>m : Symbol(m, Decl(nullishCoalescingOperator8.ts, 0, 41)) +>b.p : Symbol(p, Decl(nullishCoalescingOperator8.ts, 1, 18)) +>b : Symbol(b, Decl(nullishCoalescingOperator8.ts, 1, 13)) +>p : Symbol(p, Decl(nullishCoalescingOperator8.ts, 1, 18)) +>b.m : Symbol(m, Decl(nullishCoalescingOperator8.ts, 1, 41)) +>b : Symbol(b, Decl(nullishCoalescingOperator8.ts, 1, 13)) +>m : Symbol(m, Decl(nullishCoalescingOperator8.ts, 1, 41)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator8.types b/tests/baselines/reference/nullishCoalescingOperator8.types new file mode 100644 index 0000000000000..09d85f291e4af --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator8.types @@ -0,0 +1,46 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator8.ts === +declare const a: { p: string | undefined, m(): string | undefined }; +>a : { p: string | undefined; m(): string | undefined; } +>p : string | undefined +>m : () => string | undefined + +declare const b: { p: string | undefined, m(): string | undefined }; +>b : { p: string | undefined; m(): string | undefined; } +>p : string | undefined +>m : () => string | undefined + +const n1 = a.p ?? "default"; +>n1 : string +>a.p ?? "default" : string +>a.p : string | undefined +>a : { p: string | undefined; m(): string | undefined; } +>p : string | undefined +>"default" : "default" + +const n2 = a.m() ?? "default"; +>n2 : string +>a.m() ?? "default" : string +>a.m() : string | undefined +>a.m : () => string | undefined +>a : { p: string | undefined; m(): string | undefined; } +>m : () => string | undefined +>"default" : "default" + +const n3 = a.m() ?? b.p ?? b.m() ?? "default";; +>n3 : string +>a.m() ?? b.p ?? b.m() ?? "default" : string +>a.m() ?? b.p ?? b.m() : string | undefined +>a.m() ?? b.p : string | undefined +>a.m() : string | undefined +>a.m : () => string | undefined +>a : { p: string | undefined; m(): string | undefined; } +>m : () => string | undefined +>b.p : string | undefined +>b : { p: string | undefined; m(): string | undefined; } +>p : string | undefined +>b.m() : string | undefined +>b.m : () => string | undefined +>b : { p: string | undefined; m(): string | undefined; } +>m : () => string | undefined +>"default" : "default" + diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator8.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator8.ts new file mode 100644 index 0000000000000..228ea0ecf82ef --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator8.ts @@ -0,0 +1,8 @@ +// @strict: true + +declare const a: { p: string | undefined, m(): string | undefined }; +declare const b: { p: string | undefined, m(): string | undefined }; + +const n1 = a.p ?? "default"; +const n2 = a.m() ?? "default"; +const n3 = a.m() ?? b.p ?? b.m() ?? "default";; From c2e336b5c482384e9d36fb9be61bbe06b33fbde2 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 16 Aug 2019 15:09:14 +0800 Subject: [PATCH 11/26] use not equal to null --- src/compiler/transformers/esnext.ts | 24 +++++++------- .../reference/nullishCoalescingOperator1.js | 32 +++++++++---------- .../reference/nullishCoalescingOperator2.js | 18 +++++------ .../reference/nullishCoalescingOperator3.js | 2 +- .../reference/nullishCoalescingOperator4.js | 2 +- .../reference/nullishCoalescingOperator5.js | 24 +++++++------- .../reference/nullishCoalescingOperator6.js | 2 +- .../reference/nullishCoalescingOperator7.js | 6 ++-- .../reference/nullishCoalescingOperator8.js | 6 ++-- .../nullishCoalescingOperator_not_strict.js | 18 +++++------ 10 files changed, 66 insertions(+), 68 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index f5dacaf1b44b7..b0127d5f60319 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -30,14 +30,12 @@ namespace ts { } } - function createNotUndefinedCondition(node: Expression) { - return isIdentifier(node) && !isGeneratedIdentifier(node) - ? createStrictInequality(createTypeOf(node), createLiteral("undefined")) - : createStrictInequality(node, createVoidZero()); - } - function createNotNullCondition(node: Expression) { - return createStrictInequality(node, createNull()); + return createBinary( + node, + SyntaxKind.ExclamationEqualsToken, + createNull() + ); } function transformNullishCoalescingExpression(node: BinaryExpression) { @@ -49,12 +47,12 @@ namespace ts { left = temp; } expressions.push( - createConditional( - createLogicalAnd( - createNotUndefinedCondition(left), - createNotNullCondition(left)), - left, - visitNode(node.right, visitor, isExpression))); + createParen( + createConditional( + createNotNullCondition(left), + left, + visitNode(node.right, visitor, isExpression))) + ); return inlineExpressions(expressions); } } diff --git a/tests/baselines/reference/nullishCoalescingOperator1.js b/tests/baselines/reference/nullishCoalescingOperator1.js index f94f87acc3a8f..f4b2e4e8660a7 100644 --- a/tests/baselines/reference/nullishCoalescingOperator1.js +++ b/tests/baselines/reference/nullishCoalescingOperator1.js @@ -42,19 +42,19 @@ const dd4 = d4 ?? {b: 1}; //// [nullishCoalescingOperator1.js] "use strict"; -var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever'; -var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever'; -var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever'; -var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever'; -var bb1 = typeof b1 !== "undefined" && b1 !== null ? b1 : 1; -var bb2 = typeof b2 !== "undefined" && b2 !== null ? b2 : 1; -var bb3 = typeof b3 !== "undefined" && b3 !== null ? b3 : 1; -var bb4 = typeof b4 !== "undefined" && b4 !== null ? b4 : 1; -var cc1 = typeof c1 !== "undefined" && c1 !== null ? c1 : true; -var cc2 = typeof c2 !== "undefined" && c2 !== null ? c2 : true; -var cc3 = typeof c3 !== "undefined" && c3 !== null ? c3 : true; -var cc4 = typeof c4 !== "undefined" && c4 !== null ? c4 : true; -var dd1 = typeof d1 !== "undefined" && d1 !== null ? d1 : { b: 1 }; -var dd2 = typeof d2 !== "undefined" && d2 !== null ? d2 : { b: 1 }; -var dd3 = typeof d3 !== "undefined" && d3 !== null ? d3 : { b: 1 }; -var dd4 = typeof d4 !== "undefined" && d4 !== null ? d4 : { b: 1 }; +var aa1 = (a1 != null ? a1 : 'whatever'); +var aa2 = (a2 != null ? a2 : 'whatever'); +var aa3 = (a3 != null ? a3 : 'whatever'); +var aa4 = (a4 != null ? a4 : 'whatever'); +var bb1 = (b1 != null ? b1 : 1); +var bb2 = (b2 != null ? b2 : 1); +var bb3 = (b3 != null ? b3 : 1); +var bb4 = (b4 != null ? b4 : 1); +var cc1 = (c1 != null ? c1 : true); +var cc2 = (c2 != null ? c2 : true); +var cc3 = (c3 != null ? c3 : true); +var cc4 = (c4 != null ? c4 : true); +var dd1 = (d1 != null ? d1 : { b: 1 }); +var dd2 = (d2 != null ? d2 : { b: 1 }); +var dd3 = (d3 != null ? d3 : { b: 1 }); +var dd4 = (d4 != null ? d4 : { b: 1 }); diff --git a/tests/baselines/reference/nullishCoalescingOperator2.js b/tests/baselines/reference/nullishCoalescingOperator2.js index 133eb55d8b542..82ae05bb56379 100644 --- a/tests/baselines/reference/nullishCoalescingOperator2.js +++ b/tests/baselines/reference/nullishCoalescingOperator2.js @@ -22,12 +22,12 @@ const aa9 = a9 ?? 'whatever' //// [nullishCoalescingOperator2.js] "use strict"; -var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever'; -var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever'; -var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever'; -var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever'; -var aa5 = typeof a5 !== "undefined" && a5 !== null ? a5 : 'whatever'; -var aa6 = typeof a6 !== "undefined" && a6 !== null ? a6 : 'whatever'; -var aa7 = typeof a7 !== "undefined" && a7 !== null ? a7 : 'whatever'; -var aa8 = typeof a8 !== "undefined" && a8 !== null ? a8 : 'whatever'; -var aa9 = typeof a9 !== "undefined" && a9 !== null ? a9 : 'whatever'; +var aa1 = (a1 != null ? a1 : 'whatever'); +var aa2 = (a2 != null ? a2 : 'whatever'); +var aa3 = (a3 != null ? a3 : 'whatever'); +var aa4 = (a4 != null ? a4 : 'whatever'); +var aa5 = (a5 != null ? a5 : 'whatever'); +var aa6 = (a6 != null ? a6 : 'whatever'); +var aa7 = (a7 != null ? a7 : 'whatever'); +var aa8 = (a8 != null ? a8 : 'whatever'); +var aa9 = (a9 != null ? a9 : 'whatever'); diff --git a/tests/baselines/reference/nullishCoalescingOperator3.js b/tests/baselines/reference/nullishCoalescingOperator3.js index 8774860e3e1f7..df0a9ebe1bbd6 100644 --- a/tests/baselines/reference/nullishCoalescingOperator3.js +++ b/tests/baselines/reference/nullishCoalescingOperator3.js @@ -13,4 +13,4 @@ const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' //// [nullishCoalescingOperator3.js] var _a, _b, _c, _d, _e; "use strict"; -var aa1 = (_e = (_d = (_c = (_b = (_a = typeof a1 !== "undefined" && a1 !== null ? a1 : a2, _a !== void 0 && _a !== null ? _a : a3), _b !== void 0 && _b !== null ? _b : a4), _c !== void 0 && _c !== null ? _c : a5), _d !== void 0 && _d !== null ? _d : a6), _e !== void 0 && _e !== null ? _e : 'whatever'); +var aa1 = (_e = (_d = (_c = (_b = (_a = (a1 != null ? a1 : a2), (_a != null ? _a : a3)), (_b != null ? _b : a4)), (_c != null ? _c : a5)), (_d != null ? _d : a6)), (_e != null ? _e : 'whatever')); diff --git a/tests/baselines/reference/nullishCoalescingOperator4.js b/tests/baselines/reference/nullishCoalescingOperator4.js index d69f04a4681fd..459a5483bd5f6 100644 --- a/tests/baselines/reference/nullishCoalescingOperator4.js +++ b/tests/baselines/reference/nullishCoalescingOperator4.js @@ -6,5 +6,5 @@ const aa2 = a1 || a1.toLocaleUpperCase() //// [nullishCoalescingOperator4.js] "use strict"; -var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : a1.toLowerCase(); +var aa1 = (a1 != null ? a1 : a1.toLowerCase()); var aa2 = a1 || a1.toLocaleUpperCase(); diff --git a/tests/baselines/reference/nullishCoalescingOperator5.js b/tests/baselines/reference/nullishCoalescingOperator5.js index f235ea23ffb52..4d0cc98f56c5a 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.js +++ b/tests/baselines/reference/nullishCoalescingOperator5.js @@ -44,26 +44,26 @@ a && (b ?? c); var _a, _b, _c, _d; "use strict"; // should be a syntax error -typeof a !== "undefined" && a !== null ? a : b || c; +(a != null ? a : b || c); // should be a syntax error -_a = a || b, _a !== void 0 && _a !== null ? _a : c; +_a = a || b, (_a != null ? _a : c); // should be a syntax error -typeof a !== "undefined" && a !== null ? a : b && c; +(a != null ? a : b && c); // should be a syntax error -_b = a && b, _b !== void 0 && _b !== null ? _b : c; +_b = a && b, (_b != null ? _b : c); // Valid according to spec -typeof a !== "undefined" && a !== null ? a : (b || c); +(a != null ? a : (b || c)); // Valid according to spec -(typeof a !== "undefined" && a !== null ? a : b) || c; +((a != null ? a : b)) || c; // Valid according to spec -_c = (a || b), _c !== void 0 && _c !== null ? _c : c; +_c = (a || b), (_c != null ? _c : c); // Valid according to spec -a || (typeof b !== "undefined" && b !== null ? b : c); +a || ((b != null ? b : c)); // Valid according to spec -typeof a !== "undefined" && a !== null ? a : (b && c); +(a != null ? a : (b && c)); // Valid according to spec -(typeof a !== "undefined" && a !== null ? a : b) && c; +((a != null ? a : b)) && c; // Valid according to spec -_d = (a && b), _d !== void 0 && _d !== null ? _d : c; +_d = (a && b), (_d != null ? _d : c); // Valid according to spec -a && (typeof b !== "undefined" && b !== null ? b : c); +a && ((b != null ? b : c)); diff --git a/tests/baselines/reference/nullishCoalescingOperator6.js b/tests/baselines/reference/nullishCoalescingOperator6.js index 4ba0fddbf8a7a..816b6e1af0dbe 100644 --- a/tests/baselines/reference/nullishCoalescingOperator6.js +++ b/tests/baselines/reference/nullishCoalescingOperator6.js @@ -5,5 +5,5 @@ function foo(foo: string, bar = foo ?? "bar") { } //// [nullishCoalescingOperator6.js] "use strict"; function foo(foo, bar) { - if (bar === void 0) { bar = typeof foo !== "undefined" && foo !== null ? foo : "bar"; } + if (bar === void 0) { bar = (foo != null ? foo : "bar"); } } diff --git a/tests/baselines/reference/nullishCoalescingOperator7.js b/tests/baselines/reference/nullishCoalescingOperator7.js index bc10e7a5bdbfc..aa7e518b2eb8d 100644 --- a/tests/baselines/reference/nullishCoalescingOperator7.js +++ b/tests/baselines/reference/nullishCoalescingOperator7.js @@ -15,8 +15,8 @@ function f () { //// [nullishCoalescingOperator7.js] "use strict"; var foo1 = a ? 1 : 2; -var foo2 = typeof a !== "undefined" && a !== null ? a : 'foo' ? 1 : 2; -var foo3 = typeof a !== "undefined" && a !== null ? a : 'foo' ? (typeof b !== "undefined" && b !== null ? b : 'bar') : (typeof c !== "undefined" && c !== null ? c : 'baz'); +var foo2 = (a != null ? a : 'foo') ? 1 : 2; +var foo3 = (a != null ? a : 'foo') ? ((b != null ? b : 'bar')) : ((c != null ? c : 'baz')); function f() { - var foo4 = typeof a !== "undefined" && a !== null ? a : 'foo' ? typeof b !== "undefined" && b !== null ? b : 'bar' : typeof c !== "undefined" && c !== null ? c : 'baz'; + var foo4 = (a != null ? a : 'foo') ? (b != null ? b : 'bar') : (c != null ? c : 'baz'); } diff --git a/tests/baselines/reference/nullishCoalescingOperator8.js b/tests/baselines/reference/nullishCoalescingOperator8.js index 5c60f1f9dc1e2..313e2a2a74f7c 100644 --- a/tests/baselines/reference/nullishCoalescingOperator8.js +++ b/tests/baselines/reference/nullishCoalescingOperator8.js @@ -10,7 +10,7 @@ const n3 = a.m() ?? b.p ?? b.m() ?? "default";; //// [nullishCoalescingOperator8.js] var _a, _b, _c, _d, _e; "use strict"; -var n1 = (_a = a.p, _a !== void 0 && _a !== null ? _a : "default"); -var n2 = (_b = a.m(), _b !== void 0 && _b !== null ? _b : "default"); -var n3 = (_e = (_d = (_c = a.m(), _c !== void 0 && _c !== null ? _c : b.p), _d !== void 0 && _d !== null ? _d : b.m()), _e !== void 0 && _e !== null ? _e : "default"); +var n1 = (_a = a.p, (_a != null ? _a : "default")); +var n2 = (_b = a.m(), (_b != null ? _b : "default")); +var n3 = (_e = (_d = (_c = a.m(), (_c != null ? _c : b.p)), (_d != null ? _d : b.m())), (_e != null ? _e : "default")); ; diff --git a/tests/baselines/reference/nullishCoalescingOperator_not_strict.js b/tests/baselines/reference/nullishCoalescingOperator_not_strict.js index fd6c6e9ab374c..413a6720d15fa 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_not_strict.js +++ b/tests/baselines/reference/nullishCoalescingOperator_not_strict.js @@ -21,12 +21,12 @@ const aa8 = a8 ?? 'whatever' const aa9 = a9 ?? 'whatever' //// [nullishCoalescingOperator_not_strict.js] -var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever'; -var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever'; -var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever'; -var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever'; -var aa5 = typeof a5 !== "undefined" && a5 !== null ? a5 : 'whatever'; -var aa6 = typeof a6 !== "undefined" && a6 !== null ? a6 : 'whatever'; -var aa7 = typeof a7 !== "undefined" && a7 !== null ? a7 : 'whatever'; -var aa8 = typeof a8 !== "undefined" && a8 !== null ? a8 : 'whatever'; -var aa9 = typeof a9 !== "undefined" && a9 !== null ? a9 : 'whatever'; +var aa1 = (a1 != null ? a1 : 'whatever'); +var aa2 = (a2 != null ? a2 : 'whatever'); +var aa3 = (a3 != null ? a3 : 'whatever'); +var aa4 = (a4 != null ? a4 : 'whatever'); +var aa5 = (a5 != null ? a5 : 'whatever'); +var aa6 = (a6 != null ? a6 : 'whatever'); +var aa7 = (a7 != null ? a7 : 'whatever'); +var aa8 = (a8 != null ? a8 : 'whatever'); +var aa9 = (a9 != null ? a9 : 'whatever'); From b714a01df2f221fd223730fdb6a10f4cae0d3b71 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 16 Aug 2019 15:13:57 +0800 Subject: [PATCH 12/26] rename factory --- src/compiler/factory.ts | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index c1740b53118a9..077735a0cdeed 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -3044,7 +3044,7 @@ namespace ts { return createBinary(left, SyntaxKind.BarBarToken, right); } - export function createNullishCoalescing(left: Expression, right: Expression) { + export function createNullishCoalesce(left: Expression, right: Expression) { return createBinary(left, SyntaxKind.QuestionQuestionToken, right); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 9bc886667ef31..cd4d1211c1c6a 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4097,7 +4097,7 @@ declare namespace ts { function createPostfixIncrement(operand: Expression): PostfixUnaryExpression; function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; function createLogicalOr(left: Expression, right: Expression): BinaryExpression; - function createNullishCoalescing(left: Expression, right: Expression): BinaryExpression; + function createNullishCoalesce(left: Expression, right: Expression): BinaryExpression; function createLogicalNot(operand: Expression): PrefixUnaryExpression; function createVoidZero(): VoidExpression; function createExportDefault(expression: Expression): ExportAssignment; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2a04df7b2cf4d..1ec54147fd736 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4097,7 +4097,7 @@ declare namespace ts { function createPostfixIncrement(operand: Expression): PostfixUnaryExpression; function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; function createLogicalOr(left: Expression, right: Expression): BinaryExpression; - function createNullishCoalescing(left: Expression, right: Expression): BinaryExpression; + function createNullishCoalesce(left: Expression, right: Expression): BinaryExpression; function createLogicalNot(operand: Expression): PrefixUnaryExpression; function createVoidZero(): VoidExpression; function createExportDefault(expression: Expression): ExportAssignment; From 323ebf0b3fa3f665336bbe97bdb87cc84cb37112 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 16 Aug 2019 16:23:51 +0800 Subject: [PATCH 13/26] add grammar check --- src/compiler/checker.ts | 13 +++++ src/compiler/diagnosticMessages.json | 4 ++ src/compiler/utilities.ts | 3 +- .../nullishCoalescingOperator5.errors.txt | 55 +++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperator5.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7679cb14167bf..6924b70a24331 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23753,9 +23753,22 @@ namespace ts { if (isInJSFile(node) && getAssignedExpandoInitializer(node)) { return checkExpression(node.right, checkMode); } + checkGrammarNullishCoalesceWithLogicalExpression(node); return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node); } + function checkGrammarNullishCoalesceWithLogicalExpression (node: BinaryExpression) { + const { left, operatorToken, right } = node; + if (operatorToken.kind === SyntaxKind.QuestionQuestionToken) { + if (isBinaryExpression(left) && (left.operatorToken.kind === SyntaxKind.BarBarToken || left.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { + error(left, Diagnostics.Operator_0_cannot_immediately_contain_or_be_contained_within_an_1_operation, tokenToString(left.operatorToken.kind), tokenToString(operatorToken.kind)); + } + if (isBinaryExpression(right) && (right.operatorToken.kind === SyntaxKind.BarBarToken || right.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { + error(right, Diagnostics.Operator_0_cannot_immediately_contain_or_be_contained_within_an_1_operation, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind)); + } + } + } + function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, checkMode?: CheckMode, errorNode?: Node): Type { const operator = operatorToken.kind; if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 529484956e674..a626adb2bac2c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3104,6 +3104,10 @@ "category": "Error", "code": 5075 }, + "Operator '{0}' cannot immediately contain, or be contained within an '{1}' operation.": { + "category": "Error", + "code": 5076 + }, "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 445ca85faee37..ac6f506b78744 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3905,7 +3905,8 @@ namespace ts { export function isLogicalOperator(token: SyntaxKind): boolean { return token === SyntaxKind.BarBarToken || token === SyntaxKind.AmpersandAmpersandToken - || token === SyntaxKind.ExclamationToken; + || token === SyntaxKind.ExclamationToken + || token === SyntaxKind.QuestionQuestionToken; } export function isAssignmentOperator(token: SyntaxKind): boolean { diff --git a/tests/baselines/reference/nullishCoalescingOperator5.errors.txt b/tests/baselines/reference/nullishCoalescingOperator5.errors.txt new file mode 100644 index 0000000000000..37194b0010dfc --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator5.errors.txt @@ -0,0 +1,55 @@ +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(6,6): error TS5076: Operator '||' cannot immediately contain, or be contained within an '??' operation. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(9,1): error TS5076: Operator '||' cannot immediately contain, or be contained within an '??' operation. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(12,6): error TS5076: Operator '&&' cannot immediately contain, or be contained within an '??' operation. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(15,1): error TS5076: Operator '&&' cannot immediately contain, or be contained within an '??' operation. + + +==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts (4 errors) ==== + declare const a: string | undefined + declare const b: string | undefined + declare const c: string | undefined + + // should be a syntax error + a ?? b || c; + ~~~~~~ +!!! error TS5076: Operator '||' cannot immediately contain, or be contained within an '??' operation. + + // should be a syntax error + a || b ?? c; + ~~~~~~ +!!! error TS5076: Operator '||' cannot immediately contain, or be contained within an '??' operation. + + // should be a syntax error + a ?? b && c; + ~~~~~~ +!!! error TS5076: Operator '&&' cannot immediately contain, or be contained within an '??' operation. + + // should be a syntax error + a && b ?? c; + ~~~~~~ +!!! error TS5076: Operator '&&' cannot immediately contain, or be contained within an '??' operation. + + // Valid according to spec + a ?? (b || c); + + // Valid according to spec + (a ?? b) || c; + + // Valid according to spec + (a || b) ?? c; + + // Valid according to spec + a || (b ?? c); + + // Valid according to spec + a ?? (b && c); + + // Valid according to spec + (a ?? b) && c; + + // Valid according to spec + (a && b) ?? c; + + // Valid according to spec + a && (b ?? c); + \ No newline at end of file From d659c83b61f1ab842a93ff6a7a97aba4ac368334 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 16 Aug 2019 17:15:10 +0800 Subject: [PATCH 14/26] fix more cases --- src/compiler/factory.ts | 2 +- src/services/codefixes/inferFromUsage.ts | 1 + src/testRunner/unittests/factory.ts | 1 + tests/cases/fourslash/codefixInferFromUsageNullish.ts | 9 +++++++++ 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/codefixInferFromUsageNullish.ts diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 077735a0cdeed..86d4d925ba7da 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -4377,7 +4377,7 @@ namespace ts { const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator); const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator); const emittedOperand = skipPartiallyEmittedExpressions(operand); - if (!isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction && binaryOperatorPrecedence > 4) { + if (!isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction && binaryOperatorPrecedence > 3) { // We need to parenthesize arrow functions on the right side to avoid it being // parsed as parenthesized expression: `a && (() => {})` return true; diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 53ca335c7a5ec..2a8ff2d9cdc36 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -647,6 +647,7 @@ namespace ts.codefix { // LogicalOperator case SyntaxKind.BarBarToken: + case SyntaxKind.QuestionQuestionToken: if (node === parent.left && (node.parent.parent.kind === SyntaxKind.VariableDeclaration || isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true))) { // var x = x || {}; diff --git a/src/testRunner/unittests/factory.ts b/src/testRunner/unittests/factory.ts index 5593b39256707..ae4258287fedb 100644 --- a/src/testRunner/unittests/factory.ts +++ b/src/testRunner/unittests/factory.ts @@ -75,6 +75,7 @@ namespace ts { checkRhs(SyntaxKind.PlusEqualsToken, /*expectParens*/ false); checkRhs(SyntaxKind.BarBarToken, /*expectParens*/ true); checkRhs(SyntaxKind.AmpersandAmpersandToken, /*expectParens*/ true); + checkRhs(SyntaxKind.QuestionQuestionToken, /*expectParens*/ true); checkRhs(SyntaxKind.EqualsEqualsToken, /*expectParens*/ true); }); }); diff --git a/tests/cases/fourslash/codefixInferFromUsageNullish.ts b/tests/cases/fourslash/codefixInferFromUsageNullish.ts new file mode 100644 index 0000000000000..d1073a9d9a958 --- /dev/null +++ b/tests/cases/fourslash/codefixInferFromUsageNullish.ts @@ -0,0 +1,9 @@ +/// + +// @noImplicitAny: true +////declare const a: string +////function wat([|b |]) { +//// b(a ?? 1); +////} + +verify.rangeAfterCodeFix("b: (arg0: string | number) => void"); From 55dd6ae0fc31e53ff96aa860839b92cb8151657d Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Sun, 18 Aug 2019 18:45:41 +0300 Subject: [PATCH 15/26] Fix handling of nullish coalescing oprator in expando objects. --- src/compiler/utilities.ts | 39 ++-- .../typeFromPropertyAssignment10_1.symbols | 141 +++++++++++++ .../typeFromPropertyAssignment10_1.types | 174 ++++++++++++++++ .../typeFromPropertyAssignment8_1.symbols | 72 +++++++ .../typeFromPropertyAssignment8_1.types | 96 +++++++++ .../typeFromPropertyAssignment9_1.symbols | 139 +++++++++++++ .../typeFromPropertyAssignment9_1.types | 196 ++++++++++++++++++ .../salsa/typeFromPropertyAssignment10_1.ts | 48 +++++ .../salsa/typeFromPropertyAssignment8_1.ts | 28 +++ .../salsa/typeFromPropertyAssignment9_1.ts | 39 ++++ 10 files changed, 956 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/typeFromPropertyAssignment10_1.symbols create mode 100644 tests/baselines/reference/typeFromPropertyAssignment10_1.types create mode 100644 tests/baselines/reference/typeFromPropertyAssignment8_1.symbols create mode 100644 tests/baselines/reference/typeFromPropertyAssignment8_1.types create mode 100644 tests/baselines/reference/typeFromPropertyAssignment9_1.symbols create mode 100644 tests/baselines/reference/typeFromPropertyAssignment9_1.types create mode 100644 tests/cases/conformance/salsa/typeFromPropertyAssignment10_1.ts create mode 100644 tests/cases/conformance/salsa/typeFromPropertyAssignment8_1.ts create mode 100644 tests/cases/conformance/salsa/typeFromPropertyAssignment9_1.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ac6f506b78744..27ff60ce07a1a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1803,22 +1803,26 @@ namespace ts { name = node.parent.name; decl = node.parent; } - else if (isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken && node.parent.right === node) { - name = node.parent.left; - decl = name; - } - else if (isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.BarBarToken) { - if (isVariableDeclaration(node.parent.parent) && node.parent.parent.initializer === node.parent) { - name = node.parent.parent.name; - decl = node.parent.parent; - } - else if (isBinaryExpression(node.parent.parent) && node.parent.parent.operatorToken.kind === SyntaxKind.EqualsToken && node.parent.parent.right === node.parent) { - name = node.parent.parent.left; + else if (isBinaryExpression(node.parent)) { + const parentNode = node.parent; + const parentNodeOperator = node.parent.operatorToken.kind; + if (parentNodeOperator === SyntaxKind.EqualsToken && parentNode.right === node) { + name = parentNode.left; decl = name; } + else if (parentNodeOperator === SyntaxKind.BarBarToken || parentNodeOperator === SyntaxKind.QuestionQuestionToken) { + if (isVariableDeclaration(parentNode.parent) && parentNode.parent.initializer === parentNode) { + name = parentNode.parent.name; + decl = parentNode.parent; + } + else if (isBinaryExpression(parentNode.parent) && parentNode.parent.operatorToken.kind === SyntaxKind.EqualsToken && parentNode.parent.right === parentNode) { + name = parentNode.parent.left; + decl = name; + } - if (!name || !isEntityNameExpression(name) || !isSameEntityName(name, node.parent.left)) { - return undefined; + if (!name || !isEntityNameExpression(name) || !isSameEntityName(name, parentNode.left)) { + return undefined; + } } } @@ -1835,7 +1839,8 @@ namespace ts { /** Get the initializer, taking into account defaulted Javascript initializers */ export function getEffectiveInitializer(node: HasExpressionInitializer) { if (isInJSFile(node) && node.initializer && - isBinaryExpression(node.initializer) && node.initializer.operatorToken.kind === SyntaxKind.BarBarToken && + isBinaryExpression(node.initializer) && + (node.initializer.operatorToken.kind === SyntaxKind.BarBarToken || node.initializer.operatorToken.kind === SyntaxKind.QuestionQuestionToken) && node.name && isEntityNameExpression(node.name) && isSameEntityName(node.name, node.initializer.left)) { return node.initializer.right; } @@ -1904,7 +1909,9 @@ namespace ts { * 'window.', 'global.' or 'self.' The second Lhs is otherwise ignored by the binder and checker. */ function getDefaultedExpandoInitializer(name: EntityNameExpression, initializer: Expression, isPrototypeAssignment: boolean) { - const e = isBinaryExpression(initializer) && initializer.operatorToken.kind === SyntaxKind.BarBarToken && getExpandoInitializer(initializer.right, isPrototypeAssignment); + const e = isBinaryExpression(initializer) + && (initializer.operatorToken.kind === SyntaxKind.BarBarToken || initializer.operatorToken.kind === SyntaxKind.QuestionQuestionToken) + && getExpandoInitializer(initializer.right, isPrototypeAssignment); if (e && isSameEntityName(name, (initializer as BinaryExpression).left as EntityNameExpression)) { return e; } @@ -2168,7 +2175,7 @@ namespace ts { isBinaryExpression(node.expression) && getAssignmentDeclarationKind(node.expression) !== AssignmentDeclarationKind.None && isBinaryExpression(node.expression.right) && - node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken + (node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken || node.expression.right.operatorToken.kind === SyntaxKind.QuestionQuestionToken) ? node.expression.right.right : undefined; } diff --git a/tests/baselines/reference/typeFromPropertyAssignment10_1.symbols b/tests/baselines/reference/typeFromPropertyAssignment10_1.symbols new file mode 100644 index 0000000000000..85b4b448fb4eb --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment10_1.symbols @@ -0,0 +1,141 @@ +=== tests/cases/conformance/salsa/module.js === +var Outer = Outer ?? {}; +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) + +Outer.app = Outer.app ?? {}; +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) + +=== tests/cases/conformance/salsa/someview.js === +Outer.app.SomeView = (function () { +>Outer.app.SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) + + var SomeView = function() { +>SomeView : Symbol(SomeView, Decl(someview.js, 1, 7)) + + var me = this; +>me : Symbol(me, Decl(someview.js, 2, 11)) + } + return SomeView; +>SomeView : Symbol(SomeView, Decl(someview.js, 1, 7)) + +})(); +Outer.app.Inner = class { +>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) + + constructor() { + /** @type {number} */ + this.y = 12; +>this.y : Symbol(Inner.y, Decl(someview.js, 7, 19)) +>this : Symbol(Inner, Decl(someview.js, 6, 17)) +>y : Symbol(Inner.y, Decl(someview.js, 7, 19)) + } +} +var example = new Outer.app.Inner(); +>example : Symbol(example, Decl(someview.js, 12, 3)) +>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) + +example.y; +>example.y : Symbol(Inner.y, Decl(someview.js, 7, 19)) +>example : Symbol(example, Decl(someview.js, 12, 3)) +>y : Symbol(Inner.y, Decl(someview.js, 7, 19)) + +/** @param {number} k */ +Outer.app.statische = function (k) { +>Outer.app.statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) +>k : Symbol(k, Decl(someview.js, 15, 32)) + + return k ** k; +>k : Symbol(k, Decl(someview.js, 15, 32)) +>k : Symbol(k, Decl(someview.js, 15, 32)) +} +=== tests/cases/conformance/salsa/application.js === +Outer.app.Application = (function () { +>Outer.app.Application : Symbol(Outer.app.Application, Decl(application.js, 0, 0)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Application : Symbol(Outer.app.Application, Decl(application.js, 0, 0)) + + /** + * Application main class. + * Will be instantiated & initialized by HTML page + */ + var Application = function () { +>Application : Symbol(Application, Decl(application.js, 6, 7)) + + var me = this; +>me : Symbol(me, Decl(application.js, 7, 11)) + + me.view = new Outer.app.SomeView(); +>me : Symbol(me, Decl(application.js, 7, 11)) +>Outer.app.SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) + + }; + return Application; +>Application : Symbol(Application, Decl(application.js, 6, 7)) + +})(); +=== tests/cases/conformance/salsa/main.js === +var app = new Outer.app.Application(); +>app : Symbol(app, Decl(main.js, 0, 3)) +>Outer.app.Application : Symbol(Outer.app.Application, Decl(application.js, 0, 0)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Application : Symbol(Outer.app.Application, Decl(application.js, 0, 0)) + +var inner = new Outer.app.Inner(); +>inner : Symbol(inner, Decl(main.js, 1, 3)) +>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) + +inner.y; +>inner.y : Symbol(Inner.y, Decl(someview.js, 7, 19)) +>inner : Symbol(inner, Decl(main.js, 1, 3)) +>y : Symbol(Inner.y, Decl(someview.js, 7, 19)) + +/** @type {Outer.app.Inner} */ +var x; +>x : Symbol(x, Decl(main.js, 4, 3)) + +x.y; +>x.y : Symbol(Inner.y, Decl(someview.js, 7, 19)) +>x : Symbol(x, Decl(main.js, 4, 3)) +>y : Symbol(Inner.y, Decl(someview.js, 7, 19)) + +Outer.app.statische(101); // Infinity, duh +>Outer.app.statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment10_1.types b/tests/baselines/reference/typeFromPropertyAssignment10_1.types new file mode 100644 index 0000000000000..fa593e6dacfae --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment10_1.types @@ -0,0 +1,174 @@ +=== tests/cases/conformance/salsa/module.js === +var Outer = Outer ?? {}; +>Outer : typeof Outer +>Outer ?? {} : typeof Outer | {} +>Outer : typeof Outer +>{} : {} + +Outer.app = Outer.app ?? {}; +>Outer.app = Outer.app ?? {} : typeof Outer.app +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>Outer.app ?? {} : {} +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>{} : {} + +=== tests/cases/conformance/salsa/someview.js === +Outer.app.SomeView = (function () { +>Outer.app.SomeView = (function () { var SomeView = function() { var me = this; } return SomeView;})() : () => void +>Outer.app.SomeView : () => void +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>SomeView : () => void +>(function () { var SomeView = function() { var me = this; } return SomeView;})() : () => void +>(function () { var SomeView = function() { var me = this; } return SomeView;}) : () => () => void +>function () { var SomeView = function() { var me = this; } return SomeView;} : () => () => void + + var SomeView = function() { +>SomeView : () => void +>function() { var me = this; } : () => void + + var me = this; +>me : any +>this : any + } + return SomeView; +>SomeView : () => void + +})(); +Outer.app.Inner = class { +>Outer.app.Inner = class { constructor() { /** @type {number} */ this.y = 12; }} : typeof Inner +>Outer.app.Inner : typeof Inner +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>Inner : typeof Inner +>class { constructor() { /** @type {number} */ this.y = 12; }} : typeof Inner + + constructor() { + /** @type {number} */ + this.y = 12; +>this.y = 12 : 12 +>this.y : number +>this : this +>y : number +>12 : 12 + } +} +var example = new Outer.app.Inner(); +>example : Inner +>new Outer.app.Inner() : Inner +>Outer.app.Inner : typeof Inner +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>Inner : typeof Inner + +example.y; +>example.y : number +>example : Inner +>y : number + +/** @param {number} k */ +Outer.app.statische = function (k) { +>Outer.app.statische = function (k) { return k ** k;} : (k: number) => number +>Outer.app.statische : (k: number) => number +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>statische : (k: number) => number +>function (k) { return k ** k;} : (k: number) => number +>k : number + + return k ** k; +>k ** k : number +>k : number +>k : number +} +=== tests/cases/conformance/salsa/application.js === +Outer.app.Application = (function () { +>Outer.app.Application = (function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;})() : () => void +>Outer.app.Application : () => void +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>Application : () => void +>(function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;})() : () => void +>(function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;}) : () => () => void +>function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;} : () => () => void + + /** + * Application main class. + * Will be instantiated & initialized by HTML page + */ + var Application = function () { +>Application : () => void +>function () { var me = this; me.view = new Outer.app.SomeView(); } : () => void + + var me = this; +>me : any +>this : any + + me.view = new Outer.app.SomeView(); +>me.view = new Outer.app.SomeView() : any +>me.view : any +>me : any +>view : any +>new Outer.app.SomeView() : any +>Outer.app.SomeView : () => void +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>SomeView : () => void + + }; + return Application; +>Application : () => void + +})(); +=== tests/cases/conformance/salsa/main.js === +var app = new Outer.app.Application(); +>app : any +>new Outer.app.Application() : any +>Outer.app.Application : () => void +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>Application : () => void + +var inner = new Outer.app.Inner(); +>inner : Inner +>new Outer.app.Inner() : Inner +>Outer.app.Inner : typeof Inner +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>Inner : typeof Inner + +inner.y; +>inner.y : number +>inner : Inner +>y : number + +/** @type {Outer.app.Inner} */ +var x; +>x : Inner + +x.y; +>x.y : number +>x : Inner +>y : number + +Outer.app.statische(101); // Infinity, duh +>Outer.app.statische(101) : number +>Outer.app.statische : (k: number) => number +>Outer.app : typeof Outer.app +>Outer : typeof Outer +>app : typeof Outer.app +>statische : (k: number) => number +>101 : 101 + diff --git a/tests/baselines/reference/typeFromPropertyAssignment8_1.symbols b/tests/baselines/reference/typeFromPropertyAssignment8_1.symbols new file mode 100644 index 0000000000000..eebaa8a04afec --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment8_1.symbols @@ -0,0 +1,72 @@ +=== tests/cases/conformance/salsa/a.js === +var my = my ?? {}; +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 1, 22)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 1, 22)) + +my.app = my.app ?? {}; +>my.app : Symbol(my.app, Decl(a.js, 0, 18), Decl(a.js, 3, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 1, 22)) +>app : Symbol(my.app, Decl(a.js, 0, 18), Decl(a.js, 3, 3)) +>my.app : Symbol(my.app, Decl(a.js, 0, 18), Decl(a.js, 3, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 1, 22)) +>app : Symbol(my.app, Decl(a.js, 0, 18), Decl(a.js, 3, 3)) + +my.app.Application = (function () { +>my.app.Application : Symbol(my.app.Application, Decl(a.js, 1, 22)) +>my.app : Symbol(my.app, Decl(a.js, 0, 18), Decl(a.js, 3, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 1, 22)) +>app : Symbol(my.app, Decl(a.js, 0, 18), Decl(a.js, 3, 3)) +>Application : Symbol(my.app.Application, Decl(a.js, 1, 22)) + +var Application = function () { +>Application : Symbol(Application, Decl(a.js, 4, 3)) + + //... +}; +return Application; +>Application : Symbol(Application, Decl(a.js, 4, 3)) + +})(); +my.app.Application() +>my.app.Application : Symbol(my.app.Application, Decl(a.js, 1, 22)) +>my.app : Symbol(my.app, Decl(a.js, 0, 18), Decl(a.js, 3, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 1, 22)) +>app : Symbol(my.app, Decl(a.js, 0, 18), Decl(a.js, 3, 3)) +>Application : Symbol(my.app.Application, Decl(a.js, 1, 22)) + +=== tests/cases/conformance/salsa/b.js === +var min = window.min ?? {}; +>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 0, 27), Decl(b.js, 1, 24)) +>window : Symbol(window, Decl(lib.dom.d.ts, --, --)) + +min.app = min.app ?? {}; +>min.app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) +>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 0, 27), Decl(b.js, 1, 24)) +>app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) +>min.app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) +>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 0, 27), Decl(b.js, 1, 24)) +>app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) + +min.app.Application = (function () { +>min.app.Application : Symbol(min.app.Application, Decl(b.js, 1, 24)) +>min.app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) +>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 0, 27), Decl(b.js, 1, 24)) +>app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) +>Application : Symbol(min.app.Application, Decl(b.js, 1, 24)) + +var Application = function () { +>Application : Symbol(Application, Decl(b.js, 4, 3)) + + //... +}; +return Application; +>Application : Symbol(Application, Decl(b.js, 4, 3)) + +})(); +min.app.Application() +>min.app.Application : Symbol(min.app.Application, Decl(b.js, 1, 24)) +>min.app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) +>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 0, 27), Decl(b.js, 1, 24)) +>app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) +>Application : Symbol(min.app.Application, Decl(b.js, 1, 24)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment8_1.types b/tests/baselines/reference/typeFromPropertyAssignment8_1.types new file mode 100644 index 0000000000000..4474ba705bf73 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment8_1.types @@ -0,0 +1,96 @@ +=== tests/cases/conformance/salsa/a.js === +var my = my ?? {}; +>my : typeof my +>my ?? {} : typeof my | {} +>my : typeof my +>{} : {} + +my.app = my.app ?? {}; +>my.app = my.app ?? {} : typeof my.app +>my.app : typeof my.app +>my : typeof my +>app : typeof my.app +>my.app ?? {} : {} +>my.app : typeof my.app +>my : typeof my +>app : typeof my.app +>{} : {} + +my.app.Application = (function () { +>my.app.Application = (function () {var Application = function () { //...};return Application;})() : () => void +>my.app.Application : () => void +>my.app : typeof my.app +>my : typeof my +>app : typeof my.app +>Application : () => void +>(function () {var Application = function () { //...};return Application;})() : () => void +>(function () {var Application = function () { //...};return Application;}) : () => () => void +>function () {var Application = function () { //...};return Application;} : () => () => void + +var Application = function () { +>Application : () => void +>function () { //...} : () => void + + //... +}; +return Application; +>Application : () => void + +})(); +my.app.Application() +>my.app.Application() : void +>my.app.Application : () => void +>my.app : typeof my.app +>my : typeof my +>app : typeof my.app +>Application : () => void + +=== tests/cases/conformance/salsa/b.js === +var min = window.min ?? {}; +>min : typeof min +>window.min ?? {} : any +>window.min : error +>window : Window +>min : any +>{} : {} + +min.app = min.app ?? {}; +>min.app = min.app ?? {} : typeof min.app +>min.app : typeof min.app +>min : typeof min +>app : typeof min.app +>min.app ?? {} : {} +>min.app : typeof min.app +>min : typeof min +>app : typeof min.app +>{} : {} + +min.app.Application = (function () { +>min.app.Application = (function () {var Application = function () { //...};return Application;})() : () => void +>min.app.Application : () => void +>min.app : typeof min.app +>min : typeof min +>app : typeof min.app +>Application : () => void +>(function () {var Application = function () { //...};return Application;})() : () => void +>(function () {var Application = function () { //...};return Application;}) : () => () => void +>function () {var Application = function () { //...};return Application;} : () => () => void + +var Application = function () { +>Application : () => void +>function () { //...} : () => void + + //... +}; +return Application; +>Application : () => void + +})(); +min.app.Application() +>min.app.Application() : void +>min.app.Application : () => void +>min.app : typeof min.app +>min : typeof min +>app : typeof min.app +>Application : () => void + diff --git a/tests/baselines/reference/typeFromPropertyAssignment9_1.symbols b/tests/baselines/reference/typeFromPropertyAssignment9_1.symbols new file mode 100644 index 0000000000000..46474f4d50f03 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment9_1.symbols @@ -0,0 +1,139 @@ +=== tests/cases/conformance/salsa/a.js === +var my = my ?? {}; +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) + +/** @param {number} n */ +my.method = function(n) { +>my.method : Symbol(my.method, Decl(a.js, 0, 18)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>method : Symbol(my.method, Decl(a.js, 0, 18)) +>n : Symbol(n, Decl(a.js, 2, 21)) + + return n + 1; +>n : Symbol(n, Decl(a.js, 2, 21)) +} +my.number = 1; +>my.number : Symbol(my.number, Decl(a.js, 4, 1)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>number : Symbol(my.number, Decl(a.js, 4, 1)) + +my.object = {}; +>my.object : Symbol(my.object, Decl(a.js, 5, 14)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>object : Symbol(my.object, Decl(a.js, 5, 14)) + +my.predicate = my.predicate ?? {}; +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) + +my.predicate.query = function () { +>my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) + + var me = this; +>me : Symbol(me, Decl(a.js, 9, 7)) +>this : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) + + me.property = false; +>me : Symbol(me, Decl(a.js, 9, 7)) + +}; +var q = new my.predicate.query(); +>q : Symbol(q, Decl(a.js, 12, 3)) +>my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) + +my.predicate.query.another = function () { +>my.predicate.query.another : Symbol(my.predicate.query.another, Decl(a.js, 12, 33)) +>my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>another : Symbol(my.predicate.query.another, Decl(a.js, 12, 33)) + + return 1; +} +my.predicate.query.result = 'none' +>my.predicate.query.result : Symbol(my.predicate.query.result, Decl(a.js, 15, 1)) +>my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>result : Symbol(my.predicate.query.result, Decl(a.js, 15, 1)) + +/** @param {number} first + * @param {number} second + */ +my.predicate.sort = my.predicate.sort ?? function (first, second) { +>my.predicate.sort : Symbol(my.predicate.sort, Decl(a.js, 16, 34)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>sort : Symbol(my.predicate.sort, Decl(a.js, 16, 34)) +>my.predicate.sort : Symbol(my.predicate.sort, Decl(a.js, 16, 34)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>sort : Symbol(my.predicate.sort, Decl(a.js, 16, 34)) +>first : Symbol(first, Decl(a.js, 20, 51)) +>second : Symbol(second, Decl(a.js, 20, 57)) + + return first > second ? first : second; +>first : Symbol(first, Decl(a.js, 20, 51)) +>second : Symbol(second, Decl(a.js, 20, 57)) +>first : Symbol(first, Decl(a.js, 20, 51)) +>second : Symbol(second, Decl(a.js, 20, 57)) +} +my.predicate.type = class { +>my.predicate.type : Symbol(my.predicate.type, Decl(a.js, 22, 1)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>type : Symbol(my.predicate.type, Decl(a.js, 22, 1)) + + m() { return 101; } +>m : Symbol(type.m, Decl(a.js, 23, 27)) +} + + +// global-ish prefixes +var min = window.min ?? {}; +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>window : Symbol(window, Decl(lib.dom.d.ts, --, --)) + +min.nest = this.min.nest ?? function () { }; +>min.nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) +>this.min.nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) +>this.min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>this : Symbol(globalThis) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) + +min.nest.other = self.min.nest.other ?? class { }; +>min.nest.other : Symbol(min.nest.other, Decl(a.js, 30, 44)) +>min.nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) +>other : Symbol(min.nest.other, Decl(a.js, 30, 44)) +>self : Symbol(self, Decl(lib.dom.d.ts, --, --)) + +min.property = global.min.property ?? {}; +>min.property : Symbol(min.property, Decl(a.js, 31, 50)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>property : Symbol(min.property, Decl(a.js, 31, 50)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment9_1.types b/tests/baselines/reference/typeFromPropertyAssignment9_1.types new file mode 100644 index 0000000000000..fdfa0a96083f4 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment9_1.types @@ -0,0 +1,196 @@ +=== tests/cases/conformance/salsa/a.js === +var my = my ?? {}; +>my : typeof my +>my ?? {} : typeof my | {} +>my : typeof my +>{} : {} + +/** @param {number} n */ +my.method = function(n) { +>my.method = function(n) { return n + 1;} : (n: number) => number +>my.method : (n: number) => number +>my : typeof my +>method : (n: number) => number +>function(n) { return n + 1;} : (n: number) => number +>n : number + + return n + 1; +>n + 1 : number +>n : number +>1 : 1 +} +my.number = 1; +>my.number = 1 : 1 +>my.number : number +>my : typeof my +>number : number +>1 : 1 + +my.object = {}; +>my.object = {} : {} +>my.object : {} +>my : typeof my +>object : {} +>{} : {} + +my.predicate = my.predicate ?? {}; +>my.predicate = my.predicate ?? {} : typeof my.predicate +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>my.predicate ?? {} : {} +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>{} : {} + +my.predicate.query = function () { +>my.predicate.query = function () { var me = this; me.property = false;} : { (): void; another(): number; result: string; } +>my.predicate.query : { (): void; another(): number; result: string; } +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>query : { (): void; another(): number; result: string; } +>function () { var me = this; me.property = false;} : { (): void; another(): number; result: string; } + + var me = this; +>me : typeof my.predicate +>this : typeof my.predicate + + me.property = false; +>me.property = false : false +>me.property : any +>me : typeof my.predicate +>property : any +>false : false + +}; +var q = new my.predicate.query(); +>q : any +>new my.predicate.query() : any +>my.predicate.query : { (): void; another(): number; result: string; } +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>query : { (): void; another(): number; result: string; } + +my.predicate.query.another = function () { +>my.predicate.query.another = function () { return 1;} : () => number +>my.predicate.query.another : () => number +>my.predicate.query : { (): void; another(): number; result: string; } +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>query : { (): void; another(): number; result: string; } +>another : () => number +>function () { return 1;} : () => number + + return 1; +>1 : 1 +} +my.predicate.query.result = 'none' +>my.predicate.query.result = 'none' : "none" +>my.predicate.query.result : string +>my.predicate.query : { (): void; another(): number; result: string; } +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>query : { (): void; another(): number; result: string; } +>result : string +>'none' : "none" + +/** @param {number} first + * @param {number} second + */ +my.predicate.sort = my.predicate.sort ?? function (first, second) { +>my.predicate.sort = my.predicate.sort ?? function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number +>my.predicate.sort : (first: number, second: number) => number +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>sort : (first: number, second: number) => number +>my.predicate.sort ?? function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number +>my.predicate.sort : (first: number, second: number) => number +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>sort : (first: number, second: number) => number +>function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number +>first : number +>second : number + + return first > second ? first : second; +>first > second ? first : second : number +>first > second : boolean +>first : number +>second : number +>first : number +>second : number +} +my.predicate.type = class { +>my.predicate.type = class { m() { return 101; }} : typeof type +>my.predicate.type : typeof type +>my.predicate : typeof my.predicate +>my : typeof my +>predicate : typeof my.predicate +>type : typeof type +>class { m() { return 101; }} : typeof type + + m() { return 101; } +>m : () => number +>101 : 101 +} + + +// global-ish prefixes +var min = window.min ?? {}; +>min : typeof min +>window.min ?? {} : any +>window.min : error +>window : Window +>min : any +>{} : {} + +min.nest = this.min.nest ?? function () { }; +>min.nest = this.min.nest ?? function () { } : { (): void; other: typeof other; } +>min.nest : { (): void; other: typeof other; } +>min : typeof min +>nest : { (): void; other: typeof other; } +>this.min.nest ?? function () { } : { (): void; other: typeof other; } +>this.min.nest : { (): void; other: typeof other; } +>this.min : typeof min +>this : typeof globalThis +>min : typeof min +>nest : { (): void; other: typeof other; } +>function () { } : { (): void; other: typeof other; } + +min.nest.other = self.min.nest.other ?? class { }; +>min.nest.other = self.min.nest.other ?? class { } : typeof other +>min.nest.other : typeof other +>min.nest : { (): void; other: typeof other; } +>min : typeof min +>nest : { (): void; other: typeof other; } +>other : typeof other +>self.min.nest.other ?? class { } : typeof other +>self.min.nest.other : error +>self.min.nest : any +>self.min : any +>self : Window +>min : any +>nest : any +>other : any +>class { } : typeof other + +min.property = global.min.property ?? {}; +>min.property = global.min.property ?? {} : {} +>min.property : {} +>min : typeof min +>property : {} +>global.min.property ?? {} : {} +>global.min.property : error +>global.min : any +>global : any +>min : any +>property : any +>{} : {} + diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment10_1.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment10_1.ts new file mode 100644 index 0000000000000..5e5228874d223 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment10_1.ts @@ -0,0 +1,48 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @target: esnext +// @Filename: module.js +var Outer = Outer ?? {}; +Outer.app = Outer.app ?? {}; + +// @Filename: someview.js +Outer.app.SomeView = (function () { + var SomeView = function() { + var me = this; + } + return SomeView; +})(); +Outer.app.Inner = class { + constructor() { + /** @type {number} */ + this.y = 12; + } +} +var example = new Outer.app.Inner(); +example.y; +/** @param {number} k */ +Outer.app.statische = function (k) { + return k ** k; +} +// @Filename: application.js +Outer.app.Application = (function () { + + /** + * Application main class. + * Will be instantiated & initialized by HTML page + */ + var Application = function () { + var me = this; + me.view = new Outer.app.SomeView(); + }; + return Application; +})(); +// @Filename: main.js +var app = new Outer.app.Application(); +var inner = new Outer.app.Inner(); +inner.y; +/** @type {Outer.app.Inner} */ +var x; +x.y; +Outer.app.statische(101); // Infinity, duh diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment8_1.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment8_1.ts new file mode 100644 index 0000000000000..2d6040e319dba --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment8_1.ts @@ -0,0 +1,28 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @target: esnext +// @lib: es6,dom +// @Filename: a.js +var my = my ?? {}; +my.app = my.app ?? {}; + +my.app.Application = (function () { +var Application = function () { + //... +}; +return Application; +})(); +my.app.Application() + +// @Filename: b.js +var min = window.min ?? {}; +min.app = min.app ?? {}; + +min.app.Application = (function () { +var Application = function () { + //... +}; +return Application; +})(); +min.app.Application() diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment9_1.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment9_1.ts new file mode 100644 index 0000000000000..61f6de98abbae --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment9_1.ts @@ -0,0 +1,39 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @target: esnext +// @Filename: a.js + +var my = my ?? {}; +/** @param {number} n */ +my.method = function(n) { + return n + 1; +} +my.number = 1; +my.object = {}; +my.predicate = my.predicate ?? {}; +my.predicate.query = function () { + var me = this; + me.property = false; +}; +var q = new my.predicate.query(); +my.predicate.query.another = function () { + return 1; +} +my.predicate.query.result = 'none' +/** @param {number} first + * @param {number} second + */ +my.predicate.sort = my.predicate.sort ?? function (first, second) { + return first > second ? first : second; +} +my.predicate.type = class { + m() { return 101; } +} + + +// global-ish prefixes +var min = window.min ?? {}; +min.nest = this.min.nest ?? function () { }; +min.nest.other = self.min.nest.other ?? class { }; +min.property = global.min.property ?? {}; From 22d1c073fe891d364a07ddb39d87782c9c80650e Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Sun, 18 Aug 2019 21:11:56 +0300 Subject: [PATCH 16/26] Fixed classifier to support ?? operator. --- src/services/classifier.ts | 1 + src/testRunner/unittests/services/colorization.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/services/classifier.ts b/src/services/classifier.ts index f85a69681de50..9c83568fa72db 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -390,6 +390,7 @@ namespace ts { case SyntaxKind.PercentEqualsToken: case SyntaxKind.EqualsToken: case SyntaxKind.CommaToken: + case SyntaxKind.QuestionQuestionToken: return true; default: return false; diff --git a/src/testRunner/unittests/services/colorization.ts b/src/testRunner/unittests/services/colorization.ts index 71ba8bad3940e..82d9d29dac635 100644 --- a/src/testRunner/unittests/services/colorization.ts +++ b/src/testRunner/unittests/services/colorization.ts @@ -57,7 +57,7 @@ describe("unittests:: services:: Colorization", () => { describe("test getClassifications", () => { it("Returns correct token classes", () => { - testLexicalClassification("var x: string = \"foo\"; //Hello", + testLexicalClassification("var x: string = \"foo\" ?? \"bar\"; //Hello", ts.EndOfLineState.None, keyword("var"), whitespace(" "), @@ -66,6 +66,9 @@ describe("unittests:: services:: Colorization", () => { keyword("string"), operator("="), stringLiteral("\"foo\""), + whitespace(" "), + operator("??"), + stringLiteral("\"foo\""), comment("//Hello"), punctuation(";")); }); From 7d3ccae9fb029a79a6f2a5cddabe9153a9dbb2b1 Mon Sep 17 00:00:00 2001 From: kingwl Date: Tue, 20 Aug 2019 13:13:54 +0800 Subject: [PATCH 17/26] update baseline --- .../reference/api/tsserverlibrary.d.ts | 94 ++++++++++--------- tests/baselines/reference/api/typescript.d.ts | 94 ++++++++++--------- 2 files changed, 96 insertions(+), 92 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 8c5e00e1a2f59..2268b2cd3dc3c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -375,28 +375,30 @@ declare namespace ts { JSDocOptionalType = 295, JSDocFunctionType = 296, JSDocVariadicType = 297, - JSDocComment = 298, - JSDocTypeLiteral = 299, - JSDocSignature = 300, - JSDocTag = 301, - JSDocAugmentsTag = 302, - JSDocClassTag = 303, - JSDocCallbackTag = 304, - JSDocEnumTag = 305, - JSDocParameterTag = 306, - JSDocReturnTag = 307, - JSDocThisTag = 308, - JSDocTypeTag = 309, - JSDocTemplateTag = 310, - JSDocTypedefTag = 311, - JSDocPropertyTag = 312, - SyntaxList = 313, - NotEmittedStatement = 314, - PartiallyEmittedExpression = 315, - CommaListExpression = 316, - MergeDeclarationMarker = 317, - EndOfDeclarationMarker = 318, - Count = 319, + JSDocNamepathType = 298, + JSDocComment = 299, + JSDocTypeLiteral = 300, + JSDocSignature = 301, + JSDocTag = 302, + JSDocAugmentsTag = 303, + JSDocAuthorTag = 304, + JSDocClassTag = 305, + JSDocCallbackTag = 306, + JSDocEnumTag = 307, + JSDocParameterTag = 308, + JSDocReturnTag = 309, + JSDocThisTag = 310, + JSDocTypeTag = 311, + JSDocTemplateTag = 312, + JSDocTypedefTag = 313, + JSDocPropertyTag = 314, + SyntaxList = 315, + NotEmittedStatement = 316, + PartiallyEmittedExpression = 317, + CommaListExpression = 318, + MergeDeclarationMarker = 319, + EndOfDeclarationMarker = 320, + Count = 321, FirstAssignment = 61, LastAssignment = 73, FirstCompoundAssignment = 62, @@ -423,9 +425,9 @@ declare namespace ts { LastBinaryOperator = 73, FirstNode = 150, FirstJSDocNode = 290, - LastJSDocNode = 312, - FirstJSDocTagNode = 301, - LastJSDocTagNode = 312, + LastJSDocNode = 314, + FirstJSDocTagNode = 302, + LastJSDocTagNode = 314, } export enum NodeFlags { None = 0, @@ -925,27 +927,27 @@ declare namespace ts { isSpread: boolean; type: Type; } - type ExponentiationOperator = SyntaxKind.AsteriskAsteriskToken; - type MultiplicativeOperator = SyntaxKind.AsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken; - type MultiplicativeOperatorOrHigher = ExponentiationOperator | MultiplicativeOperator; - type AdditiveOperator = SyntaxKind.PlusToken | SyntaxKind.MinusToken; - type AdditiveOperatorOrHigher = MultiplicativeOperatorOrHigher | AdditiveOperator; - type ShiftOperator = SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken; - type ShiftOperatorOrHigher = AdditiveOperatorOrHigher | ShiftOperator; - type RelationalOperator = SyntaxKind.LessThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.InstanceOfKeyword | SyntaxKind.InKeyword; - type RelationalOperatorOrHigher = ShiftOperatorOrHigher | RelationalOperator; - type EqualityOperator = SyntaxKind.EqualsEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.ExclamationEqualsToken; - type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; - type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; - type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; - type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken; - type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; - type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; - type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; - type AssignmentOperatorOrHigher = LogicalOperatorOrHigher | AssignmentOperator; - type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; - type BinaryOperatorToken = Token; - interface BinaryExpression extends Expression, Declaration { + export type ExponentiationOperator = SyntaxKind.AsteriskAsteriskToken; + export type MultiplicativeOperator = SyntaxKind.AsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken; + export type MultiplicativeOperatorOrHigher = ExponentiationOperator | MultiplicativeOperator; + export type AdditiveOperator = SyntaxKind.PlusToken | SyntaxKind.MinusToken; + export type AdditiveOperatorOrHigher = MultiplicativeOperatorOrHigher | AdditiveOperator; + export type ShiftOperator = SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + export type ShiftOperatorOrHigher = AdditiveOperatorOrHigher | ShiftOperator; + export type RelationalOperator = SyntaxKind.LessThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.InstanceOfKeyword | SyntaxKind.InKeyword; + export type RelationalOperatorOrHigher = ShiftOperatorOrHigher | RelationalOperator; + export type EqualityOperator = SyntaxKind.EqualsEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.ExclamationEqualsToken; + export type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; + export type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; + export type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; + export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken; + export type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; + export type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; + export type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; + export type AssignmentOperatorOrHigher = LogicalOperatorOrHigher | AssignmentOperator; + export type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; + export type BinaryOperatorToken = Token; + export interface BinaryExpression extends Expression, Declaration { kind: SyntaxKind.BinaryExpression; left: Expression; operatorToken: BinaryOperatorToken; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 988493a222a0f..e1e4889748f44 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -375,28 +375,30 @@ declare namespace ts { JSDocOptionalType = 295, JSDocFunctionType = 296, JSDocVariadicType = 297, - JSDocComment = 298, - JSDocTypeLiteral = 299, - JSDocSignature = 300, - JSDocTag = 301, - JSDocAugmentsTag = 302, - JSDocClassTag = 303, - JSDocCallbackTag = 304, - JSDocEnumTag = 305, - JSDocParameterTag = 306, - JSDocReturnTag = 307, - JSDocThisTag = 308, - JSDocTypeTag = 309, - JSDocTemplateTag = 310, - JSDocTypedefTag = 311, - JSDocPropertyTag = 312, - SyntaxList = 313, - NotEmittedStatement = 314, - PartiallyEmittedExpression = 315, - CommaListExpression = 316, - MergeDeclarationMarker = 317, - EndOfDeclarationMarker = 318, - Count = 319, + JSDocNamepathType = 298, + JSDocComment = 299, + JSDocTypeLiteral = 300, + JSDocSignature = 301, + JSDocTag = 302, + JSDocAugmentsTag = 303, + JSDocAuthorTag = 304, + JSDocClassTag = 305, + JSDocCallbackTag = 306, + JSDocEnumTag = 307, + JSDocParameterTag = 308, + JSDocReturnTag = 309, + JSDocThisTag = 310, + JSDocTypeTag = 311, + JSDocTemplateTag = 312, + JSDocTypedefTag = 313, + JSDocPropertyTag = 314, + SyntaxList = 315, + NotEmittedStatement = 316, + PartiallyEmittedExpression = 317, + CommaListExpression = 318, + MergeDeclarationMarker = 319, + EndOfDeclarationMarker = 320, + Count = 321, FirstAssignment = 61, LastAssignment = 73, FirstCompoundAssignment = 62, @@ -423,9 +425,9 @@ declare namespace ts { LastBinaryOperator = 73, FirstNode = 150, FirstJSDocNode = 290, - LastJSDocNode = 312, - FirstJSDocTagNode = 301, - LastJSDocTagNode = 312, + LastJSDocNode = 314, + FirstJSDocTagNode = 302, + LastJSDocTagNode = 314, } export enum NodeFlags { None = 0, @@ -925,27 +927,27 @@ declare namespace ts { isSpread: boolean; type: Type; } - type ExponentiationOperator = SyntaxKind.AsteriskAsteriskToken; - type MultiplicativeOperator = SyntaxKind.AsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken; - type MultiplicativeOperatorOrHigher = ExponentiationOperator | MultiplicativeOperator; - type AdditiveOperator = SyntaxKind.PlusToken | SyntaxKind.MinusToken; - type AdditiveOperatorOrHigher = MultiplicativeOperatorOrHigher | AdditiveOperator; - type ShiftOperator = SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken; - type ShiftOperatorOrHigher = AdditiveOperatorOrHigher | ShiftOperator; - type RelationalOperator = SyntaxKind.LessThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.InstanceOfKeyword | SyntaxKind.InKeyword; - type RelationalOperatorOrHigher = ShiftOperatorOrHigher | RelationalOperator; - type EqualityOperator = SyntaxKind.EqualsEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.ExclamationEqualsToken; - type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; - type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; - type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; - type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken; - type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; - type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; - type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; - type AssignmentOperatorOrHigher = LogicalOperatorOrHigher | AssignmentOperator; - type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; - type BinaryOperatorToken = Token; - interface BinaryExpression extends Expression, Declaration { + export type ExponentiationOperator = SyntaxKind.AsteriskAsteriskToken; + export type MultiplicativeOperator = SyntaxKind.AsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken; + export type MultiplicativeOperatorOrHigher = ExponentiationOperator | MultiplicativeOperator; + export type AdditiveOperator = SyntaxKind.PlusToken | SyntaxKind.MinusToken; + export type AdditiveOperatorOrHigher = MultiplicativeOperatorOrHigher | AdditiveOperator; + export type ShiftOperator = SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + export type ShiftOperatorOrHigher = AdditiveOperatorOrHigher | ShiftOperator; + export type RelationalOperator = SyntaxKind.LessThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.InstanceOfKeyword | SyntaxKind.InKeyword; + export type RelationalOperatorOrHigher = ShiftOperatorOrHigher | RelationalOperator; + export type EqualityOperator = SyntaxKind.EqualsEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.ExclamationEqualsToken; + export type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; + export type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; + export type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; + export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken; + export type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; + export type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; + export type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; + export type AssignmentOperatorOrHigher = LogicalOperatorOrHigher | AssignmentOperator; + export type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; + export type BinaryOperatorToken = Token; + export interface BinaryExpression extends Expression, Declaration { kind: SyntaxKind.BinaryExpression; left: Expression; operatorToken: BinaryOperatorToken; From b412e50c3b0e489eb70518199045fcf9e642daf1 Mon Sep 17 00:00:00 2001 From: kingwl Date: Tue, 20 Aug 2019 15:29:01 +0800 Subject: [PATCH 18/26] accept baseline --- .../typeFromPropertyAssignment10_1.symbols | 70 ++++++------ .../typeFromPropertyAssignment8_1.symbols | 2 + .../typeFromPropertyAssignment8_1.types | 8 +- .../typeFromPropertyAssignment9_1.symbols | 102 ++++++++++-------- .../typeFromPropertyAssignment9_1.types | 22 ++-- 5 files changed, 107 insertions(+), 97 deletions(-) diff --git a/tests/baselines/reference/typeFromPropertyAssignment10_1.symbols b/tests/baselines/reference/typeFromPropertyAssignment10_1.symbols index 85b4b448fb4eb..9f0d484d8f40a 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment10_1.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment10_1.symbols @@ -1,22 +1,22 @@ === tests/cases/conformance/salsa/module.js === var Outer = Outer ?? {}; ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) Outer.app = Outer.app ?? {}; ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) === tests/cases/conformance/salsa/someview.js === Outer.app.SomeView = (function () { >Outer.app.SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) var SomeView = function() { @@ -31,9 +31,9 @@ Outer.app.SomeView = (function () { })(); Outer.app.Inner = class { >Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) constructor() { @@ -47,9 +47,9 @@ Outer.app.Inner = class { var example = new Outer.app.Inner(); >example : Symbol(example, Decl(someview.js, 12, 3)) >Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) example.y; @@ -60,9 +60,9 @@ example.y; /** @param {number} k */ Outer.app.statische = function (k) { >Outer.app.statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) >k : Symbol(k, Decl(someview.js, 15, 32)) @@ -73,9 +73,9 @@ Outer.app.statische = function (k) { === tests/cases/conformance/salsa/application.js === Outer.app.Application = (function () { >Outer.app.Application : Symbol(Outer.app.Application, Decl(application.js, 0, 0)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >Application : Symbol(Outer.app.Application, Decl(application.js, 0, 0)) /** @@ -91,9 +91,9 @@ Outer.app.Application = (function () { me.view = new Outer.app.SomeView(); >me : Symbol(me, Decl(application.js, 7, 11)) >Outer.app.SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) }; @@ -105,17 +105,17 @@ Outer.app.Application = (function () { var app = new Outer.app.Application(); >app : Symbol(app, Decl(main.js, 0, 3)) >Outer.app.Application : Symbol(Outer.app.Application, Decl(application.js, 0, 0)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >Application : Symbol(Outer.app.Application, Decl(application.js, 0, 0)) var inner = new Outer.app.Inner(); >inner : Symbol(inner, Decl(main.js, 1, 3)) >Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) inner.y; @@ -134,8 +134,8 @@ x.y; Outer.app.statische(101); // Infinity, duh >Outer.app.statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) ->Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) ->app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) +>Outer.app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 24), Decl(someview.js, 0, 0), Decl(someview.js, 5, 5), Decl(someview.js, 13, 10) ... and 1 more) +>app : Symbol(Outer.app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(someview.js, 6, 6), Decl(someview.js, 15, 6), Decl(application.js, 0, 6)) >statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) diff --git a/tests/baselines/reference/typeFromPropertyAssignment8_1.symbols b/tests/baselines/reference/typeFromPropertyAssignment8_1.symbols index eebaa8a04afec..21054155016bc 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment8_1.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment8_1.symbols @@ -37,7 +37,9 @@ my.app.Application() === tests/cases/conformance/salsa/b.js === var min = window.min ?? {}; >min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 0, 27), Decl(b.js, 1, 24)) +>window.min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 0, 27), Decl(b.js, 1, 24)) >window : Symbol(window, Decl(lib.dom.d.ts, --, --)) +>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 0, 27), Decl(b.js, 1, 24)) min.app = min.app ?? {}; >min.app : Symbol(min.app, Decl(b.js, 0, 27), Decl(b.js, 3, 4)) diff --git a/tests/baselines/reference/typeFromPropertyAssignment8_1.types b/tests/baselines/reference/typeFromPropertyAssignment8_1.types index 4474ba705bf73..fd30f6168b657 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment8_1.types +++ b/tests/baselines/reference/typeFromPropertyAssignment8_1.types @@ -48,10 +48,10 @@ my.app.Application() === tests/cases/conformance/salsa/b.js === var min = window.min ?? {}; >min : typeof min ->window.min ?? {} : any ->window.min : error ->window : Window ->min : any +>window.min ?? {} : typeof min | {} +>window.min : typeof min +>window : Window & typeof globalThis +>min : typeof min >{} : {} min.app = min.app ?? {}; diff --git a/tests/baselines/reference/typeFromPropertyAssignment9_1.symbols b/tests/baselines/reference/typeFromPropertyAssignment9_1.symbols index 46474f4d50f03..bd81d2cf9ab62 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment9_1.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment9_1.symbols @@ -1,12 +1,12 @@ === tests/cases/conformance/salsa/a.js === var my = my ?? {}; ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) /** @param {number} n */ my.method = function(n) { >my.method : Symbol(my.method, Decl(a.js, 0, 18)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) >method : Symbol(my.method, Decl(a.js, 0, 18)) >n : Symbol(n, Decl(a.js, 2, 21)) @@ -15,32 +15,32 @@ my.method = function(n) { } my.number = 1; >my.number : Symbol(my.number, Decl(a.js, 4, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) >number : Symbol(my.number, Decl(a.js, 4, 1)) my.object = {}; >my.object : Symbol(my.object, Decl(a.js, 5, 14)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) >object : Symbol(my.object, Decl(a.js, 5, 14)) my.predicate = my.predicate ?? {}; ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) my.predicate.query = function () { ->my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13), Decl(a.js, 16, 13)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13), Decl(a.js, 16, 13)) var me = this; >me : Symbol(me, Decl(a.js, 9, 7)) ->this : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>this : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) me.property = false; >me : Symbol(me, Decl(a.js, 9, 7)) @@ -48,30 +48,30 @@ my.predicate.query = function () { }; var q = new my.predicate.query(); >q : Symbol(q, Decl(a.js, 12, 3)) ->my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13), Decl(a.js, 16, 13)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13), Decl(a.js, 16, 13)) my.predicate.query.another = function () { >my.predicate.query.another : Symbol(my.predicate.query.another, Decl(a.js, 12, 33)) ->my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13), Decl(a.js, 16, 13)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13), Decl(a.js, 16, 13)) >another : Symbol(my.predicate.query.another, Decl(a.js, 12, 33)) return 1; } my.predicate.query.result = 'none' >my.predicate.query.result : Symbol(my.predicate.query.result, Decl(a.js, 15, 1)) ->my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate.query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13), Decl(a.js, 16, 13)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>query : Symbol(my.predicate.query, Decl(a.js, 7, 34), Decl(a.js, 13, 13), Decl(a.js, 16, 13)) >result : Symbol(my.predicate.query.result, Decl(a.js, 15, 1)) /** @param {number} first @@ -79,14 +79,14 @@ my.predicate.query.result = 'none' */ my.predicate.sort = my.predicate.sort ?? function (first, second) { >my.predicate.sort : Symbol(my.predicate.sort, Decl(a.js, 16, 34)) ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) >sort : Symbol(my.predicate.sort, Decl(a.js, 16, 34)) >my.predicate.sort : Symbol(my.predicate.sort, Decl(a.js, 16, 34)) ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) >sort : Symbol(my.predicate.sort, Decl(a.js, 16, 34)) >first : Symbol(first, Decl(a.js, 20, 51)) >second : Symbol(second, Decl(a.js, 20, 57)) @@ -99,9 +99,9 @@ my.predicate.sort = my.predicate.sort ?? function (first, second) { } my.predicate.type = class { >my.predicate.type : Symbol(my.predicate.type, Decl(a.js, 22, 1)) ->my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 12, 33)) ->predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3)) +>my.predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 4, 1), Decl(a.js, 5, 14), Decl(a.js, 6, 15) ... and 5 more) +>predicate : Symbol(my.predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 16, 3), Decl(a.js, 20, 3) ... and 1 more) >type : Symbol(my.predicate.type, Decl(a.js, 22, 1)) m() { return 101; } @@ -111,29 +111,37 @@ my.predicate.type = class { // global-ish prefixes var min = window.min ?? {}; ->min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) +>window.min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) >window : Symbol(window, Decl(lib.dom.d.ts, --, --)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) min.nest = this.min.nest ?? function () { }; >min.nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) ->min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) >nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) >this.min.nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) ->this.min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>this.min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) >this : Symbol(globalThis) ->min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) >nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) min.nest.other = self.min.nest.other ?? class { }; >min.nest.other : Symbol(min.nest.other, Decl(a.js, 30, 44)) >min.nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) ->min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) >nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) >other : Symbol(min.nest.other, Decl(a.js, 30, 44)) +>self.min.nest.other : Symbol(min.nest.other, Decl(a.js, 30, 44)) +>self.min.nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) +>self.min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) >self : Symbol(self, Decl(lib.dom.d.ts, --, --)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) +>nest : Symbol(min.nest, Decl(a.js, 29, 27), Decl(a.js, 31, 4)) +>other : Symbol(min.nest.other, Decl(a.js, 30, 44)) min.property = global.min.property ?? {}; >min.property : Symbol(min.property, Decl(a.js, 31, 50)) ->min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44)) +>min : Symbol(min, Decl(a.js, 29, 3), Decl(a.js, 29, 27), Decl(a.js, 30, 44), Decl(a.js, 31, 50)) >property : Symbol(min.property, Decl(a.js, 31, 50)) diff --git a/tests/baselines/reference/typeFromPropertyAssignment9_1.types b/tests/baselines/reference/typeFromPropertyAssignment9_1.types index fdfa0a96083f4..059466c8cfc0c 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment9_1.types +++ b/tests/baselines/reference/typeFromPropertyAssignment9_1.types @@ -145,10 +145,10 @@ my.predicate.type = class { // global-ish prefixes var min = window.min ?? {}; >min : typeof min ->window.min ?? {} : any ->window.min : error ->window : Window ->min : any +>window.min ?? {} : typeof min | {} +>window.min : typeof min +>window : Window & typeof globalThis +>min : typeof min >{} : {} min.nest = this.min.nest ?? function () { }; @@ -172,13 +172,13 @@ min.nest.other = self.min.nest.other ?? class { }; >nest : { (): void; other: typeof other; } >other : typeof other >self.min.nest.other ?? class { } : typeof other ->self.min.nest.other : error ->self.min.nest : any ->self.min : any ->self : Window ->min : any ->nest : any ->other : any +>self.min.nest.other : typeof other +>self.min.nest : { (): void; other: typeof other; } +>self.min : typeof min +>self : Window & typeof globalThis +>min : typeof min +>nest : { (): void; other: typeof other; } +>other : typeof other >class { } : typeof other min.property = global.min.property ?? {}; From 57be95d33881b5f9df2418e6f787c164899b80d2 Mon Sep 17 00:00:00 2001 From: kingwl Date: Sat, 14 Sep 2019 03:05:56 +0800 Subject: [PATCH 19/26] fix review --- src/compiler/binder.ts | 3 +- src/compiler/checker.ts | 4 +-- src/compiler/diagnosticMessages.json | 2 +- src/compiler/parser.ts | 2 +- src/compiler/scanner.ts | 8 ++--- src/compiler/utilities.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- .../reference/nullishCoalescingOperator3.js | 2 +- .../nullishCoalescingOperator5.errors.txt | 16 +++++----- .../reference/nullishCoalescingOperator5.js | 2 +- .../reference/nullishCoalescingOperator8.js | 2 +- .../reference/nullishCoalescingOperator9.js | 11 +++++++ .../nullishCoalescingOperator9.symbols | 21 ++++++++++++ .../nullishCoalescingOperator9.types | 32 +++++++++++++++++++ .../nullishCoalescingOperator9.ts | 6 ++++ 16 files changed, 93 insertions(+), 24 deletions(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperator9.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator9.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator9.types create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator9.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index da05c8c1406b5..031356042af49 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1375,7 +1375,6 @@ namespace ts { } } - // TODO(rbuckton): Determine how to hook ?? into flow typing function bindBinaryExpressionFlow(node: BinaryExpression) { const operator = node.operatorToken.kind; if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { @@ -2730,7 +2729,7 @@ namespace ts { init = init && getRightMostAssignedExpression(init); if (init) { const isPrototypeAssignment = isPrototypeAccess(isVariableDeclaration(node) ? node.name : isBinaryExpression(node) ? node.left : node); - return !!getExpandoInitializer(isBinaryExpression(init) && init.operatorToken.kind === SyntaxKind.BarBarToken ? init.right : init, isPrototypeAssignment); + return !!getExpandoInitializer(isBinaryExpression(init) && (init.operatorToken.kind === SyntaxKind.BarBarToken || init.operatorToken.kind === SyntaxKind.QuestionQuestionToken) ? init.right : init, isPrototypeAssignment); } return false; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5027ddd95ebd1..9b20b0843cf4c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24514,10 +24514,10 @@ namespace ts { const { left, operatorToken, right } = node; if (operatorToken.kind === SyntaxKind.QuestionQuestionToken) { if (isBinaryExpression(left) && (left.operatorToken.kind === SyntaxKind.BarBarToken || left.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { - error(left, Diagnostics.Operator_0_cannot_immediately_contain_or_be_contained_within_an_1_operation, tokenToString(left.operatorToken.kind), tokenToString(operatorToken.kind)); + grammarErrorOnNode(left, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(left.operatorToken.kind), tokenToString(operatorToken.kind)); } if (isBinaryExpression(right) && (right.operatorToken.kind === SyntaxKind.BarBarToken || right.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { - error(right, Diagnostics.Operator_0_cannot_immediately_contain_or_be_contained_within_an_1_operation, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind)); + grammarErrorOnNode(right, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind)); } } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8d5dbe0a213ac..d18f8094ee701 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3180,7 +3180,7 @@ "category": "Error", "code": 5075 }, - "Operator '{0}' cannot immediately contain, or be contained within an '{1}' operation.": { + "'{0}' and '{1}' operations cannot be mixed without parentheses.": { "category": "Error", "code": 5076 }, diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6a6c03f5fedc0..d1962c88ecdcf 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3006,7 +3006,7 @@ namespace ts { return parseJSDocAllType(/*postfixEquals*/ true); case SyntaxKind.QuestionQuestionToken: // If there is '??', consider that is prefix '?' in JSDoc type. - scanner.reScanQuestionQuestionToken(); + scanner.reScanQuestionToken(); // falls through case SyntaxKind.QuestionToken: return parseJSDocUnknownOrNullableType(); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 6c36a7edd3334..b79285f2853dd 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -33,7 +33,7 @@ namespace ts { scanJsxAttributeValue(): SyntaxKind; reScanJsxToken(): JsxTokenSyntaxKind; reScanLessThanToken(): SyntaxKind; - reScanQuestionQuestionToken(): SyntaxKind; + reScanQuestionToken(): SyntaxKind; scanJsxToken(): JsxTokenSyntaxKind; scanJsDocToken(): JSDocSyntaxKind; scan(): SyntaxKind; @@ -902,7 +902,7 @@ namespace ts { scanJsxAttributeValue, reScanJsxToken, reScanLessThanToken, - reScanQuestionQuestionToken, + reScanQuestionToken, scanJsxToken, scanJsDocToken, scan, @@ -2023,8 +2023,8 @@ namespace ts { return token; } - function reScanQuestionQuestionToken(): SyntaxKind { - Debug.assert(token === SyntaxKind.QuestionQuestionToken, "'reScanQuestionQuestionToken' should only be called on a '??'"); + function reScanQuestionToken(): SyntaxKind { + Debug.assert(token === SyntaxKind.QuestionQuestionToken, "'reScanQuestionToken' should only be called on a '??'"); pos = tokenPos + 1; return token = SyntaxKind.QuestionToken; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 2c130f0e871ab..d3b749ba6dc8f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1982,7 +1982,7 @@ namespace ts { /** Given an expando initializer, return its declaration name, or the left-hand side of the assignment if it's part of an assignment declaration. */ export function getNameOfExpando(node: Declaration): DeclarationName | undefined { if (isBinaryExpression(node.parent)) { - const parent = (node.parent.operatorToken.kind === SyntaxKind.BarBarToken && isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; + const parent = ((node.parent.operatorToken.kind === SyntaxKind.BarBarToken || node.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken) && isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; if (parent.operatorToken.kind === SyntaxKind.EqualsToken && isIdentifier(parent.left)) { return parent.left; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index be62a41ae7053..99711c11557ba 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3203,7 +3203,7 @@ declare namespace ts { scanJsxAttributeValue(): SyntaxKind; reScanJsxToken(): JsxTokenSyntaxKind; reScanLessThanToken(): SyntaxKind; - reScanQuestionQuestionToken(): SyntaxKind; + reScanQuestionToken(): SyntaxKind; scanJsxToken(): JsxTokenSyntaxKind; scanJsDocToken(): JSDocSyntaxKind; scan(): SyntaxKind; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index bac6172d685d4..48d60ea504cf6 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3203,7 +3203,7 @@ declare namespace ts { scanJsxAttributeValue(): SyntaxKind; reScanJsxToken(): JsxTokenSyntaxKind; reScanLessThanToken(): SyntaxKind; - reScanQuestionQuestionToken(): SyntaxKind; + reScanQuestionToken(): SyntaxKind; scanJsxToken(): JsxTokenSyntaxKind; scanJsDocToken(): JSDocSyntaxKind; scan(): SyntaxKind; diff --git a/tests/baselines/reference/nullishCoalescingOperator3.js b/tests/baselines/reference/nullishCoalescingOperator3.js index df0a9ebe1bbd6..908fbabbfc742 100644 --- a/tests/baselines/reference/nullishCoalescingOperator3.js +++ b/tests/baselines/reference/nullishCoalescingOperator3.js @@ -11,6 +11,6 @@ const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' //// [nullishCoalescingOperator3.js] -var _a, _b, _c, _d, _e; "use strict"; +var _a, _b, _c, _d, _e; var aa1 = (_e = (_d = (_c = (_b = (_a = (a1 != null ? a1 : a2), (_a != null ? _a : a3)), (_b != null ? _b : a4)), (_c != null ? _c : a5)), (_d != null ? _d : a6)), (_e != null ? _e : 'whatever')); diff --git a/tests/baselines/reference/nullishCoalescingOperator5.errors.txt b/tests/baselines/reference/nullishCoalescingOperator5.errors.txt index 37194b0010dfc..f5a0c68bf251b 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.errors.txt +++ b/tests/baselines/reference/nullishCoalescingOperator5.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(6,6): error TS5076: Operator '||' cannot immediately contain, or be contained within an '??' operation. -tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(9,1): error TS5076: Operator '||' cannot immediately contain, or be contained within an '??' operation. -tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(12,6): error TS5076: Operator '&&' cannot immediately contain, or be contained within an '??' operation. -tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(15,1): error TS5076: Operator '&&' cannot immediately contain, or be contained within an '??' operation. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(6,6): error TS5076: '||' and '??' operations cannot be mixed without parentheses. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(9,1): error TS5076: '||' and '??' operations cannot be mixed without parentheses. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(12,6): error TS5076: '&&' and '??' operations cannot be mixed without parentheses. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts(15,1): error TS5076: '&&' and '??' operations cannot be mixed without parentheses. ==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator5.ts (4 errors) ==== @@ -12,22 +12,22 @@ tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingO // should be a syntax error a ?? b || c; ~~~~~~ -!!! error TS5076: Operator '||' cannot immediately contain, or be contained within an '??' operation. +!!! error TS5076: '||' and '??' operations cannot be mixed without parentheses. // should be a syntax error a || b ?? c; ~~~~~~ -!!! error TS5076: Operator '||' cannot immediately contain, or be contained within an '??' operation. +!!! error TS5076: '||' and '??' operations cannot be mixed without parentheses. // should be a syntax error a ?? b && c; ~~~~~~ -!!! error TS5076: Operator '&&' cannot immediately contain, or be contained within an '??' operation. +!!! error TS5076: '&&' and '??' operations cannot be mixed without parentheses. // should be a syntax error a && b ?? c; ~~~~~~ -!!! error TS5076: Operator '&&' cannot immediately contain, or be contained within an '??' operation. +!!! error TS5076: '&&' and '??' operations cannot be mixed without parentheses. // Valid according to spec a ?? (b || c); diff --git a/tests/baselines/reference/nullishCoalescingOperator5.js b/tests/baselines/reference/nullishCoalescingOperator5.js index 4d0cc98f56c5a..0a3a70106e063 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.js +++ b/tests/baselines/reference/nullishCoalescingOperator5.js @@ -41,8 +41,8 @@ a && (b ?? c); //// [nullishCoalescingOperator5.js] -var _a, _b, _c, _d; "use strict"; +var _a, _b, _c, _d; // should be a syntax error (a != null ? a : b || c); // should be a syntax error diff --git a/tests/baselines/reference/nullishCoalescingOperator8.js b/tests/baselines/reference/nullishCoalescingOperator8.js index 313e2a2a74f7c..7e451913e214b 100644 --- a/tests/baselines/reference/nullishCoalescingOperator8.js +++ b/tests/baselines/reference/nullishCoalescingOperator8.js @@ -8,8 +8,8 @@ const n3 = a.m() ?? b.p ?? b.m() ?? "default";; //// [nullishCoalescingOperator8.js] -var _a, _b, _c, _d, _e; "use strict"; +var _a, _b, _c, _d, _e; var n1 = (_a = a.p, (_a != null ? _a : "default")); var n2 = (_b = a.m(), (_b != null ? _b : "default")); var n3 = (_e = (_d = (_c = a.m(), (_c != null ? _c : b.p)), (_d != null ? _d : b.m())), (_e != null ? _e : "default")); diff --git a/tests/baselines/reference/nullishCoalescingOperator9.js b/tests/baselines/reference/nullishCoalescingOperator9.js new file mode 100644 index 0000000000000..de6134b5b052e --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator9.js @@ -0,0 +1,11 @@ +//// [nullishCoalescingOperator9.ts] +declare let f: null | ((x: string) => void); + +let g = f || (abc => { void abc.toLowerCase() }) +let gg = f ?? (abc => { void abc.toLowerCase() }) + + +//// [nullishCoalescingOperator9.js] +"use strict"; +var g = f || (function (abc) { void abc.toLowerCase(); }); +var gg = (f != null ? f : (function (abc) { void abc.toLowerCase(); })); diff --git a/tests/baselines/reference/nullishCoalescingOperator9.symbols b/tests/baselines/reference/nullishCoalescingOperator9.symbols new file mode 100644 index 0000000000000..e1006af93447b --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator9.symbols @@ -0,0 +1,21 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator9.ts === +declare let f: null | ((x: string) => void); +>f : Symbol(f, Decl(nullishCoalescingOperator9.ts, 0, 11)) +>x : Symbol(x, Decl(nullishCoalescingOperator9.ts, 0, 24)) + +let g = f || (abc => { void abc.toLowerCase() }) +>g : Symbol(g, Decl(nullishCoalescingOperator9.ts, 2, 3)) +>f : Symbol(f, Decl(nullishCoalescingOperator9.ts, 0, 11)) +>abc : Symbol(abc, Decl(nullishCoalescingOperator9.ts, 2, 14)) +>abc.toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --)) +>abc : Symbol(abc, Decl(nullishCoalescingOperator9.ts, 2, 14)) +>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --)) + +let gg = f ?? (abc => { void abc.toLowerCase() }) +>gg : Symbol(gg, Decl(nullishCoalescingOperator9.ts, 3, 3)) +>f : Symbol(f, Decl(nullishCoalescingOperator9.ts, 0, 11)) +>abc : Symbol(abc, Decl(nullishCoalescingOperator9.ts, 3, 15)) +>abc.toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --)) +>abc : Symbol(abc, Decl(nullishCoalescingOperator9.ts, 3, 15)) +>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator9.types b/tests/baselines/reference/nullishCoalescingOperator9.types new file mode 100644 index 0000000000000..e03ad4221ea60 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator9.types @@ -0,0 +1,32 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator9.ts === +declare let f: null | ((x: string) => void); +>f : ((x: string) => void) | null +>null : null +>x : string + +let g = f || (abc => { void abc.toLowerCase() }) +>g : (x: string) => void +>f || (abc => { void abc.toLowerCase() }) : (x: string) => void +>f : ((x: string) => void) | null +>(abc => { void abc.toLowerCase() }) : (abc: string) => void +>abc => { void abc.toLowerCase() } : (abc: string) => void +>abc : string +>void abc.toLowerCase() : undefined +>abc.toLowerCase() : string +>abc.toLowerCase : () => string +>abc : string +>toLowerCase : () => string + +let gg = f ?? (abc => { void abc.toLowerCase() }) +>gg : (x: string) => void +>f ?? (abc => { void abc.toLowerCase() }) : (x: string) => void +>f : ((x: string) => void) | null +>(abc => { void abc.toLowerCase() }) : (abc: string) => void +>abc => { void abc.toLowerCase() } : (abc: string) => void +>abc : string +>void abc.toLowerCase() : undefined +>abc.toLowerCase() : string +>abc.toLowerCase : () => string +>abc : string +>toLowerCase : () => string + diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator9.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator9.ts new file mode 100644 index 0000000000000..bd47a0ff7cb63 --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator9.ts @@ -0,0 +1,6 @@ +// @strict: true + +declare let f: null | ((x: string) => void); + +let g = f || (abc => { void abc.toLowerCase() }) +let gg = f ?? (abc => { void abc.toLowerCase() }) From de8152038c2046d628899f2ea34a94bd4969a762 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 27 Sep 2019 10:59:30 +0800 Subject: [PATCH 20/26] update emitter and more testcase --- src/compiler/transformers/esnext.ts | 14 ++++++-- .../reference/nullishCoalescingOperator1.js | 32 +++++++++---------- .../reference/nullishCoalescingOperator10.js | 11 +++++++ .../nullishCoalescingOperator10.symbols | 9 ++++++ .../nullishCoalescingOperator10.types | 12 +++++++ .../reference/nullishCoalescingOperator2.js | 18 +++++------ .../reference/nullishCoalescingOperator3.js | 2 +- .../reference/nullishCoalescingOperator4.js | 2 +- .../reference/nullishCoalescingOperator5.js | 24 +++++++------- .../reference/nullishCoalescingOperator6.js | 2 +- .../reference/nullishCoalescingOperator7.js | 6 ++-- .../reference/nullishCoalescingOperator8.js | 6 ++-- .../reference/nullishCoalescingOperator9.js | 2 +- .../nullishCoalescingOperator_not_strict.js | 18 +++++------ .../nullishCoalescingOperator10.ts | 6 ++++ 15 files changed, 105 insertions(+), 59 deletions(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperator10.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator10.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator10.types create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator10.ts diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index b0127d5f60319..dfce7a4fa8941 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -32,9 +32,17 @@ namespace ts { function createNotNullCondition(node: Expression) { return createBinary( - node, - SyntaxKind.ExclamationEqualsToken, - createNull() + createBinary( + node, + createToken(SyntaxKind.ExclamationEqualsEqualsToken), + createNull() + ), + createToken(SyntaxKind.AmpersandAmpersandToken), + createBinary( + node, + createToken(SyntaxKind.ExclamationEqualsEqualsToken), + createVoidZero() + ) ); } diff --git a/tests/baselines/reference/nullishCoalescingOperator1.js b/tests/baselines/reference/nullishCoalescingOperator1.js index f4b2e4e8660a7..87a149c1855aa 100644 --- a/tests/baselines/reference/nullishCoalescingOperator1.js +++ b/tests/baselines/reference/nullishCoalescingOperator1.js @@ -42,19 +42,19 @@ const dd4 = d4 ?? {b: 1}; //// [nullishCoalescingOperator1.js] "use strict"; -var aa1 = (a1 != null ? a1 : 'whatever'); -var aa2 = (a2 != null ? a2 : 'whatever'); -var aa3 = (a3 != null ? a3 : 'whatever'); -var aa4 = (a4 != null ? a4 : 'whatever'); -var bb1 = (b1 != null ? b1 : 1); -var bb2 = (b2 != null ? b2 : 1); -var bb3 = (b3 != null ? b3 : 1); -var bb4 = (b4 != null ? b4 : 1); -var cc1 = (c1 != null ? c1 : true); -var cc2 = (c2 != null ? c2 : true); -var cc3 = (c3 != null ? c3 : true); -var cc4 = (c4 != null ? c4 : true); -var dd1 = (d1 != null ? d1 : { b: 1 }); -var dd2 = (d2 != null ? d2 : { b: 1 }); -var dd3 = (d3 != null ? d3 : { b: 1 }); -var dd4 = (d4 != null ? d4 : { b: 1 }); +var aa1 = (a1 !== null && a1 !== void 0 ? a1 : 'whatever'); +var aa2 = (a2 !== null && a2 !== void 0 ? a2 : 'whatever'); +var aa3 = (a3 !== null && a3 !== void 0 ? a3 : 'whatever'); +var aa4 = (a4 !== null && a4 !== void 0 ? a4 : 'whatever'); +var bb1 = (b1 !== null && b1 !== void 0 ? b1 : 1); +var bb2 = (b2 !== null && b2 !== void 0 ? b2 : 1); +var bb3 = (b3 !== null && b3 !== void 0 ? b3 : 1); +var bb4 = (b4 !== null && b4 !== void 0 ? b4 : 1); +var cc1 = (c1 !== null && c1 !== void 0 ? c1 : true); +var cc2 = (c2 !== null && c2 !== void 0 ? c2 : true); +var cc3 = (c3 !== null && c3 !== void 0 ? c3 : true); +var cc4 = (c4 !== null && c4 !== void 0 ? c4 : true); +var dd1 = (d1 !== null && d1 !== void 0 ? d1 : { b: 1 }); +var dd2 = (d2 !== null && d2 !== void 0 ? d2 : { b: 1 }); +var dd3 = (d3 !== null && d3 !== void 0 ? d3 : { b: 1 }); +var dd4 = (d4 !== null && d4 !== void 0 ? d4 : { b: 1 }); diff --git a/tests/baselines/reference/nullishCoalescingOperator10.js b/tests/baselines/reference/nullishCoalescingOperator10.js new file mode 100644 index 0000000000000..60556609fb576 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator10.js @@ -0,0 +1,11 @@ +//// [nullishCoalescingOperator10.ts] +declare function f(): string | undefined; + +let gg = f() ?? 'foo' + + + +//// [nullishCoalescingOperator10.js] +"use strict"; +var _a; +var gg = (_a = f(), (_a !== null && _a !== void 0 ? _a : 'foo')); diff --git a/tests/baselines/reference/nullishCoalescingOperator10.symbols b/tests/baselines/reference/nullishCoalescingOperator10.symbols new file mode 100644 index 0000000000000..7ee6248cf3093 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator10.symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator10.ts === +declare function f(): string | undefined; +>f : Symbol(f, Decl(nullishCoalescingOperator10.ts, 0, 0)) + +let gg = f() ?? 'foo' +>gg : Symbol(gg, Decl(nullishCoalescingOperator10.ts, 2, 3)) +>f : Symbol(f, Decl(nullishCoalescingOperator10.ts, 0, 0)) + + diff --git a/tests/baselines/reference/nullishCoalescingOperator10.types b/tests/baselines/reference/nullishCoalescingOperator10.types new file mode 100644 index 0000000000000..4885f3717318c --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator10.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator10.ts === +declare function f(): string | undefined; +>f : () => string | undefined + +let gg = f() ?? 'foo' +>gg : string +>f() ?? 'foo' : string +>f() : string | undefined +>f : () => string | undefined +>'foo' : "foo" + + diff --git a/tests/baselines/reference/nullishCoalescingOperator2.js b/tests/baselines/reference/nullishCoalescingOperator2.js index 82ae05bb56379..e36a526c04842 100644 --- a/tests/baselines/reference/nullishCoalescingOperator2.js +++ b/tests/baselines/reference/nullishCoalescingOperator2.js @@ -22,12 +22,12 @@ const aa9 = a9 ?? 'whatever' //// [nullishCoalescingOperator2.js] "use strict"; -var aa1 = (a1 != null ? a1 : 'whatever'); -var aa2 = (a2 != null ? a2 : 'whatever'); -var aa3 = (a3 != null ? a3 : 'whatever'); -var aa4 = (a4 != null ? a4 : 'whatever'); -var aa5 = (a5 != null ? a5 : 'whatever'); -var aa6 = (a6 != null ? a6 : 'whatever'); -var aa7 = (a7 != null ? a7 : 'whatever'); -var aa8 = (a8 != null ? a8 : 'whatever'); -var aa9 = (a9 != null ? a9 : 'whatever'); +var aa1 = (a1 !== null && a1 !== void 0 ? a1 : 'whatever'); +var aa2 = (a2 !== null && a2 !== void 0 ? a2 : 'whatever'); +var aa3 = (a3 !== null && a3 !== void 0 ? a3 : 'whatever'); +var aa4 = (a4 !== null && a4 !== void 0 ? a4 : 'whatever'); +var aa5 = (a5 !== null && a5 !== void 0 ? a5 : 'whatever'); +var aa6 = (a6 !== null && a6 !== void 0 ? a6 : 'whatever'); +var aa7 = (a7 !== null && a7 !== void 0 ? a7 : 'whatever'); +var aa8 = (a8 !== null && a8 !== void 0 ? a8 : 'whatever'); +var aa9 = (a9 !== null && a9 !== void 0 ? a9 : 'whatever'); diff --git a/tests/baselines/reference/nullishCoalescingOperator3.js b/tests/baselines/reference/nullishCoalescingOperator3.js index 908fbabbfc742..c0f56552433a0 100644 --- a/tests/baselines/reference/nullishCoalescingOperator3.js +++ b/tests/baselines/reference/nullishCoalescingOperator3.js @@ -13,4 +13,4 @@ const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' //// [nullishCoalescingOperator3.js] "use strict"; var _a, _b, _c, _d, _e; -var aa1 = (_e = (_d = (_c = (_b = (_a = (a1 != null ? a1 : a2), (_a != null ? _a : a3)), (_b != null ? _b : a4)), (_c != null ? _c : a5)), (_d != null ? _d : a6)), (_e != null ? _e : 'whatever')); +var aa1 = (_e = (_d = (_c = (_b = (_a = (a1 !== null && a1 !== void 0 ? a1 : a2), (_a !== null && _a !== void 0 ? _a : a3)), (_b !== null && _b !== void 0 ? _b : a4)), (_c !== null && _c !== void 0 ? _c : a5)), (_d !== null && _d !== void 0 ? _d : a6)), (_e !== null && _e !== void 0 ? _e : 'whatever')); diff --git a/tests/baselines/reference/nullishCoalescingOperator4.js b/tests/baselines/reference/nullishCoalescingOperator4.js index 459a5483bd5f6..0018a3880cf03 100644 --- a/tests/baselines/reference/nullishCoalescingOperator4.js +++ b/tests/baselines/reference/nullishCoalescingOperator4.js @@ -6,5 +6,5 @@ const aa2 = a1 || a1.toLocaleUpperCase() //// [nullishCoalescingOperator4.js] "use strict"; -var aa1 = (a1 != null ? a1 : a1.toLowerCase()); +var aa1 = (a1 !== null && a1 !== void 0 ? a1 : a1.toLowerCase()); var aa2 = a1 || a1.toLocaleUpperCase(); diff --git a/tests/baselines/reference/nullishCoalescingOperator5.js b/tests/baselines/reference/nullishCoalescingOperator5.js index 0a3a70106e063..c74f3da0827b1 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.js +++ b/tests/baselines/reference/nullishCoalescingOperator5.js @@ -44,26 +44,26 @@ a && (b ?? c); "use strict"; var _a, _b, _c, _d; // should be a syntax error -(a != null ? a : b || c); +(a !== null && a !== void 0 ? a : b || c); // should be a syntax error -_a = a || b, (_a != null ? _a : c); +_a = a || b, (_a !== null && _a !== void 0 ? _a : c); // should be a syntax error -(a != null ? a : b && c); +(a !== null && a !== void 0 ? a : b && c); // should be a syntax error -_b = a && b, (_b != null ? _b : c); +_b = a && b, (_b !== null && _b !== void 0 ? _b : c); // Valid according to spec -(a != null ? a : (b || c)); +(a !== null && a !== void 0 ? a : (b || c)); // Valid according to spec -((a != null ? a : b)) || c; +((a !== null && a !== void 0 ? a : b)) || c; // Valid according to spec -_c = (a || b), (_c != null ? _c : c); +_c = (a || b), (_c !== null && _c !== void 0 ? _c : c); // Valid according to spec -a || ((b != null ? b : c)); +a || ((b !== null && b !== void 0 ? b : c)); // Valid according to spec -(a != null ? a : (b && c)); +(a !== null && a !== void 0 ? a : (b && c)); // Valid according to spec -((a != null ? a : b)) && c; +((a !== null && a !== void 0 ? a : b)) && c; // Valid according to spec -_d = (a && b), (_d != null ? _d : c); +_d = (a && b), (_d !== null && _d !== void 0 ? _d : c); // Valid according to spec -a && ((b != null ? b : c)); +a && ((b !== null && b !== void 0 ? b : c)); diff --git a/tests/baselines/reference/nullishCoalescingOperator6.js b/tests/baselines/reference/nullishCoalescingOperator6.js index 816b6e1af0dbe..698ccb311b62b 100644 --- a/tests/baselines/reference/nullishCoalescingOperator6.js +++ b/tests/baselines/reference/nullishCoalescingOperator6.js @@ -5,5 +5,5 @@ function foo(foo: string, bar = foo ?? "bar") { } //// [nullishCoalescingOperator6.js] "use strict"; function foo(foo, bar) { - if (bar === void 0) { bar = (foo != null ? foo : "bar"); } + if (bar === void 0) { bar = (foo !== null && foo !== void 0 ? foo : "bar"); } } diff --git a/tests/baselines/reference/nullishCoalescingOperator7.js b/tests/baselines/reference/nullishCoalescingOperator7.js index aa7e518b2eb8d..443ec066ea5a1 100644 --- a/tests/baselines/reference/nullishCoalescingOperator7.js +++ b/tests/baselines/reference/nullishCoalescingOperator7.js @@ -15,8 +15,8 @@ function f () { //// [nullishCoalescingOperator7.js] "use strict"; var foo1 = a ? 1 : 2; -var foo2 = (a != null ? a : 'foo') ? 1 : 2; -var foo3 = (a != null ? a : 'foo') ? ((b != null ? b : 'bar')) : ((c != null ? c : 'baz')); +var foo2 = (a !== null && a !== void 0 ? a : 'foo') ? 1 : 2; +var foo3 = (a !== null && a !== void 0 ? a : 'foo') ? ((b !== null && b !== void 0 ? b : 'bar')) : ((c !== null && c !== void 0 ? c : 'baz')); function f() { - var foo4 = (a != null ? a : 'foo') ? (b != null ? b : 'bar') : (c != null ? c : 'baz'); + var foo4 = (a !== null && a !== void 0 ? a : 'foo') ? (b !== null && b !== void 0 ? b : 'bar') : (c !== null && c !== void 0 ? c : 'baz'); } diff --git a/tests/baselines/reference/nullishCoalescingOperator8.js b/tests/baselines/reference/nullishCoalescingOperator8.js index 7e451913e214b..3b56a1de01006 100644 --- a/tests/baselines/reference/nullishCoalescingOperator8.js +++ b/tests/baselines/reference/nullishCoalescingOperator8.js @@ -10,7 +10,7 @@ const n3 = a.m() ?? b.p ?? b.m() ?? "default";; //// [nullishCoalescingOperator8.js] "use strict"; var _a, _b, _c, _d, _e; -var n1 = (_a = a.p, (_a != null ? _a : "default")); -var n2 = (_b = a.m(), (_b != null ? _b : "default")); -var n3 = (_e = (_d = (_c = a.m(), (_c != null ? _c : b.p)), (_d != null ? _d : b.m())), (_e != null ? _e : "default")); +var n1 = (_a = a.p, (_a !== null && _a !== void 0 ? _a : "default")); +var n2 = (_b = a.m(), (_b !== null && _b !== void 0 ? _b : "default")); +var n3 = (_e = (_d = (_c = a.m(), (_c !== null && _c !== void 0 ? _c : b.p)), (_d !== null && _d !== void 0 ? _d : b.m())), (_e !== null && _e !== void 0 ? _e : "default")); ; diff --git a/tests/baselines/reference/nullishCoalescingOperator9.js b/tests/baselines/reference/nullishCoalescingOperator9.js index de6134b5b052e..a547d28911a86 100644 --- a/tests/baselines/reference/nullishCoalescingOperator9.js +++ b/tests/baselines/reference/nullishCoalescingOperator9.js @@ -8,4 +8,4 @@ let gg = f ?? (abc => { void abc.toLowerCase() }) //// [nullishCoalescingOperator9.js] "use strict"; var g = f || (function (abc) { void abc.toLowerCase(); }); -var gg = (f != null ? f : (function (abc) { void abc.toLowerCase(); })); +var gg = (f !== null && f !== void 0 ? f : (function (abc) { void abc.toLowerCase(); })); diff --git a/tests/baselines/reference/nullishCoalescingOperator_not_strict.js b/tests/baselines/reference/nullishCoalescingOperator_not_strict.js index 413a6720d15fa..e8e6d41291ded 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_not_strict.js +++ b/tests/baselines/reference/nullishCoalescingOperator_not_strict.js @@ -21,12 +21,12 @@ const aa8 = a8 ?? 'whatever' const aa9 = a9 ?? 'whatever' //// [nullishCoalescingOperator_not_strict.js] -var aa1 = (a1 != null ? a1 : 'whatever'); -var aa2 = (a2 != null ? a2 : 'whatever'); -var aa3 = (a3 != null ? a3 : 'whatever'); -var aa4 = (a4 != null ? a4 : 'whatever'); -var aa5 = (a5 != null ? a5 : 'whatever'); -var aa6 = (a6 != null ? a6 : 'whatever'); -var aa7 = (a7 != null ? a7 : 'whatever'); -var aa8 = (a8 != null ? a8 : 'whatever'); -var aa9 = (a9 != null ? a9 : 'whatever'); +var aa1 = (a1 !== null && a1 !== void 0 ? a1 : 'whatever'); +var aa2 = (a2 !== null && a2 !== void 0 ? a2 : 'whatever'); +var aa3 = (a3 !== null && a3 !== void 0 ? a3 : 'whatever'); +var aa4 = (a4 !== null && a4 !== void 0 ? a4 : 'whatever'); +var aa5 = (a5 !== null && a5 !== void 0 ? a5 : 'whatever'); +var aa6 = (a6 !== null && a6 !== void 0 ? a6 : 'whatever'); +var aa7 = (a7 !== null && a7 !== void 0 ? a7 : 'whatever'); +var aa8 = (a8 !== null && a8 !== void 0 ? a8 : 'whatever'); +var aa9 = (a9 !== null && a9 !== void 0 ? a9 : 'whatever'); diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator10.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator10.ts new file mode 100644 index 0000000000000..bc86af57a8e8a --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator10.ts @@ -0,0 +1,6 @@ +// @strict: true + +declare function f(): string | undefined; + +let gg = f() ?? 'foo' + From 6418943f03f9aa2fec63c17cf4aa32e5280cbe05 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 27 Sep 2019 11:45:45 +0800 Subject: [PATCH 21/26] update control flow --- src/compiler/binder.ts | 14 ++++++++++++-- src/compiler/types.ts | 4 ++-- src/compiler/utilities.ts | 3 +-- src/services/codefixes/inferFromUsage.ts | 2 +- .../nullishCoalescingOperator11.errors.txt | 17 +++++++++++++++++ .../reference/nullishCoalescingOperator11.js | 11 +++++++++++ .../nullishCoalescingOperator11.symbols | 11 +++++++++++ .../reference/nullishCoalescingOperator11.types | 16 ++++++++++++++++ .../reference/nullishCoalescingOperator5.types | 2 +- .../nullishCoalescingOperator11.ts | 7 +++++++ 10 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/nullishCoalescingOperator11.errors.txt create mode 100644 tests/baselines/reference/nullishCoalescingOperator11.js create mode 100644 tests/baselines/reference/nullishCoalescingOperator11.symbols create mode 100644 tests/baselines/reference/nullishCoalescingOperator11.types create mode 100644 tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index e28ba0ca73de0..e93950c74a349 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1009,8 +1009,7 @@ namespace ts { else { return node.kind === SyntaxKind.BinaryExpression && ( (node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || - (node).operatorToken.kind === SyntaxKind.BarBarToken || - (node).operatorToken.kind === SyntaxKind.QuestionQuestionToken); + (node).operatorToken.kind === SyntaxKind.BarBarToken); } } } @@ -1436,6 +1435,14 @@ namespace ts { bindCondition(node.right, trueTarget, falseTarget); } + function bindNullishCollasingExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { + const notNullLabel = createBranchLabel(); + bindCondition(node.left, trueTarget, notNullLabel); + currentFlow = finishFlowLabel(notNullLabel); + bind(node.operatorToken); + bindCondition(node.right, trueTarget, falseTarget!); + } + function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) { if (node.operator === SyntaxKind.ExclamationToken) { const saveTrueTarget = currentTrueTarget; @@ -1468,6 +1475,9 @@ namespace ts { bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); currentFlow = finishFlowLabel(postExpressionLabel); } + else if (operator === SyntaxKind.QuestionQuestionToken) { + bindNullishCollasingExpression(node, currentTrueTarget!, currentFalseTarget!); + } else { bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 38b7fa0371936..921a0b7fc9fb3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1514,7 +1514,6 @@ namespace ts { export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken - | SyntaxKind.QuestionQuestionToken ; // see: https://tc39.github.io/ecma262/#prod-LogicalANDExpression @@ -1548,7 +1547,8 @@ namespace ts { // see: https://tc39.github.io/ecma262/#prod-AssignmentExpression export type AssignmentOperatorOrHigher - = LogicalOperatorOrHigher + = SyntaxKind.QuestionQuestionToken + | LogicalOperatorOrHigher | AssignmentOperator ; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index cd1db16df58f1..6f617b306bbf2 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4028,8 +4028,7 @@ namespace ts { export function isLogicalOperator(token: SyntaxKind): boolean { return token === SyntaxKind.BarBarToken || token === SyntaxKind.AmpersandAmpersandToken - || token === SyntaxKind.ExclamationToken - || token === SyntaxKind.QuestionQuestionToken; + || token === SyntaxKind.ExclamationToken; } export function isAssignmentOperator(token: SyntaxKind): boolean { diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 368bbdc52031a..11c3fbace614b 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -719,7 +719,7 @@ namespace ts.codefix { } break; - // LogicalOperator + // LogicalOperator Or NullishCoalescing case SyntaxKind.BarBarToken: case SyntaxKind.QuestionQuestionToken: if (node === parent.left && diff --git a/tests/baselines/reference/nullishCoalescingOperator11.errors.txt b/tests/baselines/reference/nullishCoalescingOperator11.errors.txt new file mode 100644 index 0000000000000..528d8ae026ad3 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator11.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts(3,18): error TS2533: Object is possibly 'null' or 'undefined'. +tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts(3,22): error TS2339: Property 'toFixed' does not exist on type '"" | 0'. + Property 'toFixed' does not exist on type '""'. + + +==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts (2 errors) ==== + declare const f11: 1 | 0 | '' | null | undefined; + + let g11 = f11 ?? f11.toFixed() + ~~~ +!!! error TS2533: Object is possibly 'null' or 'undefined'. + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type '"" | 0'. +!!! error TS2339: Property 'toFixed' does not exist on type '""'. + + + \ No newline at end of file diff --git a/tests/baselines/reference/nullishCoalescingOperator11.js b/tests/baselines/reference/nullishCoalescingOperator11.js new file mode 100644 index 0000000000000..c716d1ce88b23 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator11.js @@ -0,0 +1,11 @@ +//// [nullishCoalescingOperator11.ts] +declare const f11: 1 | 0 | '' | null | undefined; + +let g11 = f11 ?? f11.toFixed() + + + + +//// [nullishCoalescingOperator11.js] +"use strict"; +var g11 = (f11 !== null && f11 !== void 0 ? f11 : f11.toFixed()); diff --git a/tests/baselines/reference/nullishCoalescingOperator11.symbols b/tests/baselines/reference/nullishCoalescingOperator11.symbols new file mode 100644 index 0000000000000..a6f8240be66c9 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator11.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts === +declare const f11: 1 | 0 | '' | null | undefined; +>f11 : Symbol(f11, Decl(nullishCoalescingOperator11.ts, 0, 13)) + +let g11 = f11 ?? f11.toFixed() +>g11 : Symbol(g11, Decl(nullishCoalescingOperator11.ts, 2, 3)) +>f11 : Symbol(f11, Decl(nullishCoalescingOperator11.ts, 0, 13)) +>f11 : Symbol(f11, Decl(nullishCoalescingOperator11.ts, 0, 13)) + + + diff --git a/tests/baselines/reference/nullishCoalescingOperator11.types b/tests/baselines/reference/nullishCoalescingOperator11.types new file mode 100644 index 0000000000000..c83a3cfe933e1 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator11.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts === +declare const f11: 1 | 0 | '' | null | undefined; +>f11 : "" | 0 | 1 | null | undefined +>null : null + +let g11 = f11 ?? f11.toFixed() +>g11 : any +>f11 ?? f11.toFixed() : any +>f11 : "" | 0 | 1 | null | undefined +>f11.toFixed() : any +>f11.toFixed : any +>f11 : "" | 0 | null | undefined +>toFixed : any + + + diff --git a/tests/baselines/reference/nullishCoalescingOperator5.types b/tests/baselines/reference/nullishCoalescingOperator5.types index bbf526d774339..3a3b1ba3497b3 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.types +++ b/tests/baselines/reference/nullishCoalescingOperator5.types @@ -20,7 +20,7 @@ a ?? b || c; a || b ?? c; >a || b ?? c : string | undefined >a || b : string | undefined ->a : string | undefined +>a : string >b : string | undefined >c : string | undefined diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts new file mode 100644 index 0000000000000..0121ecee890eb --- /dev/null +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts @@ -0,0 +1,7 @@ +// @strict: true + +declare const f11: 1 | 0 | '' | null | undefined; + +let g11 = f11 ?? f11.toFixed() + + From a719f664af8a27b7bfe685e32ce3746c6600a1ee Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 27 Sep 2019 18:18:21 +0800 Subject: [PATCH 22/26] make linter happy --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 020a10a83a519..eab248e9e7ab8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26252,7 +26252,7 @@ namespace ts { return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node); } - function checkGrammarNullishCoalesceWithLogicalExpression (node: BinaryExpression) { + function checkGrammarNullishCoalesceWithLogicalExpression(node: BinaryExpression) { const { left, operatorToken, right } = node; if (operatorToken.kind === SyntaxKind.QuestionQuestionToken) { if (isBinaryExpression(left) && (left.operatorToken.kind === SyntaxKind.BarBarToken || left.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { From cb187cbfe307771faaf0d2f58c53f351ce1ec8ff Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 27 Sep 2019 18:43:03 +0800 Subject: [PATCH 23/26] update libs --- tests/baselines/reference/api/tsserverlibrary.d.ts | 4 ++-- tests/baselines/reference/api/typescript.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 1a590cbf678e7..2c0285450f314 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -945,11 +945,11 @@ declare namespace ts { export type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; export type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; export type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; - export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken; + export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken; export type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; export type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; export type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; - export type AssignmentOperatorOrHigher = LogicalOperatorOrHigher | AssignmentOperator; + export type AssignmentOperatorOrHigher = SyntaxKind.QuestionQuestionToken | LogicalOperatorOrHigher | AssignmentOperator; export type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; export type BinaryOperatorToken = Token; export interface BinaryExpression extends Expression, Declaration { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index b0c5fe74da184..7ceb77eb7d745 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -945,11 +945,11 @@ declare namespace ts { export type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; export type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; export type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; - export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken; + export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken; export type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; export type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; export type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; - export type AssignmentOperatorOrHigher = LogicalOperatorOrHigher | AssignmentOperator; + export type AssignmentOperatorOrHigher = SyntaxKind.QuestionQuestionToken | LogicalOperatorOrHigher | AssignmentOperator; export type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; export type BinaryOperatorToken = Token; export interface BinaryExpression extends Expression, Declaration { From 7fd86584cbfd1eedfadf805f21d54252b9d65e20 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 27 Sep 2019 21:43:15 +0800 Subject: [PATCH 24/26] avoid unnecessary assert --- src/compiler/binder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index e93950c74a349..8fc0b6161ed9e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1440,7 +1440,7 @@ namespace ts { bindCondition(node.left, trueTarget, notNullLabel); currentFlow = finishFlowLabel(notNullLabel); bind(node.operatorToken); - bindCondition(node.right, trueTarget, falseTarget!); + bindCondition(node.right, trueTarget, falseTarget); } function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) { From 6ef160fb31f6ac20f08a711fe0829c77e66d797c Mon Sep 17 00:00:00 2001 From: kingwl Date: Sat, 28 Sep 2019 01:26:49 +0800 Subject: [PATCH 25/26] fix typooo --- src/compiler/binder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8fc0b6161ed9e..39b57d8116b69 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1435,7 +1435,7 @@ namespace ts { bindCondition(node.right, trueTarget, falseTarget); } - function bindNullishCollasingExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { + function bindNullishCoalescingExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { const notNullLabel = createBranchLabel(); bindCondition(node.left, trueTarget, notNullLabel); currentFlow = finishFlowLabel(notNullLabel); @@ -1476,7 +1476,7 @@ namespace ts { currentFlow = finishFlowLabel(postExpressionLabel); } else if (operator === SyntaxKind.QuestionQuestionToken) { - bindNullishCollasingExpression(node, currentTrueTarget!, currentFalseTarget!); + bindNullishCoalescingExpression(node, currentTrueTarget!, currentFalseTarget!); } else { bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!); From b030f730d029422ca7a6767134f51bed48354675 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 30 Sep 2019 15:14:31 -0700 Subject: [PATCH 26/26] Fixes for control-flow analysis --- src/compiler/binder.ts | 14 +------ src/compiler/checker.ts | 3 +- .../controlFlowNullishCoalesce.errors.txt | 19 +++++++++ .../reference/controlFlowNullishCoalesce.js | 25 ++++++++++++ .../controlFlowNullishCoalesce.symbols | 32 +++++++++++++++ .../controlFlowNullishCoalesce.types | 40 +++++++++++++++++++ .../nullishCoalescingOperator11.errors.txt | 7 +--- .../nullishCoalescingOperator11.types | 2 +- .../nullishCoalescingOperator5.types | 2 +- .../controlFlow/controlFlowNullishCoalesce.ts | 14 +++++++ 10 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 tests/baselines/reference/controlFlowNullishCoalesce.errors.txt create mode 100644 tests/baselines/reference/controlFlowNullishCoalesce.js create mode 100644 tests/baselines/reference/controlFlowNullishCoalesce.symbols create mode 100644 tests/baselines/reference/controlFlowNullishCoalesce.types create mode 100644 tests/cases/conformance/controlFlow/controlFlowNullishCoalesce.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 1aec0e21a2219..030ece62b21a8 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1015,7 +1015,8 @@ namespace ts { else { return node.kind === SyntaxKind.BinaryExpression && ( (node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || - (node).operatorToken.kind === SyntaxKind.BarBarToken); + (node).operatorToken.kind === SyntaxKind.BarBarToken || + (node).operatorToken.kind === SyntaxKind.QuestionQuestionToken); } } } @@ -1440,14 +1441,6 @@ namespace ts { bindCondition(node.right, trueTarget, falseTarget); } - function bindNullishCoalescingExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { - const notNullLabel = createBranchLabel(); - bindCondition(node.left, trueTarget, notNullLabel); - currentFlow = finishFlowLabel(notNullLabel); - bind(node.operatorToken); - bindCondition(node.right, trueTarget, falseTarget); - } - function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) { if (node.operator === SyntaxKind.ExclamationToken) { const saveTrueTarget = currentTrueTarget; @@ -1480,9 +1473,6 @@ namespace ts { bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); currentFlow = finishFlowLabel(postExpressionLabel); } - else if (operator === SyntaxKind.QuestionQuestionToken) { - bindNullishCoalescingExpression(node, currentTrueTarget!, currentFalseTarget!); - } else { bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 77f04622f5458..14e64d0a8feb3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19697,7 +19697,8 @@ namespace ts { // will be a subtype or the same type as the argument. function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { // for `a?.b`, we emulate a synthetic `a !== null && a !== undefined` condition for `a` - if (isOptionalChainRoot(expr.parent)) { + if (isOptionalChainRoot(expr.parent) || + isBinaryExpression(expr.parent) && expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken && expr.parent.left === expr) { return narrowTypeByOptionality(type, expr, assumeTrue); } switch (expr.kind) { diff --git a/tests/baselines/reference/controlFlowNullishCoalesce.errors.txt b/tests/baselines/reference/controlFlowNullishCoalesce.errors.txt new file mode 100644 index 0000000000000..1e32f86a46019 --- /dev/null +++ b/tests/baselines/reference/controlFlowNullishCoalesce.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/controlFlow/controlFlowNullishCoalesce.ts(4,1): error TS2454: Variable 'a' is used before being assigned. + + +==== tests/cases/conformance/controlFlow/controlFlowNullishCoalesce.ts (1 errors) ==== + // assignments in shortcutting rhs + let a: number; + o ?? (a = 1); + a.toString(); + ~ +!!! error TS2454: Variable 'a' is used before being assigned. + + // assignment flow + declare const o: { x: number } | undefined; + let x: { x: number } | boolean; + if (x = o ?? true) { + x; + } + + \ No newline at end of file diff --git a/tests/baselines/reference/controlFlowNullishCoalesce.js b/tests/baselines/reference/controlFlowNullishCoalesce.js new file mode 100644 index 0000000000000..f49414771d3aa --- /dev/null +++ b/tests/baselines/reference/controlFlowNullishCoalesce.js @@ -0,0 +1,25 @@ +//// [controlFlowNullishCoalesce.ts] +// assignments in shortcutting rhs +let a: number; +o ?? (a = 1); +a.toString(); + +// assignment flow +declare const o: { x: number } | undefined; +let x: { x: number } | boolean; +if (x = o ?? true) { + x; +} + + + +//// [controlFlowNullishCoalesce.js] +"use strict"; +// assignments in shortcutting rhs +var a; +(o !== null && o !== void 0 ? o : (a = 1)); +a.toString(); +var x; +if (x = (o !== null && o !== void 0 ? o : true)) { + x; +} diff --git a/tests/baselines/reference/controlFlowNullishCoalesce.symbols b/tests/baselines/reference/controlFlowNullishCoalesce.symbols new file mode 100644 index 0000000000000..6b8f58db20b34 --- /dev/null +++ b/tests/baselines/reference/controlFlowNullishCoalesce.symbols @@ -0,0 +1,32 @@ +=== tests/cases/conformance/controlFlow/controlFlowNullishCoalesce.ts === +// assignments in shortcutting rhs +let a: number; +>a : Symbol(a, Decl(controlFlowNullishCoalesce.ts, 1, 3)) + +o ?? (a = 1); +>o : Symbol(o, Decl(controlFlowNullishCoalesce.ts, 6, 13)) +>a : Symbol(a, Decl(controlFlowNullishCoalesce.ts, 1, 3)) + +a.toString(); +>a.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(controlFlowNullishCoalesce.ts, 1, 3)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + +// assignment flow +declare const o: { x: number } | undefined; +>o : Symbol(o, Decl(controlFlowNullishCoalesce.ts, 6, 13)) +>x : Symbol(x, Decl(controlFlowNullishCoalesce.ts, 6, 18)) + +let x: { x: number } | boolean; +>x : Symbol(x, Decl(controlFlowNullishCoalesce.ts, 7, 3)) +>x : Symbol(x, Decl(controlFlowNullishCoalesce.ts, 7, 8)) + +if (x = o ?? true) { +>x : Symbol(x, Decl(controlFlowNullishCoalesce.ts, 7, 3)) +>o : Symbol(o, Decl(controlFlowNullishCoalesce.ts, 6, 13)) + + x; +>x : Symbol(x, Decl(controlFlowNullishCoalesce.ts, 7, 3)) +} + + diff --git a/tests/baselines/reference/controlFlowNullishCoalesce.types b/tests/baselines/reference/controlFlowNullishCoalesce.types new file mode 100644 index 0000000000000..f94bbfd3baf3f --- /dev/null +++ b/tests/baselines/reference/controlFlowNullishCoalesce.types @@ -0,0 +1,40 @@ +=== tests/cases/conformance/controlFlow/controlFlowNullishCoalesce.ts === +// assignments in shortcutting rhs +let a: number; +>a : number + +o ?? (a = 1); +>o ?? (a = 1) : { x: number; } | 1 +>o : { x: number; } | undefined +>(a = 1) : 1 +>a = 1 : 1 +>a : number +>1 : 1 + +a.toString(); +>a.toString() : string +>a.toString : (radix?: number | undefined) => string +>a : number +>toString : (radix?: number | undefined) => string + +// assignment flow +declare const o: { x: number } | undefined; +>o : { x: number; } | undefined +>x : number + +let x: { x: number } | boolean; +>x : boolean | { x: number; } +>x : number + +if (x = o ?? true) { +>x = o ?? true : true | { x: number; } +>x : boolean | { x: number; } +>o ?? true : true | { x: number; } +>o : { x: number; } | undefined +>true : true + + x; +>x : true | { x: number; } +} + + diff --git a/tests/baselines/reference/nullishCoalescingOperator11.errors.txt b/tests/baselines/reference/nullishCoalescingOperator11.errors.txt index 528d8ae026ad3..45faaea8767ac 100644 --- a/tests/baselines/reference/nullishCoalescingOperator11.errors.txt +++ b/tests/baselines/reference/nullishCoalescingOperator11.errors.txt @@ -1,17 +1,12 @@ tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts(3,18): error TS2533: Object is possibly 'null' or 'undefined'. -tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts(3,22): error TS2339: Property 'toFixed' does not exist on type '"" | 0'. - Property 'toFixed' does not exist on type '""'. -==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts (2 errors) ==== +==== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator11.ts (1 errors) ==== declare const f11: 1 | 0 | '' | null | undefined; let g11 = f11 ?? f11.toFixed() ~~~ !!! error TS2533: Object is possibly 'null' or 'undefined'. - ~~~~~~~ -!!! error TS2339: Property 'toFixed' does not exist on type '"" | 0'. -!!! error TS2339: Property 'toFixed' does not exist on type '""'. \ No newline at end of file diff --git a/tests/baselines/reference/nullishCoalescingOperator11.types b/tests/baselines/reference/nullishCoalescingOperator11.types index c83a3cfe933e1..5c168dd463271 100644 --- a/tests/baselines/reference/nullishCoalescingOperator11.types +++ b/tests/baselines/reference/nullishCoalescingOperator11.types @@ -9,7 +9,7 @@ let g11 = f11 ?? f11.toFixed() >f11 : "" | 0 | 1 | null | undefined >f11.toFixed() : any >f11.toFixed : any ->f11 : "" | 0 | null | undefined +>f11 : null | undefined >toFixed : any diff --git a/tests/baselines/reference/nullishCoalescingOperator5.types b/tests/baselines/reference/nullishCoalescingOperator5.types index 3a3b1ba3497b3..bbf526d774339 100644 --- a/tests/baselines/reference/nullishCoalescingOperator5.types +++ b/tests/baselines/reference/nullishCoalescingOperator5.types @@ -20,7 +20,7 @@ a ?? b || c; a || b ?? c; >a || b ?? c : string | undefined >a || b : string | undefined ->a : string +>a : string | undefined >b : string | undefined >c : string | undefined diff --git a/tests/cases/conformance/controlFlow/controlFlowNullishCoalesce.ts b/tests/cases/conformance/controlFlow/controlFlowNullishCoalesce.ts new file mode 100644 index 0000000000000..2e5a8ea1a60fe --- /dev/null +++ b/tests/cases/conformance/controlFlow/controlFlowNullishCoalesce.ts @@ -0,0 +1,14 @@ +// @strict: true + +// assignments in shortcutting rhs +let a: number; +o ?? (a = 1); +a.toString(); + +// assignment flow +declare const o: { x: number } | undefined; +let x: { x: number } | boolean; +if (x = o ?? true) { + x; +} +