Giter Site home page Giter Site logo

jsdoctypeparser / jsdoctypeparser Goto Github PK

View Code? Open in Web Editor NEW
54.0 3.0 11.0 5.39 MB

Parser module for JsDoc or Closure Compiler format type-annotation.

Home Page: https://jsdoctypeparser.github.io/

License: MIT License

JavaScript 100.00%
jsdoc parser javascript

jsdoctypeparser's Introduction

jsdoctypeparser

NPM version Node.js CI status npm

The parser can parse:

Live demo

The live demo is available.

Usage (Programmatic)

Parsing

const {parse} = require('jsdoctypeparser');

const ast = parse('Array<MyClass>');

The ast becomes:

{
  "type": "GENERIC",
  "subject": {
    "type": "NAME",
    "name": "Array"
  },
  "objects": [
    {
      "type": "NAME",
      "name": "MyClass"
    }
  ],
  "meta": {
    "syntax": "ANGLE_BRACKET"
  }
}

See the AST specifications.

Publishing

We can stringify the AST nodes by using publish.

const {publish} = require('jsdoctypeparser');

const ast = {
  type: 'GENERIC',
  subject: {
    type: 'NAME',
    name: 'Array'
  },
  objects: [
    {
      type: 'NAME',
      name: 'MyClass'
    }
  ]
};

const string = publish(ast);

The string becomes:

"Array<MyClass>"

Custom publishing

We can change the stringification strategy by using the 2nd parameter of publish(node, publisher). The publisher MUST have handlers for all node types (see lib/NodeType.js).

And we can override default behavior by using createDefaultPublisher.

const {publish, createDefaultPublisher} = require('jsdoctypeparser');

const ast = {
  type: 'NAME',
  name: 'MyClass',
};

const customPublisher = createDefaultPublisher();
customPublisher.NAME = (node, pub) =>
  `<a href="./types/${node.name}.html">${node.name}</a>`;

const string = publish(ast, customPublisher);

The string becomes:

<a href="./types/MyClass.html">MyClass</a>

Traversing

We can traverse the AST by using traverse. This function takes 3 parameters (a node and an onEnter handler, an onLeave handler). The handlers take a visiting node.

const {parse, traverse} = require('jsdoctypeparser');
const ast = parse('Array<{ key1: function(), key2: A.B.C }>');

function onEnter(node, parentName, parentNode) {
  console.log('enter', node.type, parentName, parentNode.type);
}

function onLeave(node, parentName, parentNode) {
  console.log('leave', node.type, parentName, parentNode.type);
}

traverse(ast, onEnter, onLeave);

The output will be:

enter GENERIC null null
enter NAME subject GENERIC
leave NAME subject GENERIC
enter RECORD objects GENERIC
enter RECORD_ENTRY entries RECORD
enter FUNCTION value RECORD_ENTRY
leave FUNCTION value RECORD_ENTRY
leave RECORD_ENTRY entries RECORD
enter RECORD_ENTRY entries RECORD
enter MEMBER value RECORD_ENTRY
enter MEMBER owner MEMBER
enter NAME owner MEMBER
leave NAME owner MEMBER
leave MEMBER owner MEMBER
leave MEMBER value RECORD_ENTRY
leave RECORD_ENTRY entries RECORD
leave RECORD objects GENERIC
leave GENERIC null null

AST Specifications

NAME

Example:

/**
 * @type {name}
 */

Structure:

{
  "type": "NAME",
  "name": string
}

MEMBER

Example:

/**
 * @type {owner.name}
 * @type {superOwner.owner.name}
 */

Structure:

{
  "type": "MEMBER",
  "name": string,
  "quoteStyle": "none",
  "owner": node,
  "hasEventPrefix": boolean
}

INNER_MEMBER

Example:

/**
 * @type {owner~name}
 */

Structure:

{
  "type": "INNER_MEMBER",
  "name": string,
  "quoteStyle": "none",
  "owner": node,
  "hasEventPrefix": boolean
}

INSTANCE_MEMBER

Example:

/**
 * @type {owner#name}
 */

Structure:

{
  "type": "INSTANCE_MEMBER",
  "name": string,
  "quoteStyle": "none",
  "owner": node,
  "hasEventPrefix": boolean
}

UNION

Example:

/**
 * @type {left|right}
 * @type {(left|right)}
 */

Structure:

{
  "type": "UNION",
  "left": node,
  "right": node
}

INTERSECTION

Example:

/**
 * @type {left&right}
 * @type {(left&right)}
 */

Structure:

{
  "type": "INTERSECTION",
  "left": node,
  "right": node
}

RECORD

Example:

/**
 * @type {{}}
 * @type {{ key: value }}
 * @type {{ key: value, anyKey }}
 */

Structure:

{
  "type": "RECORD",
  "entries": [
    recordEntryNode,
    recordEntryNode,
    ...
  ]
}

RECORD_ENTRY

Structure:

{
  "type": "RECORD_ENTRY",
  "key": string,
  "value": node (or null)
}

GENERIC

Example:

/**
 * @type {Subject<Object, Object>}
 * @type {Object[]}
 */

Structure:

{
  "type": "GENERIC",
  "subject": node,
  "objects": [
    node,
    node,
    ...
  ],
  "meta": {
    "syntax": ("ANGLE_BRACKET" or "ANGLE_BRACKET_WITH_DOT" or "SQUARE_BRACKET")
  }
}

FUNCTION

Example:

/**
 * @type {function()}
 * @type {function(param, param): return}
 * @type {function(this: Context)}
 * @type {function(new: Class)}
 */

Structure:

{
  "type": "FUNCTION",
  "params": [
    node,
    node,
    ...
  ],
  "returns": node (or null),
  "new": node (or null),
  "this": node (or null)
}

OPTIONAL

Example:

/**
 * @type {Optional=}
 */

Structure:

{
  "type": "OPTIONAL",
  "value": node,
  "meta": {
    "syntax": "SUFFIX_EQUALS_SIGN"
  }
}

NULLABLE

Example:

/**
 * @type {?Nullable}
 */

Structure:

{
  "type": "NULLABLE",
  "value": node,
  "meta": {
    "syntax": ("PREFIX_QUESTION_MARK" or "SUFFIX_QUESTION_MARK")
  }
}

NOT_NULLABLE

Example:

/**
 * @type {!NotNullable}
 */

Structure:

{
  "type": "NOT_NULLABLE",
  "value": node,
  "meta": {
    "syntax": ("PREFIX_BANG" or "SUFFIX_BANG")
  }
}

VARIADIC

Example:

/**
 * @type {...Variadic}
 * @type {Variadic...}
 * @type {...}
 */

Structure:

{
  "type": "VARIADIC",
  "value": node (or null),
  "meta": {
    "syntax": ("PREFIX_DOTS" or "SUFFIX_DOTS" or "ONLY_DOTS")
  }
}

MODULE

Example:

/**
 * @type {module:path/to/file.Module}
 */

Structure:

{
  "type": "MODULE",
  "value": node
}

FILE_PATH

Example:

/**
 * @type {module:path/to/file.Module}
 *               ^^^^^^^^^^^^
 */

Structure:

{
  "type": "FILE_PATH",
  "path": string
}

EXTERNAL

Example:

/**
 * @type {external:External}
 */

Structure:

{
  "type": "EXTERNAL",
  "value": node
}

STRING_VALUE

Example:

/**
 * @type {"abc"}
 * @type {"can\"escape"}
 */

Structure:

{
  "type": "STRING_VALUE",
  "quoteStyle": "double",
  "string": string
}

NUMBER_VALUE

Example:

/**
 * @type {123}
 * @type {0b11}
 * @type {0o77}
 * @type {0xff}
 */

Structure:

{
  "type": "NUMBER_VALUE",
  "number": string
}

ANY

Example:

/**
 * @type {*}
 */

Structure:

{
  "type": "ANY"
}

UNKNOWN

Example:

/**
 * @type {?}
 */

Structure:

{
  "type": "UNKNOWN"
}

PARENTHESIS

Example:

/**
 * @type {(Foo)}
 */

Structure:

{
  "type": "PARENTHESIS",
  "value": node
}

Others

We can use a parenthesis to change operator orders.

/**
 * @type {(module:path/to/file.js).foo}
 */

Usage (CLI)

To parse a type into a JSON structure, you may pass a string argument containing the structure to parse (with the JSON results equivalent to the parsing example above):

jsdoctypeparser 'Array<MyClass>'

Note: There is no need to prefix the path to the jsdoctypeparser binary, e.g., with ./node_modules/.bin/ when you are running within one of the package.json scripts or if you have installed the package globally.

License

This script is licensed under the MIT.

jsdoctypeparser's People

Contributors

brettz9 avatar dependabot[bot] avatar exe-boss avatar jcvernaleo avatar kuniwak avatar renovate-bot avatar sandersn avatar simong avatar voxpelli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

jsdoctypeparser's Issues

Spec discussion for v2.0.0

New specs

  • New AST (see schemas)
  • Add parse function
  • Add publish function
  • Add traverse function
  • Support @type {my-type} (#15)
  • Support @type {external:String#rot13} (#11)
  • Support @type {String[]/Number[]} (#16)
  • Support @type {"string"}, @type {123} (#16)

Allow quotation marks for "external:" and "module:" paths

Per http://jsdoc.app/tags-external.html , external type paths should allow namespaces to be added via quotation marks: e.g., external:"jQuery.fn".starfairy may exist and this is expected in jsdoc3/jsdoc.

Per jsdoc/jsdoc#490 , @module may also use quotes (even at the top level, though presumably one must use the optional "module:" prefix if inside of a type expression to avoid it being treated as a string).

In theory the top level of a regular namepath ought to allow for quoted forms as well (e.g., "goofy.global".child.path, possible through window['goofy.global'] = {child: {path: ''}};), no less if a type name with special characters wasn't even mapped to a variable, but since there would be ambiguity with strings if referencing the top level alone (and unlike module:, there is no prefix for regular name paths to avoid this ambiguity) and few global objects (or types) would tend to be named with non-JsIdentifier characters, I guess this is not of concern. Also, though properties would not need to be restricted as variable names, I see that jsdoc ruled it out because of the string ambiguity per jsdoc/jsdoc#395 (comment) , so I guess we don't need to support quoted properties at the top level for regular name paths.

Trouble with parsing invalid type with space

Code

var TypeParser = require('jsdoctypeparser').Parser;
var parser = new TypeParser();
console.log(parser.parse('Invalid type').toString());

outputs Invalidtype instead of throwing lexical error or something.

Function parsing is strange

Parsing function(string) returns

{ "types": [
  { "parameterTypeUnions": [
    { "types": [
      { "name": "string"
        } ] } ] } ] }

While parsing array Array.<string> returns very similar to

{ "types": [
  { "parameterTypeUnions": [
    { "types": [
      { "name": "string"
        } ] } ],
    "genericTypeName": {
      "name": "Array"
    } } ] }

So how to differentiate function(string) and Array.<string>?


Also, parsing default example from README function(function(Function)) throws

Parameter parenthesis was not closed:
function(function(Function))
                           ^

Role with `catharsis`, jsdoc's type parser, and TypeScript's parser

In trying to get to the bottom of #99, I steeled myself for what I imagined would be unpleasant work of digging through custom parser code to find out the actual jsdoc manner of parsing types and was surprised to find it not only has its own separate parser, "catharsis", created under the same ownership as jsdoc, but it is using a PEG.JS grammar as is ours.

(I had seen our repo refer to "catharsis types", but wasn't sure where that had come from.)

I should have investigated this earlier, but anyways, are there any good reasons we aren't using catharsis or working with them? It started back in 2012 and has had commits as recently as two months ago. @Kuniwak , any recollections (or @gajus if it informed your choice to use jsdoctypeparser)?

I'm wondering whether jsdoctypeparser may have originally been started because of:

  • Lack of awareness of the parser's existence
  • NIH (Not Invented Here): easier to start fresh for custom needs
  • Perceived performance or functionality concerns with then catharsis?

I know we have the additional goal of extending for TypeScript, but it appears per jsdoc/jsdoc#1631 (comment) and jsdoc/jsdoc#272 that the the author, hegemonic, is eager for TypeScript support (and that, jsdoc/jsdoc#1631 may not be enough ), whether he wished to apply the proposed catharsis retooling to jsdoc itself as well or at least to make catharsis configurable for different modes, equivalent to our #96 (or perhaps a fork of catharsis on our part if working with them was not practical for some reason and if it was not deemed easier than integrating its code into our existing project).

catharsis is already oriented as "A PEG.js grammar for Google Closure Compiler and JSDoc type expressions", and if we added support in the parser, it ought to make work easier for jsdoc to work with it, e.g., properly linking to TypeScript types in its own documentation, if they were moving toward such support (I also came across https://github.com/hegemonic/jsdoc-baseline and it's nice to know jsdoc may be supporting more readily extensible templates, making it more appealing as a generic documentation tool).

And if we were to use it, the authority for jsdoc types, I think it may resolve #99, #86 and maybe #68 and help with #96 . There'd be a good amount of work to merge our changes into it (or if there was reason, for us to eschew from adopting that repo as a base in favor of cross-porting its changes here).

Unfortunately for us, it looks like TypeScript went the dogfooding route (and didn't spec the jsdoc behaviors in detail), making it somewhat less pleasant to ascertain rules.

(To give an idea of the complexity but also to point us to parts of the source which may help our work, looking for example at the @param parsing of parseTag at https://github.com/microsoft/TypeScript/blob/master/src/compiler/parser.ts#L6903-L6906 , I see parseParameterOrPropertyTag is invoked which invokes tryParseTypeExpression for its type which in turn invokes parseJSDocTypeExpression which invokes doInsideOfContext with the callback parseJSDocType which bases its type on parseTypeOrTypePredicate which bases its type on parseType which invokes doOutsideOfContext with parseTypeWorker as callback which can invoke a couple high-level functions like parseUnionTypeOrHigher which starts to give some idea of the grammar. And at the scanner level, the parser periodically calls such as nextTokenJSDoc which invokes the scanner, e.g., scanJsDocToken, which taken together with the parser, seems would help more authoritatively identify current TypeScript behavior for our needs.)

@sandersn : Would TypeScript itself by chance see any advantages to using a grammar, possibly even the proposed catharsis/jsdoctypeparser harmonization, or if not, then providing a grammar in its spec that its implementation follows?

Anyways, seems may involve some time-consuming and/or challenging choices or work, but it would be nice not to flounder around in the dark in trying to reverse engineer all of the parsing rules.

Allow "(parenthesis)" within types as per JSDoc specs for variations

We are finding an upstream issue with jsdoctypeparser not supporting parenthesis in the memberof tag while using the JSDoc ESLint plugin (eslint-plugin-jsdoc).

As per the @variation documentation https://jsdoc.app/tags-variation.html parenthesis are allowed in tags to associate members to a particular variant.

I've also reported this as a bug over on the JSDoc ESLint project and the full contents of the issue reported are below for clarity.

Thank you for all your work on this project!

--/--
gajus/eslint-plugin-jsdoc#521
Without going into too much detail: We can have many classes with the same name living in a system of versioned/grouped components. We are documenting these versions using the @variation tag.
https://jsdoc.app/tags-variation.html

We are using the @memberof tag to list which version those methods belong to using the variation syntax. This setup throws a "Syntax error in namepath" error.
We believe this may be a bug because the documentation is being created in the correct format.

Some example code:

//Class level
/**
 * @class ComponentA
 * @variation groupA/v1
 */

//Method level
/**
 * @function method1
 * @memberof ComponentA(groupA/v1)
 */

A visualization of how the output looks in the sidebar nav using docdash template:

ComponentA
ComponentA(groupA/v1)
  method1
  method2
  Method3
ComponentA(groupB/v3)
  method1
  method2
  Method3

Dropping `=` prefix (optional type indicator)

There is the PrefixOptionalTypeExpr which indicates as an example =string (while mentioning it is deprecated--the suffixed version is not), but I don't see this in catharsis or mention of it in Closure docs, so it seems that one should be dropped from jsdoctypeparser entirely now, unless TS is using it. (If TS is using it, we could still handle it in check-syntax in eslint-plugin-jsdoc for the other modes.)

Strategy for operator precedence

Problem

In v2.0.0-alpha-5, jsdoctypeparser do not have something to control operator precedence.

Related: #32

Approach

  1. When given the type expression:

    op1 op2 OPERAND op3 op4
    
  2. We will get the 2 groups of tokens:

    var prefixOps = [op2, op1];
    var suffixOps = [op3, op4];
  3. Mix tokens groups (in the example, prefix token have higher priority):

    var mixedOps = flatten(zip(prefixOps, suffixOps))
    // [op2, op3, op1, op4]
  4. Given a strategy function and sort by using it:

    mixedOps.sort(strategyFn);
    // [op3, op2, op1, op4]

Maybe it is useful that operator tokens have own priority level and strategyFn care only the level.

Related codes: https://github.com/Kuniwak/jsdoctypeparser/blob/793483b1556974ead42e1514d762001680211d6f/peg_src/jsdoctype.pegjs#L52

Allow "event:" within types as per JSDoc specs

Hi,

I'm appreciating your library as used by https://github.com/gajus/eslint-plugin-jsdoc ...

I've run into two issues, however, one of which pertains to events...

If I add the event type module:hurler~event:snowball (as shown on http://usejsdoc.org/tags-listens.html ), at http://kuniwak.github.io/jsdoctypeparser/ , I get an error. Removing "event:" makes it work.

Per http://usejsdoc.org/tags-event.html , "event:" is allowed in the signature and apparently is even required in some locations:

Syntax

@event <className>#[event:]<eventName>
...
JSDoc automatically prepends the namespace event: to each event's name. In general, you must include this namespace when you link to the event in another doclet. (The @fires tag is a notable exception; it allows you to omit the namespace.)

Moreover, the JSDoc (for @listens) states:

The following example shows how to document an event named module:hurler~event:snowball, as well as a method named module:playground/monitor.reportThrowage that listens for the event...

So "event:" should be permitted within references to events (including @param) without complaint, at least at preceding a property name at the beginning of namepaths (#, ., or ~ for JSDoc 3, and apparently -, if supporting JSDoc 2), so, e.g., MyClass#event:foo or MyClass~event:foo.

Even if one could work around this by avoiding "event:" within event names, it is not only explicitly permitted by JSDoc but is helpfully descriptive in distinguishing such events from other object references.

Thanks!

(Btw, FWIW, I had reported a similar issue for ESLint's subproject, at eslint/doctrine#221 , but this project is no longer being maintained.)

Nested TypeScript types

I'm having trouble with jsdoc/valid-types in regards to nested TypeScript types:

/**
 * @param {import('../../..').PickListState['data']} data
 */
error  Syntax error in type: import('../../..').PickListState['data'] jsdoc/valid-types

The problem is from the ['data'] accessor. TypeScript is okay with it, jsdoctypeparser is not.

I'm open to doing the PR for this work if I'm given a pointer on where to look.

Infinity loops on incorrect nested brackets closing

how to reproduce:

var Parser = require('jsdoctypeparser').Parser;
var parser = new Parser();
var result = parser.parse('Array.<Array.<String}>'); // hangs here

other problem strings:
{test: function(Function}
{test: Array.<String}
{test: Array.<String}>}

Importing a type from another file appears to break

This concerns jsdoctypeparser version 9.0.0.

A type defined with an import (like import("./package").Type) results in a syntax error being reported by jsdoc/valid-types. I provide a minimal reproducible example below. I also provide contents of my package-lock.json to affirm the version being used.

As far as I can tell, the import is written correctly and should work.

This relates to issue #50, and is similar to an issue previously raised on another repository (gajus/eslint-plugin-jsdoc#343). The bug report page at eslint-plugin-jsdoc says type parsing issues should be reported here, at time of writing under "Note 3" near the top.

Minimal reproducible example

  1. Create a new folder (in my case jsdoc-test-app) containing the three files found further down in this report: you should have package.json, src/first.js, and src/second.js. Note the package.json is using exact version numbers for its dependencies for the sake of reproducibility, you could feel free to add a ^ beforehand if you wish.
  2. Run npm install
  3. Run npm run lint

Expected: Everything is OK. This is a straightforward type import.

Actual: eslint reports an error originating from jsdoc/valid-types.

jsdoc-test-app/src/second.js
  1:0  warning  Syntax error in type: import("./first").Foo  jsdoc/valid-types

✖ 1 problem (0 errors, 1 warning)

Files

package.json

{
  "name": "jsdoc-test-app",
  "private": true,
  "scripts": {
    "lint": "eslint src/**/*.js"
  },
  "dependencies": {
    "eslint": "7.6.0",
    "eslint-plugin-jsdoc": "30.2.1"
  },
  "eslintConfig": {
    "root": true,
    "parserOptions": {
      "ecmaVersion": 11,
      "sourceType": "module"
    },
    "rules": {
      "valid-jsdoc": "off"
    },
    "plugins": [
      "jsdoc"
    ],
    "extends": [
      "eslint:recommended",
      "plugin:jsdoc/recommended"
    ]
  }
}

src/first.js

/** @interface Foo */

src/second.js

/** @typedef {import("./first").Foo} FooBar */

Package-lock information

My package-lock.json file reports the following entries for jsdoctypeparser.

  1. As a referenced dependency:

    "eslint-plugin-jsdoc": {
      "version": "30.2.1",
      "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-30.2.1.tgz",
      "integrity": "sha512-9Nx+BKMBoCTDRIbVpMV4MYfw+lvfnfsWTWYX9vwRRZrkXBpZkKtE3dsFcG6MhF7N/vW1cwpjEnoAIAtn0+a6gw==",
      "requires": {
        "comment-parser": "^0.7.5",
        "debug": "^4.1.1",
        "jsdoctypeparser": "^9.0.0",
        "lodash": "^4.17.19",
        "regextras": "^0.7.1",
        "semver": "^7.3.2",
        "spdx-expression-parse": "^3.0.1"
      }
    },
  2. As the actual locked package:

    "jsdoctypeparser": {
      "version": "9.0.0",
      "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz",
      "integrity": "sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw=="
    },

Schema considerations in testing

To confirm the validity of our output and/or the completeness/accuracy of our JSON schemas, I think the schemas would ideally be part of the parsing tests. (Ajv is a good schema tester from my experience.)

Alternatively perhaps, we might instead represent JSON Schemas with TypeScript and use https://github.com/YousefED/typescript-json-schema to convert them to JSON Schema (leveraging the latter's ability to also convert some custom jsdoc tags found in the TypeScript (meant to represent structures in JSON Schema which TypeScript does not apparently have a way to represent), such as @minimum per the README, into JSON Schema).

In such a case, besides being able to have our tests confirm the validity of the JSON Schema (or just confirm some structures against TypeScript), the TypeScript might find a place in our own internal documentation (even if pegjs doesn't add this).

(And Btw, FWIW, I pushed a few missing schema items to `master.)

Typescript types should parse correctly

The Typescript language service supports Typescript types in jsdoc. That means that anybody editing Javascript code with the Typescript language service, such as users of VS Code, Webstorm, Visual Studio, Sublime, Vim or Emacs, will expect eslint rules to understand Typescript types. Since eslint-plugin-jsdoc is the now-recommended way to lint jsdoc, and it relies on jsdoctypeparser, jsdoctypeparser should parse Typescript types.

Here's a list of the types that I've found so far that need support:

  • Tuple types: [string, string]
    • Labelled tuple types: [a: string, b: string]
    • Multi-variadic tuple types: [...A, ...B]
  • Arrow functions: (x: string) => number
  • Signatures in object literal types: { x: string, (some: string, func: string) => void }
  • Construct signatures: { staticX: string, new (some: string, ctor: string): C }
  • Import types: import("./package").Type
  • Mapped types, index access types, keyof types : { [K in keyof T]: Boxed<T[K]> }
  • Conditional type: A extends B ? C : D
  • Type queries: typeof someVariable
  • Readonly properties { readonly a: string }
  • Type parameters on arrow functions: <T>(a: T) => T
  • Intersection type: A & B
  • Type guard: param is Type
    • Assertion functions: asserts param is Type

I've got type queries working and import types mostly working, so I'll probably create a PR for those before continuing with the rest.

Bug in parsing module type

{module:stream.Readable}
actual:

{
  "type": "MODULE",
  "path": "stream.Readable"
}

expected (something like):

{
  "type": "INNER_MEMBER",
  "owner": {
    "type": "MODULE",
    "path": "stream"
  },
  "name": "Readable",
  "meta": { "delimiter": "." }
}

Proof: http://usejsdoc.org/tags-module.html (last examples)

Deprecate .toHTML method

I want to deprecate .toHTML method on v2.x.
This method is not useful, because this spec highly depend on the HTML markup.

Function parsing

Hi and thank you for your job !

The basic parsing of callback functions as you describe it is :
function(type1, type2, ...): returnType
This format does not allow naming of different args. Could you support this type of format :
function(var1:type1, var2:type2, ...): returnType
or the arrow function format
(var1:type1, var2:type2, ...) => returnType

As your project is used within ESLint this could be very usefull.
Thanks

Move GitHub Page to root

Since JSDocTypeParser is now in its own GitHub organisation, it might be a good idea to move the contents of the gh‑pages branch to https://github.com/jsdoctypeparser/JSDocTypeParser.GitHub.io.

Preferably by pushing the current gh‑pages branch as the master branch of https://github.com/jsdoctypeparser/JSDocTypeParser.GitHub.io.

I have currently pushed that as the master-disabled branch (this is because GitHub pages on the root page are deployed from the master branch).

To enable https://JSDocTypeParser.GitHub.io, the master-disabled branch will have to be renamed to master.

Different parsing modes: jsdoc, TypeScript, closure

Related to #50 and maybe #86 , especially now with our working on implementing settings.jsdoc.mode on eslint-plugin-jsdoc (e.g., gajus/eslint-plugin-jsdoc#400 ), it would be nice if jsdoctypeparser could have different modes to ensure that say developers accustomed to TypeScript did not use its features in a jsdoc-only project (or perhaps for jsdoc developers not to use tags as yet unsupported by TypeScript).

I think we could allow different parsing modes by adding comments to the PEG source and then having a build process which stripped out blocks irrelevant to different modes, and generated multiple lib PEG files for each mode (and the main parsing code, etc., could require these multiple generated PEG lib files).

No plans to implement now, but wanted to share and track the idea at least.

Escaped strings in `MemberName`

Filing an issue also for handling escaped strings within MemberName. Currently it is:

MemberName = "'" name:$([^']*) "'" {
               return name;
             }
           / '"' name:$([^"]*) '"' {
               return name;
             }
           / JsIdentifier

JSDoc3 `~` namepaths are not supported

JSDoc3 allows to use ~ character to refer to the inner member of the class/namespace (docs), but jsdoctypeparser does not recognize such declarations as a valid types:

>parser.parse('Name~property')
Unexpected token: "":
Name~property
   ^

Variadic without an operand

An issue was reported on eslint-plugin-jsdoc which shows a case where valid parsing is returned, but an error encountered upon traversal.

The error occurs upon encountering the type, function(...), which is expected to be equivalent to function(...*).

This can be replicated with:

const {parse, traverse} = require('./');

traverse(
  parse('function(...)')
);

The intermediate parsed structured looks like:

  { type: 'FUNCTION',
  params: [ { type: 'VARIADIC', value: null, meta: { syntax: 'ONLY_DOTS' } } ],
  returns: null,
  this: null,
  new: null }

That is in contrast to other VARIADIC nodes which have had params objects with value, such as this:

{ type: 'VARIADIC', value: { type: 'ANY' }, meta: { syntax: 'PREFIX_DOTS' }

I'm not sure whether we should fix traverse to allow or to actually prohibit this form. It is not entirely clear that this variadic format is considered acceptable or not (and if so by which jsdoc dialects).

I would prefer to be more liberal (and allow this format in traverse as with parse) if there is some uncertainty, but just wanted to file an issue.

Demo site / `gh-pages` update

Just posting as an FYI that the gh-pages branch which powers https://jsdoctypeparser.github.io/jsdoctypeparser/ has now been updated with 4.0.0 so one can test things out there with more recent code.

I also updated the dependencies, dropped deprecated bower in favor of npm, etc., to make it more current and easier to update upon future jsdoctypeparser updates.

Will close this issue as it is just an FYI.

Support parsing namepaths without allowing types

As raised in gajus/eslint-plugin-jsdoc#308 , a type expression such as Array<string> should not be allowed in contexts where only a namepath is allowed (e.g., @typedef {StringArray} Array<string>).

It would help if we could have a mode for parsing namepaths strictly, and I think that while this is jsdoctypeparser, it would seem to me a natural extension to allow for a distinct mode for parsing strict namepaths.

Avoid shadowing `SyntaxError` or offer alternative

I don't think we should be shadowing SyntaxError by exposing it as an export whereupon imports must rename it to avoid shadowing rather than just use simple destructuring.

Or, if we do keep it, at least offer an alternative export of a different name like JSDocTypeSyntaxError.

TypeError during traversal

I'm encountering a TypeError in jsdoctypeparser while linting some javascript source file via eslint and eslint-plugin-jsdoc:

[Error - 10:36:57] TypeError: Cannot convert undefined or null to object
Occurred while linting C:\...\src\lib\FooFactory.js:1
    at Function.keys (<anonymous>)
    at _collectChildNodeInfo (C:\...\node_modules\jsdoctypeparser\lib\traversing.js:139:10)
    at traverse (C:\...\node_modules\jsdoctypeparser\lib\traversing.js:17:27)
    at C:\...\node_modules\jsdoctypeparser\lib\traversing.js:19:7
    at Array.forEach (<anonymous>)
    at traverse (C:\...\node_modules\jsdoctypeparser\lib\traversing.js:18:19)
    at C:\...\node_modules\eslint-plugin-jsdoc\dist\rules\checkTypes.js:130:35
    at Array.forEach (<anonymous>)
    at _default.iterateAllJsdocs (C:\...\node_modules\eslint-plugin-jsdoc\dist\rules\checkTypes.js:44:29)
    at C:\...\node_modules\eslint-plugin-jsdoc\dist\iterateJsdoc.js:444:13

See gajus/eslint-plugin-jsdoc#145 for additional background.

Unfortunately, I cannot publish the actual source file.

Exporting schemas publicly

While the issue of schemas was raised in #77, as per #120 (comment) , I realized it may benefit our demo to be able to dynamically introspect on public start rules and modes (which may end up changing over time as we incorporate catharsis (#109).

Unexpected token error in type.

Hi, I was trying to do

/*
 * @function contextWithPerspective
 * @param {integer} perspective
 * @returns {famous/core/Context} The context with the applied perspective.
 */

in a comment, and the @returns type errors out because of the slashes. I'm using dox which uses jsdoctypeparser to parse types.

The reason I was trying to use famous/core/Context is to indicate where the class is loacated in the famous library. In famo.us, you would import Context from 'famous/core/Context', so I thought I could reflect this fact.

As a workaround, I'm thinking perhaps just doing

/*
 * @function contextWithPerspective
 * @param {integer} perspective
 * @returns {Context} The `famous/core/Context` with the applied perspective.
 */

I haven't tried jsdoc, will jsdoc error out on this? Maybe jsdoctypeparser can have a non-strict option that will convert non-conforming characters to hyphens for the generated link?

EDIT: I can just use famous.core.Context for now.

Bug in rendering function

(module:path/to/file.js).foo

module:path/to/file.js.foo

Place for meta: { parenthesized: true }?

Spread + question sign support

Hey there. I've got an issue about {...?}.

What you think about supporting this?

Actual:

Syntax Error
Expected "!", "(", "*", "-", "...", "0b", "0o", "0x", "=", "?", "\"", "external", "function", "module", "{", [ \t\r\n ], [0-9.] or [a-zA-Z_$] but end of input found.

Looks like it's not a big deal.

Ref: jscs-dev/node-jscs#1577 (comment)

/cc @kobezzza

Distinguish names from namepaths?

Though #116 should now allow distinguishing namepaths from other types, the docs for jsdoc sometimes mention only a "name" (and not "namepath") being allowed in certain contexts.

If we find "name" to indeed be more confined than "namepath", we may want to define its own rule and expose it as a starting rule.

E.g., these list "name" in their signature (rather than "namepath" as with other tags):

  'class', 'constructor',
  'constant', 'const',
  'function', 'func', 'method',
  'member', 'var',
  'mixin',
  'modifies', // (Undocumented but supported more recently within codebase)
  'namespace',
  'interface',

However, sometimes it may say "name" but it seems a full "namepath" is actually allowed, so would need some investigation.

These also list "name", but they clearly support paths (in the examples), but I'm not as sure about the above.

  'event',
  'module',
  'external', 'host',
  'listens',

This shows as a namepath on the event page:

  'emits', 'fires',

These do not have a formal signature in the jsdoc docs, but clearly do use names over namepaths.

  'param', 'property'

What will probably be involved to address this is to move over catharsis and export the name rule in addition to the namepath one so that the likes of param do not allow full namepaths (and we'll have to figure out in eslint-plugin-jsdoc what other tags may only accept names proper).

Dash deemed illegal

I use dashed names for my custom types in jsDoc to distinguish them from identifiers in code. jsDoc hs nothing against it. But jsdoctypeparser does:

$ cat <<——— | dox
/**
 * @typedef my-type
 */
———

…/dox/node_modules/jsdoctypeparser/lib/index.js:53
          throw new Lexer.SyntaxError(e.message, typeExp, e.offset);
                ^
TypeLexerSyntaxError: Expected "!", "#", ".", ".<", "<", "=", "?", "[]", "|", "~", [ \t\r\n ], [a-zA-Z0-9_$] or end of input but "-" found.:
y-typ
^

Restrict `GenericTypeExprOperand`

A user reported an issue at that generic type expressions are quite broad in the operand before the type list, e.g., Object<Object> and even string<Object> are being accepted.

While Promise and of course Array make sense (or user-defined types which are promise/array subclasses), as well as Closure generics (which jsdoc inherits, though without @template support) which takes a class and indicates a subset whose type doesn't necessarily indicate a direct property as with Object (see https://github.com/google/closure-compiler/wiki/Generic-Types ).

But it seems in any case that GenericTypeExprOperand is too permissive now as it allows generics based on even string literals.

Travis build failing

Hi,

I performed an npm update and discovered it caused the Travis build to fail, as eslint 6 no longer supports Node 6.

I should be able to address this tomorrow, using an approach taken in eslint-plugin-jsdoc, but at the end of my day here. I figured this should be ok as I imagine there is no pressing need to revert on master before a release. The code is working locally still, so it should just be due to that Node version (and these are dev deps. anyways).

Large size of published npm package

Hi 👋
Npm package of this lib has a size around 9Mb because your fixtures from the tests directory automatically added to the published package. To prevent this behavior, you should explicitly define files property in package.json or create .npmignore file in the root directory (documentation).

I can send PR for this change if you want.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.