@rightcapital/phpdoc-parser 0.5.3 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/index.d.ts +10 -1
  2. package/dist/index.js +22 -4
  3. package/dist/phpdoc-parser/ast/comment.d.ts +7 -0
  4. package/dist/phpdoc-parser/ast/comment.js +14 -0
  5. package/dist/phpdoc-parser/ast/const-expr/const-expr-node.d.ts +0 -2
  6. package/dist/phpdoc-parser/ast/const-expr/const-expr-node.js +0 -3
  7. package/dist/phpdoc-parser/ast/const-expr/const-expr-string-node.d.ts +5 -1
  8. package/dist/phpdoc-parser/ast/const-expr/const-expr-string-node.js +33 -2
  9. package/dist/phpdoc-parser/ast/php-doc/param-closure-this-tag-value-node.d.ts +10 -0
  10. package/dist/phpdoc-parser/ast/php-doc/param-closure-this-tag-value-node.js +19 -0
  11. package/dist/phpdoc-parser/ast/php-doc/param-immediately-invoked-callable-tag-value-node.d.ts +8 -0
  12. package/dist/phpdoc-parser/ast/php-doc/param-immediately-invoked-callable-tag-value-node.js +18 -0
  13. package/dist/phpdoc-parser/ast/php-doc/param-later-invoked-callable-tag-value-node.d.ts +8 -0
  14. package/dist/phpdoc-parser/ast/php-doc/param-later-invoked-callable-tag-value-node.js +18 -0
  15. package/dist/phpdoc-parser/ast/php-doc/php-doc-node.d.ts +2 -0
  16. package/dist/phpdoc-parser/ast/php-doc/php-doc-node.js +6 -0
  17. package/dist/phpdoc-parser/ast/php-doc/pure-unless-callable-is-impure-tag-value-node.d.ts +8 -0
  18. package/dist/phpdoc-parser/ast/php-doc/pure-unless-callable-is-impure-tag-value-node.js +18 -0
  19. package/dist/phpdoc-parser/ast/php-doc/require-extends-tag-value-node.d.ts +9 -0
  20. package/dist/phpdoc-parser/ast/php-doc/require-extends-tag-value-node.js +18 -0
  21. package/dist/phpdoc-parser/ast/php-doc/require-implements-tag-value-node.d.ts +9 -0
  22. package/dist/phpdoc-parser/ast/php-doc/require-implements-tag-value-node.js +18 -0
  23. package/dist/phpdoc-parser/ast/php-doc/sealed-tag-value-node.d.ts +9 -0
  24. package/dist/phpdoc-parser/ast/php-doc/sealed-tag-value-node.js +18 -0
  25. package/dist/phpdoc-parser/ast/php-doc/template-tag-value-node.d.ts +2 -1
  26. package/dist/phpdoc-parser/ast/php-doc/template-tag-value-node.js +4 -2
  27. package/dist/phpdoc-parser/ast/type/array-shape-item-node.d.ts +3 -2
  28. package/dist/phpdoc-parser/ast/type/array-shape-node.d.ts +8 -2
  29. package/dist/phpdoc-parser/ast/type/array-shape-node.js +13 -3
  30. package/dist/phpdoc-parser/ast/type/array-shape-unsealed-type-node.d.ts +8 -0
  31. package/dist/phpdoc-parser/ast/type/array-shape-unsealed-type-node.js +21 -0
  32. package/dist/phpdoc-parser/ast/type/callable-type-node.d.ts +3 -1
  33. package/dist/phpdoc-parser/ast/type/callable-type-node.js +4 -2
  34. package/dist/phpdoc-parser/ast/types.d.ts +2 -1
  35. package/dist/phpdoc-parser/ast/types.js +1 -0
  36. package/dist/phpdoc-parser/lexer/lexer.d.ts +2 -0
  37. package/dist/phpdoc-parser/lexer/lexer.js +3 -0
  38. package/dist/phpdoc-parser/parser/const-expr-parser.d.ts +2 -4
  39. package/dist/phpdoc-parser/parser/const-expr-parser.js +6 -20
  40. package/dist/phpdoc-parser/parser/php-doc-parser.d.ts +11 -9
  41. package/dist/phpdoc-parser/parser/php-doc-parser.js +112 -66
  42. package/dist/phpdoc-parser/parser/string-unescaper.js +2 -2
  43. package/dist/phpdoc-parser/parser/token-iterator.d.ts +4 -0
  44. package/dist/phpdoc-parser/parser/token-iterator.js +31 -3
  45. package/dist/phpdoc-parser/parser/type-parser.d.ts +8 -2
  46. package/dist/phpdoc-parser/parser/type-parser.js +205 -76
  47. package/dist/phpdoc-parser/parser-config.d.ts +10 -0
  48. package/dist/phpdoc-parser/parser-config.js +12 -0
  49. package/dist/phpdoc-parser/transpiler/php-doc-to-typescript-type-transpiler.js +9 -2
  50. package/package.json +8 -5
  51. package/dist/phpdoc-parser/ast/const-expr/quote-aware-const-expr-string-node.d.ts +0 -10
  52. package/dist/phpdoc-parser/ast/const-expr/quote-aware-const-expr-string-node.js +0 -47
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ArrayShapeUnsealedTypeNode = void 0;
4
+ const type_node_1 = require("./type-node");
5
+ class ArrayShapeUnsealedTypeNode extends type_node_1.TypeNode {
6
+ constructor(valueType, keyType) {
7
+ super();
8
+ this.valueType = valueType;
9
+ this.keyType = keyType;
10
+ }
11
+ toString() {
12
+ if (this.keyType !== null) {
13
+ return `<${this.keyType.toString()}, ${this.valueType.toString()}>`;
14
+ }
15
+ return `<${this.valueType.toString()}>`;
16
+ }
17
+ getNodeType() {
18
+ return 'ArrayShapeUnsealedTypeNode';
19
+ }
20
+ }
21
+ exports.ArrayShapeUnsealedTypeNode = ArrayShapeUnsealedTypeNode;
@@ -1,3 +1,4 @@
1
+ import type { TemplateTagValueNode } from '../php-doc/template-tag-value-node';
1
2
  import type { CallableTypeParameterNode } from './callable-type-parameter-node';
2
3
  import type { IdentifierTypeNode } from './identifier-type-node';
3
4
  import { TypeNode } from './type-node';
@@ -5,7 +6,8 @@ export declare class CallableTypeNode extends TypeNode {
5
6
  identifier: IdentifierTypeNode;
6
7
  parameters: CallableTypeParameterNode[];
7
8
  returnType: TypeNode;
8
- constructor(identifier: IdentifierTypeNode, parameters: CallableTypeParameterNode[], returnType: TypeNode);
9
+ templateTypes: TemplateTagValueNode[];
10
+ constructor(identifier: IdentifierTypeNode, parameters: CallableTypeParameterNode[], returnType: TypeNode, templateTypes?: TemplateTagValueNode[]);
9
11
  toString(): string;
10
12
  getNodeType(): string;
11
13
  }
@@ -3,19 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CallableTypeNode = void 0;
4
4
  const type_node_1 = require("./type-node");
5
5
  class CallableTypeNode extends type_node_1.TypeNode {
6
- constructor(identifier, parameters, returnType) {
6
+ constructor(identifier, parameters, returnType, templateTypes = []) {
7
7
  super();
8
8
  this.identifier = identifier;
9
9
  this.parameters = parameters;
10
10
  this.returnType = returnType;
11
+ this.templateTypes = templateTypes;
11
12
  }
12
13
  toString() {
13
14
  let { returnType } = this;
14
15
  if (returnType instanceof CallableTypeNode) {
15
16
  returnType = `(${returnType.toString()})`;
16
17
  }
18
+ const template = this.templateTypes.length > 0 ? `<${this.templateTypes.join(', ')}>` : '';
17
19
  const parameters = this.parameters.join(', ');
18
- return `${this.identifier.toString()}(${parameters}): ${returnType.toString()}`;
20
+ return `${this.identifier.toString()}${template}(${parameters}): ${returnType.toString()}`;
19
21
  }
20
22
  getNodeType() {
21
23
  return 'CallableTypeNode';
@@ -9,5 +9,6 @@ export declare enum Attribute {
9
9
  END_LINE = "endLine",
10
10
  START_INDEX = "startIndex",
11
11
  END_INDEX = "endIndex",
12
- ORIGINAL_NODE = "originalNode"
12
+ ORIGINAL_NODE = "originalNode",
13
+ COMMENTS = "comments"
13
14
  }
@@ -15,4 +15,5 @@ var Attribute;
15
15
  Attribute["START_INDEX"] = "startIndex";
16
16
  Attribute["END_INDEX"] = "endIndex";
17
17
  Attribute["ORIGINAL_NODE"] = "originalNode";
18
+ Attribute["COMMENTS"] = "comments";
18
19
  })(Attribute || (exports.Attribute = Attribute = {}));
@@ -34,6 +34,7 @@ export declare class Lexer {
34
34
  static TOKEN_CLOSE_CURLY_BRACKET: string;
35
35
  static TOKEN_NEGATED: string;
36
36
  static TOKEN_ARROW: string;
37
+ static TOKEN_COMMENT: string;
37
38
  static TOKEN_LABELS: {
38
39
  [Lexer.TOKEN_REFERENCE]: string;
39
40
  [Lexer.TOKEN_UNION]: string;
@@ -49,6 +50,7 @@ export declare class Lexer {
49
50
  [Lexer.TOKEN_OPEN_CURLY_BRACKET]: string;
50
51
  [Lexer.TOKEN_CLOSE_CURLY_BRACKET]: string;
51
52
  [Lexer.TOKEN_COMMA]: string;
53
+ [Lexer.TOKEN_COMMENT]: string;
52
54
  [Lexer.TOKEN_COLON]: string;
53
55
  [Lexer.TOKEN_VARIADIC]: string;
54
56
  [Lexer.TOKEN_DOUBLE_COLON]: string;
@@ -40,6 +40,7 @@ class Lexer {
40
40
  [Lexer.TOKEN_OPEN_CURLY_BRACKET]: '\\{',
41
41
  [Lexer.TOKEN_CLOSE_CURLY_BRACKET]: '\\}',
42
42
  [Lexer.TOKEN_COMMA]: ',',
43
+ [Lexer.TOKEN_COMMENT]: '\\/\\/[^\\r\\n]*(?=\\n|\\r|\\*\\/)',
43
44
  [Lexer.TOKEN_VARIADIC]: '\\.\\.\\.',
44
45
  [Lexer.TOKEN_DOUBLE_COLON]: '::',
45
46
  [Lexer.TOKEN_DOUBLE_ARROW]: '=>',
@@ -101,6 +102,7 @@ Lexer.TOKEN_OPEN_CURLY_BRACKET = 'TOKEN_OPEN_CURLY_BRACKET';
101
102
  Lexer.TOKEN_CLOSE_CURLY_BRACKET = 'TOKEN_CLOSE_CURLY_BRACKET';
102
103
  Lexer.TOKEN_NEGATED = 'TOKEN_NEGATED';
103
104
  Lexer.TOKEN_ARROW = 'TOKEN_ARROW';
105
+ Lexer.TOKEN_COMMENT = 'TOKEN_COMMENT';
104
106
  Lexer.TOKEN_LABELS = {
105
107
  [Lexer.TOKEN_REFERENCE]: '&',
106
108
  [Lexer.TOKEN_UNION]: '|',
@@ -116,6 +118,7 @@ Lexer.TOKEN_LABELS = {
116
118
  [Lexer.TOKEN_OPEN_CURLY_BRACKET]: '{',
117
119
  [Lexer.TOKEN_CLOSE_CURLY_BRACKET]: '}',
118
120
  [Lexer.TOKEN_COMMA]: ',',
121
+ [Lexer.TOKEN_COMMENT]: '//',
119
122
  [Lexer.TOKEN_COLON]: ':',
120
123
  [Lexer.TOKEN_VARIADIC]: '...',
121
124
  [Lexer.TOKEN_DOUBLE_COLON]: '::',
@@ -1,15 +1,13 @@
1
1
  import type { ConstExprNode } from '../ast/const-expr/const-expr-node';
2
2
  import type { TokenIterator } from './token-iterator';
3
3
  export declare class ConstExprParser {
4
- private unescapeStrings;
5
- private quoteAwareConstExprString;
6
4
  private useLinesAttributes;
7
5
  private useIndexAttributes;
8
- constructor(unescapeStrings?: boolean, quoteAwareConstExprString?: boolean, usedAttributes?: {
6
+ constructor(usedAttributes?: {
9
7
  lines?: boolean;
10
8
  indexes?: boolean;
11
9
  });
12
- parse(tokens: TokenIterator, trimStrings?: boolean): ConstExprNode;
10
+ parse(tokens: TokenIterator): ConstExprNode;
13
11
  private parseArray;
14
12
  private parseArrayItem;
15
13
  private enrichWithAttributes;
@@ -10,20 +10,17 @@ const const_expr_null_node_1 = require("../ast/const-expr/const-expr-null-node")
10
10
  const const_expr_string_node_1 = require("../ast/const-expr/const-expr-string-node");
11
11
  const const_expr_true_node_1 = require("../ast/const-expr/const-expr-true-node");
12
12
  const const_fetch_node_1 = require("../ast/const-expr/const-fetch-node");
13
- const quote_aware_const_expr_string_node_1 = require("../ast/const-expr/quote-aware-const-expr-string-node");
14
13
  const types_1 = require("../ast/types");
15
14
  const lexer_1 = require("../lexer/lexer");
16
15
  const parser_exception_1 = require("./parser-exception");
17
16
  const string_unescaper_1 = require("./string-unescaper");
18
17
  class ConstExprParser {
19
- constructor(unescapeStrings = false, quoteAwareConstExprString = false, usedAttributes = {}) {
18
+ constructor(usedAttributes = {}) {
20
19
  var _a, _b;
21
- this.unescapeStrings = unescapeStrings;
22
- this.quoteAwareConstExprString = quoteAwareConstExprString;
23
20
  this.useLinesAttributes = (_a = usedAttributes.lines) !== null && _a !== void 0 ? _a : false;
24
21
  this.useIndexAttributes = (_b = usedAttributes.indexes) !== null && _b !== void 0 ? _b : false;
25
22
  }
26
- parse(tokens, trimStrings = false) {
23
+ parse(tokens) {
27
24
  const startLine = tokens.currentTokenLine();
28
25
  const startIndex = tokens.currentTokenIndex();
29
26
  if (tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_FLOAT)) {
@@ -37,23 +34,12 @@ class ConstExprParser {
37
34
  return this.enrichWithAttributes(tokens, new const_expr_integer_node_1.ConstExprIntegerNode(value.replaceAll('_', '')), startLine, startIndex);
38
35
  }
39
36
  if (tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_SINGLE_QUOTED_STRING, lexer_1.Lexer.TOKEN_DOUBLE_QUOTED_STRING)) {
40
- let value = tokens.currentTokenValue();
37
+ const value = string_unescaper_1.StringUnescaper.unescapeString(tokens.currentTokenValue());
41
38
  const type = tokens.currentTokenType();
42
- if (trimStrings) {
43
- if (this.unescapeStrings) {
44
- value = string_unescaper_1.StringUnescaper.unescapeString(value);
45
- }
46
- else {
47
- value = value.substring(1, value.length - 1);
48
- }
49
- }
50
39
  tokens.next();
51
- if (this.quoteAwareConstExprString) {
52
- return this.enrichWithAttributes(tokens, new quote_aware_const_expr_string_node_1.QuoteAwareConstExprStringNode(value, type === lexer_1.Lexer.TOKEN_SINGLE_QUOTED_STRING
53
- ? quote_aware_const_expr_string_node_1.QuoteAwareConstExprStringNode.SINGLE_QUOTED
54
- : quote_aware_const_expr_string_node_1.QuoteAwareConstExprStringNode.DOUBLE_QUOTED), startLine, startIndex);
55
- }
56
- return this.enrichWithAttributes(tokens, new const_expr_string_node_1.ConstExprStringNode(value), startLine, startIndex);
40
+ return this.enrichWithAttributes(tokens, new const_expr_string_node_1.ConstExprStringNode(value, type === lexer_1.Lexer.TOKEN_SINGLE_QUOTED_STRING
41
+ ? const_expr_string_node_1.ConstExprStringNode.SINGLE_QUOTED
42
+ : const_expr_string_node_1.ConstExprStringNode.DOUBLE_QUOTED), startLine, startIndex);
57
43
  }
58
44
  if (tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_IDENTIFIER)) {
59
45
  const identifier = tokens.currentTokenValue();
@@ -7,17 +7,13 @@ import type { TypeParser } from './type-parser';
7
7
  export declare class PhpDocParser {
8
8
  typeParser: TypeParser;
9
9
  constantExprParser: ConstExprParser;
10
- requireWhitespaceBeforeDescription: boolean;
11
- preserveTypeAliasesWithInvalidTypes: boolean;
12
- parseDoctrineAnnotations: boolean;
13
- private textBetweenTagsBelongsToDescription;
14
10
  private useLinesAttributes;
15
11
  private useIndexAttributes;
16
12
  private static readonly DISALLOWED_DESCRIPTION_START_TOKENS;
17
- constructor(typeParser: TypeParser, constantExprParser: ConstExprParser, requireWhitespaceBeforeDescription?: boolean, preserveTypeAliasesWithInvalidTypes?: boolean, usedAttributes?: {
18
- lines: boolean;
19
- indexes: boolean;
20
- }, parseDoctrineAnnotations?: boolean, textBetweenTagsBelongsToDescription?: boolean);
13
+ constructor(typeParser: TypeParser, constantExprParser: ConstExprParser, usedAttributes?: {
14
+ lines?: boolean;
15
+ indexes?: boolean;
16
+ });
21
17
  parse(tokens: TokenIterator): PhpDocNode;
22
18
  private parseChild;
23
19
  private enrichWithAttributes;
@@ -30,10 +26,16 @@ export declare class PhpDocParser {
30
26
  private parseThrowsTagValue;
31
27
  private parseMixinTagValue;
32
28
  private parseDeprecatedTagValue;
29
+ private parseParamImmediatelyInvokedCallableTagValue;
30
+ private parseParamLaterInvokedCallableTagValue;
31
+ private parseParamClosureThisTagValue;
32
+ private parsePureUnlessCallableIsImpureTagValue;
33
+ private parseRequireExtendsTagValue;
34
+ private parseRequireImplementsTagValue;
35
+ private parseSealedTagValue;
33
36
  private parsePropertyTagValue;
34
37
  private parseMethodTagValue;
35
38
  private parseMethodTagValueParameter;
36
- private parseTemplateTagValue;
37
39
  private parseExtendsTagValue;
38
40
  private parseTypeAliasTagValue;
39
41
  private parseTypeAliasImportTagValue;
@@ -12,15 +12,21 @@ const invalid_tag_value_node_1 = require("../ast/php-doc/invalid-tag-value-node"
12
12
  const method_tag_value_node_1 = require("../ast/php-doc/method-tag-value-node");
13
13
  const method_tag_value_parameter_node_1 = require("../ast/php-doc/method-tag-value-parameter-node");
14
14
  const mixin_tag_value_node_1 = require("../ast/php-doc/mixin-tag-value-node");
15
+ const param_closure_this_tag_value_node_1 = require("../ast/php-doc/param-closure-this-tag-value-node");
16
+ const param_immediately_invoked_callable_tag_value_node_1 = require("../ast/php-doc/param-immediately-invoked-callable-tag-value-node");
17
+ const param_later_invoked_callable_tag_value_node_1 = require("../ast/php-doc/param-later-invoked-callable-tag-value-node");
15
18
  const param_out_tag_value_node_1 = require("../ast/php-doc/param-out-tag-value-node");
16
19
  const param_tag_value_node_1 = require("../ast/php-doc/param-tag-value-node");
17
20
  const php_doc_node_1 = require("../ast/php-doc/php-doc-node");
18
21
  const php_doc_tag_node_1 = require("../ast/php-doc/php-doc-tag-node");
19
22
  const php_doc_text_node_1 = require("../ast/php-doc/php-doc-text-node");
20
23
  const property_tag_value_node_1 = require("../ast/php-doc/property-tag-value-node");
24
+ const pure_unless_callable_is_impure_tag_value_node_1 = require("../ast/php-doc/pure-unless-callable-is-impure-tag-value-node");
25
+ const require_extends_tag_value_node_1 = require("../ast/php-doc/require-extends-tag-value-node");
26
+ const require_implements_tag_value_node_1 = require("../ast/php-doc/require-implements-tag-value-node");
21
27
  const return_tag_value_node_1 = require("../ast/php-doc/return-tag-value-node");
28
+ const sealed_tag_value_node_1 = require("../ast/php-doc/sealed-tag-value-node");
22
29
  const self_out_tag_value_node_1 = require("../ast/php-doc/self-out-tag-value-node");
23
- const template_tag_value_node_1 = require("../ast/php-doc/template-tag-value-node");
24
30
  const throws_tag_value_node_1 = require("../ast/php-doc/throws-tag-value-node");
25
31
  const type_alias_import_tag_value_node_1 = require("../ast/php-doc/type-alias-import-tag-value-node");
26
32
  const type_alias_tag_value_node_1 = require("../ast/php-doc/type-alias-tag-value-node");
@@ -36,17 +42,10 @@ const DISALLOWED_DESCRIPTION_START_TOKENS = [
36
42
  lexer_1.Lexer.TOKEN_INTERSECTION,
37
43
  ];
38
44
  class PhpDocParser {
39
- constructor(typeParser, constantExprParser, requireWhitespaceBeforeDescription = false, preserveTypeAliasesWithInvalidTypes = false, usedAttributes = {
40
- lines: false,
41
- indexes: false,
42
- }, parseDoctrineAnnotations = false, textBetweenTagsBelongsToDescription = false) {
45
+ constructor(typeParser, constantExprParser, usedAttributes = {}) {
43
46
  var _a, _b;
44
47
  this.typeParser = typeParser;
45
48
  this.constantExprParser = constantExprParser;
46
- this.requireWhitespaceBeforeDescription = requireWhitespaceBeforeDescription;
47
- this.preserveTypeAliasesWithInvalidTypes = preserveTypeAliasesWithInvalidTypes;
48
- this.parseDoctrineAnnotations = parseDoctrineAnnotations;
49
- this.textBetweenTagsBelongsToDescription = textBetweenTagsBelongsToDescription;
50
49
  this.useLinesAttributes = (_a = usedAttributes.lines) !== null && _a !== void 0 ? _a : false;
51
50
  this.useIndexAttributes = (_b = usedAttributes.indexes) !== null && _b !== void 0 ? _b : false;
52
51
  }
@@ -109,32 +108,22 @@ class PhpDocParser {
109
108
  parseText(tokens) {
110
109
  var _a, _b;
111
110
  let text = '';
112
- let endTokens = [
113
- lexer_1.Lexer.TOKEN_PHPDOC_EOL,
114
- lexer_1.Lexer.TOKEN_CLOSE_PHPDOC,
115
- lexer_1.Lexer.TOKEN_END,
116
- ];
117
- if (this.textBetweenTagsBelongsToDescription) {
118
- endTokens = [lexer_1.Lexer.TOKEN_CLOSE_PHPDOC, lexer_1.Lexer.TOKEN_END];
119
- }
111
+ const endTokens = [lexer_1.Lexer.TOKEN_CLOSE_PHPDOC, lexer_1.Lexer.TOKEN_END];
120
112
  let savepoint = false;
121
- while (this.textBetweenTagsBelongsToDescription ||
122
- !tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_PHPDOC_EOL)) {
113
+ while (true) {
123
114
  const tmpText = tokens.getSkippedHorizontalWhiteSpaceIfAny() +
124
115
  tokens.joinUntil(lexer_1.Lexer.TOKEN_PHPDOC_EOL, ...endTokens);
125
116
  text += tmpText;
126
117
  if (!tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_PHPDOC_EOL)) {
127
118
  break;
128
119
  }
129
- if (this.textBetweenTagsBelongsToDescription) {
130
- if (!savepoint) {
131
- tokens.pushSavePoint();
132
- savepoint = true;
133
- }
134
- else if (tmpText !== '') {
135
- tokens.dropSavePoint();
136
- tokens.pushSavePoint();
137
- }
120
+ if (!savepoint) {
121
+ tokens.pushSavePoint();
122
+ savepoint = true;
123
+ }
124
+ else if (tmpText !== '') {
125
+ tokens.dropSavePoint();
126
+ tokens.pushSavePoint();
138
127
  }
139
128
  tokens.pushSavePoint();
140
129
  tokens.next();
@@ -167,16 +156,36 @@ class PhpDocParser {
167
156
  case '@param':
168
157
  case '@phpstan-param':
169
158
  case '@psalm-param':
159
+ case '@phan-param':
170
160
  tagValue = this.parseParamTagValue(tokens);
171
161
  break;
162
+ case '@param-immediately-invoked-callable':
163
+ case '@phpstan-param-immediately-invoked-callable':
164
+ tagValue = this.parseParamImmediatelyInvokedCallableTagValue(tokens);
165
+ break;
166
+ case '@param-later-invoked-callable':
167
+ case '@phpstan-param-later-invoked-callable':
168
+ tagValue = this.parseParamLaterInvokedCallableTagValue(tokens);
169
+ break;
170
+ case '@param-closure-this':
171
+ case '@phpstan-param-closure-this':
172
+ tagValue = this.parseParamClosureThisTagValue(tokens);
173
+ break;
174
+ case '@pure-unless-callable-is-impure':
175
+ case '@phpstan-pure-unless-callable-is-impure':
176
+ tagValue = this.parsePureUnlessCallableIsImpureTagValue(tokens);
177
+ break;
172
178
  case '@var':
173
179
  case '@phpstan-var':
174
180
  case '@psalm-var':
181
+ case '@phan-var':
175
182
  tagValue = this.parseVarTagValue(tokens);
176
183
  break;
177
184
  case '@return':
178
185
  case '@phpstan-return':
179
186
  case '@psalm-return':
187
+ case '@phan-return':
188
+ case '@phan-real-return':
180
189
  tagValue = this.parseReturnTagValue(tokens);
181
190
  break;
182
191
  case '@throws':
@@ -184,8 +193,21 @@ class PhpDocParser {
184
193
  tagValue = this.parseThrowsTagValue(tokens);
185
194
  break;
186
195
  case '@mixin':
196
+ case '@phan-mixin':
187
197
  tagValue = this.parseMixinTagValue(tokens);
188
198
  break;
199
+ case '@psalm-require-extends':
200
+ case '@phpstan-require-extends':
201
+ tagValue = this.parseRequireExtendsTagValue(tokens);
202
+ break;
203
+ case '@psalm-require-implements':
204
+ case '@phpstan-require-implements':
205
+ tagValue = this.parseRequireImplementsTagValue(tokens);
206
+ break;
207
+ case '@psalm-inheritors':
208
+ case '@phpstan-sealed':
209
+ tagValue = this.parseSealedTagValue(tokens);
210
+ break;
189
211
  case '@deprecated':
190
212
  tagValue = this.parseDeprecatedTagValue(tokens);
191
213
  break;
@@ -198,26 +220,33 @@ class PhpDocParser {
198
220
  case '@psalm-property':
199
221
  case '@psalm-property-read':
200
222
  case '@psalm-property-write':
223
+ case '@phan-property':
224
+ case '@phan-property-read':
225
+ case '@phan-property-write':
201
226
  tagValue = this.parsePropertyTagValue(tokens);
202
227
  break;
203
228
  case '@method':
204
229
  case '@phpstan-method':
205
230
  case '@psalm-method':
231
+ case '@phan-method':
206
232
  tagValue = this.parseMethodTagValue(tokens);
207
233
  break;
208
234
  case '@template':
209
235
  case '@phpstan-template':
210
236
  case '@psalm-template':
237
+ case '@phan-template':
211
238
  case '@template-covariant':
212
239
  case '@phpstan-template-covariant':
213
240
  case '@psalm-template-covariant':
214
241
  case '@template-contravariant':
215
242
  case '@phpstan-template-contravariant':
216
243
  case '@psalm-template-contravariant':
217
- tagValue = this.parseTemplateTagValue(tokens, true);
244
+ tagValue = this.typeParser.parseTemplateTagValue(tokens, (t) => this.parseOptionalDescription(t, true));
218
245
  break;
219
246
  case '@extends':
220
247
  case '@phpstan-extends':
248
+ case '@phan-extends':
249
+ case '@phan-inherits':
221
250
  case '@template-extends':
222
251
  tagValue = this.parseExtendsTagValue('@extends', tokens);
223
252
  break;
@@ -233,6 +262,7 @@ class PhpDocParser {
233
262
  break;
234
263
  case '@phpstan-type':
235
264
  case '@psalm-type':
265
+ case '@phan-type':
236
266
  tagValue = this.parseTypeAliasTagValue(tokens);
237
267
  break;
238
268
  case '@phpstan-import-type':
@@ -245,6 +275,9 @@ class PhpDocParser {
245
275
  case '@psalm-assert':
246
276
  case '@psalm-assert-if-true':
247
277
  case '@psalm-assert-if-false':
278
+ case '@phan-assert':
279
+ case '@phan-assert-if-true':
280
+ case '@phan-assert-if-false':
248
281
  tagValue = this.parseAssertTagValue(tokens);
249
282
  break;
250
283
  case '@phpstan-this-out':
@@ -309,6 +342,42 @@ class PhpDocParser {
309
342
  const description = this.parseOptionalDescription(tokens);
310
343
  return new deprecated_tag_value_node_1.DeprecatedTagValueNode(description);
311
344
  }
345
+ parseParamImmediatelyInvokedCallableTagValue(tokens) {
346
+ const parameterName = this.parseRequiredVariableName(tokens);
347
+ const description = this.parseOptionalDescription(tokens);
348
+ return new param_immediately_invoked_callable_tag_value_node_1.ParamImmediatelyInvokedCallableTagValueNode(parameterName, description);
349
+ }
350
+ parseParamLaterInvokedCallableTagValue(tokens) {
351
+ const parameterName = this.parseRequiredVariableName(tokens);
352
+ const description = this.parseOptionalDescription(tokens);
353
+ return new param_later_invoked_callable_tag_value_node_1.ParamLaterInvokedCallableTagValueNode(parameterName, description);
354
+ }
355
+ parseParamClosureThisTagValue(tokens) {
356
+ const type = this.typeParser.parse(tokens);
357
+ const parameterName = this.parseRequiredVariableName(tokens);
358
+ const description = this.parseOptionalDescription(tokens);
359
+ return new param_closure_this_tag_value_node_1.ParamClosureThisTagValueNode(type, parameterName, description);
360
+ }
361
+ parsePureUnlessCallableIsImpureTagValue(tokens) {
362
+ const parameterName = this.parseRequiredVariableName(tokens);
363
+ const description = this.parseOptionalDescription(tokens);
364
+ return new pure_unless_callable_is_impure_tag_value_node_1.PureUnlessCallableIsImpureTagValueNode(parameterName, description);
365
+ }
366
+ parseRequireExtendsTagValue(tokens) {
367
+ const type = this.typeParser.parse(tokens);
368
+ const description = this.parseOptionalDescription(tokens, true);
369
+ return new require_extends_tag_value_node_1.RequireExtendsTagValueNode(type, description);
370
+ }
371
+ parseRequireImplementsTagValue(tokens) {
372
+ const type = this.typeParser.parse(tokens);
373
+ const description = this.parseOptionalDescription(tokens, true);
374
+ return new require_implements_tag_value_node_1.RequireImplementsTagValueNode(type, description);
375
+ }
376
+ parseSealedTagValue(tokens) {
377
+ const type = this.typeParser.parse(tokens);
378
+ const description = this.parseOptionalDescription(tokens, true);
379
+ return new sealed_tag_value_node_1.SealedTagValueNode(type, description);
380
+ }
312
381
  parsePropertyTagValue(tokens) {
313
382
  const type = this.typeParser.parse(tokens);
314
383
  const name = this.parseRequiredVariableName(tokens);
@@ -342,7 +411,7 @@ class PhpDocParser {
342
411
  do {
343
412
  startLine = tokens.currentTokenLine();
344
413
  startIndex = tokens.currentTokenIndex();
345
- const templateType = this.parseTemplateTagValue(tokens, false);
414
+ const templateType = this.typeParser.parseTemplateTagValue(tokens);
346
415
  templateTypes.push(this.enrichWithAttributes(tokens, templateType, startLine, startIndex));
347
416
  } while (tokens.tryConsumeTokenType(lexer_1.Lexer.TOKEN_COMMA));
348
417
  tokens.consumeTokenType(lexer_1.Lexer.TOKEN_CLOSE_ANGLE_BRACKET);
@@ -383,24 +452,6 @@ class PhpDocParser {
383
452
  }
384
453
  return this.enrichWithAttributes(tokens, new method_tag_value_parameter_node_1.MethodTagValueParameterNode(type, isReference, isVariadic, name, defaultValue), startLine, startIndex);
385
454
  }
386
- parseTemplateTagValue(tokens, parseDescription) {
387
- const name = tokens.currentTokenValue();
388
- tokens.consumeTokenType(lexer_1.Lexer.TOKEN_IDENTIFIER);
389
- let bound = null;
390
- if (tokens.tryConsumeTokenValue('of') ||
391
- tokens.tryConsumeTokenValue('as')) {
392
- bound = this.typeParser.parse(tokens);
393
- }
394
- let defaultValue = null;
395
- if (tokens.tryConsumeTokenValue('=')) {
396
- defaultValue = this.typeParser.parse(tokens);
397
- }
398
- let description = '';
399
- if (parseDescription) {
400
- description = this.parseOptionalDescription(tokens);
401
- }
402
- return new template_tag_value_node_1.TemplateTagValueNode(name, bound, description, defaultValue);
403
- }
404
455
  parseExtendsTagValue(tagName, tokens) {
405
456
  const startLine = tokens.currentTokenLine();
406
457
  const startIndex = tokens.currentTokenIndex();
@@ -423,25 +474,21 @@ class PhpDocParser {
423
474
  const alias = tokens.currentTokenValue();
424
475
  tokens.consumeTokenType(lexer_1.Lexer.TOKEN_IDENTIFIER);
425
476
  tokens.tryConsumeTokenType(lexer_1.Lexer.TOKEN_EQUAL);
426
- if (this.preserveTypeAliasesWithInvalidTypes) {
427
- const startLine = tokens.currentTokenLine();
428
- const startIndex = tokens.currentTokenIndex();
429
- try {
430
- const type = this.typeParser.parse(tokens);
431
- if (!tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_CLOSE_PHPDOC)) {
432
- if (!tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_PHPDOC_EOL)) {
433
- throw new Error('Expected end of line');
434
- }
477
+ const startLine = tokens.currentTokenLine();
478
+ const startIndex = tokens.currentTokenIndex();
479
+ try {
480
+ const type = this.typeParser.parse(tokens);
481
+ if (!tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_CLOSE_PHPDOC)) {
482
+ if (!tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_PHPDOC_EOL)) {
483
+ throw new Error('Expected end of line');
435
484
  }
436
- return new type_alias_tag_value_node_1.TypeAliasTagValueNode(alias, type);
437
- }
438
- catch (e) {
439
- this.parseOptionalDescription(tokens);
440
- return new type_alias_tag_value_node_1.TypeAliasTagValueNode(alias, this.enrichWithAttributes(tokens, new invalid_type_node_1.InvalidTypeNode(e), startLine, startIndex));
441
485
  }
486
+ return new type_alias_tag_value_node_1.TypeAliasTagValueNode(alias, type);
487
+ }
488
+ catch (e) {
489
+ this.parseOptionalDescription(tokens);
490
+ return new type_alias_tag_value_node_1.TypeAliasTagValueNode(alias, this.enrichWithAttributes(tokens, new invalid_type_node_1.InvalidTypeNode(e), startLine, startIndex));
442
491
  }
443
- const type = this.typeParser.parse(tokens);
444
- return new type_alias_tag_value_node_1.TypeAliasTagValueNode(alias, type);
445
492
  }
446
493
  parseTypeAliasImportTagValue(tokens) {
447
494
  const importedAlias = tokens.currentTokenValue();
@@ -542,8 +589,7 @@ class PhpDocParser {
542
589
  }
543
590
  tokens.consumeTokenType(lexer_1.Lexer.TOKEN_OTHER);
544
591
  }
545
- if (this.requireWhitespaceBeforeDescription &&
546
- !tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_PHPDOC_EOL, lexer_1.Lexer.TOKEN_CLOSE_PHPDOC, lexer_1.Lexer.TOKEN_END) &&
592
+ if (!tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_PHPDOC_EOL, lexer_1.Lexer.TOKEN_CLOSE_PHPDOC, lexer_1.Lexer.TOKEN_END) &&
547
593
  !tokens.isPrecededByHorizontalWhitespace()) {
548
594
  tokens.consumeTokenType(lexer_1.Lexer.TOKEN_HORIZONTAL_WS);
549
595
  }
@@ -5,12 +5,12 @@ class StringUnescaper {
5
5
  static unescapeString(input) {
6
6
  const quote = input[0];
7
7
  if (quote === "'") {
8
- return input.slice(1, input.length - 1).replaceAll(/\\([\\\.])/g, '$1');
8
+ return input.slice(1, input.length - 1).replaceAll(/\\([\\'])/g, '$1');
9
9
  }
10
10
  return this.parseEscapeSequences(input.slice(1, input.length - 1), '"');
11
11
  }
12
12
  static parseEscapeSequences(input, quote) {
13
- input = input.replaceAll(new RegExp(`\\${quote}`, 'g'), quote);
13
+ input = input.replaceAll(new RegExp(`\\\\${quote}`, 'g'), quote);
14
14
  return input.replaceAll(/\\([\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\{([0-9a-fA-F]+)\})/g, (substring, ...matches) => {
15
15
  const firstCaptureGroup = matches[0];
16
16
  if (this.REPLACEMENTS[firstCaptureGroup]) {
@@ -1,6 +1,8 @@
1
+ import { Comment } from '../ast/comment';
1
2
  export declare class TokenIterator {
2
3
  private tokens;
3
4
  private index;
5
+ private comments;
4
6
  private savePoints;
5
7
  private skippedTokenTypes;
6
8
  private newline;
@@ -21,6 +23,8 @@ export declare class TokenIterator {
21
23
  consumeTokenValue(tokenType: string, tokenValue: string): void;
22
24
  tryConsumeTokenValue(tokenValue: string): boolean;
23
25
  tryConsumeTokenType(tokenType: string): boolean;
26
+ flushComments(): Comment[];
27
+ skipNewLineTokensAndConsumeComments(): void;
24
28
  private detectNewline;
25
29
  getSkippedHorizontalWhiteSpaceIfAny(): string;
26
30
  joinUntil(...tokenType: string[]): string;
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TokenIterator = void 0;
4
+ const comment_1 = require("../ast/comment");
4
5
  const lexer_1 = require("../lexer/lexer");
5
6
  const parser_exception_1 = require("./parser-exception");
6
7
  class TokenIterator {
7
8
  constructor(tokens, index = 0) {
9
+ this.comments = [];
8
10
  this.savePoints = [];
9
11
  this.skippedTokenTypes = [lexer_1.Lexer.TOKEN_HORIZONTAL_WS];
10
12
  this.newline = null;
@@ -110,6 +112,29 @@ class TokenIterator {
110
112
  this.skipIrrelevantTokens();
111
113
  return true;
112
114
  }
115
+ flushComments() {
116
+ const res = this.comments;
117
+ this.comments = [];
118
+ return res;
119
+ }
120
+ skipNewLineTokensAndConsumeComments() {
121
+ if (this.currentTokenType() === lexer_1.Lexer.TOKEN_COMMENT) {
122
+ this.comments.push(new comment_1.Comment(this.currentTokenValue(), this.currentTokenLine(), this.currentTokenIndex()));
123
+ this.next();
124
+ }
125
+ if (!this.isCurrentTokenType(lexer_1.Lexer.TOKEN_PHPDOC_EOL)) {
126
+ return;
127
+ }
128
+ let foundNewLine;
129
+ do {
130
+ foundNewLine = this.tryConsumeTokenType(lexer_1.Lexer.TOKEN_PHPDOC_EOL);
131
+ if (this.currentTokenType() !== lexer_1.Lexer.TOKEN_COMMENT) {
132
+ continue;
133
+ }
134
+ this.comments.push(new comment_1.Comment(this.currentTokenValue(), this.currentTokenLine(), this.currentTokenIndex()));
135
+ this.next();
136
+ } while (foundNewLine);
137
+ }
113
138
  detectNewline() {
114
139
  const value = this.currentTokenValue();
115
140
  if (value.substring(0, 2) === '\r\n') {
@@ -162,14 +187,17 @@ class TokenIterator {
162
187
  this.index = lastToken;
163
188
  }
164
189
  pushSavePoint() {
165
- this.savePoints.push(this.index);
190
+ this.savePoints.push([this.index, [...this.comments]]);
166
191
  }
167
192
  dropSavePoint() {
168
193
  this.savePoints.pop();
169
194
  }
170
195
  rollback() {
171
- const index = this.savePoints.pop();
172
- this.index = index;
196
+ const savepoint = this.savePoints.pop();
197
+ if (savepoint === undefined) {
198
+ throw new Error('No save point to rollback to');
199
+ }
200
+ [this.index, this.comments] = savepoint;
173
201
  }
174
202
  throwError(expectedTokenType, expectedTokenValue = null) {
175
203
  throw new parser_exception_1.ParserException(this.currentTokenValue(), this.currentTokenType(), this.currentTokenOffset(), expectedTokenType, expectedTokenValue, this.currentTokenLine());