diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index bd3c5d2609d..92781227758 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2042,6 +2042,9 @@ namespace ts { case SpecialPropertyAssignmentKind.PrototypeProperty: bindPrototypePropertyAssignment((node as BinaryExpression).left as PropertyAccessEntityNameExpression, node); break; + case SpecialPropertyAssignmentKind.Prototype: + bindPrototypeAssignment(node as BinaryExpression); + break; case SpecialPropertyAssignmentKind.ThisProperty: bindThisPropertyAssignment(node as BinaryExpression); break; @@ -2360,15 +2363,23 @@ namespace ts { } } + /** For `x.prototype = { p, ... }`, declare members p,... if `x` is function/class/{}, or not declared. */ + function bindPrototypeAssignment(node: BinaryExpression) { + node.left.parent = node; + node.right.parent = node; + const lhs = node.left as PropertyAccessEntityNameExpression; + bindPropertyAssignment(lhs, lhs, /*isPrototypeProperty*/ false); + } + /** - * For 'x.prototype.y = z', declare a 'member' y on x if x is a function or class, or not declared. + * For `x.prototype.y = z`, declare a member `y` on `x` if `x` is a function or class, or not declared. * Note that jsdoc preceding an ExpressionStatement like `x.prototype.y;` is also treated as a declaration. */ function bindPrototypePropertyAssignment(lhs: PropertyAccessEntityNameExpression, parent: Node) { // Look up the function in the local scope, since prototype assignments should // follow the function declaration const classPrototype = lhs.expression as PropertyAccessEntityNameExpression; - const constructorFunction = classPrototype.expression as Identifier; + const constructorFunction = classPrototype.expression; // Fix up parent pointers since we're going to use these nodes before we bind into them lhs.parent = parent; @@ -2382,7 +2393,8 @@ namespace ts { function bindSpecialPropertyAssignment(node: BinaryExpression) { const lhs = node.left as PropertyAccessEntityNameExpression; // Fix up parent pointers since we're going to use these nodes before we bind into them - lhs.parent = node; + node.left.parent = node; + node.right.parent = node; if (isIdentifier(lhs.expression) && container === file && isNameOfExportsOrModuleExportsAliasDeclaration(file, lhs.expression)) { // This can be an alias for the 'exports' or 'module.exports' names, e.g. // var util = module.exports; @@ -2433,7 +2445,9 @@ namespace ts { (symbol.exports || (symbol.exports = createSymbolTable())); // Declare the method/property - declareSymbol(symbolTable, symbol, propertyAccess, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + const symbolFlags = SymbolFlags.Property | (isToplevelNamespaceableInitializer ? SymbolFlags.JSContainer : 0); + const symbolExcludes = SymbolFlags.PropertyExcludes & ~(isToplevelNamespaceableInitializer ? SymbolFlags.JSContainer : 0); + declareSymbol(symbolTable, symbol, propertyAccess, symbolFlags, symbolExcludes); } function lookupSymbolForPropertyAccess(node: EntityNameExpression): Symbol | undefined { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62113ed8dfd..cbbd377fdaa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2002,21 +2002,7 @@ namespace ts { } } else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) { - let left: EntityNameOrEntityNameExpression; - - if (name.kind === SyntaxKind.QualifiedName) { - left = name.left; - } - else if (name.kind === SyntaxKind.PropertyAccessExpression) { - left = name.expression; - } - else { - // If the expression in property-access expression is not entity-name or parenthsizedExpression (e.g. it is a call expression), it won't be able to successfully resolve the name. - // This is the case when we are trying to do any language service operation in heritage clauses. By return undefined, the getSymbolOfEntityNameOrPropertyAccessExpression - // will attempt to checkPropertyAccessExpression to resolve symbol. - // i.e class C extends foo()./*do language service operation here*/B {} - return undefined; - } + const left = name.kind === SyntaxKind.QualifiedName ? name.left : name.expression; const right = name.kind === SyntaxKind.QualifiedName ? name.right : name.name; let namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors, /*dontResolveAlias*/ false, location); if (!namespace || nodeIsMissing(right)) { @@ -2025,8 +2011,11 @@ namespace ts { else if (namespace === unknownSymbol) { return namespace; } - if (isInJavaScriptFile(name) && isDeclarationOfFunctionOrClassExpression(namespace)) { - namespace = getSymbolOfNode((namespace.valueDeclaration as VariableDeclaration).initializer); + if (isInJavaScriptFile(name)) { + const initializer = getDeclaredJavascriptInitializer(namespace.valueDeclaration); + if (initializer) { + namespace = getSymbolOfNode(initializer); + } } symbol = getSymbol(getExportsOfSymbol(namespace), right.escapedText, meaning); if (!symbol) { @@ -4186,7 +4175,7 @@ namespace ts { } function getWidenedTypeFromJSSpecialPropertyDeclarations(symbol: Symbol) { - // function/class/{} assignments are fresh declarations, not property assignments, so return immediately + // function/class/{} assignments are fresh declarations, not property assignments, so only add prototype assignments const specialDeclaration = getAssignedJavascriptInitializer(symbol.valueDeclaration); if (specialDeclaration) { return getWidenedLiteralType(checkExpressionCached(specialDeclaration)); @@ -7246,12 +7235,11 @@ namespace ts { // A jsdoc TypeReference may have resolved to a value (as opposed to a type). If // the symbol is a constructor function, return the inferred class type; otherwise, // the type of this reference is just the type of the value we resolved to. + const assignedType = getAssignedClassType(symbol); const valueType = getTypeOfSymbol(symbol); - if (valueType.symbol && !isInferredClassType(valueType)) { - const referenceType = getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments); - if (referenceType) { - return referenceType; - } + const referenceType = valueType.symbol && !isInferredClassType(valueType) && getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments); + if (referenceType || assignedType) { + return referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType; } // Resolve the type reference as a Type for the purpose of reporting errors. @@ -14254,6 +14242,7 @@ namespace ts { case SpecialPropertyAssignmentKind.ModuleExports: case SpecialPropertyAssignmentKind.PrototypeProperty: case SpecialPropertyAssignmentKind.ThisProperty: + case SpecialPropertyAssignmentKind.Prototype: return false; default: Debug.assertNever(kind); @@ -17893,20 +17882,54 @@ namespace ts { } function getJavaScriptClassType(symbol: Symbol): Type | undefined { - if (isDeclarationOfFunctionOrClassExpression(symbol)) { - symbol = getSymbolOfNode((symbol.valueDeclaration).initializer); + const initializer = getDeclaredJavascriptInitializer(symbol.valueDeclaration); + if (initializer) { + symbol = getSymbolOfNode(initializer); } + let inferred: Type | undefined; if (isJavaScriptConstructor(symbol.valueDeclaration)) { - return getInferredClassType(symbol); + inferred = getInferredClassType(symbol); } - if (symbol.flags & SymbolFlags.Variable) { - const valueType = getTypeOfSymbol(symbol); - if (valueType.symbol && !isInferredClassType(valueType) && isJavaScriptConstructor(valueType.symbol.valueDeclaration)) { - return getInferredClassType(valueType.symbol); + const assigned = getAssignedClassType(symbol); + const valueType = getTypeOfSymbol(symbol); + if (valueType.symbol && !isInferredClassType(valueType) && isJavaScriptConstructor(valueType.symbol.valueDeclaration)) { + inferred = getInferredClassType(valueType.symbol); + } + return assigned && inferred ? + getIntersectionType([inferred, assigned]) : + assigned || inferred; + } + + function getAssignedClassType(symbol: Symbol) { + const decl = symbol.valueDeclaration; + const assignmentSymbol = decl && decl.parent && + (isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) || + isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent)); + if (assignmentSymbol) { + const prototype = forEach(assignmentSymbol.declarations, getAssignedJavascriptPrototype); + if (prototype) { + return checkExpression(prototype); } } } + function getAssignedJavascriptPrototype(node: Node) { + if (!node.parent) { + return false; + } + let parent: Node = node.parent; + while (parent && parent.kind === SyntaxKind.PropertyAccessExpression) { + parent = parent.parent; + } + return parent && isBinaryExpression(parent) && + isPropertyAccessExpression(parent.left) && + parent.left.name.escapedText === "prototype" && + parent.operatorToken.kind === SyntaxKind.EqualsToken && + isObjectLiteralExpression(parent.right) && + parent.right; + } + + function getInferredClassType(symbol: Symbol) { const links = getSymbolLinks(symbol); if (!links.inferredClassType) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 39e4f90698d..aabfd762ffb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3243,8 +3243,8 @@ namespace ts { Enum = RegularEnum | ConstEnum, Variable = FunctionScopedVariable | BlockScopedVariable, - Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor, - Type = Class | Interface | Enum | EnumMember | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias, + Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor | JSContainer, + Type = Class | Interface | Enum | EnumMember | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias | JSContainer, Namespace = ValueModule | NamespaceModule | Enum, Module = ValueModule | NamespaceModule, Accessor = GetAccessor | SetAccessor, @@ -3964,7 +3964,9 @@ namespace ts { /// this.name = expr ThisProperty, // F.name = expr - Property + Property, + // F.prototype = { ... } + Prototype, } export interface JsFileExtensionInfo { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 69bba78929b..e7bbaf966d6 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1471,18 +1471,6 @@ namespace ts { return getSourceTextOfNodeFromSourceFile(sourceFile, str).charCodeAt(0) === CharacterCodes.doubleQuote; } - /** - * Returns true if the node is a variable declaration whose initializer is a function or class expression. - * This function does not test if the node is in a JavaScript file or not. - */ - export function isDeclarationOfFunctionOrClassExpression(s: Symbol) { - if (s.valueDeclaration && isVariableDeclaration(s.valueDeclaration)) { - return s.valueDeclaration.initializer && - (s.valueDeclaration.initializer.kind === SyntaxKind.FunctionExpression || s.valueDeclaration.initializer.kind === SyntaxKind.ClassExpression); - } - return false; - } - export function getJSInitializerSymbol(symbol: Symbol) { if (!symbol || !symbol.valueDeclaration) { return symbol; @@ -1511,9 +1499,12 @@ namespace ts { const e = skipParentheses(initializer.expression); return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer : undefined; } - if (initializer.kind === SyntaxKind.FunctionExpression || - initializer.kind === SyntaxKind.ClassExpression || - isObjectLiteralExpression(initializer) && initializer.properties.length === 0) { + if (initializer.kind === SyntaxKind.FunctionExpression || initializer.kind === SyntaxKind.ClassExpression) { + return initializer; + } + if (isObjectLiteralExpression(initializer) && + (initializer.properties.length === 0 || + isBinaryExpression(initializer.parent) && isPropertyAccessExpression(initializer.parent.left) && initializer.parent.left.name.escapedText === "prototype")) { return initializer; } } @@ -1576,6 +1567,9 @@ namespace ts { return SpecialPropertyAssignmentKind.None; } const lhs = expr.left; + if (lhs.expression.kind === SyntaxKind.ThisKeyword) { + return SpecialPropertyAssignmentKind.ThisProperty; + } if (isIdentifier(lhs.expression)) { if (lhs.expression.escapedText === "exports") { // exports.name = expr @@ -1585,28 +1579,27 @@ namespace ts { // module.exports = expr return SpecialPropertyAssignmentKind.ModuleExports; } - else { - // F.x = expr - return SpecialPropertyAssignmentKind.Property; + } + if (isEntityNameExpression(lhs.expression)) { + if (lhs.name.escapedText === "prototype" && isObjectLiteralExpression(expr.right)) { + // F.prototype = { ... } + return SpecialPropertyAssignmentKind.Prototype; } - } - else if (lhs.expression.kind === SyntaxKind.ThisKeyword) { - return SpecialPropertyAssignmentKind.ThisProperty; - } - else if (isPropertyAccessExpression(lhs.expression)) { - // chained dot, e.g. x.y.z = expr; this var is the 'x.y' part - if (isIdentifier(lhs.expression.expression)) { - // module.exports.name = expr - if (lhs.expression.expression.escapedText === "module" && lhs.expression.name.escapedText === "exports") { + else if (isPropertyAccessExpression(lhs.expression)) { + // chained dot, e.g. x.y.z = expr; this var is the 'x.y' part + if (isIdentifier(lhs.expression.expression) && + lhs.expression.expression.escapedText === "module" && + lhs.expression.name.escapedText === "exports") { + // module.exports.name = expr return SpecialPropertyAssignmentKind.ExportsProperty; } if (lhs.expression.name.escapedText === "prototype") { + // F.G....prototype.x = expr return SpecialPropertyAssignmentKind.PrototypeProperty; } } - if (isEntityNameExpression(lhs.expression)) { - return SpecialPropertyAssignmentKind.Property; - } + // F.G...x = expr + return SpecialPropertyAssignmentKind.Property; } return SpecialPropertyAssignmentKind.None; diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index cdc7b2b1864..dd7f4175b71 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -275,6 +275,7 @@ namespace ts.NavigationBar { case SpecialPropertyAssignmentKind.ExportsProperty: case SpecialPropertyAssignmentKind.ModuleExports: case SpecialPropertyAssignmentKind.PrototypeProperty: + case SpecialPropertyAssignmentKind.Prototype: addNodeWithRecursiveChild(node, (node as BinaryExpression).right); break; case SpecialPropertyAssignmentKind.ThisProperty: diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index ddb13c3e04c..7f5ea7c68d9 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -16,8 +16,9 @@ namespace ts.refactor.convertFunctionToES6Class { return undefined; } - if (isDeclarationOfFunctionOrClassExpression(symbol)) { - symbol = (symbol.valueDeclaration as VariableDeclaration).initializer.symbol; + const initializer = getDeclaredJavascriptInitializer(symbol.valueDeclaration); + if (initializer) { + symbol = initializer.symbol; } if ((symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) { @@ -264,4 +265,4 @@ namespace ts.refactor.convertFunctionToES6Class { const token = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); return checker.getSymbolAtLocation(token); } -} \ No newline at end of file +} diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 263ac0f4c3b..51772b48441 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -370,6 +370,8 @@ namespace ts { case SpecialPropertyAssignmentKind.Property: // static method / property return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; + case SpecialPropertyAssignmentKind.Prototype: + return ScriptElementKind.localClassElement; default: { assertTypeIsNever(kind); return ScriptElementKind.unknown; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 86a33c179a3..e136d0ac86f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1956,28 +1956,28 @@ declare namespace ts { JSContainer = 67108864, Enum = 384, Variable = 3, - Value = 107455, - Type = 793064, + Value = 67216319, + Type = 67901928, Namespace = 1920, Module = 1536, Accessor = 98304, - FunctionScopedVariableExcludes = 107454, - BlockScopedVariableExcludes = 107455, - ParameterExcludes = 107455, + FunctionScopedVariableExcludes = 67216318, + BlockScopedVariableExcludes = 67216319, + ParameterExcludes = 67216319, PropertyExcludes = 0, - EnumMemberExcludes = 900095, - FunctionExcludes = 106927, - ClassExcludes = 899519, - InterfaceExcludes = 792968, - RegularEnumExcludes = 899327, - ConstEnumExcludes = 899967, - ValueModuleExcludes = 106639, + EnumMemberExcludes = 68008959, + FunctionExcludes = 67215791, + ClassExcludes = 68008383, + InterfaceExcludes = 67901832, + RegularEnumExcludes = 68008191, + ConstEnumExcludes = 68008831, + ValueModuleExcludes = 67215503, NamespaceModuleExcludes = 0, - MethodExcludes = 99263, - GetAccessorExcludes = 41919, - SetAccessorExcludes = 74687, - TypeParameterExcludes = 530920, - TypeAliasExcludes = 793064, + MethodExcludes = 67208127, + GetAccessorExcludes = 67150783, + SetAccessorExcludes = 67183551, + TypeParameterExcludes = 67639784, + TypeAliasExcludes = 67901928, AliasExcludes = 2097152, ModuleMember = 2623475, ExportHasLocal = 944, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1c3c13f48b0..577b4680f36 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1956,28 +1956,28 @@ declare namespace ts { JSContainer = 67108864, Enum = 384, Variable = 3, - Value = 107455, - Type = 793064, + Value = 67216319, + Type = 67901928, Namespace = 1920, Module = 1536, Accessor = 98304, - FunctionScopedVariableExcludes = 107454, - BlockScopedVariableExcludes = 107455, - ParameterExcludes = 107455, + FunctionScopedVariableExcludes = 67216318, + BlockScopedVariableExcludes = 67216319, + ParameterExcludes = 67216319, PropertyExcludes = 0, - EnumMemberExcludes = 900095, - FunctionExcludes = 106927, - ClassExcludes = 899519, - InterfaceExcludes = 792968, - RegularEnumExcludes = 899327, - ConstEnumExcludes = 899967, - ValueModuleExcludes = 106639, + EnumMemberExcludes = 68008959, + FunctionExcludes = 67215791, + ClassExcludes = 68008383, + InterfaceExcludes = 67901832, + RegularEnumExcludes = 68008191, + ConstEnumExcludes = 68008831, + ValueModuleExcludes = 67215503, NamespaceModuleExcludes = 0, - MethodExcludes = 99263, - GetAccessorExcludes = 41919, - SetAccessorExcludes = 74687, - TypeParameterExcludes = 530920, - TypeAliasExcludes = 793064, + MethodExcludes = 67208127, + GetAccessorExcludes = 67150783, + SetAccessorExcludes = 67183551, + TypeParameterExcludes = 67639784, + TypeAliasExcludes = 67901928, AliasExcludes = 2097152, ModuleMember = 2623475, ExportHasLocal = 944, diff --git a/tests/baselines/reference/typeFromPropertyAssignment11.symbols b/tests/baselines/reference/typeFromPropertyAssignment11.symbols new file mode 100644 index 00000000000..93d79e2de1c --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment11.symbols @@ -0,0 +1,52 @@ +=== tests/cases/conformance/salsa/module.js === +var Inner = function() {} +>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25)) + +Inner.prototype = { +>Inner.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) + + m() { }, +>m : Symbol(m, Decl(module.js, 1, 19)) + + i: 1 +>i : Symbol(i, Decl(module.js, 2, 12)) +} +// incremental assignments still work +Inner.prototype.j = 2 +>Inner.prototype : Symbol(Inner.j, Decl(module.js, 4, 1)) +>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>j : Symbol(Inner.j, Decl(module.js, 4, 1)) + +/** @type {string} */ +Inner.prototype.k; +>Inner.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) + +var inner = new Inner() +>inner : Symbol(inner, Decl(module.js, 9, 3)) +>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25)) + +inner.m() +>inner.m : Symbol(m, Decl(module.js, 1, 19)) +>inner : Symbol(inner, Decl(module.js, 9, 3)) +>m : Symbol(m, Decl(module.js, 1, 19)) + +inner.i +>inner.i : Symbol(i, Decl(module.js, 2, 12)) +>inner : Symbol(inner, Decl(module.js, 9, 3)) +>i : Symbol(i, Decl(module.js, 2, 12)) + +inner.j +>inner.j : Symbol(Inner.j, Decl(module.js, 4, 1)) +>inner : Symbol(inner, Decl(module.js, 9, 3)) +>j : Symbol(Inner.j, Decl(module.js, 4, 1)) + +inner.k +>inner.k : Symbol(Inner.k, Decl(module.js, 6, 21)) +>inner : Symbol(inner, Decl(module.js, 9, 3)) +>k : Symbol(Inner.k, Decl(module.js, 6, 21)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment11.types b/tests/baselines/reference/typeFromPropertyAssignment11.types new file mode 100644 index 00000000000..c0ad8c49ca0 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment11.types @@ -0,0 +1,63 @@ +=== tests/cases/conformance/salsa/module.js === +var Inner = function() {} +>Inner : () => void +>function() {} : () => void + +Inner.prototype = { +>Inner.prototype = { m() { }, i: 1} : { [x: string]: any; m(): void; i: number; } +>Inner.prototype : any +>Inner : () => void +>prototype : any +>{ m() { }, i: 1} : { [x: string]: any; m(): void; i: number; } + + m() { }, +>m : () => void + + i: 1 +>i : number +>1 : 1 +} +// incremental assignments still work +Inner.prototype.j = 2 +>Inner.prototype.j = 2 : 2 +>Inner.prototype.j : any +>Inner.prototype : any +>Inner : () => void +>prototype : any +>j : any +>2 : 2 + +/** @type {string} */ +Inner.prototype.k; +>Inner.prototype.k : any +>Inner.prototype : any +>Inner : () => void +>prototype : any +>k : any + +var inner = new Inner() +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>new Inner() : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>Inner : () => void + +inner.m() +>inner.m() : void +>inner.m : () => void +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>m : () => void + +inner.i +>inner.i : number +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>i : number + +inner.j +>inner.j : number +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>j : number + +inner.k +>inner.k : string +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>k : string + diff --git a/tests/baselines/reference/typeFromPropertyAssignment12.symbols b/tests/baselines/reference/typeFromPropertyAssignment12.symbols index 139c9c1b4d6..3f5a322078e 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment12.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment12.symbols @@ -1,34 +1,35 @@ === tests/cases/conformance/salsa/module.js === var Outer = function(element, config) {}; ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 41)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(usage.js, 0, 0)) >element : Symbol(element, Decl(module.js, 0, 21)) >config : Symbol(config, Decl(module.js, 0, 29)) +=== tests/cases/conformance/salsa/usage.js === /** @constructor */ Outer.Pos = function (line, ch) {}; ->Outer.Pos : Symbol(Outer.Pos, Decl(module.js, 0, 41)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 41)) ->Pos : Symbol(Outer.Pos, Decl(module.js, 0, 41)) ->line : Symbol(line, Decl(module.js, 2, 22)) ->ch : Symbol(ch, Decl(module.js, 2, 27)) +>Outer.Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(usage.js, 0, 0)) +>Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0)) +>line : Symbol(line, Decl(usage.js, 1, 22)) +>ch : Symbol(ch, Decl(usage.js, 1, 27)) /** @type {number} */ Outer.Pos.prototype.line; >Outer.Pos.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) ->Outer.Pos : Symbol(Outer.Pos, Decl(module.js, 0, 41)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 41)) ->Pos : Symbol(Outer.Pos, Decl(module.js, 0, 41)) +>Outer.Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(usage.js, 0, 0)) +>Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0)) >prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) var pos = new Outer.Pos(1, 'x'); ->pos : Symbol(pos, Decl(module.js, 5, 3)) ->Outer.Pos : Symbol(Outer.Pos, Decl(module.js, 0, 41)) ->Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 41)) ->Pos : Symbol(Outer.Pos, Decl(module.js, 0, 41)) +>pos : Symbol(pos, Decl(usage.js, 4, 3)) +>Outer.Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(usage.js, 0, 0)) +>Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0)) pos.line; ->pos.line : Symbol((Anonymous function).line, Decl(module.js, 2, 35)) ->pos : Symbol(pos, Decl(module.js, 5, 3)) ->line : Symbol((Anonymous function).line, Decl(module.js, 2, 35)) +>pos.line : Symbol((Anonymous function).line, Decl(usage.js, 1, 35)) +>pos : Symbol(pos, Decl(usage.js, 4, 3)) +>line : Symbol((Anonymous function).line, Decl(usage.js, 1, 35)) diff --git a/tests/baselines/reference/typeFromPropertyAssignment12.types b/tests/baselines/reference/typeFromPropertyAssignment12.types index 16bcd17e38f..77c8545a7ed 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment12.types +++ b/tests/baselines/reference/typeFromPropertyAssignment12.types @@ -1,15 +1,16 @@ === tests/cases/conformance/salsa/module.js === var Outer = function(element, config) {}; ->Outer : { (element: any, config: any): void; Pos: (line: any, ch: any) => void; } ->function(element, config) {} : { (element: any, config: any): void; Pos: (line: any, ch: any) => void; } +>Outer : typeof Outer +>function(element, config) {} : typeof Outer >element : any >config : any +=== tests/cases/conformance/salsa/usage.js === /** @constructor */ Outer.Pos = function (line, ch) {}; >Outer.Pos = function (line, ch) {} : (line: any, ch: any) => void >Outer.Pos : (line: any, ch: any) => void ->Outer : { (element: any, config: any): void; Pos: (line: any, ch: any) => void; } +>Outer : typeof Outer >Pos : (line: any, ch: any) => void >function (line, ch) {} : (line: any, ch: any) => void >line : any @@ -20,7 +21,7 @@ Outer.Pos.prototype.line; >Outer.Pos.prototype.line : any >Outer.Pos.prototype : any >Outer.Pos : (line: any, ch: any) => void ->Outer : { (element: any, config: any): void; Pos: (line: any, ch: any) => void; } +>Outer : typeof Outer >Pos : (line: any, ch: any) => void >prototype : any >line : any @@ -29,7 +30,7 @@ var pos = new Outer.Pos(1, 'x'); >pos : { line: number; } >new Outer.Pos(1, 'x') : { line: number; } >Outer.Pos : (line: any, ch: any) => void ->Outer : { (element: any, config: any): void; Pos: (line: any, ch: any) => void; } +>Outer : typeof Outer >Pos : (line: any, ch: any) => void >1 : 1 >'x' : "x" diff --git a/tests/baselines/reference/typeFromPropertyAssignment13.symbols b/tests/baselines/reference/typeFromPropertyAssignment13.symbols new file mode 100644 index 00000000000..f6d0b4bd9d3 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment13.symbols @@ -0,0 +1,65 @@ +=== tests/cases/conformance/salsa/module.js === +var Outer = {} +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27)) + +Outer.Inner = function() {} +>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27)) +>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) + +Outer.Inner.prototype = { +>Outer.Inner.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27)) +>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) + + m() { }, +>m : Symbol(m, Decl(module.js, 2, 25)) + + i: 1 +>i : Symbol(i, Decl(module.js, 3, 12)) +} +// incremental assignments still work +Outer.Inner.prototype.j = 2 +>Outer.Inner.prototype : Symbol((Anonymous function).j, Decl(module.js, 5, 1)) +>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27)) +>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>j : Symbol((Anonymous function).j, Decl(module.js, 5, 1)) + +/** @type {string} */ +Outer.Inner.prototype.k; +>Outer.Inner.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27)) +>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) + +var inner = new Outer.Inner() +>inner : Symbol(inner, Decl(module.js, 10, 3)) +>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) +>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27)) +>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6)) + +inner.m() +>inner.m : Symbol(m, Decl(module.js, 2, 25)) +>inner : Symbol(inner, Decl(module.js, 10, 3)) +>m : Symbol(m, Decl(module.js, 2, 25)) + +inner.i +>inner.i : Symbol(i, Decl(module.js, 3, 12)) +>inner : Symbol(inner, Decl(module.js, 10, 3)) +>i : Symbol(i, Decl(module.js, 3, 12)) + +inner.j +>inner.j : Symbol((Anonymous function).j, Decl(module.js, 5, 1)) +>inner : Symbol(inner, Decl(module.js, 10, 3)) +>j : Symbol((Anonymous function).j, Decl(module.js, 5, 1)) + +inner.k +>inner.k : Symbol((Anonymous function).k, Decl(module.js, 7, 27)) +>inner : Symbol(inner, Decl(module.js, 10, 3)) +>k : Symbol((Anonymous function).k, Decl(module.js, 7, 27)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment13.types b/tests/baselines/reference/typeFromPropertyAssignment13.types new file mode 100644 index 00000000000..ef0caf5c849 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment13.types @@ -0,0 +1,78 @@ +=== tests/cases/conformance/salsa/module.js === +var Outer = {} +>Outer : { [x: string]: any; Inner: () => void; } +>{} : { [x: string]: any; Inner: () => void; } + +Outer.Inner = function() {} +>Outer.Inner = function() {} : () => void +>Outer.Inner : () => void +>Outer : { [x: string]: any; Inner: () => void; } +>Inner : () => void +>function() {} : () => void + +Outer.Inner.prototype = { +>Outer.Inner.prototype = { m() { }, i: 1} : { [x: string]: any; m(): void; i: number; } +>Outer.Inner.prototype : any +>Outer.Inner : () => void +>Outer : { [x: string]: any; Inner: () => void; } +>Inner : () => void +>prototype : any +>{ m() { }, i: 1} : { [x: string]: any; m(): void; i: number; } + + m() { }, +>m : () => void + + i: 1 +>i : number +>1 : 1 +} +// incremental assignments still work +Outer.Inner.prototype.j = 2 +>Outer.Inner.prototype.j = 2 : 2 +>Outer.Inner.prototype.j : any +>Outer.Inner.prototype : any +>Outer.Inner : () => void +>Outer : { [x: string]: any; Inner: () => void; } +>Inner : () => void +>prototype : any +>j : any +>2 : 2 + +/** @type {string} */ +Outer.Inner.prototype.k; +>Outer.Inner.prototype.k : any +>Outer.Inner.prototype : any +>Outer.Inner : () => void +>Outer : { [x: string]: any; Inner: () => void; } +>Inner : () => void +>prototype : any +>k : any + +var inner = new Outer.Inner() +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>new Outer.Inner() : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>Outer.Inner : () => void +>Outer : { [x: string]: any; Inner: () => void; } +>Inner : () => void + +inner.m() +>inner.m() : void +>inner.m : () => void +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>m : () => void + +inner.i +>inner.i : number +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>i : number + +inner.j +>inner.j : number +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>j : number + +inner.k +>inner.k : string +>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; } +>k : string + diff --git a/tests/baselines/reference/typeFromPropertyAssignment14.symbols b/tests/baselines/reference/typeFromPropertyAssignment14.symbols new file mode 100644 index 00000000000..3f5035e24ad --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment14.symbols @@ -0,0 +1,57 @@ +=== tests/cases/conformance/salsa/def.js === +var Outer = {}; +>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(work.js, 0, 0), Decl(work.js, 0, 28)) + +=== tests/cases/conformance/salsa/work.js === +Outer.Inner = function () {} +>Outer.Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6)) +>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(work.js, 0, 0), Decl(work.js, 0, 28)) +>Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6)) + +Outer.Inner.prototype = { +>Outer.Inner.prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --)) +>Outer.Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6)) +>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(work.js, 0, 0), Decl(work.js, 0, 28)) +>Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6)) +>prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --)) + + x: 1, +>x : Symbol(x, Decl(work.js, 1, 25)) + + m() { } +>m : Symbol(m, Decl(work.js, 2, 9)) +} + +=== tests/cases/conformance/salsa/use.js === +/** @type {Outer.Inner} */ +var inner +>inner : Symbol(inner, Decl(use.js, 1, 3)) + +inner.x +>inner.x : Symbol(x, Decl(work.js, 1, 25)) +>inner : Symbol(inner, Decl(use.js, 1, 3)) +>x : Symbol(x, Decl(work.js, 1, 25)) + +inner.m() +>inner.m : Symbol(m, Decl(work.js, 2, 9)) +>inner : Symbol(inner, Decl(use.js, 1, 3)) +>m : Symbol(m, Decl(work.js, 2, 9)) + +var inno = new Outer.Inner() +>inno : Symbol(inno, Decl(use.js, 4, 3)) +>Outer.Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6)) +>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(work.js, 0, 0), Decl(work.js, 0, 28)) +>Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6)) + +inno.x +>inno.x : Symbol(x, Decl(work.js, 1, 25)) +>inno : Symbol(inno, Decl(use.js, 4, 3)) +>x : Symbol(x, Decl(work.js, 1, 25)) + +inno.m() +>inno.m : Symbol(m, Decl(work.js, 2, 9)) +>inno : Symbol(inno, Decl(use.js, 4, 3)) +>m : Symbol(m, Decl(work.js, 2, 9)) + + + diff --git a/tests/baselines/reference/typeFromPropertyAssignment14.types b/tests/baselines/reference/typeFromPropertyAssignment14.types new file mode 100644 index 00000000000..10a3fa00e35 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment14.types @@ -0,0 +1,66 @@ +=== tests/cases/conformance/salsa/def.js === +var Outer = {}; +>Outer : typeof Outer +>{} : typeof Outer + +=== tests/cases/conformance/salsa/work.js === +Outer.Inner = function () {} +>Outer.Inner = function () {} : () => void +>Outer.Inner : () => void +>Outer : typeof Outer +>Inner : () => void +>function () {} : () => void + +Outer.Inner.prototype = { +>Outer.Inner.prototype = { x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } +>Outer.Inner.prototype : any +>Outer.Inner : () => void +>Outer : typeof Outer +>Inner : () => void +>prototype : any +>{ x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } + + x: 1, +>x : number +>1 : 1 + + m() { } +>m : () => void +} + +=== tests/cases/conformance/salsa/use.js === +/** @type {Outer.Inner} */ +var inner +>inner : { [x: string]: any; x: number; m(): void; } + +inner.x +>inner.x : number +>inner : { [x: string]: any; x: number; m(): void; } +>x : number + +inner.m() +>inner.m() : void +>inner.m : () => void +>inner : { [x: string]: any; x: number; m(): void; } +>m : () => void + +var inno = new Outer.Inner() +>inno : { [x: string]: any; x: number; m(): void; } +>new Outer.Inner() : { [x: string]: any; x: number; m(): void; } +>Outer.Inner : () => void +>Outer : typeof Outer +>Inner : () => void + +inno.x +>inno.x : number +>inno : { [x: string]: any; x: number; m(): void; } +>x : number + +inno.m() +>inno.m() : void +>inno.m : () => void +>inno : { [x: string]: any; x: number; m(): void; } +>m : () => void + + + diff --git a/tests/baselines/reference/typeFromPropertyAssignment15.symbols b/tests/baselines/reference/typeFromPropertyAssignment15.symbols new file mode 100644 index 00000000000..21db92c0b9e --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment15.symbols @@ -0,0 +1,49 @@ +=== tests/cases/conformance/salsa/a.js === +var Outer = {}; +>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15)) + +Outer.Inner = class { +>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15)) +>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15)) +>Inner : Symbol(Inner, Decl(a.js, 0, 15)) + + constructor() { + this.x = 1 +>this.x : Symbol((Anonymous class).x, Decl(a.js, 3, 19)) +>this : Symbol((Anonymous class), Decl(a.js, 2, 13)) +>x : Symbol((Anonymous class).x, Decl(a.js, 3, 19)) + } + m() { } +>m : Symbol((Anonymous class).m, Decl(a.js, 5, 5)) +} + +/** @type {Outer.Inner} */ +var inner +>inner : Symbol(inner, Decl(a.js, 10, 3)) + +inner.x +>inner.x : Symbol((Anonymous class).x, Decl(a.js, 3, 19)) +>inner : Symbol(inner, Decl(a.js, 10, 3)) +>x : Symbol((Anonymous class).x, Decl(a.js, 3, 19)) + +inner.m() +>inner.m : Symbol((Anonymous class).m, Decl(a.js, 5, 5)) +>inner : Symbol(inner, Decl(a.js, 10, 3)) +>m : Symbol((Anonymous class).m, Decl(a.js, 5, 5)) + +var inno = new Outer.Inner() +>inno : Symbol(inno, Decl(a.js, 13, 3)) +>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15)) +>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15)) +>Inner : Symbol(Inner, Decl(a.js, 0, 15)) + +inno.x +>inno.x : Symbol((Anonymous class).x, Decl(a.js, 3, 19)) +>inno : Symbol(inno, Decl(a.js, 13, 3)) +>x : Symbol((Anonymous class).x, Decl(a.js, 3, 19)) + +inno.m() +>inno.m : Symbol((Anonymous class).m, Decl(a.js, 5, 5)) +>inno : Symbol(inno, Decl(a.js, 13, 3)) +>m : Symbol((Anonymous class).m, Decl(a.js, 5, 5)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment15.types b/tests/baselines/reference/typeFromPropertyAssignment15.types new file mode 100644 index 00000000000..e875dd9e970 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment15.types @@ -0,0 +1,57 @@ +=== tests/cases/conformance/salsa/a.js === +var Outer = {}; +>Outer : { [x: string]: any; Inner: typeof (Anonymous class); } +>{} : { [x: string]: any; Inner: typeof (Anonymous class); } + +Outer.Inner = class { +>Outer.Inner = class { constructor() { this.x = 1 } m() { }} : typeof (Anonymous class) +>Outer.Inner : typeof (Anonymous class) +>Outer : { [x: string]: any; Inner: typeof (Anonymous class); } +>Inner : typeof (Anonymous class) +>class { constructor() { this.x = 1 } m() { }} : typeof (Anonymous class) + + constructor() { + this.x = 1 +>this.x = 1 : 1 +>this.x : number +>this : this +>x : number +>1 : 1 + } + m() { } +>m : () => void +} + +/** @type {Outer.Inner} */ +var inner +>inner : (Anonymous class) + +inner.x +>inner.x : number +>inner : (Anonymous class) +>x : number + +inner.m() +>inner.m() : void +>inner.m : () => void +>inner : (Anonymous class) +>m : () => void + +var inno = new Outer.Inner() +>inno : (Anonymous class) +>new Outer.Inner() : (Anonymous class) +>Outer.Inner : typeof (Anonymous class) +>Outer : { [x: string]: any; Inner: typeof (Anonymous class); } +>Inner : typeof (Anonymous class) + +inno.x +>inno.x : number +>inno : (Anonymous class) +>x : number + +inno.m() +>inno.m() : void +>inno.m : () => void +>inno : (Anonymous class) +>m : () => void + diff --git a/tests/baselines/reference/typeFromPropertyAssignment16.symbols b/tests/baselines/reference/typeFromPropertyAssignment16.symbols new file mode 100644 index 00000000000..e7fbaed599c --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment16.symbols @@ -0,0 +1,53 @@ +=== tests/cases/conformance/salsa/a.js === +var Outer = {}; +>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15), Decl(a.js, 2, 28)) + +Outer.Inner = function () {} +>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6)) +>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15), Decl(a.js, 2, 28)) +>Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6)) + +Outer.Inner.prototype = { +>Outer.Inner.prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --)) +>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6)) +>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15), Decl(a.js, 2, 28)) +>Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6)) +>prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --)) + + x: 1, +>x : Symbol(x, Decl(a.js, 3, 25)) + + m() { } +>m : Symbol(m, Decl(a.js, 4, 9)) +} + +/** @type {Outer.Inner} */ +var inner +>inner : Symbol(inner, Decl(a.js, 9, 3)) + +inner.x +>inner.x : Symbol(x, Decl(a.js, 3, 25)) +>inner : Symbol(inner, Decl(a.js, 9, 3)) +>x : Symbol(x, Decl(a.js, 3, 25)) + +inner.m() +>inner.m : Symbol(m, Decl(a.js, 4, 9)) +>inner : Symbol(inner, Decl(a.js, 9, 3)) +>m : Symbol(m, Decl(a.js, 4, 9)) + +var inno = new Outer.Inner() +>inno : Symbol(inno, Decl(a.js, 12, 3)) +>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6)) +>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15), Decl(a.js, 2, 28)) +>Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6)) + +inno.x +>inno.x : Symbol(x, Decl(a.js, 3, 25)) +>inno : Symbol(inno, Decl(a.js, 12, 3)) +>x : Symbol(x, Decl(a.js, 3, 25)) + +inno.m() +>inno.m : Symbol(m, Decl(a.js, 4, 9)) +>inno : Symbol(inno, Decl(a.js, 12, 3)) +>m : Symbol(m, Decl(a.js, 4, 9)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment16.types b/tests/baselines/reference/typeFromPropertyAssignment16.types new file mode 100644 index 00000000000..a1167f3da6e --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment16.types @@ -0,0 +1,62 @@ +=== tests/cases/conformance/salsa/a.js === +var Outer = {}; +>Outer : { [x: string]: any; Inner: () => void; } +>{} : { [x: string]: any; Inner: () => void; } + +Outer.Inner = function () {} +>Outer.Inner = function () {} : () => void +>Outer.Inner : () => void +>Outer : { [x: string]: any; Inner: () => void; } +>Inner : () => void +>function () {} : () => void + +Outer.Inner.prototype = { +>Outer.Inner.prototype = { x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } +>Outer.Inner.prototype : any +>Outer.Inner : () => void +>Outer : { [x: string]: any; Inner: () => void; } +>Inner : () => void +>prototype : any +>{ x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } + + x: 1, +>x : number +>1 : 1 + + m() { } +>m : () => void +} + +/** @type {Outer.Inner} */ +var inner +>inner : { [x: string]: any; x: number; m(): void; } + +inner.x +>inner.x : number +>inner : { [x: string]: any; x: number; m(): void; } +>x : number + +inner.m() +>inner.m() : void +>inner.m : () => void +>inner : { [x: string]: any; x: number; m(): void; } +>m : () => void + +var inno = new Outer.Inner() +>inno : { [x: string]: any; x: number; m(): void; } +>new Outer.Inner() : { [x: string]: any; x: number; m(): void; } +>Outer.Inner : () => void +>Outer : { [x: string]: any; Inner: () => void; } +>Inner : () => void + +inno.x +>inno.x : number +>inno : { [x: string]: any; x: number; m(): void; } +>x : number + +inno.m() +>inno.m() : void +>inno.m : () => void +>inno : { [x: string]: any; x: number; m(): void; } +>m : () => void + diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment11.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment11.ts new file mode 100644 index 00000000000..308da40f3c4 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment11.ts @@ -0,0 +1,19 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @target: es6 +// @Filename: module.js +var Inner = function() {} +Inner.prototype = { + m() { }, + i: 1 +} +// incremental assignments still work +Inner.prototype.j = 2 +/** @type {string} */ +Inner.prototype.k; +var inner = new Inner() +inner.m() +inner.i +inner.j +inner.k diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment12.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment12.ts index f8833ced4e8..9724da71982 100644 --- a/tests/cases/conformance/salsa/typeFromPropertyAssignment12.ts +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment12.ts @@ -4,6 +4,7 @@ // @target: es6 // @Filename: module.js var Outer = function(element, config) {}; +// @Filename: usage.js /** @constructor */ Outer.Pos = function (line, ch) {}; /** @type {number} */ diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment13.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment13.ts new file mode 100644 index 00000000000..201560d5055 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment13.ts @@ -0,0 +1,20 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @target: es6 +// @Filename: module.js +var Outer = {} +Outer.Inner = function() {} +Outer.Inner.prototype = { + m() { }, + i: 1 +} +// incremental assignments still work +Outer.Inner.prototype.j = 2 +/** @type {string} */ +Outer.Inner.prototype.k; +var inner = new Outer.Inner() +inner.m() +inner.i +inner.j +inner.k diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment14.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment14.ts new file mode 100644 index 00000000000..b3aaaf1702b --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment14.ts @@ -0,0 +1,23 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: def.js +var Outer = {}; + +// @Filename: work.js +Outer.Inner = function () {} +Outer.Inner.prototype = { + x: 1, + m() { } +} + +// @Filename: use.js +/** @type {Outer.Inner} */ +var inner +inner.x +inner.m() +var inno = new Outer.Inner() +inno.x +inno.m() + + diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment15.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment15.ts new file mode 100644 index 00000000000..c8099a03395 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment15.ts @@ -0,0 +1,20 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: a.js +var Outer = {}; + +Outer.Inner = class { + constructor() { + this.x = 1 + } + m() { } +} + +/** @type {Outer.Inner} */ +var inner +inner.x +inner.m() +var inno = new Outer.Inner() +inno.x +inno.m() diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment16.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment16.ts new file mode 100644 index 00000000000..534e3bcc4c3 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment16.ts @@ -0,0 +1,19 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: a.js +var Outer = {}; + +Outer.Inner = function () {} +Outer.Inner.prototype = { + x: 1, + m() { } +} + +/** @type {Outer.Inner} */ +var inner +inner.x +inner.m() +var inno = new Outer.Inner() +inno.x +inno.m()