Skip to content

Commit

Permalink
Merge pull request #10 from haxiomic/interface-structure-improvements
Browse files Browse the repository at this point in the history
Interface structure improvements
  • Loading branch information
haxiomic authored May 8, 2020
2 parents 6bfe03a + 9b13f02 commit 0c2b7b4
Show file tree
Hide file tree
Showing 1,758 changed files with 57,908 additions and 53,218 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ dts2hx is currently in alpha release, everything _should_ work but please report
- [ ] Support constructor signature in types with `@:genericBuild` abstract
- If a constructor type is used as a type parameter we can use haxe's `Constructible` type
- [x] Abstracts to implement Tuples (named fields for array indexes)
- [ ] Extract hints from JSDoc like @nosideeffects -> @:pure (See also https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler)
- [ ] Extract hints from JSDoc
- @nosideeffects -> @:pure (See also https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler)
- @deprecated
- [ ] CLI: Add `--install` option
- [ ] Automatically try `install @types/{name}` if no types found in main module
- [ ] CLI: Add option to automatically bundle `@:jsRequire()` so a separate bundler isn't required. Maybe a we could use a macro for this
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dts2hx",
"version": "0.4.5",
"version": "0.5.0",
"description": "Converts TypeScript definition files (d.ts) to haxe externs",
"keywords": ["haxe", "typescript", "externs", "dts2hx", "type definitions", "types", "cross-platform"],
"main": "dist/dts2hx.js",
Expand Down
511 changes: 281 additions & 230 deletions src/ConverterContext.hx

Large diffs are not rendered by default.

49 changes: 29 additions & 20 deletions src/HaxeTypePathMap.hx
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@ class HaxeTypePathMap {
var modules = symbolTypePathMap.get(symbol.getId());

if (modules != null) {
// filter modules for just those with `isInterfaceStructure`
if (preferInterfaceStructure) {
var interfaceStructureModules = modules.filter(m -> m.isInterfaceStructure == true);
// if we don't have any, that's ok, but if we do, we should select from those
if (interfaceStructureModules.length > 0) {
modules = interfaceStructureModules;
}
// filter modules for just those with, or without `isInterfaceStructure` (depending on `preferInterfaceStructure`)
var interfaceStructureFilteredModules = modules.filter(m -> m.isInterfaceStructure == preferInterfaceStructure);
// if we don't have any, that's ok, but if we do, we should select from those
if (interfaceStructureFilteredModules.length > 0) {
modules = interfaceStructureFilteredModules;
}
// find one with a matching access context if possible
var matchingModule = modules.find(m -> m.access.getIndex() == accessContext.getIndex());
Expand Down Expand Up @@ -240,20 +238,20 @@ class HaxeTypePathMap {

function generateTypePath(symbol: Symbol, access: SymbolAccess, asInterfaceStructure: Bool) {
// if the symbol is declared (at least once) in a built-in library, js.html or js.lib
var defaultLibName: Null<String> = null;
var defaultLibOnlyDeclarations = true;
var isBuiltIn = false; // symbol is declared in a built-in lib file (but may be extended in user-code)
var defaultLibOnlyDeclarations = true; // symbol is declared in a built-in lib file and **is not** extended in user-code
for (declaration in symbol.getDeclarationsArray()) {
var sourceFile = declaration.getSourceFile();
if (sourceFile.hasNoDefaultLib) {
defaultLibName = Path.withoutDirectory(sourceFile.fileName);
isBuiltIn = true;
} else {
defaultLibOnlyDeclarations = false;
}
}

// handle built-ins and types available in the haxe standard library
// if the symbol has a non-default-lib declaration, it is considered to be a custom extension and so will be generated
if (defaultLibOnlyDeclarations) {
if (defaultLibOnlyDeclarations && !asInterfaceStructure) {
final specialTypeMap = [
// we want to avoid generating the following types into ts.lib.*
// preferring to map them to haxe types instead
Expand All @@ -275,16 +273,23 @@ class HaxeTypePathMap {
}
}

function hasDeclarationInLib(symbol: Symbol, filename: String) {
for (declaration in symbol.getDeclarationsArray()) {
var sourceFile = declaration.getSourceFile();
if (sourceFile.hasNoDefaultLib && Path.withoutDirectory(sourceFile.fileName).toLowerCase() == filename) {
return true;
}
}
return false;
}

// if the symbol derives from a built-in, prefix js.lib or js.html
// otherwise prefix the module name (if it's a path, add a pack for each directory)
var pack = if (defaultLibName != null) {
switch defaultLibName.toLowerCase() {
case 'lib.dom.d.ts': ['ts', 'html'];
default: ['ts', 'lib'];
}
var pack = if (isBuiltIn) {
if (hasDeclarationInLib(symbol, 'lib.dom.d.ts')) ['ts', 'html']
else ['ts', 'lib'];
} else {
[];
//TsProgramTools.isDirectPathReferenceModule(entryPointModuleId) ? [] : splitModulePath(entryPointModuleId);
}

// we prepend the module path to avoid collisions if the symbol is exported from multiple modules
Expand All @@ -311,7 +316,7 @@ class HaxeTypePathMap {
case Global(_):
// only prefix global package if it's not a built-in
// global types are _not_ prefixed with the module name, this might change in the future
pack = pack.concat((defaultLibName != null) ? [] : ['global']).concat(identifierChain);
pack = pack.concat(isBuiltIn ? [] : ['global']).concat(identifierChain);
pack.pop(); // remove symbol ident; only want parents
case Inaccessible:
var entryPointPack = splitModulePath(entryPointModuleId);
Expand Down Expand Up @@ -370,6 +375,8 @@ class HaxeTypePathMap {
symbol.name;
}
var name = typeIdentifier.toSafeTypeName();
// prefix I if interface-structure version of a type
name = asInterfaceStructure ? 'I' + name : name;

// rename if name that conflict with std.* types
// @! we should generate this list automatically in the future
Expand Down Expand Up @@ -399,13 +406,14 @@ class HaxeTypePathMap {
'UnicodeString',
'Xml',
];
// add '_' to avoid disallowed names
if (disallowedNames.indexOf(name) != -1) {
name = name + '_';
}

// handle short aliases
return {
name: asInterfaceStructure ? 'I' + name : name,
name: name,
pack: pack,
isExistingStdLibType: false,
}
Expand All @@ -426,7 +434,8 @@ class HaxeTypePathMap {
**/
inline function renameability(m: InternalModule) {
return
m.renameable ? 1 : 0 << 5 | // prefer renameable, with highest priority
m.renameable ? 1 : 0 << 6 | // prefer renameable, with highest priority
(!m.isExistingStdLibType ? 1 : 0) << 5 | // prefer non-existing std lib types
(m.access.match(Inaccessible) ? 1 : 0) << 4 | // prefer inaccessible
(m.symbol.flags & SymbolFlags.ValueModule == 0 ? 1 : 0) << 3 | // prefer **not** ValueModule
(m.symbol.flags & SymbolFlags.Class == 0 ? 1 : 0) << 2 | // prefer **not** class
Expand Down
23 changes: 23 additions & 0 deletions src/tool/TsSymbolTools.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tool;

import typescript.ts.ExpressionWithTypeArguments;
import haxe.DynamicAccess;
import haxe.ds.ReadOnlyArray;
import typescript.Ts;
Expand All @@ -17,6 +18,8 @@ using Lambda;
using TsInternal;
using tool.HaxeTools;

typedef TsType = typescript.ts.Type;

@:nullSafety
class TsSymbolTools {

Expand Down Expand Up @@ -147,6 +150,26 @@ class TsSymbolTools {
return members;
}

/**
Return TsType of super class (`extends T`) if there is one
**/
public static function getClassExtendsType(tc: TypeChecker, symbol: Symbol): Null<TsType> {
// determine super type (if class declaration)
var classDeclaration: Null<ClassDeclaration> = symbol.valueDeclaration != null && Ts.isClassDeclaration(symbol.valueDeclaration) ? cast symbol.valueDeclaration : null;

if (classDeclaration != null && classDeclaration.heritageClauses != null) {
// classes can only extend one class in TypeScript
var extendsClause = (cast classDeclaration.heritageClauses: Array<HeritageClause>).find(h -> h.token == ExtendsKeyword);
if (extendsClause != null) {
var superTypeNode = (cast extendsClause.types: Array<ExpressionWithTypeArguments>)[0];
var superType = tc.getTypeFromTypeNode(superTypeNode);
return superType;
}
}

return null;
}

/**
symbol.declarations may be null, this method always returns an array
**/
Expand Down
2 changes: 1 addition & 1 deletion test/_generated-libs/Three.hx
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@
static var TextureIdCount : Float;
static var MaterialIdCount : Float;
static var DefaultLoadingManager : three.LoadingManager;
static var AudioContext : ts.html.IAudioContext;
static var AudioContext : ts.html.AudioContext;
static var GeometryIdCount : Float;
static var Object3DIdCount : Float;
static var REVISION : String;
Expand Down
14 changes: 7 additions & 7 deletions test/_generated-libs/global/BaseJQueryEventObject.hx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ typedef BaseJQueryEventObject = {
/**
The current DOM element within the event bubbling phase.
**/
var currentTarget : ts.html.IElement;
var currentTarget : ts.html.Element;
/**
An optional object of data passed to an event method when the current executing handler is bound.
**/
var data : Dynamic;
/**
The element where the currently-called jQuery event handler was attached.
**/
var delegateTarget : ts.html.IElement;
var delegateTarget : ts.html.Element;
/**
Returns whether event.preventDefault() was ever called on this event object.
**/
Expand All @@ -31,15 +31,15 @@ typedef BaseJQueryEventObject = {
/**
The browser's original Event object.
**/
var originalEvent : ts.html.IEvent;
var originalEvent : ts.html.Event;
/**
If this method is called, the default action of the event will not be triggered.
**/
function preventDefault():Dynamic;
/**
The other DOM element involved in the event, if any.
**/
var relatedTarget : ts.html.IElement;
var relatedTarget : ts.html.Element;
/**
The last value returned by an event handler that was triggered by this event, unless the value was undefined.
**/
Expand All @@ -55,7 +55,7 @@ typedef BaseJQueryEventObject = {
/**
The DOM element that initiated the event.
**/
var target : ts.html.IElement;
var target : ts.html.Element;
/**
The mouse position relative to the left edge of the document.
**/
Expand Down Expand Up @@ -98,7 +98,7 @@ typedef BaseJQueryEventObject = {
**/
final isTrusted : Bool;
var returnValue : Bool;
final srcElement : Null<ts.html.IEventTarget>;
final srcElement : Null<ts.html.EventTarget>;
/**
Returns the event's timestamp as the number of milliseconds measured relative to the time origin.
**/
Expand All @@ -110,7 +110,7 @@ typedef BaseJQueryEventObject = {
/**
Returns the invocation target objects of event's path (objects on which listeners will be invoked), except for any nodes in shadow trees of which the shadow root's mode is "closed" that are not reachable from event's currentTarget.
**/
function composedPath():Array<ts.html.IEventTarget>;
function composedPath():Array<ts.html.EventTarget>;
function initEvent(type:String, ?bubbles:Bool, ?cancelable:Bool):Void;
final AT_TARGET : Float;
final BUBBLING_PHASE : Float;
Expand Down
Loading

0 comments on commit 0c2b7b4

Please sign in to comment.