Skip to content

Last signature is missing when multiple are defined #1878

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

Closed
ST-DDT opened this issue Mar 6, 2022 · 5 comments
Closed

Last signature is missing when multiple are defined #1878

ST-DDT opened this issue Mar 6, 2022 · 5 comments
Labels
no bug This is expected behavior

Comments

@ST-DDT
Copy link

ST-DDT commented Mar 6, 2022

Search terms

  • signature
  • missing

Expected Behavior

If I scan a method with multiple signatures, then I expect all of them to be present in the typedoc.json/reflection data.

Actual Behavior

The last one is always missing.
I need that at least for the default value.

Steps to reproduce the bug

export class SignatureTest {
  /**
   * Test with multiple signatures.
   *
   * @param a The value to return.
   */
  multiSignature(a: boolean): boolean;
  multiSignature(a: number): number;
  multiSignature(a: unknown = 1): unknown {
    return a;
  }
}
typedoc.json
{
	"id": 0,
	"name": "@faker-js/faker",
	"kind": 1,
	"kindString": "Project",
	"flags": {},
	"originalName": "",
	"children": [
		{
			"id": 1,
			"name": "SignatureTest",
			"kind": 128,
			"kindString": "Class",
			"flags": {},
			"children": [
[...]
				{
					"id": 4,
					"name": "multiSignature",
					"kind": 2048,
					"kindString": "Method",
					"flags": {},
					"sources": [...]
					"signatures": [
						{
							"id": 5,
							"name": "multiSignature",
							"kind": 4096,
							"kindString": "Call signature",
							"flags": {},
							"comment": {
								"shortText": "Test with multiple signatures."
							},
							"parameters": [
								{
									"id": 6,
									"name": "a",
									"kind": 32768,
									"kindString": "Parameter",
									"flags": {},
									"comment": {
										"shortText": "The value to return.\n"
									},
									"type": {
										"type": "intrinsic",
										"name": "boolean"
									}
								}
							],
							"type": {
								"type": "intrinsic",
								"name": "boolean"
							}
						},
						{
							"id": 7,
							"name": "multiSignature",
							"kind": 4096,
							"kindString": "Call signature",
							"flags": {},
							"parameters": [
								{
									"id": 8,
									"name": "a",
									"kind": 32768,
									"kindString": "Parameter",
									"flags": {},
									"type": {
										"type": "intrinsic",
										"name": "number"
									}
								}
							],
							"type": {
								"type": "intrinsic",
								"name": "number"
							}
						},
+						{
+							"id": 9,
+							"name": "multiSignature",
+							"kind": 4096,
+							"kindString": "Call signature",
+							"flags": {},
+							"parameters": [
+								{
+									"id": 10,
+									"name": "a",
+									"kind": 32768,
+									"kindString": "Parameter",
+									"flags": {},
+									"type": {
+										"type": "intrinsic",
+										"name": "unknown"
+									},
+									"defaultValue": "1"
+								}
+							],
+							"type": {
+								"type": "intrinsic",
+								"name": "unknown"
+							}
+						}
					]
				}
			],
[...]
		}
	],
[...]
}

Environment

@Gerrit0
Copy link
Collaborator

Gerrit0 commented Mar 6, 2022

This is working as expected. The implementation signature is not visible to consumers of the function and is therefore not included in the documentation. You could create a plugin which extracts the information you need at conversion time.

const td = require("typedoc")

exports.load = function(app) {
  app.converter.on(td.Converter.EVENT_CREATE_DECLARATION, (context, reflection) => {
    // getSymbolFromReflection is marked @internal, in the next version with breaking changes
    // the symbol should be passed in to this listener so it shouldn't be necessary here
    const symbol = context.project.getSymbolFromReflection(reflection);
    if (!symbol) return;

    if (reflection.kindOf(td.ReflectionKind.Function | td.ReflectionKind.Method)) {
      console.log(symbol.declarations?.map(d => d.getText()))
    }
  });
}

@ST-DDT
Copy link
Author

ST-DDT commented Mar 7, 2022

What would be the best way to get the complete default value from the implementation signature?

@Dayday10
Copy link

Dayday10 commented Mar 8, 2022

Has this issue been fixed?

@Gerrit0
Copy link
Collaborator

Gerrit0 commented Mar 19, 2022

What would be the best way to get the complete default value from the implementation signature?

That's going to depend on what you mean by "complete". Default values are an arbitrary expression, there's no guarantee that they are a simple value... so it really depends on your use case. The simplest way to do this is, of course, to just get the text from the source file. This will put the default parameters in the JSON as strings from the source file, or null if a parameter doesn't have a default value.

// typedoc --plugin path/to/this/file.js
const td = require("typedoc");

/** @param {td.Application} app */
exports.load = function (app) {
    app.converter.on(
        td.Converter.EVENT_CREATE_DECLARATION,
        /**
         * @param {td.Context} context
         * @param {td.Reflection} reflection
         */
        (context, reflection) => {
            const symbol = context.project.getSymbolFromReflection(reflection);
            if (!symbol) return;

            if (
                reflection.kindOf(td.ReflectionKind.Function | td.ReflectionKind.Method) &&
                (symbol.declarations?.length ?? 0) > 1
            ) {
                const lastDeclaration = symbol.declarations[symbol.declarations.length - 1];
                if (td.TypeScript.isFunctionLike(lastDeclaration)) {
                    reflection.implementationDefaultParameters = lastDeclaration.parameters.map(
                        (param) => param.initializer?.getText() || null
                    );
                    console.log(reflection.implementationDefaultParameters);
                }
            }
        }
    );

    // So that it shows up in JSON output
    app.serializer.addSerializer({
        serializeGroup(item) {
            return item instanceof td.Reflection;
        },
        supports(item) {
            return true;
        },
        toObject(refl, obj) {
            obj.implementationDefaultParameters = refl.implementationDefaultParameters;
            return obj;
        },
    });
};

@ST-DDT
Copy link
Author

ST-DDT commented Mar 22, 2022

Thanks for this example.
I added this to our project in faker-js/faker#656

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no bug This is expected behavior
Projects
None yet
Development

No branches or pull requests

3 participants