Repository: rokucommunity/brighterscript
Pull request #954 (2023-11-22 13:45:04)

Fix param order for AST class constructors for interface/class members 
In order to maintain a little bit of backwards compatibility, moves the `optional` token to the end for `InterfaceMethodStatement`, `InterfaceFieldStatement`, and `FieldStatement`. 


Patch:
diff --git a/src/parser/Parser.ts b/src/parser/Parser.ts
index d3a98d9f..8de45bee 100644
--- a/src/parser/Parser.ts
+++ b/src/parser/Parser.ts
@@ -34,8 +34,8 @@ import {
     ExitForStatement,
     ExitWhileStatement,
     ExpressionStatement,
-    FieldStatement,
     ForEachStatement,
+    FieldStatement,
     ForStatement,
     FunctionStatement,
     GotoStatement,
@@ -401,7 +401,7 @@ export class Parser {
         if (this.check(TokenKind.As)) {
             [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
         }
-        return new InterfaceFieldStatement(optionalKeyword, name, asToken, typeExpression);
+        return new InterfaceFieldStatement(name, asToken, typeExpression, optionalKeyword);
     }
 
     private consumeAsTokenAndTypeExpression(): [Token, TypeExpression] {
@@ -459,14 +459,14 @@ export class Parser {
         }
 
         return new InterfaceMethodStatement(
-            optionalKeyword,
             functionType,
             name,
             leftParen,
             params,
             rightParen,
             asToken,
-            returnTypeExpression
+            returnTypeExpression,
+            optionalKeyword
         );
     }
 
@@ -804,12 +804,12 @@ export class Parser {
 
         return new FieldStatement(
             accessModifier,
-            optionalKeyword,
             name,
             asToken,
             fieldTypeExpression,
             equal,
-            initialValue
+            initialValue,
+            optionalKeyword
         );
     }
 
diff --git a/src/parser/Statement.ts b/src/parser/Statement.ts
index ed1b035f..572185a9 100644
--- a/src/parser/Statement.ts
+++ b/src/parser/Statement.ts
@@ -1536,14 +1536,14 @@ export class InterfaceFieldStatement extends Statement implements TypedefProvide
         throw new Error('Method not implemented.');
     }
     constructor(
-        optionalToken: Token,
         nameToken: Identifier,
         asToken: Token,
-        public typeExpression?: TypeExpression
+        public typeExpression?: TypeExpression,
+        optionalToken?: Token
     ) {
         super();
-        this.tokens.name = nameToken;
         this.tokens.optional = optionalToken;
+        this.tokens.name = nameToken;
         this.tokens.as = asToken;
         this.range = util.createBoundingRange(
             this.tokens.optional,
@@ -1558,9 +1558,9 @@ export class InterfaceFieldStatement extends Statement implements TypedefProvide
     public range: Range;
 
     public tokens = {} as {
-        optional: Token;
         name: Identifier;
         as: Token;
+        optional?: Token;
     };
 
     public getLeadingTrivia(): Token[] {
@@ -1600,9 +1600,7 @@ export class InterfaceFieldStatement extends Statement implements TypedefProvide
         result.push(
             this.tokens.name.text
         );
-        if (this.tokens.optional) {
-            result.push(this.tokens.optional.text);
-        }
+
         if (this.typeExpression) {
             result.push(
                 ' as ',
@@ -1625,14 +1623,14 @@ export class InterfaceMethodStatement extends Statement implements TypedefProvid
         throw new Error('Method not implemented.');
     }
     constructor(
-        optionalToken: Token,
         functionTypeToken: Token,
         nameToken: Identifier,
         leftParen: Token,
         public params: FunctionParameterExpression[],
         rightParen: Token,
         asToken?: Token,
-        public returnTypeExpression?: TypeExpression
+        public returnTypeExpression?: TypeExpression,
+        optionalToken?: Token
     ) {
         super();
         this.tokens.optional = optionalToken;
@@ -1665,7 +1663,7 @@ export class InterfaceMethodStatement extends Statement implements TypedefProvid
     }
 
     public tokens = {} as {
-        optional: Token;
+        optional?: Token;
         functionType: Token;
         name: Identifier;
         leftParen: Token;
@@ -1706,7 +1704,7 @@ export class InterfaceMethodStatement extends Statement implements TypedefProvid
             this.tokens.functionType.text,
             ' ',
             this.tokens.name.text,
-            this.tokens.leftParen.text
+            '('
         );
         const params = this.params ?? [];
         for (let i = 0; i < params.length; i++) {
@@ -1723,7 +1721,7 @@ export class InterfaceMethodStatement extends Statement implements TypedefProvid
             }
         }
         result.push(
-            this.tokens.rightParen.text
+            ')'
         );
         if (this.returnTypeExpression) {
             result.push(
@@ -2364,16 +2362,17 @@ export class MethodStatement extends FunctionStatement {
 export class FieldStatement extends Statement implements TypedefProvider {
     constructor(
         readonly accessModifier?: Token,
-        readonly optional?: Token,
         readonly name?: Identifier,
         readonly as?: Token,
         readonly typeExpression?: TypeExpression,
         readonly equal?: Token,
-        readonly initialValue?: Expression
+        readonly initialValue?: Expression,
+        readonly optional?: Token
     ) {
         super();
         this.range = util.createBoundingRange(
             accessModifier,
+            optional,
             name,
             as,
             typeExpression,


Test patch:
diff --git a/src/parser/tests/statement/InterfaceStatement.spec.ts b/src/parser/tests/statement/InterfaceStatement.spec.ts
index 2a1c0b2e..af153221 100644
--- a/src/parser/tests/statement/InterfaceStatement.spec.ts
+++ b/src/parser/tests/statement/InterfaceStatement.spec.ts
@@ -96,4 +96,13 @@ describe('InterfaceStatement', () => {
             end interface
         `, undefined, undefined, undefined, true);
     });
+
+    it('includes "optional" modifier in typedef', async () => {
+        await testGetTypedef(`
+            interface Person
+                name as string
+                optional age as integer
+            end interface
+        `);
+    });
 });