From a1117789b253d2461bfcd2a01f5e876d87ed655d Mon Sep 17 00:00:00 2001 From: Shagen Ogandzhanian Date: Thu, 4 Jun 2020 00:53:28 +0200 Subject: [PATCH] Resolve correctly exported type aliases see https://github.com/Kotlin/dukat/issues/270 see https://github.com/Kotlin/dukat/issues/299 --- .../data/typescript/import/typeAlias/_api.ts | 4 ++ .../import/typeAlias/importTypeAlias.d.kt | 21 +++++++++++ .../import/typeAlias/importTypeAlias.d.ts | 6 +++ .../addMissingMemberFromImportedEntities.d.kt | 2 +- typescript/ts-converter/src/AstConverter.ts | 17 ++++----- .../ts-converter/src/DependencyBuilder.ts | 37 +------------------ typescript/ts-converter/src/ExportContext.ts | 34 +++++++++++++++++ 7 files changed, 75 insertions(+), 46 deletions(-) create mode 100644 compiler/test/data/typescript/import/typeAlias/_api.ts create mode 100644 compiler/test/data/typescript/import/typeAlias/importTypeAlias.d.kt create mode 100644 compiler/test/data/typescript/import/typeAlias/importTypeAlias.d.ts diff --git a/compiler/test/data/typescript/import/typeAlias/_api.ts b/compiler/test/data/typescript/import/typeAlias/_api.ts new file mode 100644 index 000000000..50776f229 --- /dev/null +++ b/compiler/test/data/typescript/import/typeAlias/_api.ts @@ -0,0 +1,4 @@ + +export type Environment = 'production' | 'development'; + +export type DefaultPorts = 80 | 440; \ No newline at end of file diff --git a/compiler/test/data/typescript/import/typeAlias/importTypeAlias.d.kt b/compiler/test/data/typescript/import/typeAlias/importTypeAlias.d.kt new file mode 100644 index 000000000..b964b83b0 --- /dev/null +++ b/compiler/test/data/typescript/import/typeAlias/importTypeAlias.d.kt @@ -0,0 +1,21 @@ +@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", "EXTERNAL_DELEGATION") + +import kotlin.js.* +import kotlin.js.Json +import org.khronos.webgl.* +import org.w3c.dom.* +import org.w3c.dom.events.* +import org.w3c.dom.parsing.* +import org.w3c.dom.svg.* +import org.w3c.dom.url.* +import org.w3c.fetch.* +import org.w3c.files.* +import org.w3c.notifications.* +import org.w3c.performance.* +import org.w3c.workers.* +import org.w3c.xhr.* + +external interface State { + var currentEnvironment: String /* 'production' | 'development' */ + fun ping(port: Number /* 80 | 440 */) +} \ No newline at end of file diff --git a/compiler/test/data/typescript/import/typeAlias/importTypeAlias.d.ts b/compiler/test/data/typescript/import/typeAlias/importTypeAlias.d.ts new file mode 100644 index 000000000..1c4da3a5d --- /dev/null +++ b/compiler/test/data/typescript/import/typeAlias/importTypeAlias.d.ts @@ -0,0 +1,6 @@ +import {DefaultPorts, Environment} from './_api'; + +export interface State { + currentEnvironment: Environment; + ping(port: DefaultPorts); +} \ No newline at end of file diff --git a/compiler/test/data/typescript/inheritance/missingMembers/addMissingMemberFromImportedEntities.d.kt b/compiler/test/data/typescript/inheritance/missingMembers/addMissingMemberFromImportedEntities.d.kt index 984bc5cef..1d6bbd85d 100644 --- a/compiler/test/data/typescript/inheritance/missingMembers/addMissingMemberFromImportedEntities.d.kt +++ b/compiler/test/data/typescript/inheritance/missingMembers/addMissingMemberFromImportedEntities.d.kt @@ -20,7 +20,7 @@ external open class C : A { override fun ping(a: String) } -external open class D : A { +external open class D : B { open fun ping(d: Any) override fun ping(a: String) } diff --git a/typescript/ts-converter/src/AstConverter.ts b/typescript/ts-converter/src/AstConverter.ts index 3f04c83dd..7defadba9 100644 --- a/typescript/ts-converter/src/AstConverter.ts +++ b/typescript/ts-converter/src/AstConverter.ts @@ -24,7 +24,7 @@ import { import {AstFactory} from "./ast/AstFactory"; import {DeclarationResolver} from "./DeclarationResolver"; import {AstExpressionConverter} from "./ast/AstExpressionConverter"; -import {ExportContext} from "./ExportContext"; +import {ExportContext, resolveDeclarations} from "./ExportContext"; import {tsInternals} from "./TsInternals"; import { CaseDeclarationProto, @@ -404,16 +404,13 @@ export class AstConverter { } private createUid(identifier: ts.Identifier): string | null { - let typeOfSymbol = this.typeChecker.getDeclaredTypeOfSymbol(this.typeChecker.getSymbolAtLocation(identifier)); - let uid: string | null = null; - if (typeOfSymbol && typeOfSymbol.symbol && Array.isArray(typeOfSymbol.symbol.declarations)) { - let declarationFromSymbol = typeOfSymbol.symbol.declarations[0]; - //TODO: encountered in @types/express, need to work on a separate test case - let uidContext = (declarationFromSymbol.parent && ts.isTypeAliasDeclaration(declarationFromSymbol.parent)) ? - declarationFromSymbol.parent : declarationFromSymbol; - uid = this.exportContext.getUID(uidContext); + let declarations = resolveDeclarations(identifier, this.typeChecker); + + if (declarations[0]) { + return this.exportContext.getUID(declarations[0]); } - return uid; + + return null; } private createTypeReferenceFromSymbol(declaration: ts.Declaration | null): ReferenceEntity | null { diff --git a/typescript/ts-converter/src/DependencyBuilder.ts b/typescript/ts-converter/src/DependencyBuilder.ts index 47cff3703..e8864d46e 100644 --- a/typescript/ts-converter/src/DependencyBuilder.ts +++ b/typescript/ts-converter/src/DependencyBuilder.ts @@ -6,6 +6,7 @@ import { TranslateAllSymbolsDependency, TranslateSubsetOfSymbolsDependency } from "./Dependency"; +import {resolveDeclarations} from "./ExportContext"; export class DependencyBuilder { private dependencies = new Map(); @@ -53,42 +54,8 @@ export class DependencyBuilder { ) { } - private getDeclarations(node: ts.Node): Array { - let symbolAtLocation = this.typeChecker.getSymbolAtLocation(node); - if (symbolAtLocation) { - - if (symbolAtLocation.flags & ts.SymbolFlags.Alias) { - let aliasedSymbol = this.typeChecker.getAliasedSymbol(symbolAtLocation); - if (aliasedSymbol && Array.isArray(aliasedSymbol.declarations)) { - return aliasedSymbol.declarations; - } else { - return []; - } - } - - if (Array.isArray(symbolAtLocation.declarations)) { - return symbolAtLocation.declarations; - } else { - let declaredTyped = this.typeChecker.getDeclaredTypeOfSymbol(symbolAtLocation); - if (declaredTyped) { - let resolvedASymbol = declaredTyped.symbol || declaredTyped.aliasSymbol; - if (resolvedASymbol && Array.isArray(resolvedASymbol.declarations)) { - return resolvedASymbol.declarations; - } - } - } - } - - let symbol = this.typeChecker.getTypeAtLocation(node).symbol; - if (symbol && Array.isArray(symbol.declarations)) { - return symbol.declarations; - } - - return []; - } - private checkReferences(node: ts.Node) { - let declarations = this.getDeclarations(node); + let declarations = resolveDeclarations(node, this.typeChecker); for (let declaration of declarations) { if (this.checkedReferences.has(declaration)) { diff --git a/typescript/ts-converter/src/ExportContext.ts b/typescript/ts-converter/src/ExportContext.ts index 9fdc662e5..a5f499b84 100644 --- a/typescript/ts-converter/src/ExportContext.ts +++ b/typescript/ts-converter/src/ExportContext.ts @@ -14,6 +14,40 @@ function resolveName(node: ts.Node): string | null { return null; } +export function resolveDeclarations(node: ts.Identifier, typeChecker: ts.TypeChecker): Array { + let symbolAtLocation = typeChecker.getSymbolAtLocation(node); + if (symbolAtLocation) { + + if (symbolAtLocation.flags & ts.SymbolFlags.Alias) { + let aliasedSymbol = typeChecker.getAliasedSymbol(symbolAtLocation); + if (aliasedSymbol && Array.isArray(aliasedSymbol.declarations)) { + return aliasedSymbol.declarations; + } else { + return []; + } + } + + if (Array.isArray(symbolAtLocation.declarations)) { + return symbolAtLocation.declarations; + } else { + let declaredTyped = typeChecker.getDeclaredTypeOfSymbol(symbolAtLocation); + if (declaredTyped) { + let resolvedASymbol = declaredTyped.symbol || declaredTyped.aliasSymbol; + if (resolvedASymbol && Array.isArray(resolvedASymbol.declarations)) { + return resolvedASymbol.declarations; + } + } + } + } + + let symbol = typeChecker.getTypeAtLocation(node).symbol; + if (symbol && Array.isArray(symbol.declarations)) { + return symbol.declarations; + } + + return []; +} + export class ExportContext { private exportTable: Map = new Map(); private log = createLogger("ExportContext");