diff --git a/.gitignore b/.gitignore index 14d4ba0..cfa0b08 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ #folder is available **/out/* !client/out/*.tmp +client/src/syntaxes/dev* .antlr node_modules diff --git a/client/src/syntaxes/vba.tmLanguage.yaml b/client/src/syntaxes/vba.tmLanguage.yaml index 49465bc..67f664e 100644 --- a/client/src/syntaxes/vba.tmLanguage.yaml +++ b/client/src/syntaxes/vba.tmLanguage.yaml @@ -8,6 +8,47 @@ fileTypes: patterns: - include: "#fileStructure" + +# --- Notes ------------------------------------------------------------------------------------ +# * TextMate will only evaluate a single line at a time. For syntax spanning multiple lines, +# a begin/end rule is the only option. +# * TextMate will always fail gracefully. You can misspell a key or name, write an invalid +# regex pattern, or summon Beetlejuice. It will still run, it just won't work as expected. +# +# --- Match Rules ------------------------------------------------------------------------------ +# * Match rules contain a match key. +# * Matches are always consumed but can be passed down to captures key. +# * Patterns, begin, end, beginCaptures, and endCaptures keys will be ignored. +# * Repository key contains more rules but you can only call down the tree or to a top level. + +# --- Begin/End Rules -------------------------------------------------------------------------- +# * Begin/end rules contain a begin key and (usually) an end key. +# * Rules missing an end key will match to the end of the document (or capture - see tips). +# * Similar to match/captures, you can pair begin/beginCaptures and end/endCaptures. +# * Repository key is ignored and rules within are not accessible from anywhere. + +# --- Empty Rules ------------------------------------------------------------------------------ +# * Empty rules are used to organise rule flow with a patterns key, and optionally, repository. +# * They will never consume any content as they have no regex. +# * These rules cannot assign scope, so the name key wil be ignored. This may help to organise +# * your grammar, but can make it more difficult to test and debug. + +# --- Tips and Tricks -------------------------------------------------------------------------- +# * It can be advantageous to match without consuming anything, e.g., multi-level begin/end +# rules. You can cascade ends with (?=.) to match anything without consuming. +# Similarly, you may wish to end at [':\n] but consuming will cause comments to fail. +# * You can strategically consume content to skip it matching elsewhere, e.g., line continuation +# on a comment. Begin on ' and end on \n. If you consume the continuation _\s*\n then the +# comment will continue until the next line that doesn't have the continuation pattern. +# * Begin/End rules run until ended or until they reach the end of their scope of operation. +# This means passing a capture group from (begin|end)?capture down to a begin/end will _always +# end at the end of the what was captured!_. This cannot be more than to the end of the line. +# +# "Put conventional logic aside and enjoy. Well... I say, 'enjoy.'" +# - Garth Marenghi +# ---------------------------------------------------------------------------------------------- + + repository: fileStructure: patterns: @@ -15,12 +56,11 @@ repository: - include: "#comments" # Handle comments here so they aren't broken by other stuff. - include: "#strings" # Handle strings here so they aren't broken by other stuff. - include: "#labels" # Handle labels first so they aren't handled by lines. - - include: "#inlineMethod" # Try not to be too sad people can, and do, do this. - include: "#methodSignature" - - include: "#continuations" # Consume continuations so they "continue" other matches. - include: "#enum" - include: "#struct" - - include: "#syntaxLines" # Split document lines into syntax lines. + - include: "#variableDeclarations" + - include: "#main" continuations: name: meta.has-continuation.vba @@ -38,19 +78,8 @@ repository: - include: "#lineContinuation" lineContinuation: - name: support.vba - match: \s*_\s*\n - - syntaxLines: - name: meta.syntax-lines.vba - match: ((?:[^\n"':]|"(?:\\.|[^\n"\\])*")+|"(?:\\.|[^\n"\\])*")(?:('.*)*)? - captures: - 1: # Split line - patterns: - - include: "#main" - 2: # Comments - patterns: - - include: "#comments" + name: keyword.control.line-continuation.vba + match: (?<=\s)_\s*\n main: patterns: @@ -68,16 +97,20 @@ repository: - include: "#literals" - include: "#operators" - include: "#keywords" + - include: "#kw-storageMe" - include: "#functionCall" - include: "#objectModel" - include: "#subCall" + - include: "#subCallNoArgs" + - name: keyword.control.line-separator.vba + match: ':' literals: patterns: - - include: "#comments" - include: "#string" - include: "#boolean" + - include: "#nothing" - include: "#number" - include: "#hexadecimal" repository: @@ -87,9 +120,12 @@ repository: boolean: name: constant.language.boolean.vba match: "(?i)(true|false)" + nothing: + name: constant.language.null.vba + match: (?i)\bnothing\b number: name: constant.numeric.vba - match: "-?\\d+\\.?\\d*" + match: -?\d+\.?\d*[%&@!#]? hexadecimal: name: constant.numeric.hex.vba match: "(?i)&H[0-9a-f]+(&)?" @@ -129,30 +165,47 @@ repository: repository: kw-controlAs: name: keyword.control.as.vba - match: "(?i)\\bas\\b" + match: (?i)\bas\b kw-controlTo: - name: keyword.control.as.vba - match: "(?i)\\bto\\b" + name: keyword.control.to.vba + match: (?i)\bto\b kw-storageMe: - name: keyword.storage.me.vba - match: "(?i)\\bme\\b" + name: variable.language.me.vba + match: (?i)\bme\b kw-flow: patterns: - include: "#inlineIfElse" - include: "#inlineIf" - - include: "#flowDecision" + - include: "#blockIf" + - include: "#blockIfEnd" - include: "#forEachLoop" - include: "#flowLoop" - include: "#flowCall" + - include: "#methodClose" - include: "#flowPauseExit" - include: "#flowBranch" repository: - flowDecision: - name: keyword.control.flow.decision.vba - match: (?i)(^|\s+)(#if|then|#elseif|[#]?else|[#]?end if|select case|case|switch|end select)\b + blockIf: + name: meta.flow.block-if-else.vba + match: (?i)(?:^|\s+)((?:[#]?else\s+)?[#]?if)(.*?)(then) + captures: + 1: + name: keyword.control.flow.block-decision.vba + 2: + patterns: + - include: "#expression" + - include: "#functionCall" + 3: + name: keyword.control.flow.block-decision.vba + blockIfEnd: + name: meta.flow.block-if-else.vba + match: (?i)([#]?end\s+if) + captures: + 1: + name: keyword.control.flow.block-decision.vba flowLoop: name: keyword.control.flow.loop.vba @@ -196,7 +249,7 @@ repository: inlineIf: name: meta.flow.inline-if.vba - match: (?i)\s*((?:else)?if)\s+(.*?)\s+(then) + match: (?i)\s*((?:else\s+)?if)\s+(.*?)\s+(then)\s+([^'\n]+) captures: 1: name: keyword.control.flow.decision.vba @@ -213,7 +266,7 @@ repository: flowPauseExit: name: keyword.control.flow.other.vba - match: "(?i)\\b(doevents|end(?! property)|exit\\s+sub|exit\\s+function|exit\\s+property|stop)\\b" + match: "(?i)\\b(doevents|end(?! (sub|property|function))|exit\\s+sub|exit\\s+function|exit\\s+property|stop)\\b" flowBranch: patterns: @@ -346,72 +399,116 @@ repository: match: (?i)\b(debug)(\.([a-z][a-z0-9_]*)) types: + name: meta.variables.type.vba + # As New? Type + match: (?i)(As)\s+(New\s)?\s*([A-Z][a-z0-9_.]*) + captures: + 1: + name: keyword.control.as.vba + 2: + name: keyword.storage.new.vba + 3: + patterns: + - include: "#AsTypePrimative" + - include: "#AsTypeObject" + AsTypePrimative: + name: support.type.primitive.$1.vba + match: (?i)(boolean|byte|currency|date|decimal|double|integer|long(long|ptr)?|single|string|variant)\b + AsTypeObject: + name: support.type.object.$1.vba + match: (?i)([a-z][a-z0-9._]*) + + argumentsSignature: + name: meta.arguments.signature.vba + begin: (?=[^ ():_]) + end: (?=\)) patterns: - - include: "#language" - - include: "#primativeType" - - include: "#objectType" - repository: - primativeType: - name: support.type.primitive.vba - match: (?i)(?<=\bAs)(?:\s+|\s+_\s*\n)+(boolean|byte|currency|date|decimal|double|integer|long(long|ptr)?|single|string|variant)\b - objectType: - name: support.type.object.vba - match: (?i)(?<=\bAs)((?:\s+(?:\s*_\s*\n)*)New)?(?:\s+(?:\s*_\s*\n)*)([A-Z][A-Z0-9_]*)\b - captures: - 1: - name: keyword.storage.new.vba - 2: - name: support.type.object.vba + - include: "#separator" + - include: "#lineContinuation" + - include: "#argumentSignatureFromParamArray" + - include: "#argumentSignatureFromOptional" + - include: "#argumentSignatureFromBy" + - include: "#argumentSignatureFromParam" - arguments: - # Rules that have no match will never return a name in the hierarchy. - # This name doesn't do anything but leaving this as usage notes. - name: source.args.vba + argumentSignatureFromParamArray: + name: meta.argument-signature.paramarray.vba + begin: (?i)paramarray + end: (?=[,):'\n]) + beginCaptures: + 0: + name: storage.type.modifier.vba patterns: + - include: "#argumentSignatureFromParam" - include: "#lineContinuation" - - include: "#paramArray" - - include: "#functionCall" - - include: "#argsVariable" - - include: "#language" - - include: "#argsLiteral" - repository: - argsVariable: - name: meta.arguments.argsVariable.vba - match: (?i),?\s*((?:Optional\s+)?(?:(?:ByVal|ByRef)\s+)?)?([a-z][a-z0-9_]*)(\(\))?(?:\s+(as\s+[a-z][a-z0-9_]*))?(\s*=\s*[^,)]+)? - # Attempted replacing \s with (?:\s+|\s*_\s*\n) to consume a space or a line ending but it refuses to play the game. - # match: ~~ doesn't work (?i),?(?:\s+|\s*_\s*\n)*((?:Optional(?:\s+|\s*_\s*\n)+)?(?:(?:ByVal|ByRef)(?:\s+|\s*_\s*\n)+)?)?([a-z][a-z0-9_]*)(?:(?:\s+|\s*_\s*\n)+(as(?:\s+|\s*_\s*\n)+[a-z][a-z0-9_]*))?((?:\s+|\s*_\s*\n)*=(?:\s+|\s*_\s*\n)*[^,\n)]+)? - # match: ~~ all broken (?i),?(?:\s*_\s*\n)*((?:Optional(?:\s+(?:\s*_\s*\n)*))?(?:(?:ByVal|ByRef)(?:\s+(?:\s*_\s*\n)*))?)?([a-z][a-z0-9_]*)(?:(?:\s+(?:\s*_\s*\n)*)(as\(?:\s+(?:\s*_\s*\n)*)[a-z][a-z0-9_]*))?((?:\s*_\s*\n)*=(?:\s*_\s*\n)*[^,)]+)? - captures: - 1: # Optional? ByVal|ByRef? - name: storage.type.modifier.vba - 2: # Identifier - name: variable.parameter.vba - 3: # As Type? - patterns: - - include: "#types" - 4: - patterns: - - include: "#language" - argsLiteral: - name: meta.arguments.argsLiteral.vba - match: ((?:[^\n",]|"(?:\\.|[^\n"\\])*")+|"(?:\\.|[^\n"\\])*") - captures: - 1: - patterns: - - include: "#literals" + argumentSignatureFromOptional: + name: meta.argument-signature.optional.vba + begin: (?i)optional + end: (?=[,):'\n]) + beginCaptures: + 0: + name: storage.type.modifier.vba + patterns: + - include: "#argumentSignatureFromBy" + - include: "#argumentSignatureFromParam" + - include: "#lineContinuation" - paramArray: - name: meta.args.paramarray.vba - match: (?i),?\s*(ParamArray)\s+([a-z][a-z0-9_]*)(?:\(\))(\s+As\s+Variant)? - captures: - 1: - name: storage.type.modifier.array.vba - 2: - name: variable.parameter.vba - 3: - patterns: - - include: "#types" + argumentSignatureFromBy: + name: meta.argument-signature.by.vba + begin: (?i)(byref|byval) + end: (?=[,):'\n]) + beginCaptures: + 0: + name: storage.type.modifier.vba + patterns: + - include: "#argumentSignatureFromParam" + - include: "#lineContinuation" + + argumentSignatureFromParam: + name: meta.argument-signature.param.vba + begin: (?i)[a-z][a-z0-9]*(\(\))? + end: (?=[,):'\n]) + beginCaptures: + 0: + name: variable.parameter.vba + patterns: + - include: "#argumentSignatureFromTypeAs" + - include: "#lineContinuation" + + argumentSignatureFromTypeAs: + name: meta.argument-signature.as.vba + begin: (?i)\bas\b + end: (?=[,):'\n]) + beginCaptures: + 0: + patterns: + - include: "#keywords" + patterns: + - include: "#argumentSignatureFromTypeName" + - include: "#lineContinuation" + + argumentSignatureFromTypeName: + name: meta.argument-signature.type.vba + begin: (?i)([a-z][a-z0-9._]*) + end: (?=[,):'\n]) + beginCaptures: + 0: + patterns: + - include: "#AsTypePrimative" + - include: "#AsTypeObject" + patterns: + - include: "#variableAssignment" + - include: "#lineContinuation" + + arguments: + name: meta.arguments.vba + begin: (\s+|\(\s*) + end: (?=[\n')]) + patterns: + - include: "#lineContinuation" + - include: "#functionCall" + - include: "#separator" + - include: "#expression" comments: patterns: @@ -424,12 +521,12 @@ repository: # Capturing it there prevents the end pattern being matched. name: comment.block.vba begin: (?i)(\s*'|(?<=^\d*?|:)\s*Rem\b).*\s_\s* - end: \n + end: (?=\n) patterns: - include: "#lineContinuation" apostropheComments: name: comment.line.apostrophe.vba - match: (?i)\s*'.* + match: (?i)\s*'[^\n]* remarkComments: name: comment.line.remark.vba match: (?i)(?<=^\d*?|:)\s*Rem\b.* @@ -446,26 +543,56 @@ repository: moduleHeader: patterns: + - include: "#moduleVersion" - include: "#moduleAttributeBlock" - include: "#moduleAttribute" - include: "#moduleOption" repository: + moduleVersion: + name: entity.other.attribute-name.block.vba + match: (?i)^VERSION\s+([.\d]+)\s+CLASS + captures: + 1: + patterns: + - include: "#literals" moduleAttribute: - patterns: - - include: "#attribute" + name: meta.attribute.vba + match: (?i)^\s*(Attribute)\s+(VB_\w+)\s+(=)\s+(.*)$ + captures: + 1: # Attribute + name: keyword.attribute.vba + 2: # VB_Name + name: support.variable.property.vba + 3: # = + name: keyword.operator.assignment.vba + 4: # "Sam" + patterns: + - include: "#literals" moduleAttributeBlock: name: entity.other.attribute-name.block.vba - begin: (?i)^VERSION + begin: (?i)^BEGIN end: (?i)^END patterns: - include: "#comments" - - include: "#literals" - - include: "#operators" + - include: "#attributeAssignment" moduleOption: name: keyword.control.vba match: (?i)^\s*Option\s+(Explicit|Base|Private\s+Module)\b + attributeAssignment: + name: meta.attribute-assignment.vba + match: (?i)([a-z.][a-z0-9._]*)(\s*=\s*)(.*) + captures: + 1: + name: support.variable.property.vba + 2: + name: keyword.operator.assignment.vba + 3: + patterns: + - include: "#literals" + - include: "#comments" + enum: name: meta.enum.declaration.vba begin: (?i)^\s*((?:(?:Public|Private)\s+)?\s*Enum)\s+([a-z][a-z0-9_]+)(\s+(?:'|Rem).*)? @@ -571,81 +698,63 @@ repository: patterns: - include: "#types" patterns: - - include: "#arguments" - - inlineMethod: - name: source.inline-method.please-dont.vba - match: (?i)^\s*((?:Public|Private)?\b\s*(?:(?:Sub|Function)|Property\s+(?:Let|Get|Set)))\s+([a-z][a-z0-9_]*)\s*\((.+)?\)(\s+as\s+[a-z][a-z0-9_]*)?:(.*)?:\s*(End\s+(?:Sub|Function|Property)) - captures: - 1: # Method type - name: storage.type.method.vba - 2: # Identifier - name: entity.name.function.vba - 3: # Arguments? - patterns: - - include: "#arguments" - 4: # Return type? - patterns: - - include: "#types" - 5: # Method lines - patterns: - - include: "#fileStructure" - 6: # End method - name: storage.type.method.close.vba - - + - include: "#argumentsSignature" methodSignature: name: source.method.signature.vba begin: (?i)^\s*((?:Public|Private)?\b\s*(?:(?:Sub|Function)|Property\s+(?:Let|Get|Set)))\s+([a-z][a-z0-9_]*)\s*(\() - end: (?i)\s*(\))\s+(as\s+[a-z][a-z0-9_]*)? + end: (?i)(?<=\))(\s+as\s+[a-z][a-z0-9_]*)? beginCaptures: 1: name: storage.type.method.vba 2: # name name: entity.name.function.vba - 3: - name: punctuation.definition.parameters.begin.vba endCaptures: - 1: - name: punctuation.definition.parameters.end.vba - 2: # return type + 1: # return type patterns: - include: "#types" patterns: - - include: "#arguments" - - methodClose: - name: storage.type.method.close.vba - match: (?i)^\s*End\s+(Sub|Function|Property) + - include: "#argumentsSignature" + - include: "#lineContinuation" - expression: - # (?:[*&\/\+-]|\bMod\b)| - # (?:[<>=]|\b(is|like)\b)| - # (?:[&+])| - # (?:\b(and|eqv|imp|not|or|xor)\b)| - # (?:\b(addressof|typeof)\b) - - # This match just made up of the operators matchs. Don't look at it too hard. - match: (?i)(.*?)\s+((?:[*&\/\+-]|\bMod\b)|(?:[<>=]|\b(is|like)\b)|(?:[&+])|(?:\b(and|eqv|imp|not|or|xor)\b)|(?:\b(addressof|typeof)\b))\s+(.*) + methodAttribute: + name: source.method.attribute.vba + match: (?i)^\s*(Attribute)\s+([a-z][a-z0-9_]*)(\.VB_(?:Description|UserMemId))\s+(=)\s+(.*) captures: - 1: # Left sided of expression - patterns: - - include: "#functionCall" - - include: "#literal" - 2: # Operator - patterns: - - include: "#operators" - 3: # Operator + 1: + name: keyword.attribute.vba + 2: + name: entity.name.function.vba + 3: + name: support.variable.property.vba + 4: + name: keyword.operator.assignment.vba + 5: patterns: - include: "#literals" - - include: "#functionCall" - - include: "#expression" + + methodClose: + name: storage.type.method.close.vba + match: (?i)End\s+(Sub|Function|Property) + + expression: + # Begins and ends without consuming anything. + name: meta.expression.vba + begin: (?=.) + end: (?=\n|\sThen|\)|'|,|:) + patterns: + - include: "#literals" + - include: "#operators" + - include: "#functionCall" + - include: "#variable" + - include: "#lineContinuation" block: patterns: + - include: "#testing" - include: "#variableDeclarations" - include: "#variableAssignment" + - include: "#methodAttribute" - include: "#methodClose" - include: "#language" @@ -653,19 +762,16 @@ repository: blockLines: name: source.methodlines.vba match: (?:(^(?:\s*[a-z0-9]*?:\s*)(?:\s+'.*)?$)|(.*):) - # match: (?:(^(?:\s*[a-z0-9]*?:\s*)(?:\s+'.*)?$)|(.*):) captures: 1: # label name: source.methodlines.label.vba - # patterns: - # - include: "#labels" 2: # colon separated line patterns: - include: "#block" - # blockAttribute: - # patterns: - # - include: "#attribute" + separator: + name: punctuation.separator.vba + match: ',' variableDeclarations: patterns: @@ -673,36 +779,51 @@ repository: - include: "#variableDeclaration" repository: variableDeclaration: - name: storage.var-declaration.vba - match: (?i)^\s*(Dim|Public|Private|Global)\s+([a-z][a-z0-9_]*)([&%#!@$^])?(\(.*\))?(\s+As(?:\s+New)?\s+[A-Z][A-Z0-9_]*)? - captures: + name: meta.variable.declaration.vba + begin: (?i)(global|public|private|dim\s+)(?!const) + end: (?=[':\n]) + beginCaptures: 1: - # Dim|Private - name: storage.type.vba - 2: - # varName - name: variable.other.readwrite.vba - 3: - # Type hint? - name: support.type.primitive.vba - 4: - # Array bounds? - patterns: - - include: "#language" - 5: - # As Type - patterns: - - include: "#types" + name: storage.modifier.declare-variable.vba + patterns: + - include: "#lineContinuation" + - include: "#separator" + - include: "#types" + - include: "#variable" + constDeclaration: + name: meta.const.declaration.vba + begin: (?i)(?:(global|public|private)\s+)?(const) + end: (?=[':\n]) + beginCaptures: + 1: + name: storage.modifier.vba + 2: + name: storage.type.vba + patterns: + - include: "#lineContinuation" + - include: "#separator" + - include: "#types" + - include: "#variable" + - match: (=)\s+([^,'_\n]*) + captures: + 1: + name: keyword.operator.assignment.vba + 2: + patterns: + - include: "#literals" + + + constDeclaration2: name: storage.const-declaration.vba - match: ^\s*((?i)(?:(?:Public|Private)\s+)?Const)\s+([A-Z][A-Z0-9_]*)([&%#!@$^])?((?i)\s+As\s+[A-Z][A-Z0-9_]*)?(.*) + match: (?i)^\s*((?:(?:Public|Private)\s+)?Const)\s+([a-z][a-z0-9_]*)([&%#!@$^])?(\s+As\s+[a-z][a-z0-9_]*)?(.*) captures: 1: # Public|Private Const name: storage.type.vba 2: # CONSTNAME - name: variable.other.constant.vba + name: variable.other.constant 3: # Type hint? name: support.type.primitive.vba @@ -715,49 +836,101 @@ repository: patterns: - include: "#language" - # TODO: Redo this so it can take into account chaining, e.g.: - # MyClass.MyProp = SomeObject.Foo(20) variableAssignment: - match: (?i)((Get|Let|Set)\s+)?([a-z.][a-z0-9._]*)(\s*=\s*)(.*) + name: meta.variable-assignment.vba + begin: (?i)(?:(Let|Set)\s+)?((?:[a-z][a-z0-9_]*)?(?:\.(?:(?:[a-z][a-z0-9_]*)?\.)*)?(?:[a-z][a-z0-9_]*)?)(\s*=\s*) + end: (?=[',:)\n]) + beginCaptures: + 1: # Let|Set + name: keyword.control.vba + 2: # Variable property chain name + patterns: + - include: "#variable" + 3: # = + name: keyword.operator.assignment.vba + patterns: + - include: "#expression" + - include: "#functionCall" + - include: "#variable" + - include: "#language" + - include: "#lineContinuation" + + propertyChain: + match: (?i)(\.)([a-z][a-z0-9_]*)* captures: + 1: + name: punctuation.accessor.vba 2: - name: keyword.control.vba + name: support.variable.property.vba + + variable: + name: meta.variable-or-property.vba + match: (?i)(?:(?:(Me)|([a-z][a-z0-9_]*)))((?:\.(?:[a-z][a-z0-9_]*))+)? + captures: + 1: + patterns: + - include: "#kw-storageMe" + 2: + patterns: + - name: variable.other.constant + match: ([A-Z][A-Z0-9_]*)\b + - name: variable.other.readwrite.vba + match: (?i)([a-z][a-z0-9_]*) 3: - name: variable.other.assignment.vba - 4: - name: keyword.operator.assignment.vba - 5: patterns: - - include: "#functionCall" - - include: "#language" + - include: "#propertyChain" functionCall: name: meta.function.call.vba - begin: (?i)([a-z][a-z0-9_]*)\( - end: \) + begin: (?i)(?:([a-z][a-z0-9_]*)(?=\.))?(\.(?:(?:[a-z][a-z0-9_]*)?\.)*)?([a-z][a-z0-9_]*)([&%#!@$^])?(?=\() + end: (\)|(?=')) beginCaptures: 1: + patterns: + - include: "#kw-storageMe" + - include: "#variable" + 2: + patterns: + - include: "#propertyChain" + 3: name: entity.name.function.call.vba + 4: + name: support.type.primitive.vba patterns: # These calls need to be back to a top level group because # textMate does not seem to support a repository in a begin/end - include: "#arguments" - - include: "#lineContinuation" subCall: name: meta.sub-call.vba - begin: (?i)([a-z][a-z0-9._]*)\s+(.*) + begin: (?i)(?:([a-z][a-z0-9_]*)(?=\.))?(\.(?:(?:[a-z][a-z0-9_]*)?\.)*)?([a-z][a-z0-9_]*)\s*(?=\s[^,'\n]) + end: (?=[\n']) beginCaptures: 1: - name: entity.name.function.call.vba + patterns: + - include: "#variable" 2: patterns: - - include: "#arguments" - end: \n + - include: "#propertyChain" + 3: + name: entity.name.function.call.vba patterns: - # - include: "#subCallMultiLine" - include: "#arguments" + subCallNoArgs: + name: meta.sub-call.vba + match: (?i)(?:([a-z][a-z0-9_]*)(?=\.))?(\.(?:(?:[a-z][a-z0-9_]*)?\.)*)?([a-z][a-z0-9_]*) + captures: + 1: + patterns: + - include: "#kw-storageMe" + - include: "#variable" + 2: + patterns: + - include: "#propertyChain" + 3: + name: entity.name.function.call.vba + testing: patterns: - name: keyword.control @@ -956,6 +1129,8 @@ repository: match: ^brackethighlighter.unmatched$ - name: constant.other.reference.link match: ^constant.other.reference.link$ + - name: constant.other.identifier.vba + match: ^constant.other.identifier.vba$ - name: string.other.link match: ^string.other.link$ - name: entity.name.tag.yaml diff --git a/package-lock.json b/package-lock.json index 3bb690f..62d4e9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vba-lsp", - "version": "1.4.7", + "version": "1.4.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vba-lsp", - "version": "1.4.7", + "version": "1.4.8", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 25b828d..5154e5f 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "icon": "images/vba-lsp-icon.png", "author": "SSlinky", "license": "MIT", - "version": "1.4.7", + "version": "1.4.8", "repository": { "type": "git", "url": "https://github.com/SSlinky/VBA-LanguageServer" @@ -124,6 +124,7 @@ "lint": "eslint ./client/src ./server/src --ext .ts,.tsx", "postinstall": "cd client && npm install && cd ../server && npm install && cd ..", "textMate": "npx js-yaml client/src/syntaxes/vba.tmLanguage.yaml > client/out/vba.tmLanguage.json", + "devMate": "npx js-yaml client/src/syntaxes/dev.tmLanguage.yaml > client/out/vba.tmLanguage.json", "antlr4ng": "antlr4ng -Dlanguage=TypeScript -visitor ./server/src/antlr/vba.g4 -o ./server/src/antlr/out/", "antlr4ngPre": "antlr4ng -Dlanguage=TypeScript -visitor ./server/src/antlr/vbapre.g4 -o ./server/src/antlr/out/", "test": "npm run tmSnapTest && npm run tmUnitTest && npm run vsctest", diff --git a/server/src/antlr/vbapre.g4 b/server/src/antlr/vbapre.g4 index 5e77e1a..760b037 100644 --- a/server/src/antlr/vbapre.g4 +++ b/server/src/antlr/vbapre.g4 @@ -38,23 +38,23 @@ compilerConditionalStatement ; compilerIfStatement - : IF WS? booleanExpression WS? THEN endOfStatement + : WS? IF WS? booleanExpression WS? THEN endOfStatement ; compilerElseIfStatement - : ELSEIF WS? booleanExpression WS? THEN endOfStatement + : WS? ELSEIF WS? booleanExpression WS? THEN endOfStatement ; compilerElseStatement - : ELSE endOfStatement + : WS? ELSE endOfStatement ; compilerEndIfStatement - : ENDIF endOfStatement? + : WS? ENDIF endOfStatement? ; compilerBlockContent - : (anyOtherLine | endOfLine)+ + : (anyOtherLine | endOfLine | compilerIfBlock)+ ; // ************************* @@ -81,7 +81,7 @@ anyWord ; anyOtherLine - : (WS* anyWord)+ //endOfLine? + : (WS* anyWord)+ ; endOfLine @@ -93,7 +93,7 @@ endOfLineNoWs ; endOfStatement - : (endOfLine | COLON)+ + : (endOfLine | WS? COLON WS? )+ ; commentBody: COMMENT; @@ -169,7 +169,7 @@ LINE_CONTINUATION ; WS - : NBSP NBSP* + : NBSP+ ; fragment NBSP @@ -219,9 +219,9 @@ NOT // Any non-whitespace or new line characters. ANYCHARS - : ANYCHAR + : ANYCHAR+ ; fragment ANYCHAR - : . + : ~[\r\n\u2028\u2029 \t\u0019\u3000] ; \ No newline at end of file diff --git a/server/src/capabilities/capabilities.ts b/server/src/capabilities/capabilities.ts index 25293d7..264eecf 100644 --- a/server/src/capabilities/capabilities.ts +++ b/server/src/capabilities/capabilities.ts @@ -14,7 +14,7 @@ import { ParserRuleContext, TerminalNode } from 'antlr4ng'; // Project import { SemanticToken } from '../capabilities/semanticTokens'; import { FoldingRange, FoldingRangeKind } from '../capabilities/folding'; -import { BaseContextSyntaxElement, BaseIdentifyableSyntaxElement, HasSemanticTokenCapability } from '../project/elements/base'; +import { BaseContextSyntaxElement, BaseIdentifyableSyntaxElement, Context, HasSemanticTokenCapability } from '../project/elements/base'; abstract class BaseCapability { @@ -52,28 +52,39 @@ export class DiagnosticCapability extends BaseCapability { export class SemanticTokenCapability extends BaseCapability { - semanticToken: SemanticToken; - - constructor(element: BaseContextSyntaxElement & HasSemanticTokenCapability, tokenType: SemanticTokenTypes, tokenModifiers: SemanticTokenModifiers[], range?: Range, tokLength?: number) { - super(element); + private tokenType: SemanticTokenTypes; + private tokenModifiers: SemanticTokenModifiers[]; + private overrideRange?: Range; + private overrideLength?: number; + get semanticToken(): SemanticToken { + const element = this.element as BaseContextSyntaxElement & HasSemanticTokenCapability; const context = !!element.identifierCapability - ? element.identifierCapability.element.context + ? new Context(element.identifierCapability.nameContext, element.context.document) : element.context; - const startLine = range?.start.line ?? context.range.start.line; - const startChar = range?.start.character ?? context.range.start.character; - const textLength = tokLength ?? context.text.length; + const range = this.overrideRange ?? context.range; + const startLine = range.start.line; + const startChar = range.start.character; + const textLength = this.overrideLength ?? context.text.length; - this.semanticToken = new SemanticToken( + return new SemanticToken( element, startLine, startChar, textLength, - tokenType, - tokenModifiers + this.tokenType, + this.tokenModifiers ); } + + constructor(element: BaseContextSyntaxElement & HasSemanticTokenCapability, tokenType: SemanticTokenTypes, tokenModifiers: SemanticTokenModifiers[], overrideRange?: Range, overrideLength?: number) { + super(element); + this.tokenType = tokenType; + this.tokenModifiers = tokenModifiers; + this.overrideRange = overrideRange; + this.overrideLength = overrideLength; + } } @@ -106,16 +117,18 @@ interface IdentifierArgs { export class IdentifierCapability extends BaseCapability { - nameContext?: ParserRuleContext | TerminalNode | null; + nameContext: ParserRuleContext | TerminalNode; range: Range; name: string; + isDefaultMode: boolean; constructor(args: IdentifierArgs) { super(args.element); - this.nameContext = (args.getNameContext ?? (() => args.element.context.rule))(); + this.nameContext = ((args.getNameContext ?? (() => args.element.context.rule))() ?? args.element.context.rule); + this.isDefaultMode = !(!!args.getNameContext && !!args.getNameContext()); - if (!!this.nameContext) { + if (!this.isDefaultMode) { // Use the context to set the values. this.name = (args.formatName ?? ((name: string) => name))(this.nameContext.getText()); this.range = this.nameContext.toRange(args.element.context.document); diff --git a/server/src/extensions/parserExtensions.ts b/server/src/extensions/parserExtensions.ts index 10e67ee..52c61d6 100644 --- a/server/src/extensions/parserExtensions.ts +++ b/server/src/extensions/parserExtensions.ts @@ -28,11 +28,15 @@ declare module 'antlr4ng' { interface ParserRuleContext { /** Convert the node to a range. */ toRange(doc: TextDocument): Range; + startIndex(): number; + stopIndex(): number; } interface TerminalNode { /** Convert the node to a range. */ toRange(doc: TextDocument): Range; + startIndex(): number; + stopIndex(): number; } } @@ -108,16 +112,30 @@ ParserRuleContext.prototype.toRange = function (doc: TextDocument): Range { ); }; +ParserRuleContext.prototype.startIndex = function (): number { + return this.start?.start ?? 0; +} + +ParserRuleContext.prototype.stopIndex = function (): number { + return this.stop?.stop ?? this.startIndex(); +} + TerminalNode.prototype.toRange = function (doc: TextDocument): Range { - const startIndex = this.getPayload()?.start ?? 0; - const stopIndex = this.getPayload()?.stop ?? startIndex; return Range.create( - doc.positionAt(startIndex), - doc.positionAt(stopIndex + 1) + doc.positionAt(this.startIndex()), + doc.positionAt(this.stopIndex() + 1) ); }; +TerminalNode.prototype.startIndex = function (): number { + return this.getPayload()?.start ?? 0; +} + +TerminalNode.prototype.stopIndex = function (): number { + return this.getPayload()?.stop ?? this.startIndex(); +} + CompilerConditionalStatementContext.prototype.vbaExpression = function (): string { return (this.compilerIfStatement() ?? this.compilerElseIfStatement())! diff --git a/server/src/project/elements/base.ts b/server/src/project/elements/base.ts index ad6e8ee..f3da4c9 100644 --- a/server/src/project/elements/base.ts +++ b/server/src/project/elements/base.ts @@ -3,7 +3,7 @@ import { Position, Range } from 'vscode-languageserver'; import { TextDocument } from 'vscode-languageserver-textdocument'; // Antlr -import { ParserRuleContext } from 'antlr4ng'; +import { ParserRuleContext, TerminalNode } from 'antlr4ng'; // Project import { @@ -93,7 +93,7 @@ export abstract class BaseIdentifyableSyntaxElement // Utilities // --------------------------------------------------------- -export class Context { +export class Context { rule: T; document: TextDocument; range: Range; @@ -102,8 +102,8 @@ export class Context { return this.rule.getText(); } - get startIndex() { return this.rule.start?.start ?? 0; } - get stopIndex() { return this.rule.stop?.stop ?? 0; } + get startIndex() { return this.rule.startIndex(); } + get stopIndex() { return this.rule.stopIndex(); } constructor(context: T, document: TextDocument) { this.rule = context; diff --git a/server/src/project/elements/module.ts b/server/src/project/elements/module.ts index ca40024..1570ac2 100644 --- a/server/src/project/elements/module.ts +++ b/server/src/project/elements/module.ts @@ -44,7 +44,7 @@ abstract class BaseModuleElement extends BaseIdenti // Helpers protected addMissingAttributesDiagnostics(diagnostics: Diagnostic[]): void { - if (!!this.identifierCapability.nameContext) return; + if (!this.identifierCapability.isDefaultMode) return; diagnostics.push(new MissingAttributeDiagnostic( Range.create(this.context.range.start, this.context.range.start), 'VB_NAME' diff --git a/server/src/project/elements/typing.ts b/server/src/project/elements/typing.ts index 5b9d98d..4454e51 100644 --- a/server/src/project/elements/typing.ts +++ b/server/src/project/elements/typing.ts @@ -70,7 +70,6 @@ export class TypeDeclarationElement extends BaseTypeDeclarationElement ctx.udtDeclaration().untypedName() }); - this.symbolInformationCapability = new SymbolInformationCapability(this, SymbolKind.Struct); } } @@ -107,11 +106,11 @@ export class DeclarationStatementElement exte } -export class VariableDeclarationElement extends BaseContextSyntaxElement implements HasDiagnosticCapability, HasSymbolInformationCapability, HasSemanticTokenCapability { +export class VariableDeclarationElement extends BaseContextSyntaxElement implements HasDiagnosticCapability, HasSymbolInformationCapability { //, HasSemanticTokenCapability { identifierCapability: IdentifierCapability; diagnosticCapability: DiagnosticCapability; symbolInformationCapability: SymbolInformationCapability; - semanticTokenCapability: SemanticTokenCapability; + // semanticTokenCapability: SemanticTokenCapability; private _isPublic: boolean; get isPublic(): boolean { return this._isPublic; } @@ -121,7 +120,7 @@ export class VariableDeclarationElement extends BaseContextSyntaxElement ctx.ambiguousIdentifier()}); } } diff --git a/snippets/vba.json b/snippets/vba.json index ec4e546..68300fa 100644 --- a/snippets/vba.json +++ b/snippets/vba.json @@ -5,7 +5,7 @@ "body": [ "Private m${1:PropertyName} As ${2:PropertyType}", "Public Property Let $1(var As $2)", - "Attribute $1.VB_Description = \"${3:Dosctring}.\"", + "Attribute $1.VB_Description = \"${3:docstring}.\"", "' $3.", " m$1 = var", "End Property", @@ -23,7 +23,7 @@ "body": [ "Private m${1:PropertyName} As ${2:PropertyType}", "Public Property Set $1(var As $2)", - "Attribute $1.VB_Description = \"${3:Dosctring}.\"", + "Attribute $1.VB_Description = \"${3:docstring}.\"", "' $3.", " Set m$1 = var", "End Property", @@ -40,7 +40,7 @@ "description": "Property get only", "body": [ "Public Property Get ${1:PropertyName}() As ${2:PropertyType}", - "Attribute $1.VB_Description = \"${3:Dosctring}.\"", + "Attribute $1.VB_Description = \"${3:docstring}.\"", "' $3.", " $0", "End Property", @@ -52,7 +52,7 @@ "description": "Subroutine", "body": [ "${1:Public }Sub ${2:Identifier}($3)", - "Attribute $2.VB_Description = \"${4:Dosctring}.\"", + "Attribute $2.VB_Description = \"${4:docstring}.\"", "' $4.", "'", "' Args:", @@ -70,7 +70,7 @@ "description": "Function", "body": [ "${1:Public }Function ${2:Identifier}($3) As ${4:Variant}", - "Attribute $2.VB_Description = \"${5:Dosctring}.\"", + "Attribute $2.VB_Description = \"${5:docstring}.\"", "' $5.", "'", "' Args:", diff --git a/test/textmate/snapshot/class.cls.snap b/test/textmate/snapshot/class.cls.snap index 31d0110..6da11df 100644 --- a/test/textmate/snapshot/class.cls.snap +++ b/test/textmate/snapshot/class.cls.snap @@ -1,52 +1,63 @@ >VERSION 1.0 CLASS -#^^^^^^^ source.vba entity.other.attribute-name.block.vba -# ^ source.vba entity.other.attribute-name.block.vba +#^^^^^^^^ source.vba entity.other.attribute-name.block.vba # ^^^ source.vba entity.other.attribute-name.block.vba constant.numeric.vba -# ^^^^^^^ source.vba entity.other.attribute-name.block.vba +# ^^^^^^ source.vba entity.other.attribute-name.block.vba >BEGIN -#^^^^^^ source.vba entity.other.attribute-name.block.vba +#^^^^^ source.vba entity.other.attribute-name.block.vba > MultiUse = -1 'True -#^^^^^^^^^^^ source.vba entity.other.attribute-name.block.vba -# ^ source.vba entity.other.attribute-name.block.vba keyword.operator.comparison.vba -# ^ source.vba entity.other.attribute-name.block.vba -# ^^ source.vba entity.other.attribute-name.block.vba constant.numeric.vba -# ^^^^^^^ source.vba entity.other.attribute-name.block.vba comment.line.apostrophe.vba +#^^ source.vba entity.other.attribute-name.block.vba +# ^^^^^^^^ source.vba entity.other.attribute-name.block.vba meta.attribute-assignment.vba support.variable.property.vba +# ^^^ source.vba entity.other.attribute-name.block.vba meta.attribute-assignment.vba keyword.operator.assignment.vba +# ^^ source.vba entity.other.attribute-name.block.vba meta.attribute-assignment.vba constant.numeric.vba +# ^^^^^^^ source.vba entity.other.attribute-name.block.vba meta.attribute-assignment.vba comment.line.apostrophe.vba >END #^^^ source.vba entity.other.attribute-name.block.vba >Attribute VB_Name = "ClassName" -#^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba entity.other.attribute-name.vba +#^^^^^^^^^ source.vba meta.attribute.vba keyword.attribute.vba +# ^ source.vba meta.attribute.vba +# ^^^^^^^ source.vba meta.attribute.vba support.variable.property.vba # ^ source.vba meta.attribute.vba -# ^ source.vba meta.attribute.vba keyword.operator.comparison.vba +# ^ source.vba meta.attribute.vba keyword.operator.assignment.vba # ^ source.vba meta.attribute.vba # ^^^^^^^^^^^ source.vba meta.attribute.vba string.quoted.double.vba >Attribute VB_Description = "Class description goes here" -#^^^^^^^^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba entity.other.attribute-name.vba +#^^^^^^^^^ source.vba meta.attribute.vba keyword.attribute.vba +# ^ source.vba meta.attribute.vba +# ^^^^^^^^^^^^^^ source.vba meta.attribute.vba support.variable.property.vba # ^ source.vba meta.attribute.vba -# ^ source.vba meta.attribute.vba keyword.operator.comparison.vba +# ^ source.vba meta.attribute.vba keyword.operator.assignment.vba # ^ source.vba meta.attribute.vba # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba string.quoted.double.vba >Attribute VB_GlobalNameSpace = False -#^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba entity.other.attribute-name.vba +#^^^^^^^^^ source.vba meta.attribute.vba keyword.attribute.vba +# ^ source.vba meta.attribute.vba +# ^^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba support.variable.property.vba # ^ source.vba meta.attribute.vba -# ^ source.vba meta.attribute.vba keyword.operator.comparison.vba +# ^ source.vba meta.attribute.vba keyword.operator.assignment.vba # ^ source.vba meta.attribute.vba # ^^^^^ source.vba meta.attribute.vba constant.language.boolean.vba >Attribute VB_Creatable = False -#^^^^^^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba entity.other.attribute-name.vba +#^^^^^^^^^ source.vba meta.attribute.vba keyword.attribute.vba +# ^ source.vba meta.attribute.vba +# ^^^^^^^^^^^^ source.vba meta.attribute.vba support.variable.property.vba # ^ source.vba meta.attribute.vba -# ^ source.vba meta.attribute.vba keyword.operator.comparison.vba +# ^ source.vba meta.attribute.vba keyword.operator.assignment.vba # ^ source.vba meta.attribute.vba # ^^^^^ source.vba meta.attribute.vba constant.language.boolean.vba >Attribute VB_PredeclaredId = False -#^^^^^^^^^^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba entity.other.attribute-name.vba +#^^^^^^^^^ source.vba meta.attribute.vba keyword.attribute.vba +# ^ source.vba meta.attribute.vba +# ^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba support.variable.property.vba # ^ source.vba meta.attribute.vba -# ^ source.vba meta.attribute.vba keyword.operator.comparison.vba +# ^ source.vba meta.attribute.vba keyword.operator.assignment.vba # ^ source.vba meta.attribute.vba # ^^^^^ source.vba meta.attribute.vba constant.language.boolean.vba >Attribute VB_Exposed = False -#^^^^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba entity.other.attribute-name.vba +#^^^^^^^^^ source.vba meta.attribute.vba keyword.attribute.vba +# ^ source.vba meta.attribute.vba +# ^^^^^^^^^^ source.vba meta.attribute.vba support.variable.property.vba # ^ source.vba meta.attribute.vba -# ^ source.vba meta.attribute.vba keyword.operator.comparison.vba +# ^ source.vba meta.attribute.vba keyword.operator.assignment.vba # ^ source.vba meta.attribute.vba # ^^^^^ source.vba meta.attribute.vba constant.language.boolean.vba > diff --git a/test/textmate/snapshot/module.bas.snap b/test/textmate/snapshot/module.bas.snap index 05a4dde..31d7ec0 100644 --- a/test/textmate/snapshot/module.bas.snap +++ b/test/textmate/snapshot/module.bas.snap @@ -1,7 +1,9 @@ >Attribute VB_Name = "ModuleName" -#^^^^^^^^^^^^^^^^^ source.vba meta.attribute.vba entity.other.attribute-name.vba +#^^^^^^^^^ source.vba meta.attribute.vba keyword.attribute.vba +# ^ source.vba meta.attribute.vba +# ^^^^^^^ source.vba meta.attribute.vba support.variable.property.vba # ^ source.vba meta.attribute.vba -# ^ source.vba meta.attribute.vba keyword.operator.comparison.vba +# ^ source.vba meta.attribute.vba keyword.operator.assignment.vba # ^ source.vba meta.attribute.vba # ^^^^^^^^^^^^ source.vba meta.attribute.vba string.quoted.double.vba > diff --git a/test/textmate/unit/classHeaders.vba b/test/textmate/unit/classHeaders.vba new file mode 100644 index 0000000..91a5184 --- /dev/null +++ b/test/textmate/unit/classHeaders.vba @@ -0,0 +1,64 @@ +' SYNTAX TEST "source.vba" "class headers" + + +VERSION 1.0 CLASS +' <---------------- entity.other.attribute-name.block.vba +' ^^^ constant.numeric.vba + +BEGIN +' <----- entity.other.attribute-name.block.vba + + MultiUse = -1 'True +' ^^^^^^^^^^^^^^^^^^^^ entity.other.attribute-name.block.vba +' ^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^ constant.numeric.vba +' ^^^^^ comment.line.apostrophe.vba + +END +' <--- entity.other.attribute-name.block.vba + +Attribute VB_Name = "ClassName" +' <------------------------------ meta.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^^^^^^^ string.quoted.double.vba + +Attribute VB_Description = "Class description goes here" +' <------------------------------------------------------- meta.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.vba + +Attribute VB_GlobalNameSpace = False +' <----------------------------------- meta.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^ constant.language.boolean.vba + +Attribute VB_Creatable = False +' <----------------------------- meta.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^ constant.language.boolean.vba + +Attribute VB_PredeclaredId = False +' <--------------------------------- meta.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^ constant.language.boolean.vba + +Attribute VB_Exposed = False +' <--------------------------- meta.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^ constant.language.boolean.vba + +Option Explicit +' <--------------- keyword.control.vba \ No newline at end of file diff --git a/test/textmate/unit/module/comments.vba b/test/textmate/unit/comments.vba similarity index 100% rename from test/textmate/unit/module/comments.vba rename to test/textmate/unit/comments.vba diff --git a/test/textmate/unit/declarations.vba b/test/textmate/unit/declarations.vba new file mode 100644 index 0000000..18ae445 --- /dev/null +++ b/test/textmate/unit/declarations.vba @@ -0,0 +1,106 @@ +' SYNTAX TEST "source.vba" "declarations" + +' Variable, constant, and function declarations. + + +Dim x As Long, y As Long, z ' Comment +'<------------------------------- meta.variable.declaration.vba +'<--- storage.modifier.declare-variable.vba +' ^ ^ ^ variable.other.readwrite.vba +' ^^ ^^ keyword.control.as.vba +' ^^^^ ^^^^ support.type.primitive.Long.vba +' ^ ^ punctuation.separator.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba +Private x As Long, y As Long, z ' Comment +'<------------------------------- meta.variable.declaration.vba +'<------- storage.modifier.declare-variable.vba +' ^ ^ ^ variable.other.readwrite.vba +' ^^ ^^ keyword.control.as.vba +' ^^^^ ^^^^ support.type.primitive.Long.vba +' ^ ^ punctuation.separator.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba +Public x As Long, y As Long, z ' Comment +'<------------------------------- meta.variable.declaration.vba +'<------ storage.modifier.declare-variable.vba +' ^ ^ ^ variable.other.readwrite.vba +' ^^ ^^ keyword.control.as.vba +' ^^^^ ^^^^ support.type.primitive.Long.vba +' ^ ^ punctuation.separator.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba +Global x As Long, y As Long, z ' Comment +'<------------------------------- meta.variable.declaration.vba +'<------ storage.modifier.declare-variable.vba +' ^ ^ ^ variable.other.readwrite.vba +' ^^ ^^ keyword.control.as.vba +' ^^^^ ^^^^ support.type.primitive.Long.vba +' ^ ^ punctuation.separator.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba + + Const X As Long = 0, Y As Long = 0, Z = 0 ' Comment +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.const.declaration.vba +' ^^^^^ storage.type.vba +' ^ ^ ^ variable.other.constant +' ^^ ^^ keyword.control.as.vba +' ^^^^ ^^^^ support.type.primitive.Long.vba +' ^ ^ punctuation.separator.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba +Private Const X As Long = 0, Y As Long = 0, Z = 0 ' Comment +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.const.declaration.vba +' ^^^^^ storage.type.vba +' ^ ^ ^ variable.other.constant +' ^^ ^^ keyword.control.as.vba +' ^^^^ ^^^^ support.type.primitive.Long.vba +' ^ ^ punctuation.separator.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba +Public Const X As Long = 0, Y As Long = 0, Z = 0 ' Comment +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.const.declaration.vba +' ^^^^^ storage.type.vba +' ^ ^ ^ variable.other.constant +' ^^ ^^ keyword.control.as.vba +' ^^^^ ^^^^ support.type.primitive.Long.vba +' ^ ^ punctuation.separator.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba +Global Const X As Long = 0, Y As Long = 0, Z = 0 ' Comment +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.const.declaration.vba +' ^^^^^ storage.type.vba +' ^ ^ ^ variable.other.constant +' ^^ ^^ keyword.control.as.vba +' ^^^^ ^^^^ support.type.primitive.Long.vba +' ^ ^ punctuation.separator.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba +Dim x As Long, _ +'<--- meta.variable.declaration.vba storage.modifier.declare-variable.vba +' ^ meta.variable.declaration.vba variable.other.readwrite.vba +' ^^ meta.variable.declaration.vba keyword.control.as.vba +' ^^^^ meta.variable.declaration.vba support.type.primitive.Long.vba +' ^ meta.variable.declaration.vba punctuation.separator.vba +' ^ meta.variable.declaration.vba keyword.control.line-continuation.vba + y As Long, _ +' ^ meta.variable.declaration.vba variable.other.readwrite.vba +' ^^ meta.variable.declaration.vba keyword.control.as.vba +' ^^^^ meta.variable.declaration.vba support.type.primitive.Long.vba +' ^ meta.variable.declaration.vba punctuation.separator.vba +' ^ meta.variable.declaration.vba keyword.control.line-continuation.vba + z ' Comment +' ^ meta.variable.declaration.vba variable.other.readwrite.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba +Const X As Long = 0, _ +'<----- meta.const.declaration.vba storage.type.vba +' ^ meta.const.declaration.vba variable.other.constant +' ^^ meta.const.declaration.vba keyword.control.as.vba +' ^^^^ meta.const.declaration.vba support.type.primitive.Long.vba +' ^ meta.const.declaration.vba keyword.operator.assignment.vba +' ^ meta.const.declaration.vba constant.numeric.vba +' ^ meta.const.declaration.vba keyword.control.line-continuation.vba + Y As Long = 0, _ +' ^ meta.const.declaration.vba variable.other.constant +' ^^ meta.const.declaration.vba keyword.control.as.vba +' ^^^^ meta.const.declaration.vba support.type.primitive.Long.vba +' ^ meta.const.declaration.vba keyword.operator.assignment.vba +' ^ meta.const.declaration.vba constant.numeric.vba +' ^ meta.const.declaration.vba keyword.control.line-continuation.vba + Z = 0 ' Comment +' ^ meta.const.declaration.vba variable.other.constant +' ^ meta.const.declaration.vba keyword.operator.assignment.vba +' ^ meta.const.declaration.vba constant.numeric.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.variable.declaration.vba \ No newline at end of file diff --git a/test/textmate/unit/expressions.vba b/test/textmate/unit/expressions.vba new file mode 100644 index 0000000..1d8abb3 --- /dev/null +++ b/test/textmate/unit/expressions.vba @@ -0,0 +1,49 @@ +' SYNTAX TEST "source.vba" "expressions" + +' Expressions as part of other statements. + +Sub Test() + foo = bar ' Comment +' ^^^ meta.expression.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.expression.vba + foo.bar = "' Not comment" +' ^^^^^^^^^^^^^^^ meta.expression.vba + foo.bar = bar.foo +' ^^^^^^^ meta.expression.vba + foo = bar And Not True +' ^^^^^^^^^^^^^^^^ meta.expression.vba + foo = bar Or Not foo = 12 +' ^^^^^^^^^^^^^^^^^^^ meta.expression.vba + foo = Not bar +' ^^^^^^^ meta.expression.vba + foo = _ +' ^ meta.expression.vba + foo.bar.baz() _ +' ^^^^^^^^^^^^^^^ meta.expression.vba + + bar.foo.biz _ +' ^^^^^^^^^^^^^^^ meta.expression.vba +' ^ keyword.operator.arithmetic.vba + * 3 +' ^^^ meta.expression.vba +' ^ keyword.operator.arithmetic.vba + + foo = Not Me.Bar( _ +' ^^^^^^^^^^^^^ meta.expression.vba +' ^^^ keyword.operator.logical.vba +' ^^ meta.function.call.vba variable.language.me.vba +' ^^^ meta.function.call.vba entity.name.function.call.vba + foo, x = 3, False) ' Comment +' ^^^^^^^^^^^^^^^^^ meta.expression.vba +' ^^^ ^^^^^ ^^^^^ meta.expression.vba meta.expression.vba +' ^^^ ^ variable.other.readwrite.vba +' ^ keyword.operator.comparison.vba +' ^ constant.numeric.vba +' ^^^^^ constant.language.boolean.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.expression.vba + + If condA And Not Foo(condB) Then +' ^^^^^^^^^^^^^^^^^^^^^^^^ meta.expression.vba +' ^^^ ^^^ keyword.operator.logical.vba +' ^^^^^ meta.expression.vba meta.expression.vba variable.other.readwrite.vba + End If +End Sub \ No newline at end of file diff --git a/test/textmate/unit/logicFlow.vba b/test/textmate/unit/logicFlow.vba new file mode 100644 index 0000000..0fb8378 --- /dev/null +++ b/test/textmate/unit/logicFlow.vba @@ -0,0 +1,125 @@ +' SYNTAX TEST "source.vba" "logic flow" + +Attribute VB_Name = "Logic" +' Copyright 2024 Sam Vanderslink +' +' Permission is hereby granted, free of charge, to any person obtaining a copy +' of this software and associated documentation files (the "Software"), to deal +' in the Software without restriction, including without limitation the rights +' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +' copies of the Software, and to permit persons to whom the Software is +' furnished to do so, subject to the following conditions: +' +' The above copyright notice and this permission notice shall be included in +' all copies or substantial portions of the Software. +' +' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +' IN THE SOFTWARE. + +Option Explicit + + +Public Sub Foo() +' Variable positive + If condition Then +' ^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^ keyword.control.flow.block-decision.vba +' ^^^^ keyword.control.flow.block-decision.vba + Else If condition Then +' ^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^^ keyword.control.flow.block-decision.vba +' ^^^^ keyword.control.flow.block-decision.vba + End If +' ^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^ keyword.control.flow.block-decision.vba + +' Variable negative + If Not condition Then +' ^^^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^ keyword.control.flow.block-decision.vba +' ^^^ keyword.operator.logical.vba +' ^^^^ keyword.control.flow.block-decision.vba + Else If Not condition Then +' ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^^ keyword.control.flow.block-decision.vba +' ^^^ keyword.operator.logical.vba +' ^^^^ keyword.control.flow.block-decision.vba + End If +' ^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^ keyword.control.flow.block-decision.vba + +' Function positive + If condition() Then +' ^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^ keyword.control.flow.block-decision.vba +' ^^^^^^^^^^^ meta.function.call.vba +' ^^^^ keyword.control.flow.block-decision.vba + Else If condition() Then +' ^^^^^^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^^ keyword.control.flow.block-decision.vba +' ^^^^^^^^^^^ meta.function.call.vba +' ^^^^ keyword.control.flow.block-decision.vba + End If +' ^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^ keyword.control.flow.block-decision.vba + +' Function negative + If Not condition() Then +' ^^^^^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^ keyword.control.flow.block-decision.vba +' ^^^ keyword.operator.logical.vba +' ^^^^^^^^^^^ meta.function.call.vba +' ^^^^ keyword.control.flow.block-decision.vba + Else If Not condition() Then +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^^ keyword.control.flow.block-decision.vba +' ^^^ keyword.operator.logical.vba +' ^^^^^^^^^^^ meta.function.call.vba +' ^^^^ keyword.control.flow.block-decision.vba + End If +' ^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^ keyword.control.flow.block-decision.vba + +' Literal + If Not True Then +' ^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^ keyword.control.flow.block-decision.vba +' ^^^ keyword.operator.logical.vba +' ^^^^ constant.language.boolean.vba +' ^^^^ keyword.control.flow.block-decision.vba + Else If Not False Then +' ^^^^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^^ keyword.control.flow.block-decision.vba +' ^^^ keyword.operator.logical.vba +' ^^^^^ constant.language.boolean.vba +' ^^^^ keyword.control.flow.block-decision.vba + + End If +' ^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^ keyword.control.flow.block-decision.vba + +' Expression + If Not condition = 5 Then +' ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^ keyword.control.flow.block-decision.vba +' ^^^ keyword.operator.logical.vba +' ^ keyword.operator.comparison.vba +' ^ constant.numeric.vba +' ^^^^ keyword.control.flow.block-decision.vba + Else If Not GetValue(x) = GetOtherValue("foo") Then +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^^ keyword.control.flow.block-decision.vba +' ^^^ keyword.operator.logical.vba +' ^^^^^^^^^^^ meta.function.call.vba +' ^ keyword.operator.comparison.vba +' ^^^^^^^^^^^^^^^^^^^^ meta.function.call.vba +' ^^^^ keyword.control.flow.block-decision.vba + End If +' ^^^^^^ meta.flow.block-if-else.vba +' ^^^^^^ keyword.control.flow.block-decision.vba +End Sub \ No newline at end of file diff --git a/test/textmate/unit/methodAttributes.vba b/test/textmate/unit/methodAttributes.vba new file mode 100644 index 0000000..31a8ccf --- /dev/null +++ b/test/textmate/unit/methodAttributes.vba @@ -0,0 +1,96 @@ +' SYNTAX TEST "source.vba" "method attributes" + +Public Function Identifier() As Variant +Attribute Identifier.VB_Description = "Docstring." +' <-------------------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^^^^^^^^ string.quoted.double.vba + +Attribute Identifier.VB_UserMemId = 0 +' <------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^ constant.numeric.vba + +End Function + +Public Sub Identifier() +Attribute Identifier.VB_Description = "Docstring." +' <-------------------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^^^^^^^^ string.quoted.double.vba + +Attribute Identifier.VB_UserMemId = 0 +' <------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^ constant.numeric.vba + +End Sub + +Public Property Let Identifier(var As PropertyType) +Attribute Identifier.VB_Description = "Docstring." +' <-------------------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^^^^^^^^ string.quoted.double.vba + +Attribute Identifier.VB_UserMemId = 0 +' <------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^ constant.numeric.vba + +End Property + +Public Property Get Identifier() As PropertyType +Attribute Identifier.VB_Description = "Docstring." +' <-------------------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^^^^^^^^ string.quoted.double.vba + +Attribute Identifier.VB_UserMemId = 0 +' <------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^ constant.numeric.vba + +End Property + +Public Property Let Identifier(var As PropertyType) +Attribute Identifier.VB_Description = "Docstring." +' <-------------------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^^^^^^^^ string.quoted.double.vba + +Attribute Identifier.VB_UserMemId = 0 +' <------------------------------------- source.method.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^^^^ entity.name.function.vba +' ^^^^^^^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^ constant.numeric.vba + +End Property \ No newline at end of file diff --git a/test/textmate/unit/methodSignatures.vba b/test/textmate/unit/methodSignatures.vba new file mode 100644 index 0000000..daa1a79 --- /dev/null +++ b/test/textmate/unit/methodSignatures.vba @@ -0,0 +1,147 @@ +' SYNTAX TEST "source.vba" "method signatures" + +' Inline sub +Sub Foo(): Debug.Print "Hello, World!": End Sub +'<-------- source.method.signature.vba +' <--- storage.type.method.vba +' ^^^ entity.name.function.vba +' ^^^^^^^ storage.type.method.close.vba + +' Standard sub +Public Sub Foo(ByVal x As Long, ByRef y As Long, ParamArray vars() As Variant) +' <------------------------------------------------------------------------------ source.method.signature.vba +' <---------- storage.type.method.vba +' ^^^ entity.name.function.vba +' ^^^^^ storage.type.modifier.vba +' ^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^ support.type.primitive.Long.vba +' ^ punctuation.separator.vba +' ^^^^^ storage.type.modifier.vba +' ^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^ support.type.primitive.Long.vba +' ^ punctuation.separator.vba +' ^^^^^^^^^^ storage.type.modifier.vba +' ^^^^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^^^^ support.type.primitive.Variant.vba +End Sub + + +' Inline Function +Function Foo() As String: Foo = "Hello, World!": End Function +' <-------------- source.method.signature.vba +' <-------- storage.type.method.vba +' ^^^ entity.name.function.vba +' ^^ keyword.control.as.vba +' ^^^^^^ support.type.primitive.String.vba +' ^^^^^^^^^^^^ storage.type.method.close.vba + +' Standard function +Public Function Foo(ByVal x As Long, ByRef y As Long, ParamArray vars() As Variant) As Object +' <--------------------------------------------------------------------------------------------- source.method.signature.vba +' <--------------- storage.type.method.vba +' ^^^ entity.name.function.vba +' ^^^^^ storage.type.modifier.vba +' ^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^ support.type.primitive.Long.vba +' ^ punctuation.separator.vba +' ^^^^^ storage.type.modifier.vba +' ^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^ support.type.primitive.Long.vba +' ^ punctuation.separator.vba +' ^^^^^^^^^^ storage.type.modifier.vba +' ^^^^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^^^^ support.type.primitive.Variant.vba +' ^^ keyword.control.as.vba +' ^^^^^^ support.type.object.Object.vba +End Function +'<------------- storage.type.method.close.vba + +' Multi-Line Sub +Public Sub Foo(Optional Bar As String, _ +' <---------- storage.type.method.vba +' ^^^ entity.name.function.vba +' ^^^^^^^^ storage.type.modifier.vba +' ^^^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^^^ support.type.primitive.String.vba +' ^ punctuation.separator.vba +' ^ keyword.control.line-continuation.vba + Optional Biz As String = "Biz", _ +' ^^^^^^^^ storage.type.modifier.vba +' ^^^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^^^ support.type.primitive.String.vba +' ^ keyword.operator.assignment.vba +' ^^^^^ string.quoted.double.vba +' ^ punctuation.separator.vba +' ^ keyword.control.line-continuation.vba + Optional ByVal Zip As Boolean = True) +' ^^^^^^^^ ^^^^^ storage.type.modifier.vba +' ^^^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^^^^ support.type.primitive.Boolean.vba +' ^ keyword.operator.assignment.vba +' ^^^^ constant.language.boolean.vba +End Sub +'<-------- storage.type.method.close.vba + +' Crazy sub - due to limitations with textMate, it does not seem possible to format +' types when using line continuations. This is because matches work on a single line, +' and it appears begin/end matches operate process "patterns" line-by-line too. An inner +' begin/end rule will only be given a line at a time to process. +Public Sub Foo( _ +' <---------- storage.type.method.vba +' ^^^ entity.name.function.vba +' ^ keyword.control.line-continuation.vba + Optional baz As String _ +' ^^^^^^^^ storage.type.modifier.vba +' ^^^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^^^^^^ support.type.primitive.String.vba +' ^ keyword.control.line-continuation.vba + = _ +' ^ keyword.operator.assignment.vba +' ^ keyword.control.line-continuation.vba + "Something", _ +' ^^^^^^^^^^^ string.quoted.double.vba +' ^ punctuation.separator.vba +' ^ keyword.control.line-continuation.vba + biz _ +' ^^^ variable.parameter.vba +' ^ keyword.control.line-continuation.vba + As String, _ +' ^^ keyword.control.as.vba +' ^^^^^^ support.type.primitive.String.vba +' ^ punctuation.separator.vba +' ^ keyword.control.line-continuation.vba + Optional _ +' ^^^^^^^^ storage.type.modifier.vba +' ^ keyword.control.line-continuation.vba + ByRef _ +' ^^^^^ storage.type.modifier.vba +' ^ keyword.control.line-continuation.vba + bix As _ +' ^^^ variable.parameter.vba +' ^^ keyword.control.as.vba +' ^ keyword.control.line-continuation.vba + String, _ +' ^^^^^^ support.type.primitive.String.vba +' ^ punctuation.separator.vba +' ^ keyword.control.line-continuation.vba + bax _ +' ^^^ variable.parameter.vba +' ^ keyword.control.line-continuation.vba + As _ +' ^^ keyword.control.as.vba +' ^ keyword.control.line-continuation.vba + Object) +' ^^^^^^ support.type.object.Object.vba + +End Sub +'<-------- storage.type.method.close.vba diff --git a/test/textmate/unit/module/classHeaders.vba b/test/textmate/unit/module/classHeaders.vba deleted file mode 100644 index 563ccb0..0000000 --- a/test/textmate/unit/module/classHeaders.vba +++ /dev/null @@ -1,57 +0,0 @@ -// SYNTAX TEST "source.vba" "class headers" - - -VERSION 1.0 CLASS -// <---------------- entity.other.attribute-name.block.vba -// ^^^ constant.numeric.vba - -BEGIN -// <----- entity.other.attribute-name.block.vba - - MultiUse = -1 'True -// ^^^^^^^^^^^^^^^^^^^^ entity.other.attribute-name.block.vba -// ^ keyword.operator.comparison.vba -// ^^ constant.numeric.vba -// ^^^^^ comment.line.apostrophe.vba - -END -// <--- entity.other.attribute-name.block.vba - -Attribute VB_Name = "ClassName" -// <------------------------------ meta.attribute.vba -// <---------------- entity.other.attribute-name.vba -// ^ keyword.operator.comparison.vba -// ^^^^^^^^^^^ string.quoted.double.vba - -Attribute VB_Description = "Class description goes here" -// <------------------------------------------------------- meta.attribute.vba -// <-------------------- entity.other.attribute-name.vba -// ^ keyword.operator.comparison.vba -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.vba - -Attribute VB_GlobalNameSpace = False -// <----------------------------------- meta.attribute.vba -// <------------------------ entity.other.attribute-name.vba -// ^ keyword.operator.comparison.vba -// ^^^^^ constant.language.boolean.vba - -Attribute VB_Creatable = False -// <----------------------------- meta.attribute.vba -// <------------------ entity.other.attribute-name.vba -// ^ keyword.operator.comparison.vba -// ^^^^^ constant.language.boolean.vba - -Attribute VB_PredeclaredId = False -// <--------------------------------- meta.attribute.vba -// <------------------------- entity.other.attribute-name.vba -// ^ keyword.operator.comparison.vba -// ^^^^^ constant.language.boolean.vba - -Attribute VB_Exposed = False -// <--------------------------- meta.attribute.vba -// <------------------- entity.other.attribute-name.vba -// ^ keyword.operator.comparison.vba -// ^^^^^ constant.language.boolean.vba - -Option Explicit -// <--------------- keyword.control.vba \ No newline at end of file diff --git a/test/textmate/unit/module/moduleHeaders.vba b/test/textmate/unit/module/moduleHeaders.vba deleted file mode 100644 index 40b04d3..0000000 --- a/test/textmate/unit/module/moduleHeaders.vba +++ /dev/null @@ -1,10 +0,0 @@ -// SYNTAX TEST "source.vba" "module headers" - -Attribute VB_Name = "ModuleName" -// <------------------------------- meta.attribute.vba -// <----------------- entity.other.attribute-name.vba -// ^ keyword.operator.comparison.vba -// ^^^^^^^^^^^^ string.quoted.double.vba - -Option Explicit -// <--------------- keyword.control.vba \ No newline at end of file diff --git a/test/textmate/unit/moduleHeaders.vba b/test/textmate/unit/moduleHeaders.vba new file mode 100644 index 0000000..764dafe --- /dev/null +++ b/test/textmate/unit/moduleHeaders.vba @@ -0,0 +1,11 @@ +' SYNTAX TEST "source.vba" "module headers" + +Attribute VB_Name = "ModuleName" +' <------------------------------- meta.attribute.vba +' <--------- keyword.attribute.vba +' ^^^^^^^ support.variable.property.vba +' ^ keyword.operator.assignment.vba +' ^^^^^^^^^^^^ string.quoted.double.vba + +Option Explicit +' <--------------- keyword.control.vba \ No newline at end of file diff --git a/test/textmate/unit/params.vba b/test/textmate/unit/params.vba new file mode 100644 index 0000000..562b466 --- /dev/null +++ b/test/textmate/unit/params.vba @@ -0,0 +1,74 @@ +' SYNTAX TEST "source.vba" "params" + +' Parameters passed to method calls. + +Sub SubCallTesting() + Foo bar, True, "abc,123", func(123, &H0000) ' Comment +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.sub-call.vba +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.arguments.vba +' ^^^ entity.name.function.call.vba +' ^^^ meta.variable-or-property.vba variable.other.readwrite.vba +' ^ ^ ^ ^ punctuation.separator.vba +' ^^^^ constant.language.boolean.vba +' ^^^^^^^^^ string.quoted.double.vba +' ^^^^^^^^^^^^^^^^^ meta.function.call.vba +' ^^^ constant.numeric.vba +' ^^^^^^ constant.numeric.hex.vba +' ^^^^^^^^ comment.line.apostrophe.vba - meta.sub-call.vba + + Foo bar, _ +' ^^^^^^^^^^ meta.sub-call.vba +' ^^^ meta.arguments.vba meta.variable-or-property.vba variable.other.readwrite.vba +' ^ meta.arguments.vba punctuation.separator.vba +' ^ meta.arguments.vba keyword.control.line-continuation.vba + True, _ +' ^^^^ meta.arguments.vba constant.language.boolean.vba + "abc,123", _ +' ^^^^^^^^^ meta.arguments.vba string.quoted.double.vba +' ^ meta.arguments.vba punctuation.separator.vba +' ^ meta.arguments.vba keyword.control.line-continuation.vba + func(123, &H0000) +' ^^^^^^^^^^^^^^^^^ meta.function.call.vba +' ^^^^^^^^^^^ meta.arguments.vba meta.arguments.vba +' ^^^ constant.numeric.vba +' ^ meta.arguments.vba punctuation.separator.vba +' ^^^^^^ constant.numeric.hex.vba +End Sub + +Sub FuncCallTesting() + x = Foo(bar, True, "abc,123", Func&(123, &H0000)) ' Comment +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function.call.vba +' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.arguments.vba +' ^ ^ ^ ^ punctuation.separator.vba +' ^^^ meta.variable-or-property.vba variable.other.readwrite.vba +' ^^^^ constant.language.boolean.vba +' ^^^^^^^^^ string.quoted.double.vba +' ^^^^^^^^^^^^^^^^^^ meta.function.call.vba +' ^^^^ entity.name.function.call.vba +' ^ support.type.primitive.vba +' ^^^ constant.numeric.vba +' ^^^^^^ constant.numeric.hex.vba +' ^^^^^^^^ comment.line.apostrophe.vba - meta.function.call.vba + + x = Foo(bar, _ +' ^^^ meta.function.call.vba entity.name.function.call.vba +' ^^^ meta.function.call.vba meta.arguments.vba variable.other.readwrite.vba +' ^ meta.function.call.vba meta.arguments.vba punctuation.separator.vba +' ^ meta.function.call.vba meta.arguments.vba keyword.control.line-continuation.vba + True, _ +' ^^^^ meta.function.call.vba meta.arguments.vba constant.language.boolean.vba +' ^ meta.function.call.vba meta.arguments.vba punctuation.separator.vba +' ^ meta.function.call.vba meta.arguments.vba keyword.control.line-continuation.vba + "abc,123", _ +' ^^^^^^^^^ meta.function.call.vba meta.arguments.vba string.quoted.double.vba +' ^ meta.function.call.vba meta.arguments.vba punctuation.separator.vba +' ^ meta.function.call.vba meta.arguments.vba keyword.control.line-continuation.vba + func&(123, &H0000)) ' Comment +' ^^^^^^^^^^^^^^^^^ meta.function.call.vba meta.arguments.vba meta.function.call.vba +' ^^^^ meta.function.call.vba meta.arguments.vba meta.function.call.vba entity.name.function.call.vba +' ^ meta.function.call.vba meta.arguments.vba meta.function.call.vba support.type.primitive.vba +' ^^^ meta.function.call.vba meta.arguments.vba meta.function.call.vba meta.arguments.vba constant.numeric.vba +' ^ meta.function.call.vba meta.arguments.vba meta.function.call.vba meta.arguments.vba punctuation.separator.vba +' ^^^^^^ meta.function.call.vba meta.arguments.vba meta.function.call.vba meta.arguments.vba constant.numeric.hex.vba +' ^^^^^^^^^ comment.line.apostrophe.vba - meta.function.call.vba +End Sub \ No newline at end of file