@@ -146,6 +146,10 @@ private void flowParseTypeInitialiser(TokenType tok, boolean allowLeadingPipeOrA
146146 boolean oldInType = inType ;
147147 inType = true ;
148148 this .expect (tok == null ? TokenType .colon : tok );
149+ if (this .type == TokenType .modulo ) {// an annotation like '%checks' without a preceeding type
150+ inType = oldInType ;
151+ return ;
152+ }
149153 if (allowLeadingPipeOrAnd ) {
150154 if (this .type == TokenType .bitwiseAND || this .type == TokenType .bitwiseOR ) {
151155 this .next ();
@@ -223,14 +227,29 @@ private void flowParseDeclareModule(Position start) {
223227 while (this .type != TokenType .braceR ) {
224228 Position stmtStart = startLoc ;
225229
226- // todo: declare check
227- this .next ();
230+ if (this .eat (TokenType ._import )) {
231+ this .flowParseDeclareImport (stmtStart );
232+ } else {
233+ // todo: declare check
234+ this .next ();
228235
229- this .flowParseDeclare (stmtStart );
236+ this .flowParseDeclare (stmtStart );
237+ }
230238 }
231239 this .expect (TokenType .braceR );
232240 }
233241
242+ private void flowParseDeclareImport (Position stmtStart ) {
243+ String kind = flowParseImportSpecifiers ();
244+ if (kind == null ) {
245+ this .raise (stmtStart , "Imports within a `declare module` body must always be `import type` or `import typeof`." );
246+ }
247+ this .expect (TokenType .name );
248+ this .expectContextual ("from" );
249+ this .expect (TokenType .string );
250+ this .semicolon ();
251+ }
252+
234253 private void flowParseDeclareModuleExports () {
235254 this .expectContextual ("module" );
236255 this .expect (TokenType .dot );
@@ -737,7 +756,7 @@ private void flowParsePrimaryType() {
737756
738757 private void flowParsePostfixType () {
739758 this .flowParsePrimaryType ();
740- if (this .type == TokenType .bracketL ) {
759+ while (this .type == TokenType .bracketL ) {
741760 this .expect (TokenType .bracketL );
742761 this .expect (TokenType .bracketR );
743762 }
@@ -807,11 +826,20 @@ protected Node parseFunctionBody(Identifier id, List<Expression> params, boolean
807826 // if allowExpression is true then we're parsing an arrow function and if
808827 // there's a return type then it's been handled elsewhere
809828 this .flowParseTypeAnnotation ();
829+ this .flowParseChecksAnnotation ();
810830 }
811831
812832 return super .parseFunctionBody (id , params , isArrowFunction );
813833 }
814834
835+ private void flowParseChecksAnnotation () {
836+ // predicate functions with the special '%checks' annotation
837+ if (this .type == TokenType .modulo && lookaheadIsIdent ("checks" , true )) {
838+ this .next ();
839+ this .next ();
840+ }
841+ }
842+
815843 // interfaces
816844 @ Override
817845 protected Statement parseStatement (boolean declaration , boolean topLevel , Set <String > exports ) {
@@ -975,24 +1003,30 @@ protected Expression processBindingListItem(Expression param) {
9751003 return param ;
9761004 }
9771005
1006+ private String flowParseImportSpecifiers () {
1007+ String kind = null ;
1008+ if (this .type == TokenType ._typeof ) {
1009+ kind = "typeof" ;
1010+ } else if (this .isContextual ("type" )) {
1011+ kind = "type" ;
1012+ }
1013+ if (kind != null ) {
1014+ String lh = lookahead (4 );
1015+ if (!lh .isEmpty ()) {
1016+ int c = lh .codePointAt (0 );
1017+ if ((Identifiers .isIdentifierStart (c , true ) && !"from" .equals (lh )) || c == '{' || c == '*' ) {
1018+ this .next ();
1019+ }
1020+ }
1021+ }
1022+ return kind ;
1023+ }
1024+
9781025 @ Override
9791026 protected List <ImportSpecifier > parseImportSpecifiers () {
9801027 String kind = null ;
9811028 if (flow ()) {
982- if (this .type == TokenType ._typeof ) {
983- kind = "typeof" ;
984- } else if (this .isContextual ("type" )) {
985- kind = "type" ;
986- }
987- if (kind != null ) {
988- String lh = lookahead (4 );
989- if (!lh .isEmpty ()) {
990- int c = lh .codePointAt (0 );
991- if ((Identifiers .isIdentifierStart (c , true ) && !"from" .equals (lh )) || c == '{' || c == '*' ) {
992- this .next ();
993- }
994- }
995- }
1029+ kind = flowParseImportSpecifiers ();
9961030 }
9971031
9981032 List <ImportSpecifier > specs = super .parseImportSpecifiers ();
@@ -1102,6 +1136,7 @@ protected ParenthesisedExpressions parseParenthesisedExpressions(DestructuringEr
11021136 boolean oldNoAnonFunctionType = noAnonFunctionType ;
11031137 noAnonFunctionType = true ;
11041138 flowParseTypeAnnotation ();
1139+ flowParseChecksAnnotation ();
11051140 noAnonFunctionType = oldNoAnonFunctionType ;
11061141 if (this .type != TokenType .arrow )
11071142 unexpected ();
@@ -1158,4 +1193,12 @@ protected void parsePropertyName(PropertyInfo result) {
11581193 this .eat (TokenType .plusMin );
11591194 super .parsePropertyName (result );
11601195 }
1196+
1197+ @ Override
1198+ protected boolean atGetterSetterName (PropertyInfo pi ) {
1199+ if (flow () && this .isRelational ("<" ))
1200+ return false ;
1201+ return super .atGetterSetterName (pi );
1202+ }
1203+
11611204}
0 commit comments