@@ -99,6 +99,12 @@ repository:
9999 comment-start :
100100 match : ' // | /\*'
101101
102+ # A pattern that can start a run of whitespace or a comment.
103+ # Commonly used as a negative lookahead in the `end` regex of a nonterminal, when searching for
104+ # tokens that can't start a child of that nonterminal.
105+ whitespace-or-comment-start :
106+ match : ' \s | $ | (?#comment-start)'
107+
102108 # All tokens that can appear in any context.
103109 non-context-sensitive :
104110 patterns :
@@ -113,7 +119,7 @@ repository:
113119 name : keyword.operator.relational.ql
114120
115121 comparison-operator :
116- match : ' =|\!- '
122+ match : ' =|\!\= '
117123 name : keyword.operator.comparison.ql
118124
119125 arithmetic-operator :
@@ -610,6 +616,12 @@ repository:
610616 - include : ' #import-directive'
611617 - include : ' #import-as-clause'
612618 - include : ' #module-declaration'
619+ - include : ' #newtype-declaration'
620+ # See the comment on newtype-declaration for why we include these next three nonterminals at the
621+ # module-member level instead of as part of the newtype-declaration.
622+ - include : ' #newtype-branch-name-with-prefix'
623+ - include : ' #predicate-parameter-list'
624+ - include : ' #predicate-body'
613625 - include : ' #class-declaration'
614626 - include : ' #select-clause'
615627 - include : ' #predicate-or-field-declaration'
@@ -781,7 +793,7 @@ repository:
781793 bindingset-annotation :
782794 beginPattern : ' #bindingset'
783795 # Ends after the next `]`, or when we encounter something other than a `[`.
784- end : ' (?! \s | (?#comment-start) | \[ ) |
796+ end : ' (?! (?#whitespace-or- comment-start) | \[ ) |
785797 (?<=\])'
786798 name : meta.block.bindingset-annotation.ql
787799 patterns :
@@ -802,7 +814,7 @@ repository:
802814 language-annotation :
803815 beginPattern : ' #language'
804816 # Ends after the next `]`, or when we encounter something other than a `[`.
805- end : ' (?! \s | (?#comment-start) | \[ ) |
817+ end : ' (?! (?#whitespace-or- comment-start) | \[ ) |
806818 (?<=\])'
807819 name : meta.block.language-annotation.ql
808820 patterns :
@@ -824,7 +836,7 @@ repository:
824836 pragma-annotation :
825837 beginPattern : ' #pragma'
826838 # Ends after the next `]`, or when we encounter something other than a `[`.
827- end : ' (?! \s | (?#comment-start) | \[ ) |
839+ end : ' (?! (?#whitespace-or- comment-start) | \[ ) |
828840 (?<=\])'
829841 name : meta.block.pragma-annotation.ql
830842 patterns :
@@ -841,34 +853,53 @@ repository:
841853 name : storage.modifier.ql
842854
843855 # The declaration of an IPA type.
856+ # This only includes the `newtype` keyword and the identifier for the IPA type itself. The
857+ # branches of the IPA type are modeled as separate nonterminals contained directly in the module
858+ # body. This is kind of hacky, but without it, we don't seem to have a way to get TextMate to
859+ # handle this:
860+ # ```ql
861+ # newtype TRoot =
862+ # TBranch1(int x) {
863+ # x = 5
864+ # } or
865+ # TBranch2() // No body
866+ #
867+ # TOther getOther() { any() }
868+ # ```
869+ # If the branches are within the newtype declaration node, it's very hard to get the upper-id for
870+ # the name of the IPA type to be included in the newtype declaration node, without also including
871+ # the `TOther` upper-id in the declaration node.
844872 newtype-declaration :
845873 beginPattern : ' #newtype'
846- # Ends when we see something other than one of:
847- # - An upper-id (branch name)
848- # - A comment
849- # - Whitespace
850- # - `=`
851- # - `(`
852- end : ' (?! \s | (?#upper-id) | (?#comment-start) | \= | \( )'
853- name : meta.block.newtype.ql
874+ # We're expecting a newtype-declaration-without-keyword immediately after the `newtype` keyword,
875+ # so end if we see anything other than the upper-id that starts it, or whitespace, or a comment.
876+ # An upper-id can't start anything else at module scope, so once we see the rest of this
877+ # newtype-declaration, whatever comes next should end this block.
878+ end : ' (?#upper-id)'
879+ endCaptures :
880+ ' 0 ' :
881+ name : entity.name.type.ql
882+ name : meta.block.newtype-declaration.ql
854883 patterns :
855884 - include : ' #non-context-sensitive'
856- - include : ' #newtype-branch'
857885
858- # The branch of an IPA type.
859- newtype-branch :
860- begin : ' (?#upper-id)'
886+ # A branch of an IPA type, including just the `=` or `or` prefix and the name of the branch.
887+ # The parameter list and body are separate nonterminals contained directly within the module body.
888+ # See the comment for newtype-declaration for why.
889+ newtype-branch-name-with-prefix :
890+ begin : ' \= | (?#or)'
861891 beginCaptures :
892+ ' 0 ' :
893+ patterns :
894+ - include : ' #or'
895+ - include : ' #comparison-operator'
896+ end : ' (?#upper-id)'
897+ endCaptures :
862898 ' 0 ' :
863899 name : entity.name.type.ql
864- # Ends after a `}`, or when we encounter something other than a `{`.
865- end : ' (?<=\}) | (?! \s | (?#comment-start) | \{ )'
866- name : meta.block.newtype-branch.ql
900+ name : meta.block.newtype-branch-name-with-prefix.ql
867901 patterns :
868- - include : ' #predicate-body'
869902 - include : ' #non-context-sensitive'
870- - match : ' (?#upper-id)'
871- name : entity.name.type.ql
872903
873904 # The declaration of a class, include an alias.
874905 class-declaration :
0 commit comments