diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ba89d4f748e..6dbc89ab3ef 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2403,12 +2403,7 @@ namespace ts { return lookupSymbolForNameWorker(container, node.escapedText); } else { - let symbol = lookupSymbolForPropertyAccess(node.expression); - symbol = symbol && isDeclarationOfJavascriptContainerExpression(symbol.valueDeclaration) ? (symbol.valueDeclaration as VariableDeclaration).initializer.symbol : - symbol && isDeclarationOfDefaultedJavascriptContainerExpression(symbol.valueDeclaration) ? ((symbol.valueDeclaration as VariableDeclaration).initializer as BinaryExpression).right.symbol : - symbol && isAssignmentOfDefaultedJavascriptContainerExpression(symbol.valueDeclaration.parent) ? (((symbol.valueDeclaration.parent as BinaryExpression).right as BinaryExpression).right as BinaryExpression).symbol : - symbol && isAssignmentOfJavascriptContainerExpression(symbol.valueDeclaration) ? ((symbol.valueDeclaration.parent as BinaryExpression).right as BinaryExpression).symbol : - symbol; + const symbol = follow(lookupSymbolForPropertyAccess(node.expression)); return symbol && symbol.exports && symbol.exports.get(node.name.escapedText); } } @@ -2417,11 +2412,7 @@ namespace ts { // Look up the property in the local scope, since property assignments should follow the declaration const symbol = lookupSymbolForPropertyAccess(name); // TODO: Should be able to structure this with less duplication - let targetSymbol = symbol && isDeclarationOfJavascriptContainerExpression(symbol.valueDeclaration) ? (symbol.valueDeclaration as VariableDeclaration).initializer.symbol : - symbol && isDeclarationOfDefaultedJavascriptContainerExpression(symbol.valueDeclaration) ? ((symbol.valueDeclaration as VariableDeclaration).initializer as BinaryExpression).right.symbol : - symbol && isAssignmentOfDefaultedJavascriptContainerExpression(symbol.valueDeclaration.parent) ? (((symbol.valueDeclaration.parent as BinaryExpression).right as BinaryExpression).right as BinaryExpression).symbol : - symbol && isAssignmentOfJavascriptContainerExpression(symbol.valueDeclaration) ? ((symbol.valueDeclaration.parent as BinaryExpression).right as BinaryExpression).symbol : - symbol; + let targetSymbol = follow(symbol); Debug.assert(propertyAccess.parent.kind === SyntaxKind.BinaryExpression || propertyAccess.parent.kind === SyntaxKind.ExpressionStatement || propertyAccess.parent.kind === SyntaxKind.PropertyAccessExpression); @@ -2430,24 +2421,40 @@ namespace ts { const initializerKind = (propertyAccess.parent as BinaryExpression).right.kind; isLegalPosition = (initializerKind === SyntaxKind.ClassExpression || initializerKind === SyntaxKind.FunctionExpression) && propertyAccess.parent.parent.parent.kind === SyntaxKind.SourceFile; + if (propertyAccess.parent.parent.parent.kind === SyntaxKind.SourceFile && initializerKind === SyntaxKind.BinaryExpression && (((propertyAccess.parent as BinaryExpression).right as BinaryExpression).right.kind === SyntaxKind.ClassExpression || ((propertyAccess.parent as BinaryExpression).right as BinaryExpression).right.kind === SyntaxKind.FunctionExpression)) { + isLegalPosition = true; + } } else { isLegalPosition = propertyAccess.parent.parent.kind === SyntaxKind.SourceFile; } if (!isPrototypeProperty && (!targetSymbol || !(targetSymbol.flags & SymbolFlags.Namespace)) && isLegalPosition) { - const identifier = isIdentifier(propertyAccess.expression) ? propertyAccess.expression : isIdentifier(propertyAccess.expression.expression) && propertyAccess.expression.expression; - Debug.assert(identifier !== undefined); const flags = SymbolFlags.Module | SymbolFlags.JSContainer; const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.JSContainer; - if (targetSymbol) { - // TODO: Not sure this is correct for nested declarations -- maybe this should be added to targetSymbol - // Note: add declaration to original symbol, not the special-syntax's symbol, so that namespaces work for type lookup - addDeclarationToSymbol(symbol, identifier, flags); - } - else { - // TODO: Not sure this branch is correct for nested declarations - targetSymbol = declareSymbol(container.locals, /*parent*/ undefined, identifier, flags, excludeFlags); - } + // const startTargetSymbol = !!targetSymbol; + // hm. This is only needed to make namespaced access of types workable. Namespaced access of *values* doesn't work now either, so something is wrong. + // (Note: for the non-nested case, at least, addDeclarationToSymbol is only needed for things that could be further namespaces, because it + // makes the intermediate namespace. However, I think something like it is needed for *all* nested assignments, in case their intermediate namespaces don't exist) + iterateEntityNameExpression(propertyAccess.expression, (id, originalSymbol, available) => { + if (targetSymbol) { + if (available) { + // Note: add declaration to original symbol, not the special-syntax's symbol, so that namespaces work for type lookup + addDeclarationToSymbol(originalSymbol, id, flags); + // TODO: Why can't I overwrite targetSymbol here? I'm having trouble tracking targetSymbol's state. + return originalSymbol; + } + else { + originalSymbol.exports = originalSymbol.exports || createSymbolTable(); + targetSymbol = declareSymbol(originalSymbol.exports, originalSymbol, id, flags, excludeFlags); + return targetSymbol; + } + } + else { + Debug.assert(!available); + targetSymbol = declareSymbol(container.locals, /*parent*/ undefined, id, flags, excludeFlags); + return targetSymbol; + } + }); } if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule | SymbolFlags.ObjectLiteral))) { return; @@ -2462,6 +2469,20 @@ namespace ts { declareSymbol(symbolTable, targetSymbol, propertyAccess, SymbolFlags.Property, SymbolFlags.PropertyExcludes); } + function iterateEntityNameExpression(e: EntityNameExpression, action: (e: Identifier, originalSymbol: Symbol, available: boolean) => Symbol): Symbol { + if (isIdentifier(e)) { + const s = lookupSymbolForPropertyAccess(e); + return action(e, s, !!s); + } + else { + const s = follow(iterateEntityNameExpression(e.expression, action)); + Debug.assert(!!s, "lost the chant"); + Debug.assert(!!s.exports, `${s.escapedName} has no exports???`); + const t = s.exports.get(e.name.escapedText); + return action(e.name, t || s, s.exports.has(e.name.escapedText)); + } + } + function bindCallExpression(node: CallExpression) { // We're only inspecting call expressions to detect CommonJS modules, so we can skip // this check if we've already seen the module indicator diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9b27b202748..737daa52e24 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -835,7 +835,7 @@ namespace ts { function mergeSymbol(target: Symbol, source: Symbol) { if (!(target.flags & getExcludedSymbolFlags(source.flags)) || - source.flags & SymbolFlags.JSContainer || target.flags & SymbolFlags.JSContainer) { + (source.flags | target.flags) & SymbolFlags.JSContainer) { // Javascript static-property-assignment declarations always merge, even though they are also values if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) { // reset flag when merging instantiated module into value module that has only const enums @@ -857,6 +857,14 @@ namespace ts { if (!target.exports) target.exports = createSymbolTable(); mergeSymbolTable(target.exports, source.exports); } + if ((source.flags | target.flags) & SymbolFlags.JSContainer) { + const fs = follow(source); + const ft = follow(target); + if (fs !== source || ft !== target) { + // also follow the source's valueDeclaration and merge its symbol + mergeSymbol(follow(target), follow(source)); + } + } recordMergedSymbol(target, source); } else if (target.flags & SymbolFlags.NamespaceModule) { @@ -14752,14 +14760,12 @@ namespace ts { // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); - let propertiesTable = createSymbolTable(); + let propertiesTable: SymbolTable; let propertiesArray: Symbol[] = []; let spread: Type = emptyObjectType; let propagatedFlags: TypeFlags = TypeFlags.FreshLiteral; const isInJSFile = isInJavaScriptFile(node); - // TODO: Might need to skip if isDeclarationOfDefaultedJavascriptContainerExpression(node.parent.parent) instead of just checking node.properties.length > 0 - // (actually, it would be better not to skip contextual typing at all, but to do that I need to avoid the checking loop another way) const contextualType = getApparentTypeOfContextualType(node); const contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression); @@ -14768,11 +14774,15 @@ namespace ts { let patternWithComputedProperties = false; let hasComputedStringProperty = false; let hasComputedNumberProperty = false; - // TODO: This seems like the wrong way to put the assignment-properties into the type (especially the manual call to mergeSymbolTable) - if (isInJSFile && node.symbol && node.symbol.exports) { - mergeSymbolTable(propertiesTable, node.symbol.exports); - node.symbol.exports.forEach(symbol => propertiesArray.push(symbol)); + // TODO: This seems like it might be wrong, or at least should come earlier + // (maybe check SymbolFlags.JSContainer? This currently misses normal declarations like `var my = {}`, but shouldn't) + if (isInJSFile && node.symbol && node.symbol.exports && node.properties.length === 0) { + let symbol = node.symbol; + propertiesTable = symbol.exports; + symbol.exports.forEach(symbol => propertiesArray.push(getMergedSymbol(symbol))); + return createObjectLiteralType(); } + propertiesTable = createSymbolTable(); let offset = 0; for (let i = 0; i < node.properties.length; i++) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a07040eb4ad..34a804f1528 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1486,6 +1486,14 @@ namespace ts { return false; } + export function follow(symbol: Symbol) { + return symbol && isDeclarationOfJavascriptContainerExpression(symbol.valueDeclaration) ? (symbol.valueDeclaration as VariableDeclaration).initializer.symbol : + symbol && isDeclarationOfDefaultedJavascriptContainerExpression(symbol.valueDeclaration) ? ((symbol.valueDeclaration as VariableDeclaration).initializer as BinaryExpression).right.symbol : + symbol && symbol.valueDeclaration && isAssignmentOfDefaultedJavascriptContainerExpression(symbol.valueDeclaration.parent) ? (((symbol.valueDeclaration.parent as BinaryExpression).right as BinaryExpression).right as BinaryExpression).symbol : + symbol && isAssignmentOfJavascriptContainerExpression(symbol.valueDeclaration) ? ((symbol.valueDeclaration.parent as BinaryExpression).right as BinaryExpression).symbol : + symbol; + } + /** * Returns true if the node is a variable declaration whose initializer is a function or class expression, or an empty object literal. * This function does not test if the node is in a JavaScript file or not. diff --git a/tests/baselines/reference/typeFromPropertyAssignment4.symbols b/tests/baselines/reference/typeFromPropertyAssignment4.symbols index 421f3e1840f..8e74a1f935e 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment4.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment4.symbols @@ -4,7 +4,9 @@ var Outer = {}; === tests/cases/conformance/salsa/a.js === Outer.Inner = class { +>Outer.Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0)) >Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(a.js, 0, 0)) +>Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0)) constructor() { /** @type {number} */ @@ -15,9 +17,29 @@ Outer.Inner = class { } } +/** @type {Outer.Inner} */ +var local +>local : Symbol(local, Decl(a.js, 8, 3)) + +local.y +>local.y : Symbol((Anonymous class).y, Decl(a.js, 1, 19)) +>local : Symbol(local, Decl(a.js, 8, 3)) +>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19)) + +var inner = new Outer.Inner() +>inner : Symbol(inner, Decl(a.js, 10, 3)) +>Outer.Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0)) +>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(a.js, 0, 0)) +>Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0)) + +inner.y +>inner.y : Symbol((Anonymous class).y, Decl(a.js, 1, 19)) +>inner : Symbol(inner, Decl(a.js, 10, 3)) +>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19)) + === tests/cases/conformance/salsa/b.js === /** @type {Outer.Inner} */ -var x; +var x >x : Symbol(x, Decl(b.js, 1, 3)) x.y @@ -25,3 +47,14 @@ x.y >x : Symbol(x, Decl(b.js, 1, 3)) >y : Symbol((Anonymous class).y, Decl(a.js, 1, 19)) +var z = new Outer.Inner() +>z : Symbol(z, Decl(b.js, 3, 3)) +>Outer.Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0)) +>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(a.js, 0, 0)) +>Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0)) + +z.y +>z.y : Symbol((Anonymous class).y, Decl(a.js, 1, 19)) +>z : Symbol(z, Decl(b.js, 3, 3)) +>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment4.types b/tests/baselines/reference/typeFromPropertyAssignment4.types index 0f356ca5d09..9139ab4c735 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment4.types +++ b/tests/baselines/reference/typeFromPropertyAssignment4.types @@ -1,14 +1,14 @@ === tests/cases/conformance/salsa/def.js === var Outer = {}; ->Outer : { [x: string]: any; } ->{} : { [x: string]: any; } +>Outer : typeof Outer +>{} : typeof Outer === tests/cases/conformance/salsa/a.js === Outer.Inner = class { >Outer.Inner = class { constructor() { /** @type {number} */ this.y = 12 }} : typeof (Anonymous class) ->Outer.Inner : any ->Outer : { [x: string]: any; } ->Inner : any +>Outer.Inner : typeof (Anonymous class) +>Outer : typeof Outer +>Inner : typeof (Anonymous class) >class { constructor() { /** @type {number} */ this.y = 12 }} : typeof (Anonymous class) constructor() { @@ -22,9 +22,30 @@ Outer.Inner = class { } } +/** @type {Outer.Inner} */ +var local +>local : (Anonymous class) + +local.y +>local.y : number +>local : (Anonymous class) +>y : number + +var inner = new Outer.Inner() +>inner : (Anonymous class) +>new Outer.Inner() : (Anonymous class) +>Outer.Inner : typeof (Anonymous class) +>Outer : typeof Outer +>Inner : typeof (Anonymous class) + +inner.y +>inner.y : number +>inner : (Anonymous class) +>y : number + === tests/cases/conformance/salsa/b.js === /** @type {Outer.Inner} */ -var x; +var x >x : (Anonymous class) x.y @@ -32,3 +53,15 @@ x.y >x : (Anonymous class) >y : number +var z = new Outer.Inner() +>z : (Anonymous class) +>new Outer.Inner() : (Anonymous class) +>Outer.Inner : typeof (Anonymous class) +>Outer : typeof Outer +>Inner : typeof (Anonymous class) + +z.y +>z.y : number +>z : (Anonymous class) +>y : number + diff --git a/tests/baselines/reference/typeFromPropertyAssignment9.symbols b/tests/baselines/reference/typeFromPropertyAssignment9.symbols index b65c4720b67..ccf78f89dd8 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment9.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment9.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)) ->my : Symbol(my, Decl(a.js, 0, 3), 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, 13, 34), Decl(a.js, 19, 1)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) /** @param {number} n */ my.method = function(n) { >my.method : Symbol(method, Decl(a.js, 0, 18)) ->my : Symbol(my, Decl(a.js, 0, 3), 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, 13, 34), Decl(a.js, 19, 1)) >method : Symbol(method, Decl(a.js, 0, 18)) >n : Symbol(n, Decl(a.js, 2, 21)) @@ -15,27 +15,27 @@ my.method = function(n) { } my.number = 1; >my.number : Symbol(number, Decl(a.js, 4, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), 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, 13, 34), Decl(a.js, 19, 1)) >number : Symbol(number, Decl(a.js, 4, 1)) my.object = {}; >my.object : Symbol(object, Decl(a.js, 5, 14)) ->my : Symbol(my, Decl(a.js, 0, 3), 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, 13, 34), Decl(a.js, 19, 1)) >object : Symbol(object, Decl(a.js, 5, 14)) my.predicate = my.predicate || {}; ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) my.predicate.query = function () { >my.predicate.query : Symbol(query, Decl(a.js, 7, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) >query : Symbol(query, Decl(a.js, 7, 34)) var me = this; @@ -49,17 +49,17 @@ my.predicate.query = function () { var q = new my.predicate.query(); >q : Symbol(q, Decl(a.js, 12, 3)) >my.predicate.query : Symbol(query, Decl(a.js, 7, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) >query : Symbol(query, Decl(a.js, 7, 34)) my.predicate.query.result = 'none' >my.predicate.query.result : Symbol((Anonymous function).result, Decl(a.js, 12, 33)) >my.predicate.query : Symbol(query, Decl(a.js, 7, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) >query : Symbol(query, Decl(a.js, 7, 34)) >result : Symbol((Anonymous function).result, Decl(a.js, 12, 33)) @@ -68,14 +68,14 @@ my.predicate.query.result = 'none' */ my.predicate.sort = my.predicate.sort || function (first, second) { >my.predicate.sort : Symbol(sort, Decl(a.js, 13, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) >sort : Symbol(sort, Decl(a.js, 13, 34)) >my.predicate.sort : Symbol(sort, Decl(a.js, 13, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) >sort : Symbol(sort, Decl(a.js, 13, 34)) >first : Symbol(first, Decl(a.js, 17, 51)) >second : Symbol(second, Decl(a.js, 17, 57)) @@ -88,9 +88,9 @@ my.predicate.sort = my.predicate.sort || function (first, second) { } my.predicate.type = class { >my.predicate.type : Symbol(type, Decl(a.js, 19, 1)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 7, 34), Decl(a.js, 13, 34), Decl(a.js, 19, 1)) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 17, 3), Decl(a.js, 20, 3)) >type : Symbol(type, Decl(a.js, 19, 1)) m() { return 101; } @@ -100,22 +100,22 @@ my.predicate.type = class { // global-ish prefixes var min = window.min || {}; ->min : Symbol(min, Decl(a.js, 26, 3)) +>min : Symbol(min, Decl(a.js, 26, 3), Decl(a.js, 26, 27), Decl(a.js, 27, 44)) min.nest = this.min.nest || function () { }; ->min.nest : Symbol(nest, Decl(a.js, 26, 27)) ->min : Symbol(min, Decl(a.js, 26, 3)) ->nest : Symbol(nest, Decl(a.js, 26, 27)) +>min.nest : Symbol(nest, Decl(a.js, 26, 27), Decl(a.js, 28, 4)) +>min : Symbol(min, Decl(a.js, 26, 3), Decl(a.js, 26, 27), Decl(a.js, 27, 44)) +>nest : Symbol(nest, Decl(a.js, 26, 27), Decl(a.js, 28, 4)) min.nest.other = self.min.nest.other || class { }; >min.nest.other : Symbol((Anonymous function).other, Decl(a.js, 27, 44)) ->min.nest : Symbol(nest, Decl(a.js, 26, 27)) ->min : Symbol(min, Decl(a.js, 26, 3)) ->nest : Symbol(nest, Decl(a.js, 26, 27)) +>min.nest : Symbol(nest, Decl(a.js, 26, 27), Decl(a.js, 28, 4)) +>min : Symbol(min, Decl(a.js, 26, 3), Decl(a.js, 26, 27), Decl(a.js, 27, 44)) +>nest : Symbol(nest, Decl(a.js, 26, 27), Decl(a.js, 28, 4)) >other : Symbol((Anonymous function).other, Decl(a.js, 27, 44)) min.property = global.min.property || {}; >min.property : Symbol(property, Decl(a.js, 28, 50)) ->min : Symbol(min, Decl(a.js, 26, 3)) +>min : Symbol(min, Decl(a.js, 26, 3), Decl(a.js, 26, 27), Decl(a.js, 27, 44)) >property : Symbol(property, Decl(a.js, 28, 50)) diff --git a/tests/baselines/reference/typeFromPropertyAssignmentOutOfOrder.symbols b/tests/baselines/reference/typeFromPropertyAssignmentOutOfOrder.symbols index 59b42c24737..bb187808b32 100644 --- a/tests/baselines/reference/typeFromPropertyAssignmentOutOfOrder.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignmentOutOfOrder.symbols @@ -1,24 +1,24 @@ === tests/cases/conformance/salsa/index.js === Common.Item = class I {} >Common.Item : Symbol(Common.Item, Decl(index.js, 0, 0)) ->Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3)) +>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12)) >Item : Symbol(Common.Item, Decl(index.js, 0, 0)) >I : Symbol(I, Decl(index.js, 0, 13)) Common.Object = class extends Common.Item {} >Common.Object : Symbol(Common.Object, Decl(index.js, 0, 24)) ->Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3)) +>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12)) >Object : Symbol(Common.Object, Decl(index.js, 0, 24)) >Common.Item : Symbol(Common.Item, Decl(index.js, 0, 0)) ->Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3)) +>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12)) >Item : Symbol(Common.Item, Decl(index.js, 0, 0)) Workspace.Object = class extends Common.Object {} >Workspace.Object : Symbol(Workspace.Object, Decl(index.js, 1, 44)) ->Workspace : Symbol(Workspace, Decl(index.js, 1, 44), Decl(roots.js, 1, 3)) +>Workspace : Symbol(Workspace, Decl(index.js, 1, 44), Decl(roots.js, 1, 3), Decl(roots.js, 1, 15)) >Object : Symbol(Workspace.Object, Decl(index.js, 1, 44)) >Common.Object : Symbol(Common.Object, Decl(index.js, 0, 24)) ->Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3)) +>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12)) >Object : Symbol(Common.Object, Decl(index.js, 0, 24)) /** @type {Workspace.Object} */ @@ -27,8 +27,8 @@ var am; === tests/cases/conformance/salsa/roots.js === var Common = {}; ->Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3)) +>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12)) var Workspace = {}; ->Workspace : Symbol(Workspace, Decl(index.js, 1, 44), Decl(roots.js, 1, 3)) +>Workspace : Symbol(Workspace, Decl(index.js, 1, 44), Decl(roots.js, 1, 3), Decl(roots.js, 1, 15)) diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment4.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment4.ts index 5bf92934a04..14e84ad5568 100644 --- a/tests/cases/conformance/salsa/typeFromPropertyAssignment4.ts +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment4.ts @@ -13,7 +13,15 @@ Outer.Inner = class { } } +/** @type {Outer.Inner} */ +var local +local.y +var inner = new Outer.Inner() +inner.y + // @Filename: b.js /** @type {Outer.Inner} */ -var x; +var x x.y +var z = new Outer.Inner() +z.y