cincheo / jsweet

A Java to JavaScript transpiler.
http://www.jsweet.org
Other
1.45k stars 159 forks source link

Method overloading problem between Interface<T> and Impl class #748

Open EricWittmann opened 1 year ago

EricWittmann commented 1 year ago

Reproducer here: https://github.com/EricWittmann/jsweet-methodName-reproducer

Here's the scenario:

Java interface MappedNode<T> like so:

public interface MappedNode<T> {
    public void addItem(String name, T item);
}

With an interface that extends it like so:

public interface ApiPaths extends Node, MappedNode<ApiPathItem> {
}

And then another (e.g. versioned) interface that extends THAT:

public interface V1ApiPaths extends ApiPaths {
}

And then finally a versioned Impl class that implements the V1 interface:

public class V1ApiPathsImpl extends NodeImpl implements V1ApiPaths {

    private Map<String, ApiPathItem> _items = new LinkedHashMap<>();

    @Override
    public void addItem(String name, ApiPathItem item) {
        this._items.put(name, item);
    }

    @Override
    public ApiPathItem removeItem(String name) {
        return this._items.remove(name);
    }
}

This generates the following typescript for the implementation class:

export class V1ApiPathsImpl extends NodeImpl implements V1ApiPaths {
    /*private*/ _items: any;

    public addItem$java_lang_String$io_apicurio_models_ApiPathItem(name: string, item: ApiPathItem) {
        /* put */(this._items[name] = item);
    }

    /**
     * 
     * @param {string} name
     * @param {*} item
     */
    public addItem(name?: any, item?: any) {
        if (((typeof name === 'string') || name === null) && ((item != null && (item.constructor != null && item.constructor["__interfaces"] != null && item.constructor["__interfaces"].indexOf("io.apicurio.models.ApiPathItem") >= 0)) || item === null)) {
            return <any>this.addItem$java_lang_String$io_apicurio_models_ApiPathItem(name, item);
        } else throw new Error('invalid overload');
    }

    /**
     * 
     * @param {string} name
     * @return {*}
     */
    public removeItem(name: string): ApiPathItem {
        return /* remove */(map => { let deleted = this._items[name];delete this._items[name];return deleted;})(this._items);
    }

    constructor() {
        super();
        this._items = <any>({});
    }
}

Note that addItem is generated as though multiple overloaded methods with different parameters exists, but there is only one.