Giter Club home page Giter Club logo

clutz's Issues

Type 'Object' is not generic

We are writing eg var VOID_TAGS_ : Object < string , boolean > ;
but this is not valid TS.

Could be var VOID_TAGS_ : { [s: string]: string; }; instead

Get parameter types from superclass

listenable.js

/**
 * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the
 *     listeners to fire.
 * @param {boolean} capture The capture mode of the listeners to fire.
 * @param {EVENTOBJ} eventObject The event object to fire.
 * @return {boolean} Whether all listeners succeeded without
 *     attempting to prevent default behavior. If any listener returns
 *     false or called goog.events.Event#preventDefault, this returns
 *     false.
 * @template EVENTOBJ
 */
goog.events.Listenable.prototype.fireListeners;

eventtarget.js

/*
 * @implements {goog.events.Listenable}
 */
goog.events.EventTarget = function() {}

/** @override */
goog.events.EventTarget.prototype.fireListeners = function(
    type, capture, eventObject) {
}

.d.ts:

 class EventTarget implements ಠ_ಠ.cl2dts_internal.Unknown {
    fireListeners (a : any , b : any , c : any ) : any ;

Instead we should know the types from the interface being implemented.

writing spread args without array type

/**
 * Creates the composition of the functions passed in.
 * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
 * @param {function(...?):T} fn The final function.
 * @param {...Function} var_args A list of functions.
 * @return {function(...?):T} The composition of all inputs.
 * @template T
 */
goog.functions.compose = function(fn, var_args) {}

function compose < T > (fn : ( ...a : any [] ) => T , ...var_args : ( ...a : any [] ) => any [] ) : ( ...a : any [] ) => T ;

error:
/ac.jslib.d.ts:194:NaN: A rest parameter must be of an array type.

Duplicate variables in high-level namespace

Get lots of Duplicate identifier still.

/javascript/closure/ui/ac/ac.jslib.d.ts:3202:NaN: Duplicate identifier 'fx'.
/javascript/closure/ui/ac/ac.jslib.d.ts:3220:NaN: Duplicate identifier 'fx'.

Duplicate declarations

goog.provide("goog.fx.dom");
goog.provide("goog.fx.dom.ColorTransform");

/** @type {number} */
goog.fx.dom.a = 1;

/** @constructor */
goog.fx.dom.ColorTransform = function() {}

we visit the ColorTransform symbol twice: once for the first provide (which is non-default so we traverse all the symbols) and again for the second provide, where it is the default.

fail to find symbol for a provided object literal

js:

goog.provide('goog.color.names');

goog.color.names = {
    'aliceblue': '#f0f8ff',
    'antiquewhite': '#faebd7'
};

error:

java.lang.IllegalArgumentException: goog.provide not defined: goog.color.names
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:145)
    at com.google.javascript.cl2dts.DeclarationGenerator.produceDts(DeclarationGenerator.java:153)

in the debugger, can see

topScope.getOwnSlot("goog.color") -> Var goog.color{{names: {aliceblue: string, antiquewhite: string}}}
topScope.getOwnSlot("goog.color.names") -> null
topScope.getOwnSlot("goog.color.names.aliceblue") -> Var goog.color.names.aliceblue{string}

add support for type aliases

in closure

/**
 * @typedef {A}
 */
goog.namespace.foo;

should output

declare namespace internal.goog.namespace {
  type foo = A;
}
...

top-level functions pick up a `tempCtor` superclass

The following simple definitions transpile to classes that extend tempCtor.

/**
 * To assert to the compiler that an operation is needed when it would
 * otherwise be stripped. For example:
 * <code>
 *     // Force a layout
 *     goog.reflect.sinkValue(dialog.offsetHeight);
 * </code>
 * @type {!Function}
 */
goog.reflect.sinkValue = function(x) {
  goog.reflect.sinkValue[' '](x);
  return x;
};

and

/**
 * @type {!Function}
 * @throws {Error} when invoked to indicate the method should be overridden.
 */
goog.abstractMethod = function() {
  throw Error('unimplemented abstract method');
};

outputs

class sinkValue extends tempCtor 

Index out of bounds

Caused by: java.lang.RuntimeException: Failed to emit type goog.ui.ac.Renderer
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.visitType(DeclarationGenerator.java:725)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.visitUnionType(DeclarationGenerator.java:773)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.access$1100(DeclarationGenerator.java:388)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker$1.caseUnionType(DeclarationGenerator.java:606)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker$1.caseUnionType(DeclarationGenerator.java:566)
    at com.google.javascript.rhino.jstype.UnionType.visit(UnionType.java:601)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.visitType(DeclarationGenerator.java:723)
    ... 24 more
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.substring(String.java:1918)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.getRelativeName(DeclarationGenerator.java:401)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.access$1000(DeclarationGenerator.java:388)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker$1.caseObjectType(DeclarationGenerator.java:597)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker$1.caseObjectType(DeclarationGenerator.java:566)
    at com.google.javascript.rhino.jstype.ObjectType.visit(ObjectType.java:524)
    at com.google.javascript.cl2dts.DeclarationGenerator$TreeWalker.visitType(DeclarationGenerator.java:723)

Handle @dict

 * @const
 * @dict
 * @private
 */
goog.events.onStringMap_ = {};

produces

var onStringMap_ : null ;

Unstable iteration order

When running tests on OSX with JDK8, the order of declarations in the .d.ts files differs from the golden files.

Reference to nested enum broken by recent change

in https://github.com/google/closure-library/blob/master/closure/goog/events/wheelevent.js
we see

/**
 * @param {goog.events.WheelEvent.DeltaMode} deltaMode The delta mode units of
 *     the wheel event.
 * @constructor
 */
goog.events.WheelEvent = function(
    browserEvent, deltaMode, deltaX, deltaY, deltaZ) {

We emit

declare namespace ಠ_ಠ.cl2dts_internal.goog.events {
  class WheelEvent extends BrowserEvent {
    constructor (browserEvent : Event , deltaMode : WheelEvent.DeltaMode , deltaX : number , deltaY : number , deltaZ : number ) ;
    deltaMode : WheelEvent.DeltaMode ;
    type : WheelEvent.EventType ;
    static PIXELS_PER_PAGE_ : number ;
    /* not emitting EventType because it is an enum and it is not provided */
    /* not emitting DeltaMode because it is an enum and it is not provided */
    static PIXELS_PER_LINE_ : number ;
  }
}
declare module 'goog:goog.events.WheelEvent' {
  import alias = ಠ_ಠ.cl2dts_internal.goog.events.WheelEvent;
  export default alias;
}

And this is broken because DeltaMode and EventType are omitted and don't appear anywhere else.

Similar to the report in #71 and probably broken by our fix to #69

@const with no other type info

* @const
 * @private
 */
goog.userAgent.isVersionOrHigherCache_ = {};

emits a literal null (or fails with NPE with error-checking)

Self-referencing classes

in provide_single_class.js

/**
 * @param {foo.bar.Baz} b
 * @return {boolean}
 */
foo.bar.Baz.prototype.equals = function(b) {
  return false;
};

emits

declare namespace ಠ_ಠ.cl2dts_internal.foo.bar {
  class Baz {
    field : string ;
    equals (b : foo.bar.Baz ) : boolean ;
    method (a : string ) : number ;
    static staticMethod (a : string ) : number ;
  }
}

the Baz name is not correctly qualified, should probably be bare Baz or maybe fully-qualified with the look of disapproval

Emitting type alias with dotted name

like

declare namespace ಠ_ಠ.cl2dts_internal.goog.dom {
  type goog.dom.TagName = string ;
  var goog.dom.TagName : {

types can't have dotted names

support generic methods

/**
* @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
 * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
 *     method.
 * @param {boolean=} opt_useCapture Whether to fire in capture phase
 *     (defaults to false).
 * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
 *     listener.
 * @return {goog.events.ListenableKey} Unique key for the listener.
 * @template SCOPE,EVENTOBJ
 */
goog.events.Listenable.prototype.listen;

produces

listen (a : ( string | EventId < EVENTOBJ > ) , b : (a : EVENTOBJ ) => boolean , c ? : boolean , d ? : ( ) ) : goog.events.ListenableKey ;

but the EVENTOBJ template parameter was undeclared

Extending lib.d.ts classes like Error is broken when name is aliased

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {Error}
 */
goog.debug.Error = function(opt_msg) {...}

outputs

declare namespace ಠ_ಠ.cl2dts_internal.goog.debug { 
  class Error extends Error { ... }
}

which makes TS sad.

`@dict` constructors with additional properties

Currently the closure code below produces (AFAICT) only {[k: string]: any}. We should include all other defined constructor properties in the generated type, and only include the property accessor on top of that.

E.g.:

/** @dict @constructor */
X = function() {};
X.prototype.foo = function() {};

Should be:

class X {
  [k: string]: any;
  foo();
}

Emitting static members on interface

/**
 * An interface that describes a single registered listener.
 * @interface
 */
goog.events.ListenableKey = function() {};

/**
 * Reserves a key to be used for ListenableKey#key field.
 * @return {number} A number to be used to fill ListenableKey#key
 *     field.
 */
goog.events.ListenableKey.reserveKey = function() {
  return ++goog.events.ListenableKey.counter_;
};

produces

  interface ListenableKey {
    static reserveKey ( ) : number ;
  }

but TS doesn't allow static method declarations on an interface

duplicate output for interface with nested enum

see goog.fx.Transition (interface) and goog.fx.Transition.EventType (enum).

Output is

declare namespace ಠ_ಠ.cl2dts_internal.goog.fx {                                                      
  interface Transition {                                                                             
    play : any ;                                                                                     
    stop : any ;                                                                                     
  }                                                                                                  
  var Transition : { EventType : Transition.EventType }                                              
}  

declare namespace ಠ_ಠ.cl2dts_internal.goog.fx.Transition {...}

I think it is safe to assume that nested classes, enums, and interfaces will have their own goog.provide and plainly skip them from the properties of the parent classes, enums, interfaces.

In this case Transition.EventType is provided explicitly.

nested classes without provide

/**
 * @constructor
 * @struct
 * @final
 * @implements {goog.Thenable<TYPE>}
 * @template TYPE,RESOLVER_CONTEXT
 */
goog.Promise = function(resolver, opt_context) {
/**
 * @private @final @struct @constructor
 */
goog.Promise.CallbackEntry_ = function() {}
}

produces a static member:

class Promise < TYPE , RESOLVER_CONTEXT > implements Thenable {
static CallbackEntry_ ( ) : void ;

subclasses with different constructor params break static call method gen

For example if B extends A and takes string instead of number, we generate:

declare namespace f {
    class A {
        constructor(n: number);
        static call(a: A, n: number);
    }

    class B extends A {
        constructor(s: string);
        static call(b: B, n: string);
    }
}

TS barfs on the static call for B which is required to subtype A's functional type. See 'oog.fx.dom.PredefinedEffect' and 'Animation' for closure lib repro.

Maybe we should not output call and apply for constructor functions until someone really needs them. I can't come up with a good need for using those in sane TS code.

@typedef with union type

/**
 * A message value that can be handled by a Logger.
 *
 * Functions are treated like callbacks, but are only called when the event's
 * log level is enabled. This is useful for logging messages that are expensive
 * to construct.
 *
 * @typedef {string|function(): string}
 */
goog.debug.Loggable;

/**
 * Logs a message. If the logger is currently enabled for the
 * given message level then the given message is forwarded to all the
 * registered output Handler objects.
 * @param {goog.log.Logger} logger
 * @param {goog.log.Level} level One of the level identifiers.
 * @param {goog.debug.Loggable} msg The message to log.
 * @param {Error|Object=} opt_exception An exception associated with the
 *     message.
 */
goog.log.log = function(logger, level, msg, opt_exception) {
  if (goog.log.ENABLED && logger) {
    logger.log(level, msg, opt_exception);
  }
};

emits a bad syntax ( )

function log (logger : goog.debug.Logger , level : goog.debug.Logger.Level , msg : ( string | ( ) => string ) , opt_exception ? : Object ) : void ;

Support `goog.require` calls by overloading the function

To typecheck user code, written in closure module style:

var {trim} = goog.require('goog.string');

we can do so by emitting:

declare namespace ಠ_ಠ.cl2dts_internal.goog {
  function require(name: string): any;
  function require(name: 'goog.string'): typeof ಠ_ಠ.cl2dts_internal.goog.string;
}

AST is changed by closurePass

running on base/string/string.js produces

declare module 'goog:goog.string.Unicode' {
  type goog.string.Unicode = string ;
  export var goog.string.Unicode : {
    NBSP : goog.string.Unicode ,
  };
}

Try to preserve parameter names

It's going to be really confusing for developers to see different parameter names (a,b,c...) in the type definitions than were declared. It loses the documentation benefit of seeing the names of the parameters in an API you're trying to call. We should preserve them where possible. (only function literals in typescript require manufacturing names for the parameter types)

Producing constructor with return type

this input

goog.provide('a');

/**
 * @constructor
 */
a.One = function() {};
a.One.prototype.foo = function(x) {};

/**
 * @constructor
 * @extends {a.One}
 */
a.Two = function() {};

goog.inherits(a.Two, a.One);

produces a class Two which has an explicit constructor. We have a return type on the result which is invalid syntax.

declare module 'goog:a' {
  export class One {
    foo (a : any ) : void ;
  }
  export function foo (a : any ) : void ;
  export class Two {
    constructor ( ...a : any [] ) : any ;
    static superClass_ : Object ;
  }
}

`goog.require` overloading cannot create an alias for a type

With require overloading on strings, we can emulate:

var MyClass = goog.require('MyClass');

However this does not create a type alias for MyClass so the user cannot write:

var c: MyClass = new MyClass();

even though they can do

var c = new MyClass();

or even add their own type alias with type MyClass = typeof MyClass.prototype.

//cc @mhegazy

Handle multiple inputs with dependencies

When multiple files are presented, and one of them goog.require's a symbol that is goog.provide'd by another, we should

  • write one .d.ts file for each js_library input
  • use our global internal namespace to reference symbols from the other file.

generic type param missing from signature

* @param {function(this:SCOPE)|{handleEvent:function()}|null} listener Function
 *     or object that has a handleEvent method.
 * @param {number=} opt_delay Milliseconds to wait; default is 0.
 * @param {SCOPE=} opt_handler Object in whose scope to call the listener.
 * @return {number} A handle to the timer ID.
 * @template SCOPE
 */
goog.Timer.callOnce = function(listener, opt_delay, opt_handler) {
static callOnce < SCOPE > (listener : ( ( ) => any | { handleEvent : ( ) => any } ) , opt_delay ? : number , opt_handler ? : ( ) ) : number ;

the type of opt_handler is ( ) which is not valid

TS enforces generic type params are present; closure doesnt

Lots of instance of this javascript/closure/ui/ac/ac.jslib.d.ts:1409:NaN: Generic type 'EventId<T>' requires 1 type argument(s).
and more:
javascript/closure/ui/ac/ac.jslib.d.ts:606:NaN: Generic type 'EventHandler<SCOPE>' requires 1 type argument(s).
javascript/closure/ui/ac/ac.jslib.d.ts:1593:NaN: Generic type 'Promise<TYPE, RESOLVER_CONTEXT>' requires 2 type argument(s).
javascript/closure/ui/ac/ac.jslib.d.ts:1736:NaN: Generic type 'Array<T>' requires 1 type argument(s).
etc.

We might be able to determine that the number of type arguments isn't correct by looking at the type the arguments are passed to, and replace the missing ones with 'any'.
Given the number of occurrences (34 in this particular compile) I don't think we want to try to fix all the usage sites.

Allow function types

eg

/** @type {function(?):?|{handleEvent:function(?):?}|null} handler */
types.g = null;

Support goog.forwardDeclare

closure/events/events.js:

goog.forwardDeclare('goog.debug.ErrorHandler');
/**
 * Installs exception protection for the browser event entry point using the
 * given error handler.
 *
 * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
 *     protect the entry point.
 */
goog.events.protectBrowserEventEntryPoint = function(errorHandler) {
  goog.events.handleBrowserEvent_ = errorHandler.protectEntryPoint(
      goog.events.handleBrowserEvent_);
};

produces

  function protectBrowserEventEntryPoint (errorHandler : ( ) ) : void ;

Emitting a symbol which isn't provided

I added a bit of debug to show what the provides are, and ran on javascript/closure/events/events.js

// Processing provides [goog.events, goog.events.CaptureSimulationMode, goog.events.Key, goog.events.ListenableType] from input javascript/closure/events/events.js
declare namespace ಠ_ಠ.cl2dts_internal.goog.events {
...
 class BrowserEvent extends Event {

But BrowserEvent is not goog.provide'd from this file, and in fact it is in a different file.

Include supertypes

eg. from javascript/closure/ui/zippy.js

 * @extends {goog.events.EventTarget}

should produce a class goog.ui.Zippy that inherits from EventTarget

Support goog.inherits

/**
 * This creates a TwoThumbSlider object.
 * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
 * @constructor
 * @extends {goog.ui.SliderBase}
 */
goog.ui.TwoThumbSlider = function(opt_domHelper) {
  goog.ui.SliderBase.call(this, opt_domHelper);
};
goog.inherits(goog.ui.TwoThumbSlider, goog.ui.SliderBase);
goog.tagUnsealableClass(goog.ui.TwoThumbSlider);

results in a class definition for TwoThumbSlider without the decorate method that comes from SliderBase.

Switch to AbstractCommandLineRunner

We currently use CommandLineRunner.getDefaultExterns which gives us problems when we import code into google.
After the next release of closure compiler we can pick up my change, we should instead do
AbstractCommandLineRunner.getBuiltinExterns(opts.getCompilerOptions())

Generics in implemented interfaces are not output

The following:

 * @implements {goog.Thenable<TYPE>}
 * @template TYPE,RESOLVER_CONTEXT
 */
goog.Promise = function(resolver, opt_context) {...}

outputs

class Promise < TYPE , RESOLVER_CONTEXT > implements Thenable {

But it should be Thenable<TYPE>.

Provided enum static emit

browserevent.js

goog.provide('goog.events.BrowserEvent');
goog.provide('goog.events.BrowserEvent.MouseButton');
/**
 * @constructor
 * @extends {goog.events.Event}
 */
goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
}
/**
 * Normalized button constants for the mouse.
 * @enum {number}
 */
goog.events.BrowserEvent.MouseButton = {
  LEFT: 0,
  MIDDLE: 1,
  RIGHT: 2
};

we emit

  class BrowserEvent extends Event {
    isButton (a : BrowserEvent.MouseButton ) : boolean ;
    static MouseButton : BrowserEvent.MouseButton ;
  }

should be something like (if valid)

declare namespace goog.events {
class BrowserEvent {
  isButton (a: goog.events.BrowserEvent.MouseButton) {
}

declare namespace goog.events.BrowserEvent {
enum MouseButton {
 }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.