diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8d8666a67abac..502cb39e8fe55 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1887,18 +1887,17 @@ namespace ts { } function bindExportAssignment(node: ExportAssignment | BinaryExpression) { - const boundExpression = node.kind === SyntaxKind.ExportAssignment ? (node).expression : (node).right; if (!container.symbol || !container.symbol.exports) { // Export assignment in some sort of block construct bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)); } - else if (boundExpression.kind === SyntaxKind.Identifier && node.kind === SyntaxKind.ExportAssignment) { - // An export default clause with an identifier exports all meanings of that identifier - declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Alias, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes); - } else { - // An export default clause with an expression exports a value - declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes); + const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) + // An export default clause with an EntityNameExpression exports all meanings of that identifier + ? SymbolFlags.Alias + // An export default clause with any other expression exports a value + : SymbolFlags.Property; + declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c88ab16acd7c7..31f81dfef90d3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -664,7 +664,7 @@ namespace ts { // Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and // the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with // the given name can be found. - function resolveName(location: Node, name: string, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage, nameArg: string | Identifier): Symbol { + function resolveName(location: Node | undefined, name: string, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage, nameArg: string | Identifier): Symbol { let result: Symbol; let lastLocation: Node; let propertyWithInvalidInitializer: Node; @@ -881,7 +881,8 @@ namespace ts { if (!result) { if (nameNotFoundMessage) { - if (!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && + if (!errorLocation || + !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && !checkAndReportErrorForExtendingInterface(errorLocation)) { error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); } @@ -930,7 +931,7 @@ namespace ts { } function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: string, nameArg: string | Identifier): boolean { - if (!errorLocation || (errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(errorLocation)) || isInTypeQuery(errorLocation))) { + if ((errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(errorLocation)) || isInTypeQuery(errorLocation))) { return false; } @@ -968,29 +969,31 @@ namespace ts { function checkAndReportErrorForExtendingInterface(errorLocation: Node): boolean { - let parentClassExpression = errorLocation; - while (parentClassExpression) { - const kind = parentClassExpression.kind; - if (kind === SyntaxKind.Identifier || kind === SyntaxKind.PropertyAccessExpression) { - parentClassExpression = parentClassExpression.parent; - continue; - } - if (kind === SyntaxKind.ExpressionWithTypeArguments) { - break; - } - return false; - } - if (!parentClassExpression) { - return false; - } - const expression = (parentClassExpression).expression; - if (resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) { + const expression = getEntityNameForExtendingInterface(errorLocation); + const isError = !!(expression && resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)); + if (isError) { error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression)); - return true; } - return false; + return isError; + } + /** + * Climbs up parents to an ExpressionWithTypeArguments, and returns its expression, + * but returns undefined if that expression is not an EntityNameExpression. + */ + function getEntityNameForExtendingInterface(node: Node): EntityNameExpression | undefined { + switch (node.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: + return node.parent ? getEntityNameForExtendingInterface(node.parent) : undefined; + case SyntaxKind.ExpressionWithTypeArguments: + Debug.assert(isEntityNameExpression((node).expression)); + return (node).expression; + default: + return undefined; + } } + function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0); // Block-scoped variables cannot be used before their definition @@ -1033,7 +1036,7 @@ namespace ts { } function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration { - return forEach(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined); + return find(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined); } function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration): Symbol { @@ -1168,7 +1171,7 @@ namespace ts { } function getTargetOfExportAssignment(node: ExportAssignment): Symbol { - return resolveEntityName(node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace); + return resolveEntityName(node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace); } function getTargetOfAliasDeclaration(node: Declaration): Symbol { @@ -1278,7 +1281,7 @@ namespace ts { } // Resolves a qualified name and any involved aliases - function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol { + function resolveEntityName(name: EntityNameOrEntityNameExpression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol | undefined { if (nodeIsMissing(name)) { return undefined; } @@ -1293,7 +1296,7 @@ namespace ts { } } else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) { - const left = name.kind === SyntaxKind.QualifiedName ? (name).left : (name).expression; + const left = name.kind === SyntaxKind.QualifiedName ? (name).left : (name).expression; const right = name.kind === SyntaxKind.QualifiedName ? (name).right : (name).name; const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors); @@ -1849,7 +1852,7 @@ namespace ts { } } - function isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult { + function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult { // get symbol of the first identifier of the entityName let meaning: SymbolFlags; if (entityName.parent.kind === SyntaxKind.TypeQuery || isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent)) { @@ -3679,7 +3682,7 @@ namespace ts { const baseTypeNodes = getInterfaceBaseTypeNodes(declaration); if (baseTypeNodes) { for (const node of baseTypeNodes) { - if (isSupportedExpressionWithTypeArguments(node)) { + if (isEntityNameExpression(node.expression)) { const baseSymbol = resolveEntityName(node.expression, SymbolFlags.Type, /*ignoreErrors*/ true); if (!baseSymbol || !(baseSymbol.flags & SymbolFlags.Interface) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) { return false; @@ -5041,7 +5044,7 @@ namespace ts { return getDeclaredTypeOfSymbol(symbol); } - function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): LeftHandSideExpression | EntityName { + function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): EntityNameOrEntityNameExpression | undefined { switch (node.kind) { case SyntaxKind.TypeReference: return (node).typeName; @@ -5050,8 +5053,9 @@ namespace ts { case SyntaxKind.ExpressionWithTypeArguments: // We only support expressions that are simple qualified names. For other // expressions this produces undefined. - if (isSupportedExpressionWithTypeArguments(node)) { - return (node).expression; + const expr = (node).expression; + if (isEntityNameExpression(expr)) { + return expr; } // fall through; @@ -5062,7 +5066,7 @@ namespace ts { function resolveTypeReferenceName( node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, - typeReferenceName: LeftHandSideExpression | EntityName) { + typeReferenceName: EntityNameExpression | EntityName) { if (!typeReferenceName) { return unknownSymbol; @@ -5103,15 +5107,14 @@ namespace ts { const typeReferenceName = getTypeReferenceName(node); symbol = resolveTypeReferenceName(node, typeReferenceName); type = getTypeReferenceType(node, symbol); - - links.resolvedSymbol = symbol; - links.resolvedType = type; } else { // We only support expressions that are simple qualified names. For other expressions this produces undefined. - const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (node).typeName : - isSupportedExpressionWithTypeArguments(node) ? (node).expression : - undefined; + const typeNameOrExpression: EntityNameOrEntityNameExpression = node.kind === SyntaxKind.TypeReference + ? (node).typeName + : isEntityNameExpression((node).expression) + ? (node).expression + : undefined; symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol; type = symbol === unknownSymbol ? unknownType : symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) : @@ -16382,7 +16385,7 @@ namespace ts { const implementedTypeNodes = getClassImplementsHeritageClauseElements(node); if (implementedTypeNodes) { for (const typeRefNode of implementedTypeNodes) { - if (!isSupportedExpressionWithTypeArguments(typeRefNode)) { + if (!isEntityNameExpression(typeRefNode.expression)) { error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments); } checkTypeReferenceNode(typeRefNode); @@ -16624,7 +16627,7 @@ namespace ts { checkObjectTypeForDuplicateDeclarations(node); } forEach(getInterfaceBaseTypeNodes(node), heritageElement => { - if (!isSupportedExpressionWithTypeArguments(heritageElement)) { + if (!isEntityNameExpression(heritageElement.expression)) { error(heritageElement.expression, Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments); } checkTypeReferenceNode(heritageElement); @@ -17089,20 +17092,21 @@ namespace ts { } } - function getFirstIdentifier(node: EntityName | Expression): Identifier { - while (true) { - if (node.kind === SyntaxKind.QualifiedName) { - node = (node).left; - } - else if (node.kind === SyntaxKind.PropertyAccessExpression) { - node = (node).expression; - } - else { - break; - } + function getFirstIdentifier(node: EntityNameOrEntityNameExpression): Identifier { + switch (node.kind) { + case SyntaxKind.Identifier: + return node; + case SyntaxKind.QualifiedName: + do { + node = (node).left; + } while (node.kind !== SyntaxKind.Identifier); + return node; + case SyntaxKind.PropertyAccessExpression: + do { + node = (node).expression; + } while (node.kind !== SyntaxKind.Identifier); + return node; } - Debug.assert(node.kind === SyntaxKind.Identifier); - return node; } function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean { @@ -17801,7 +17805,7 @@ namespace ts { return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined; } - function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol { + function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol | undefined { if (isDeclarationName(entityName)) { return getSymbolOfNode(entityName.parent); } @@ -17820,22 +17824,20 @@ namespace ts { } } - if (entityName.parent.kind === SyntaxKind.ExportAssignment) { - return resolveEntityName(entityName, + if (entityName.parent.kind === SyntaxKind.ExportAssignment && isEntityNameExpression(entityName)) { + return resolveEntityName(entityName, /*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); } - if (entityName.kind !== SyntaxKind.PropertyAccessExpression) { - if (isInRightSideOfImportOrExportAssignment(entityName)) { - // Since we already checked for ExportAssignment, this really could only be an Import - const importEqualsDeclaration = getAncestor(entityName, SyntaxKind.ImportEqualsDeclaration); - Debug.assert(importEqualsDeclaration !== undefined); - return getSymbolOfPartOfRightHandSideOfImportEquals(entityName, importEqualsDeclaration, /*dontResolveAlias*/ true); - } + if (entityName.kind !== SyntaxKind.PropertyAccessExpression && isInRightSideOfImportOrExportAssignment(entityName)) { + // Since we already checked for ExportAssignment, this really could only be an Import + const importEqualsDeclaration = getAncestor(entityName, SyntaxKind.ImportEqualsDeclaration); + Debug.assert(importEqualsDeclaration !== undefined); + return getSymbolOfPartOfRightHandSideOfImportEquals(entityName, importEqualsDeclaration, /*dontResolveAlias*/ true); } if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) { - entityName = entityName.parent; + entityName = entityName.parent; } if (isHeritageClauseElementIdentifier(entityName)) { @@ -18548,7 +18550,7 @@ namespace ts { }; // defined here to avoid outer scope pollution - function getTypeReferenceDirectivesForEntityName(node: EntityName | PropertyAccessExpression): string[] { + function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): string[] { // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 6c87ad82955c3..549410159b035 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -81,7 +81,7 @@ namespace ts { * returns a truthy value, then returns that value. * If no such value is found, the callback is applied to each element of array and undefined is returned. */ - export function forEach(array: T[], callback: (element: T, index: number) => U): U { + export function forEach(array: T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined { if (array) { for (let i = 0, len = array.length; i < len; i++) { const result = callback(array[i], i); @@ -93,6 +93,17 @@ namespace ts { return undefined; } + /** Like `forEach`, but assumes existence of array and fails if no truthy value is found. */ + export function find(array: T[], callback: (element: T, index: number) => U | undefined): U { + for (let i = 0, len = array.length; i < len; i++) { + const result = callback(array[i], i); + if (result) { + return result; + } + } + Debug.fail(); + } + export function contains(array: T[], value: T): boolean { if (array) { for (const v of array) { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index d93a8a0aed027..c93784cd9e0c3 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -441,7 +441,7 @@ namespace ts { } } - function emitEntityName(entityName: EntityName | PropertyAccessExpression) { + function emitEntityName(entityName: EntityNameOrEntityNameExpression) { const visibilityResult = resolver.isEntityNameVisible(entityName, // Aliases can be written asynchronously so use correct enclosing declaration entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration); @@ -452,9 +452,9 @@ namespace ts { } function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { - if (isSupportedExpressionWithTypeArguments(node)) { + if (isEntityNameExpression(node.expression)) { Debug.assert(node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression); - emitEntityName(node.expression); + emitEntityName(node.expression); if (node.typeArguments) { write("<"); emitCommaList(node.typeArguments, emitType); @@ -1019,7 +1019,7 @@ namespace ts { } function emitTypeOfTypeReference(node: ExpressionWithTypeArguments) { - if (isSupportedExpressionWithTypeArguments(node)) { + if (isEntityNameExpression(node.expression)) { emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError); } else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a6e860450c669..11a0fd02848bc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -982,13 +982,19 @@ namespace ts { multiLine?: boolean; } + export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression; + export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression; + // @kind(SyntaxKind.PropertyAccessExpression) export interface PropertyAccessExpression extends MemberExpression, Declaration { expression: LeftHandSideExpression; name: Identifier; } - - export type IdentifierOrPropertyAccess = Identifier | PropertyAccessExpression; + /** Brand for a PropertyAccessExpression which, like a QualifiedName, consists of a sequence of identifiers separated by dots. */ + export interface PropertyAccessEntityNameExpression extends PropertyAccessExpression { + _propertyAccessExpressionLikeQualifiedNameBrand?: any; + expression: EntityNameExpression; + } // @kind(SyntaxKind.ElementAccessExpression) export interface ElementAccessExpression extends MemberExpression { @@ -2031,7 +2037,7 @@ namespace ts { writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult; - isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult; + isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getReferencedValueDeclaration(reference: Identifier): Declaration; @@ -2040,7 +2046,7 @@ namespace ts { moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean; isArgumentsLocalBinding(node: Identifier): boolean; getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile; - getTypeReferenceDirectivesForEntityName(name: EntityName | PropertyAccessExpression): string[]; + getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[]; getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 2cfaf1f5cfbc4..df9f4f952528f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1033,14 +1033,14 @@ namespace ts { && (node).expression.kind === SyntaxKind.SuperKeyword; } - - export function getEntityNameFromTypeNode(node: TypeNode): EntityName | Expression { + export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression { if (node) { switch (node.kind) { case SyntaxKind.TypeReference: return (node).typeName; case SyntaxKind.ExpressionWithTypeArguments: - return (node).expression; + Debug.assert(isEntityNameExpression((node).expression)); + return (node).expression; case SyntaxKind.Identifier: case SyntaxKind.QualifiedName: return (node); @@ -1694,8 +1694,8 @@ namespace ts { // import * as from ... // import { x as } from ... // export { x as } from ... - // export = ... - // export default ... + // export = + // export default export function isAliasSymbolDeclaration(node: Node): boolean { return node.kind === SyntaxKind.ImportEqualsDeclaration || node.kind === SyntaxKind.NamespaceExportDeclaration || @@ -1703,7 +1703,11 @@ namespace ts { node.kind === SyntaxKind.NamespaceImport || node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.ExportSpecifier || - node.kind === SyntaxKind.ExportAssignment && (node).expression.kind === SyntaxKind.Identifier; + node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node); + } + + export function exportAssignmentIsAlias(node: ExportAssignment): boolean { + return isEntityNameExpression(node.expression); } export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration | InterfaceDeclaration) { @@ -2681,22 +2685,9 @@ namespace ts { isClassLike(node.parent.parent); } - // Returns false if this heritage clause element's expression contains something unsupported - // (i.e. not a name or dotted name). - export function isSupportedExpressionWithTypeArguments(node: ExpressionWithTypeArguments): boolean { - return isSupportedExpressionWithTypeArgumentsRest(node.expression); - } - - function isSupportedExpressionWithTypeArgumentsRest(node: Expression): boolean { - if (node.kind === SyntaxKind.Identifier) { - return true; - } - else if (isPropertyAccessExpression(node)) { - return isSupportedExpressionWithTypeArgumentsRest(node.expression); - } - else { - return false; - } + export function isEntityNameExpression(node: Expression): node is EntityNameExpression { + return node.kind === SyntaxKind.Identifier || + node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((node).expression); } export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) { diff --git a/tests/baselines/reference/exportDefaultProperty.js b/tests/baselines/reference/exportDefaultProperty.js new file mode 100644 index 0000000000000..10ba6d6419a60 --- /dev/null +++ b/tests/baselines/reference/exportDefaultProperty.js @@ -0,0 +1,76 @@ +//// [tests/cases/compiler/exportDefaultProperty.ts] //// + +//// [declarations.d.ts] +// This test is just like exportEqualsProperty, but with `export default`. + +declare namespace foo.bar { + export type X = number; + export const X: number; +} + +declare module "foobar" { + export default foo.bar; +} + +declare module "foobarx" { + export default foo.bar.X; +} + +//// [a.ts] +namespace A { + export class B { constructor(b: number) {} } + export namespace B { export const b: number = 0; } +} +export default A.B; + +//// [b.ts] +export default "foo".length; + +//// [index.ts] +/// +import fooBar from "foobar"; +import X = fooBar.X; +import X2 from "foobarx"; +const x: X = X; +const x2: X2 = X2; + +import B from "./a"; +const b: B = new B(B.b); + +import fooLength from "./b"; +fooLength + 1; + + +//// [a.js] +"use strict"; +var A; +(function (A) { + var B = (function () { + function B(b) { + } + return B; + }()); + A.B = B; + var B; + (function (B) { + B.b = 0; + })(B = A.B || (A.B = {})); +})(A || (A = {})); +exports.__esModule = true; +exports["default"] = A.B; +//// [b.js] +"use strict"; +exports.__esModule = true; +exports["default"] = "foo".length; +//// [index.js] +"use strict"; +/// +var foobar_1 = require("foobar"); +var X = foobar_1["default"].X; +var foobarx_1 = require("foobarx"); +var x = X; +var x2 = foobarx_1["default"]; +var a_1 = require("./a"); +var b = new a_1["default"](a_1["default"].b); +var b_1 = require("./b"); +b_1["default"] + 1; diff --git a/tests/baselines/reference/exportDefaultProperty.symbols b/tests/baselines/reference/exportDefaultProperty.symbols new file mode 100644 index 0000000000000..f9edcd154cc05 --- /dev/null +++ b/tests/baselines/reference/exportDefaultProperty.symbols @@ -0,0 +1,92 @@ +=== tests/cases/compiler/index.ts === +/// +import fooBar from "foobar"; +>fooBar : Symbol(fooBar, Decl(index.ts, 1, 6)) + +import X = fooBar.X; +>X : Symbol(X, Decl(index.ts, 1, 28)) +>fooBar : Symbol(fooBar, Decl(index.ts, 1, 6)) +>X : Symbol(fooBar.X, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) + +import X2 from "foobarx"; +>X2 : Symbol(X2, Decl(index.ts, 3, 6)) + +const x: X = X; +>x : Symbol(x, Decl(index.ts, 4, 5)) +>X : Symbol(X, Decl(index.ts, 1, 28)) +>X : Symbol(X, Decl(index.ts, 1, 28)) + +const x2: X2 = X2; +>x2 : Symbol(x2, Decl(index.ts, 5, 5)) +>X2 : Symbol(X2, Decl(index.ts, 3, 6)) +>X2 : Symbol(X2, Decl(index.ts, 3, 6)) + +import B from "./a"; +>B : Symbol(B, Decl(index.ts, 7, 6)) + +const b: B = new B(B.b); +>b : Symbol(b, Decl(index.ts, 8, 5)) +>B : Symbol(B, Decl(index.ts, 7, 6)) +>B : Symbol(B, Decl(index.ts, 7, 6)) +>B.b : Symbol(B.b, Decl(a.ts, 2, 37)) +>B : Symbol(B, Decl(index.ts, 7, 6)) +>b : Symbol(B.b, Decl(a.ts, 2, 37)) + +import fooLength from "./b"; +>fooLength : Symbol(fooLength, Decl(index.ts, 10, 6)) + +fooLength + 1; +>fooLength : Symbol(fooLength, Decl(index.ts, 10, 6)) + +=== tests/cases/compiler/declarations.d.ts === +// This test is just like exportEqualsProperty, but with `export default`. + +declare namespace foo.bar { +>foo : Symbol(foo, Decl(declarations.d.ts, 0, 0)) +>bar : Symbol(bar, Decl(declarations.d.ts, 2, 22)) + + export type X = number; +>X : Symbol(X, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) + + export const X: number; +>X : Symbol(X, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) +} + +declare module "foobar" { + export default foo.bar; +>foo.bar : Symbol(default, Decl(declarations.d.ts, 2, 22)) +>foo : Symbol(foo, Decl(declarations.d.ts, 0, 0)) +>bar : Symbol(default, Decl(declarations.d.ts, 2, 22)) +} + +declare module "foobarx" { + export default foo.bar.X; +>foo.bar.X : Symbol(default, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) +>foo.bar : Symbol(foo.bar, Decl(declarations.d.ts, 2, 22)) +>foo : Symbol(foo, Decl(declarations.d.ts, 0, 0)) +>bar : Symbol(foo.bar, Decl(declarations.d.ts, 2, 22)) +>X : Symbol(default, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) +} + +=== tests/cases/compiler/a.ts === +namespace A { +>A : Symbol(A, Decl(a.ts, 0, 0)) + + export class B { constructor(b: number) {} } +>B : Symbol(B, Decl(a.ts, 0, 13), Decl(a.ts, 1, 48)) +>b : Symbol(b, Decl(a.ts, 1, 33)) + + export namespace B { export const b: number = 0; } +>B : Symbol(B, Decl(a.ts, 0, 13), Decl(a.ts, 1, 48)) +>b : Symbol(b, Decl(a.ts, 2, 37)) +} +export default A.B; +>A.B : Symbol(default, Decl(a.ts, 0, 13), Decl(a.ts, 1, 48)) +>A : Symbol(A, Decl(a.ts, 0, 0)) +>B : Symbol(default, Decl(a.ts, 0, 13), Decl(a.ts, 1, 48)) + +=== tests/cases/compiler/b.ts === +export default "foo".length; +>"foo".length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/exportDefaultProperty.types b/tests/baselines/reference/exportDefaultProperty.types new file mode 100644 index 0000000000000..47cfabfbc165e --- /dev/null +++ b/tests/baselines/reference/exportDefaultProperty.types @@ -0,0 +1,97 @@ +=== tests/cases/compiler/index.ts === +/// +import fooBar from "foobar"; +>fooBar : typeof fooBar + +import X = fooBar.X; +>X : number +>fooBar : typeof fooBar +>X : number + +import X2 from "foobarx"; +>X2 : number + +const x: X = X; +>x : number +>X : number +>X : number + +const x2: X2 = X2; +>x2 : number +>X2 : number +>X2 : number + +import B from "./a"; +>B : typeof B + +const b: B = new B(B.b); +>b : B +>B : B +>new B(B.b) : B +>B : typeof B +>B.b : number +>B : typeof B +>b : number + +import fooLength from "./b"; +>fooLength : number + +fooLength + 1; +>fooLength + 1 : number +>fooLength : number +>1 : number + +=== tests/cases/compiler/declarations.d.ts === +// This test is just like exportEqualsProperty, but with `export default`. + +declare namespace foo.bar { +>foo : typeof foo +>bar : typeof bar + + export type X = number; +>X : number + + export const X: number; +>X : number +} + +declare module "foobar" { + export default foo.bar; +>foo.bar : typeof default +>foo : typeof foo +>bar : typeof default +} + +declare module "foobarx" { + export default foo.bar.X; +>foo.bar.X : number +>foo.bar : typeof foo.bar +>foo : typeof foo +>bar : typeof foo.bar +>X : number +} + +=== tests/cases/compiler/a.ts === +namespace A { +>A : typeof A + + export class B { constructor(b: number) {} } +>B : B +>b : number + + export namespace B { export const b: number = 0; } +>B : typeof B +>b : number +>0 : number +} +export default A.B; +>A.B : typeof default +>A : typeof A +>B : typeof default + +=== tests/cases/compiler/b.ts === +export default "foo".length; +>"foo".length : number +>"foo" : string +>length : number + diff --git a/tests/baselines/reference/exportEqualsProperty.js b/tests/baselines/reference/exportEqualsProperty.js new file mode 100644 index 0000000000000..2fd8a8c851178 --- /dev/null +++ b/tests/baselines/reference/exportEqualsProperty.js @@ -0,0 +1,72 @@ +//// [tests/cases/compiler/exportEqualsProperty.ts] //// + +//// [declarations.d.ts] +// This test is just like exportDefaultProperty, but with `export =`. + +declare namespace foo.bar { + export type X = number; + export const X: number; +} + +declare module "foobar" { + export = foo.bar; +} + +declare module "foobarx" { + export = foo.bar.X; +} + +//// [a.ts] +namespace A { + export class B { constructor(b: number) {} } + export namespace B { export const b: number = 0; } +} +export = A.B; + +//// [b.ts] +export = "foo".length; + +//// [index.ts] +/// +import { X } from "foobar"; +import X2 = require("foobarx"); +const x: X = X; +const x2: X2 = X2; + +import B = require("./a"); +const b: B = new B(B.b); + +import fooLength = require("./b"); +fooLength + 1; + + +//// [a.js] +"use strict"; +var A; +(function (A) { + var B = (function () { + function B(b) { + } + return B; + }()); + A.B = B; + var B; + (function (B) { + B.b = 0; + })(B = A.B || (A.B = {})); +})(A || (A = {})); +module.exports = A.B; +//// [b.js] +"use strict"; +module.exports = "foo".length; +//// [index.js] +"use strict"; +/// +var foobar_1 = require("foobar"); +var X2 = require("foobarx"); +var x = foobar_1.X; +var x2 = X2; +var B = require("./a"); +var b = new B(B.b); +var fooLength = require("./b"); +fooLength + 1; diff --git a/tests/baselines/reference/exportEqualsProperty.symbols b/tests/baselines/reference/exportEqualsProperty.symbols new file mode 100644 index 0000000000000..43c9ed3251868 --- /dev/null +++ b/tests/baselines/reference/exportEqualsProperty.symbols @@ -0,0 +1,87 @@ +=== tests/cases/compiler/index.ts === +/// +import { X } from "foobar"; +>X : Symbol(X, Decl(index.ts, 1, 8)) + +import X2 = require("foobarx"); +>X2 : Symbol(X2, Decl(index.ts, 1, 27)) + +const x: X = X; +>x : Symbol(x, Decl(index.ts, 3, 5)) +>X : Symbol(X, Decl(index.ts, 1, 8)) +>X : Symbol(X, Decl(index.ts, 1, 8)) + +const x2: X2 = X2; +>x2 : Symbol(x2, Decl(index.ts, 4, 5)) +>X2 : Symbol(X2, Decl(index.ts, 1, 27)) +>X2 : Symbol(X2, Decl(index.ts, 1, 27)) + +import B = require("./a"); +>B : Symbol(B, Decl(index.ts, 4, 18)) + +const b: B = new B(B.b); +>b : Symbol(b, Decl(index.ts, 7, 5)) +>B : Symbol(B, Decl(index.ts, 4, 18)) +>B : Symbol(B, Decl(index.ts, 4, 18)) +>B.b : Symbol(B.b, Decl(a.ts, 2, 37)) +>B : Symbol(B, Decl(index.ts, 4, 18)) +>b : Symbol(B.b, Decl(a.ts, 2, 37)) + +import fooLength = require("./b"); +>fooLength : Symbol(fooLength, Decl(index.ts, 7, 24)) + +fooLength + 1; +>fooLength : Symbol(fooLength, Decl(index.ts, 7, 24)) + +=== tests/cases/compiler/declarations.d.ts === +// This test is just like exportDefaultProperty, but with `export =`. + +declare namespace foo.bar { +>foo : Symbol(foo, Decl(declarations.d.ts, 0, 0)) +>bar : Symbol(bar, Decl(declarations.d.ts, 2, 22)) + + export type X = number; +>X : Symbol(X, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) + + export const X: number; +>X : Symbol(X, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) +} + +declare module "foobar" { + export = foo.bar; +>foo.bar : Symbol(foo.bar, Decl(declarations.d.ts, 2, 22)) +>foo : Symbol(foo, Decl(declarations.d.ts, 0, 0)) +>bar : Symbol(foo.bar, Decl(declarations.d.ts, 2, 22)) +} + +declare module "foobarx" { + export = foo.bar.X; +>foo.bar.X : Symbol(foo.bar.X, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) +>foo.bar : Symbol(foo.bar, Decl(declarations.d.ts, 2, 22)) +>foo : Symbol(foo, Decl(declarations.d.ts, 0, 0)) +>bar : Symbol(foo.bar, Decl(declarations.d.ts, 2, 22)) +>X : Symbol(foo.bar.X, Decl(declarations.d.ts, 2, 27), Decl(declarations.d.ts, 4, 16)) +} + +=== tests/cases/compiler/a.ts === +namespace A { +>A : Symbol(A, Decl(a.ts, 0, 0)) + + export class B { constructor(b: number) {} } +>B : Symbol(B, Decl(a.ts, 0, 13), Decl(a.ts, 1, 48)) +>b : Symbol(b, Decl(a.ts, 1, 33)) + + export namespace B { export const b: number = 0; } +>B : Symbol(B, Decl(a.ts, 0, 13), Decl(a.ts, 1, 48)) +>b : Symbol(b, Decl(a.ts, 2, 37)) +} +export = A.B; +>A.B : Symbol(A.B, Decl(a.ts, 0, 13), Decl(a.ts, 1, 48)) +>A : Symbol(A, Decl(a.ts, 0, 0)) +>B : Symbol(A.B, Decl(a.ts, 0, 13), Decl(a.ts, 1, 48)) + +=== tests/cases/compiler/b.ts === +export = "foo".length; +>"foo".length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/exportEqualsProperty.types b/tests/baselines/reference/exportEqualsProperty.types new file mode 100644 index 0000000000000..a92af53b12bd4 --- /dev/null +++ b/tests/baselines/reference/exportEqualsProperty.types @@ -0,0 +1,92 @@ +=== tests/cases/compiler/index.ts === +/// +import { X } from "foobar"; +>X : number + +import X2 = require("foobarx"); +>X2 : number + +const x: X = X; +>x : number +>X : number +>X : number + +const x2: X2 = X2; +>x2 : number +>X2 : number +>X2 : number + +import B = require("./a"); +>B : typeof B + +const b: B = new B(B.b); +>b : B +>B : B +>new B(B.b) : B +>B : typeof B +>B.b : number +>B : typeof B +>b : number + +import fooLength = require("./b"); +>fooLength : number + +fooLength + 1; +>fooLength + 1 : number +>fooLength : number +>1 : number + +=== tests/cases/compiler/declarations.d.ts === +// This test is just like exportDefaultProperty, but with `export =`. + +declare namespace foo.bar { +>foo : typeof foo +>bar : typeof bar + + export type X = number; +>X : number + + export const X: number; +>X : number +} + +declare module "foobar" { + export = foo.bar; +>foo.bar : typeof foo.bar +>foo : typeof foo +>bar : typeof foo.bar +} + +declare module "foobarx" { + export = foo.bar.X; +>foo.bar.X : number +>foo.bar : typeof foo.bar +>foo : typeof foo +>bar : typeof foo.bar +>X : number +} + +=== tests/cases/compiler/a.ts === +namespace A { +>A : typeof A + + export class B { constructor(b: number) {} } +>B : B +>b : number + + export namespace B { export const b: number = 0; } +>B : typeof B +>b : number +>0 : number +} +export = A.B; +>A.B : typeof A.B +>A : typeof A +>B : typeof A.B + +=== tests/cases/compiler/b.ts === +export = "foo".length; +>"foo".length : number +>"foo" : string +>length : number + diff --git a/tests/cases/compiler/exportDefaultProperty.ts b/tests/cases/compiler/exportDefaultProperty.ts new file mode 100644 index 0000000000000..4a4b413902586 --- /dev/null +++ b/tests/cases/compiler/exportDefaultProperty.ts @@ -0,0 +1,39 @@ +// This test is just like exportEqualsProperty, but with `export default`. + +// @Filename: declarations.d.ts +declare namespace foo.bar { + export type X = number; + export const X: number; +} + +declare module "foobar" { + export default foo.bar; +} + +declare module "foobarx" { + export default foo.bar.X; +} + +// @Filename: a.ts +namespace A { + export class B { constructor(b: number) {} } + export namespace B { export const b: number = 0; } +} +export default A.B; + +// @Filename: b.ts +export default "foo".length; + +// @Filename: index.ts +/// +import fooBar from "foobar"; +import X = fooBar.X; +import X2 from "foobarx"; +const x: X = X; +const x2: X2 = X2; + +import B from "./a"; +const b: B = new B(B.b); + +import fooLength from "./b"; +fooLength + 1; diff --git a/tests/cases/compiler/exportEqualsProperty.ts b/tests/cases/compiler/exportEqualsProperty.ts new file mode 100644 index 0000000000000..0d14815a5bdf0 --- /dev/null +++ b/tests/cases/compiler/exportEqualsProperty.ts @@ -0,0 +1,38 @@ +// This test is just like exportDefaultProperty, but with `export =`. + +// @Filename: declarations.d.ts +declare namespace foo.bar { + export type X = number; + export const X: number; +} + +declare module "foobar" { + export = foo.bar; +} + +declare module "foobarx" { + export = foo.bar.X; +} + +// @Filename: a.ts +namespace A { + export class B { constructor(b: number) {} } + export namespace B { export const b: number = 0; } +} +export = A.B; + +// @Filename: b.ts +export = "foo".length; + +// @Filename: index.ts +/// +import { X } from "foobar"; +import X2 = require("foobarx"); +const x: X = X; +const x2: X2 = X2; + +import B = require("./a"); +const b: B = new B(B.b); + +import fooLength = require("./b"); +fooLength + 1;