runem / web-component-analyzer

CLI that analyzes web components and emits documentation
https://runem.github.io/web-component-analyzer
MIT License
499 stars 61 forks source link

Support using lib types with the @property JSDoc tag #67

Open nickpelone opened 4 years ago

nickpelone commented 4 years ago

This is an intersection with the VSCode plugin, but from my logs this is the underlying component that has the issue.

First of all, thank you very much for your plugin, it's awesome!

I just noticed that a nullable type in a @prop JSDoc tag seems to crash language server features. For example, after typing the below example @prop line, other custom elements in my template no longer get hover-info, autocomplete etc.

Example:

import {html, css, LitElement} from 'lit-element';

/**
 * @customElement error-dialog
 * @prop {?Error} error
 * @slot - Header Text
 * @event errorack When the error acknowledgement button is pressed
 *
 *   - some comments about css variables omitted -
 */
class ErrorDialog extends LitElement {
  //... code
}

The @prop {?Error} error bit seems to mess it up. Just for sureness' sake, I tried nullable notation on other types, eg. Number and the same result occurred.

The logs I get when I enable verbose logging in the VSCode plugin:

 ERROR: [ 'Error [getQuickInfoAtPosition]: (TypeError: Cannot read property \'toLowerCase\' of undefined\n    at parseJsDocTypeString (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:198:17)\n    at parseJsDocTypeString (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:226:20)\n    at /home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:817:43\n    at /home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:750:20\n    at Array.map (<anonymous>)\n    at parseJsDocForNode (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:748:14)\n    at parseDeclarationMembers$1 (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:811:26)\n    at JsDocFlavor.parseDeclarationMembers (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:907:16)\n    at _loop_1 (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1814:22)\n    at executeFirstFlavor (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1826:27)\n    at visitComponentDeclaration (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1766:25)\n    at parseComponentDeclaration (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1680:5)\n    at parseComponentDefinitions (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1936:31)\n    at Object.analyzeComponents (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:2066:32)\n    at StoreUpdater.findComponents (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/language-service/store-updater.js:104:54)\n    at StoreUpdater.findInvalidatedComponents (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/language-service/store-updater.js:70:22)\n    at StoreUpdater.update (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/language-service/store-updater.js:42:18)\n    at TsLitPlugin.getQuickInfoAtPosition (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/language-service/ts-lit-plugin.js:106:27)\n    at /home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/decorate-language-service.js:108:30\n    at Object.nextLanguageService.(anonymous function) [as getQuickInfoAtPosition] (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/decorate-language-service.js:56:71)\n    at IOSession.Session.getQuickInfoWorker (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131043:62)\n    at Session.handlers.ts.createMapFromTemplate._a.(anonymous function) (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:130049:61)\n    at /opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131665:88\n    at IOSession.Session.executeWithRequestId (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131656:28)\n    at IOSession.Session.executeCommand (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131665:33)\n    at IOSession.Session.onMessage (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131687:35)\n    at Interface.<anonymous> (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:132978:27)\n    at Interface.emit (events.js:182:13)\n    at Interface._onLine (readline.js:290:10)\n    at Interface._normalWrite (readline.js:433:12)\n    at Socket.ondata (readline.js:149:10)\n    at Socket.emit (events.js:182:13)\n    at addChunk (_stream_readable.js:283:12)\n    at readableAddChunk (_stream_readable.js:264:11)\n    at Socket.Readable.push (_stream_readable.js:219:10)\n    at Pipe.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)) Cannot read property \'toLowerCase\' of undefined',
  TypeError: Cannot read property 'toLowerCase' of undefined
      at parseJsDocTypeString (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:198:17)
      at parseJsDocTypeString (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:226:20)
      at /home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:817:43
      at /home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:750:20
      at Array.map (<anonymous>)
      at parseJsDocForNode (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:748:14)
      at parseDeclarationMembers$1 (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:811:26)
      at JsDocFlavor.parseDeclarationMembers (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:907:16)
      at _loop_1 (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1814:22)
      at executeFirstFlavor (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1826:27)
      at visitComponentDeclaration (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1766:25)
      at parseComponentDeclaration (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1680:5)
      at parseComponentDefinitions (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:1936:31)
      at Object.analyzeComponents (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/web-component-analyzer/lib/index.cjs.js:2066:32)
      at StoreUpdater.findComponents (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/language-service/store-updater.js:104:54)
      at StoreUpdater.findInvalidatedComponents (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/language-service/store-updater.js:70:22)
      at StoreUpdater.update (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/language-service/store-updater.js:42:18)
      at TsLitPlugin.getQuickInfoAtPosition (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/language-service/ts-lit-plugin.js:106:27)
      at /home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/decorate-language-service.js:108:30
      at Object.nextLanguageService.(anonymous function) [as getQuickInfoAtPosition] (/home/nick/.vscode/extensions/runem.lit-plugin-1.0.2/node_modules/ts-lit-plugin/lib/decorate-language-service.js:56:71)
      at IOSession.Session.getQuickInfoWorker (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131043:62)
      at Session.handlers.ts.createMapFromTemplate._a.(anonymous function) (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:130049:61)
      at /opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131665:88
      at IOSession.Session.executeWithRequestId (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131656:28)
      at IOSession.Session.executeCommand (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131665:33)
      at IOSession.Session.onMessage (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:131687:35)
      at Interface.<anonymous> (/opt/visual-studio-code/resources/app/extensions/node_modules/typescript/lib/tsserver.js:132978:27)
      at Interface.emit (events.js:182:13)
      at Interface._onLine (readline.js:290:10)
      at Interface._normalWrite (readline.js:433:12)
      at Socket.ondata (readline.js:149:10)
      at Socket.emit (events.js:182:13)
      at addChunk (_stream_readable.js:283:12)
      at readableAddChunk (_stream_readable.js:264:11)
      at Socket.Readable.push (_stream_readable.js:219:10)
      at Pipe.onStreamRead [as onread] (internal/stream_base_commons.js:94:17) ]

Looking at that call stack, the second section looks like this:

    // Match:
    //  {?number}       (nullable)
    //  {!number}       (not nullable)
    //  {...number}     (array of)
    var prefixMatch = str.match(/^(\?|!|(\.\.\.))(.+)$/);
    if (prefixMatch != null) {
        var modifier = prefixMatch[1];
        var type = parseJsDocTypeString(prefixMatch[2]);
        switch (modifier) {

which led me to infer that it might be the nullable notation, given the regex used there.

If I change the @prop line to: @prop {Error | null} (ultimately, the same thing), everything works again.

This is obviously not a showstopper, as like I mentioned you can just use the union type notation instead and work around it in the meantime.

Just wanted to let you know - thanks for your time!

nickpelone commented 4 years ago

Nano-update on my workaround:

It also appears that the type tag parser is interpreting my type as a String? Or maybe I'm just reading this wrong?

types_1

types_2

(notice in the hovertext the Error type is stringified, "Error")

Sorry for additional noise.

runem commented 4 years ago

Hi Nick, thanks for creating this issue and making me aware of it!

First of all, lit-plugin right now runs with a very old version of web-component-analyzer. Testing what you showed with the newest version doesn't crash for me (so your first issue seems to have been fixed with the next version):

npx web-component-analyzer analyze my-element.js

Next, the reason it doesn't see complex types such as "Error" is because of a missing feature in ts-simple-type. You can read more about it in this issue: https://github.com/runem/ts-simple-type/issues/32 . It's definitely on my list of high priority bugs, so I'll come by it soon! I'll keep you updated here, and sorry for the inconvenience :-)

nickpelone commented 4 years ago

Hey, thanks for the update! Much appreciated :smile:

runem commented 4 years ago

Update: Support for nullable JSDoc type is now live in version 1.1.6 of the vscode plugin.

You can add "lit-plugin.rules.no-incompatible-type-binding": "off" to your vscode settings to disable type checking while waiting for a fix to the above mentioned problem with the "Error" type in JSDoc.

The following would also fix your issue (if you want to use public class fields):

class ErrorDialog extends LitElement {
  /**
   * @type {Error}
   */
  error;
}

I have also taken the freedom to rename this issue :-)

nickpelone commented 4 years ago

Sweet! After updating, things no longer crash with an @prop {?Error} annotation. As you said, the typcheck on the binding still shows as incorrect, but I can patiently await that fix. :)

Thanks again! I'm going to be on-boarding some of my team to modern web practice stuff and your plugin is just a really nice quality of life enhancement.