microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.6k stars 12.44k forks source link

JSDoc tag comment parsing skips initial asterisk #21402

Closed mjbvz closed 4 years ago

mjbvz commented 6 years ago

From @DaFri-Nochiterov on January 24, 2018 23:45


Steps to Reproduce:

  1. Write an argument description in JSDocs with the markdown (bold in my case)
    /**
    * **Generates string with greeting**
    * @param {string} username **Username** for the greeting.
    */
    function greeting(username: string) {
    return `Hello, ${username}!`;
    }
  2. Hover over an argument name OR type the code to trigger the description tooltip
ℹ️ To note!
1 The behavior below occurs only if the description starts with bold formatting.
2 This only occurs with the asterisk (*) bold formatting.

Excepted Result: Username for the greeting.

Actual Result: Username* for the greeting.

Example from my code (screenshot)

Reproduces without extensions: Yes

Copied from original issue: Microsoft/vscode#42125

mjbvz commented 6 years ago

Here's the quickInfo response we get:

[Trace  - 4:17:46 PM] Response received: quickinfo (21). Request took 2 ms. Success: true 
Result: {
    "kind": "function",
    "kindModifiers": "",
    "start": {
        "line": 5,
        "offset": 10
    },
    "end": {
        "line": 5,
        "offset": 18
    },
    "displayString": "function greeting(username: string): string",
    "documentation": "**Generates string with greeting**",
    "tags": [
        {
            "name": "param",
            "text": "username *Username** for the greeting."
        }
    ]
}

Looks like one of the * before Username is lost

sandersn commented 4 years ago

the jsdoc parser is very likely getting confused and thinking that the "start of comment" state should eat an initial * the same way that the "start of line" state does.

sandersn commented 4 years ago

Repros even for simpler tags like @return:

/**
 * @return *y*
 */
function greeting(username: string, u: number) {
  return `Hello, ${username}!`;
}

Also note that the type is not needed to repro.

sandersn commented 4 years ago

Looks like the problem was truthiness; the comment parser is invoked with a "prefix margin" argument that indicates to parse in "tag mode" vs "top-level mode". But when the margin is "", the code failed to distinguish undefined from "".

I'll have the fix up shortly if this doesn't break other tests.