|
9 | 9 |
|
10 | 10 | import { |
11 | 11 | CommonFlags, |
| 12 | + Feature, |
12 | 13 | LIBRARY_PREFIX, |
13 | 14 | PATH_DELIMITER |
14 | 15 | } from "./common"; |
@@ -42,6 +43,7 @@ import { |
42 | 43 | TypeName, |
43 | 44 | NamedTypeNode, |
44 | 45 | FunctionTypeNode, |
| 46 | + TupleTypeNode, |
45 | 47 | ArrowKind, |
46 | 48 |
|
47 | 49 | Expression, |
@@ -90,6 +92,7 @@ import { |
90 | 92 |
|
91 | 93 | mangleInternalPath |
92 | 94 | } from "./ast"; |
| 95 | +import { Options } from "./compiler"; |
93 | 96 |
|
94 | 97 | /** Represents a dependee. */ |
95 | 98 | class Dependee { |
@@ -118,7 +121,9 @@ export class Parser extends DiagnosticEmitter { |
118 | 121 | sources: Source[]; |
119 | 122 | /** Current overridden module name. */ |
120 | 123 | currentModuleName: string | null = null; |
121 | | - |
| 124 | + // TODO: Remove when multi-value feature will enable by default. |
| 125 | + /** Compiler options. */ |
| 126 | + options: Options | null = null; |
122 | 127 | /** Constructs a new parser. */ |
123 | 128 | constructor( |
124 | 129 | diagnostics: DiagnosticMessage[] | null = null, |
@@ -563,6 +568,49 @@ export class Parser extends DiagnosticEmitter { |
563 | 568 | return null; |
564 | 569 | } |
565 | 570 |
|
| 571 | + // 'readonly' Type |
| 572 | + } else if (token == Token.Readonly) { |
| 573 | + let innerType = this.parseType(tn, acceptParenthesized, suppressErrors); |
| 574 | + if (!innerType) return null; |
| 575 | + type = innerType; |
| 576 | + type.range.start = startPos; |
| 577 | + |
| 578 | + // '[' ((Identifier ':')? Type (',' (Identifier ':')? Type)*)? ']' |
| 579 | + } else if (token == Token.OpenBracket && this.options && this.options!.hasFeature(Feature.MultiValue)) { |
| 580 | + let elements: TypeNode[] = []; |
| 581 | + let elementNames: (IdentifierExpression | null)[] = []; |
| 582 | + let hasElementNames = false; |
| 583 | + if (!tn.skip(Token.CloseBracket)) { |
| 584 | + do { |
| 585 | + let elementName: IdentifierExpression | null = null; |
| 586 | + let state = tn.mark(); |
| 587 | + if (tn.skip(Token.Identifier)) { |
| 588 | + let name = tn.readIdentifier(); |
| 589 | + let nameRange = tn.range(); |
| 590 | + if (tn.skip(Token.Colon)) { |
| 591 | + elementName = Node.createIdentifierExpression(name, nameRange); |
| 592 | + hasElementNames = true; |
| 593 | + } else { |
| 594 | + tn.reset(state); |
| 595 | + } |
| 596 | + } |
| 597 | + let element = this.parseType(tn, true, suppressErrors); |
| 598 | + if (!element) return null; |
| 599 | + elements.push(element); |
| 600 | + elementNames.push(elementName); |
| 601 | + } while (tn.skip(Token.Comma)); |
| 602 | + if (!tn.skip(Token.CloseBracket)) { |
| 603 | + if (!suppressErrors) { |
| 604 | + this.error( |
| 605 | + DiagnosticCode._0_expected, |
| 606 | + tn.range(tn.pos), "]" |
| 607 | + ); |
| 608 | + } |
| 609 | + return null; |
| 610 | + } |
| 611 | + } |
| 612 | + type = Node.createTupleType(elements, hasElementNames ? elementNames : null, false, tn.range(startPos, tn.pos)); |
| 613 | + |
566 | 614 | // 'void' |
567 | 615 | } else if (token == Token.Void) { |
568 | 616 | type = Node.createNamedType( |
@@ -4581,6 +4629,13 @@ function isCircularTypeAlias(name: string, type: TypeNode): bool { |
4581 | 4629 | } |
4582 | 4630 | break; |
4583 | 4631 | } |
| 4632 | + case NodeKind.TupleType: { |
| 4633 | + let elements = (<TupleTypeNode>type).elements; |
| 4634 | + for (let i = 0, k = elements.length; i < k; i++) { |
| 4635 | + if (isCircularTypeAlias(name, elements[i])) return true; |
| 4636 | + } |
| 4637 | + break; |
| 4638 | + } |
4584 | 4639 | default: assert(false); |
4585 | 4640 | } |
4586 | 4641 | return false; |
|
0 commit comments