Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS Intellisense #17938

Open
caxapexac opened this issue Sep 28, 2022 · 8 comments
Open

JS Intellisense #17938

caxapexac opened this issue Sep 28, 2022 · 8 comments

Comments

@caxapexac
Copy link

All of my js libraries looks like this:

const LibName= {
    $SomethingInternal: {
        someInternalMethod: function () {
        }
    },
    externalMethod: function () {
        SomethingInternal.someInternalMethod();
    }
};

autoAddDeps(LibName, '$log');
mergeInto(LibraryManager.library, LibName);

I won't get any intellisense because $SomethingInternal != SomethingInternal
IDE also shows SomethingInternal as non-existing

Is there any workaround/hack to this problem to get clean and easy-to-refactor JS code?
For example, now if I decide to move someInternalMethod to somewhere else I won't get IDE warning of dissapeared function and it will compile and crash at runtime

@caxapexac
Copy link
Author

It actually dawned on me!

/** @alias SomethingInternal */
$SomethingInternal: {
    someInternalMethod: function () {
    }
}

Any better solution?

@sbc100
Copy link
Collaborator

sbc100 commented Sep 29, 2022

Sadly our JS libraries are not very IDE friendly because (at least the core system one) use a lot of magic preprocessor macros and #if/#else blocks. If @alias works in your IDE thats great.

Even worse that not being IDE friendly (IMHO) this also means that linters and formatters don't work with most of out JS library code.

@caxapexac
Copy link
Author

caxapexac commented Sep 29, 2022

@sbc100 I've been making typedefs for internal library functions in separate file and linter just works (any JetBrains IDE):

    /**
     * @typedef {Object} LibraryObject
     * @typedef {{library:LibraryObject}} LibraryManager
     * @typedef {function(Object, string)} autoAddDeps
     * @typedef {function(LibraryObject, Object)} mergeInto
     */

    /**
     * @typedef {number} Ptr
     */

    /**
     * @typedef Module
     * @property {function(number) : Ptr} _malloc
     * @property {function(Ptr)} _free
     */

    /**
     * @typedef {WebAssembly.Table} wasmTable
     * @typedef {WebAssembly.Memory} wasmMemory
     */

    /**
     * @typedef {function(string)} stackTrace
     * @typedef {function(string)} allocateUTF8
     * @typedef {function(string)} UTF8ToString
     */

It helps a lot when it comes to refactoring

So maybe someday you consider making public JSDoc api for every js library out there. I know it could be long (really not at all) boring work but it could improve speed of reading/writing code, especially for inter-library communications

@caxapexac
Copy link
Author

@sbc100
I think I could be similar to this:
(even shows pointer underlying type when using wasmTable):

// Compile-time
/**
 * @typedef LibraryManager
 * @property {Object} library
 */

/**
 * @callback autoAddDeps
 * @param {Object} LibraryObject
 * @param {string} LibraryName
 */

/**
 * @callback mergeInto
 * @param {Object} Destination
 * @param {Object} Source
 */

// Runtime
/**
 * @template T
 * @interface {number} Ptr
 */

/**
 * @typedef
 */
const Module = {
    /**
     * @function
     * @param {number} size
     * @returns {Ptr<*>}
     */
    _malloc: function (size) {
        return undefined;
    },
    /**
     * @function
     * @param {Ptr<*>} pointer
     * @returns {void}
     */
    _free: function (pointer) {
    }
};

/**
 * @typedef // {WebAssembly.Table}
 */
const wasmTable = {
    /** @type {number} */
    length: undefined,

    /**
     * @function
     * @template T
     * @param {Ptr<T>} pointer
     * @returns {T}
     */
    get: function (pointer) {
        return undefined;
    },
};

/**
 * @typedef {WebAssembly.Memory} wasmMemory
 */


/**
 * @callback stackTrace
 * @returns {string}
 */

/**
 * @callback allocateUTF8
 * @param {string} str
 * @returns {Ptr<string>}
 */

/**
 * @callback UTF8ToString
 * @param {Ptr<string>} pointer
 * @returns {string}
 */

/**
 * @callback stringToAscii
 * @param {string} str
 * @param {Ptr<string>} outPointer
 */

/**
 * @callback AsciiToString
 * @param {Ptr<string>} pointer
 * @returns {string}
 */

image

@caxapexac
Copy link
Author

Okay JSDoc has several severe problems with generics so its way better (and shorter) to just write declaration .ts file and throw it into the project directory

@sbc100
Copy link
Collaborator

sbc100 commented Oct 1, 2022

If you can think of a way emscripten can/should integration such types please set a PR or suggestion here. I don't use an IDE so I'm not very familiar with any of that stuff.

@caxapexac
Copy link
Author

I'm trying to get things working, current iteration where I moved to typescript looks like this:

// noinspection JSClassNamingConvention, FunctionNamingConventionJS

// Compile-time
declare namespace LibraryManager {
    const library: Object;
}

declare function autoAddDeps(library: Object, libraryName: string): void;

declare function mergeInto(destination: Object, source: Object): void;

// Runtime

declare interface Ptr<T> extends Number {
}

declare namespace Module {
    function _malloc(size: number): Ptr<any>;

    function _free<T>(pointer: Ptr<T>): void;
}

declare namespace wasmTable {
    const length: number;

    function get<T>(pointer: Ptr<T>): T;
}

declare const wasmMemory: WebAssembly.Memory;


declare function stackTrace (): string;

declare function allocateUTF8 (str: string): Ptr<string>;

declare function UTF8ToString (pointer: Ptr<string>): string;

declare function stringToAscii (str: string, outPointer : Ptr<string>): void;

declare function AsciiToString (pointer: Ptr<string>): string;

I'll try to extend it while using in my project so we'll see if this solution would be comfortable to use. This way of types declarations is widely used by the way (e.g. https://github.com/microsoft/TypeScript/blob/main/lib/lib.dom.d.ts, https://github.com/DefinitelyTyped/DefinitelyTyped)

The one problem here is that js internal stuff such as Webassembly.Table has too broad typings:

    interface Table {
        readonly length: number;
        get(index: number): any;
        grow(delta: number, value?: any): number;
        set(index: number, value?: any): void;
    }

Look at get function - it should actually work with pointer and its value but instead it returns any. So maybe it worths to improve official Webassembly typings before, I don't know. For now Ive just make my own Webassembly.Table typing as you can see above

If you don't mind I'll reopen the issue (in case anyone interested in making typing or knows a better approach for such conflicts)

@caxapexac caxapexac reopened this Oct 1, 2022
@caxapexac
Copy link
Author

Related:
#9674
#10271

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants