From 42b15463cb3e7cfb0362e7fc4f70a8dc6e6ec6af Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Tue, 24 Mar 2020 20:30:58 +0100 Subject: [PATCH] C# improvements (#1444) A complete rewrite of the C# language to support almost every feature of C# 8.0. --- components/prism-csharp.js | 394 +++++++++++++++--- components/prism-csharp.min.js | 2 +- tests/languages/csharp/attribute_feature.test | 258 ++++++++++++ .../class-name-declaration_feature.test | 110 +++++ ...ass-name-variables-parameters_feature.test | 121 ++++++ .../languages/csharp/class-name_feature.test | 34 -- .../constructor-invocation_feature.test | 86 ++++ tests/languages/csharp/for_feature.test | 33 ++ .../csharp/generic-constraint_feature.test | 119 ++++++ tests/languages/csharp/generic_feature.test | 30 +- .../csharp/interpolation-string_feature.test | 114 +++++ tests/languages/csharp/issue1365.test | 34 +- tests/languages/csharp/issue1371.test | 128 ++++-- tests/languages/csharp/keyword_feature.test | 42 +- .../csharp/named-parameter_feature.test | 21 + tests/languages/csharp/namespace_feature.test | 25 ++ tests/languages/csharp/number_feature.test | 42 +- tests/languages/csharp/operator_feature.test | 5 +- tests/languages/csharp/range_feature.test | 42 ++ .../languages/csharp/return-type_feature.test | 166 ++++++++ .../csharp/type-expression_feature.test | 63 +++ tests/languages/csharp/type-list_feature.test | 153 +++++++ .../csharp/using-directive_feature.test | 81 ++++ .../t4-cs/block_standard_feature.test | 8 +- 24 files changed, 1934 insertions(+), 177 deletions(-) create mode 100644 tests/languages/csharp/attribute_feature.test create mode 100644 tests/languages/csharp/class-name-declaration_feature.test create mode 100644 tests/languages/csharp/class-name-variables-parameters_feature.test delete mode 100644 tests/languages/csharp/class-name_feature.test create mode 100644 tests/languages/csharp/constructor-invocation_feature.test create mode 100644 tests/languages/csharp/for_feature.test create mode 100644 tests/languages/csharp/generic-constraint_feature.test create mode 100644 tests/languages/csharp/interpolation-string_feature.test create mode 100644 tests/languages/csharp/named-parameter_feature.test create mode 100644 tests/languages/csharp/namespace_feature.test create mode 100644 tests/languages/csharp/range_feature.test create mode 100644 tests/languages/csharp/return-type_feature.test create mode 100644 tests/languages/csharp/type-expression_feature.test create mode 100644 tests/languages/csharp/type-list_feature.test create mode 100644 tests/languages/csharp/using-directive_feature.test diff --git a/components/prism-csharp.js b/components/prism-csharp.js index 8ff4e00932..4cb35fc946 100644 --- a/components/prism-csharp.js +++ b/components/prism-csharp.js @@ -1,81 +1,359 @@ -Prism.languages.csharp = Prism.languages.extend('clike', { - 'keyword': /\b(?:abstract|add|alias|as|ascending|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|do|double|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|global|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/, - 'string': [ - { - pattern: /@("|')(?:\1\1|\\[\s\S]|(?!\1)[^\\])*\1/, - greedy: true - }, - { - pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*?\1/, - greedy: true +(function (Prism) { + + /** + * Replaces all placeholders "<>" of given pattern with the n-th replacement (zero based). + * + * Note: This is a simple text based replacement. Be careful when using backreferences! + * + * @param {string} pattern the given pattern. + * @param {string[]} replacements a list of replacement which can be inserted into the given pattern. + * @returns {string} the pattern with all placeholders replaced with their corresponding replacements. + * @example replace(/a<<0>>a/.source, [/b+/.source]) === /a(?:b+)a/.source + */ + function replace(pattern, replacements) { + return pattern.replace(/<<(\d+)>>/g, function (m, index) { + return '(?:' + replacements[+index] + ')'; + }); + } + /** + * @param {string} pattern + * @param {string[]} replacements + * @param {string} [flags] + * @returns {RegExp} + */ + function re(pattern, replacements, flags) { + return RegExp(replace(pattern, replacements), flags || ''); + } + + /** + * Creates a nested pattern where all occurrences of the string `<>` are replaced with the pattern itself. + * + * @param {string} pattern + * @param {number} depthLog2 + * @returns {string} + */ + function nested(pattern, depthLog2) { + for (var i = 0; i < depthLog2; i++) { + pattern = pattern.replace(/<>/g, '(?:' + pattern + ')'); + } + return pattern.replace(/<>/g, '[^\\s\\S]'); + } + + // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ + var keywordKinds = { + // keywords which represent a return or variable type + type: 'bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void', + // keywords which are used to declare a type + typeDeclaration: 'class enum interface struct', + // contextual keywords + // ("var" and "dynamic" are missing because they are used like types) + contextual: 'add alias ascending async await by descending from get global group into join let nameof notnull on orderby partial remove select set unmanaged value when where where', + // all other keywords + other: 'abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield' + }; + + // keywords + function keywordsToPattern(words) { + return '\\b(?:' + words.trim().replace(/ /g, '|') + ')\\b'; + } + var typeDeclarationKeywords = keywordsToPattern(keywordKinds.typeDeclaration); + var keywords = RegExp(keywordsToPattern(keywordKinds.type + ' ' + keywordKinds.typeDeclaration + ' ' + keywordKinds.contextual + ' ' + keywordKinds.other)); + var nonTypeKeywords = keywordsToPattern(keywordKinds.typeDeclaration + ' ' + keywordKinds.contextual + ' ' + keywordKinds.other); + var nonContextualKeywords = keywordsToPattern(keywordKinds.type + ' ' + keywordKinds.typeDeclaration + ' ' + keywordKinds.other); + + // types + var generic = nested(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source, 2); // the idea behind the other forbidden characters is to prevent false positives. Same for tupleElement. + var nestedRound = nested(/\((?:[^()]|<>)*\)/.source, 2); + var name = /@?\b[A-Za-z_]\w*\b/.source; + var genericName = replace(/<<0>>(?:\s*<<1>>)?/.source, [name, generic]); + var identifier = replace(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source, [nonTypeKeywords, genericName]); + var array = /\[\s*(?:,\s*)*\]/.source; + var tupleElement = replace(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source, [generic, nestedRound, array]) + var tuple = replace(/\(<<0>>+(?:,<<0>>+)+\)/.source, [tupleElement]); + var typeExpression = replace(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source, [tuple, identifier, array]); + + var typeInside = { + 'keyword': keywords, + 'punctuation': /[<>()?,.:[\]]/ + }; + + // strings & characters + // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#character-literals + // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#string-literals + var character = /'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source; // simplified pattern + var regularString = /"(?:\\.|[^\\"\r\n])*"/.source; + var verbatimString = /@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source; + + + Prism.languages.csharp = Prism.languages.extend('clike', { + 'string': [ + { + pattern: re(/(^|[^$\\])<<0>>/.source, [verbatimString]), + lookbehind: true, + greedy: true + }, + { + pattern: re(/(^|[^@$\\])<<0>>/.source, [regularString]), + lookbehind: true, + greedy: true + }, + { + pattern: RegExp(character), + greedy: true, + alias: 'character' + } + ], + 'class-name': [ + { + // Using static + // using static System.Math; + pattern: re(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source, [identifier]), + lookbehind: true, + inside: typeInside + }, + { + // Using alias (type) + // using Project = PC.MyCompany.Project; + pattern: re(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source, [name, typeExpression]), + lookbehind: true, + inside: typeInside + }, + { + // Using alias (alias) + // using Project = PC.MyCompany.Project; + pattern: re(/(\busing\s+)<<0>>(?=\s*=)/.source, [name]), + lookbehind: true + }, + { + // Type declarations + // class Foo + // interface Foo + pattern: re(/(\b<<0>>\s+)<<1>>/.source, [typeDeclarationKeywords, genericName]), + lookbehind: true, + inside: typeInside + }, + { + // Single catch exception declaration + // catch(Foo) + // (things like catch(Foo e) is covered by variable declaration) + pattern: re(/(\bcatch\s*\(\s*)<<0>>/.source, [identifier]), + lookbehind: true, + inside: typeInside + }, + { + // Name of the type parameter of generic constraints + // where Foo : class + pattern: re(/(\bwhere\s+)<<0>>/.source, [name]), + lookbehind: true + }, + { + // Casts and checks via as and is. + // as Foo, is Bar + // (things like if(a is Foo b) is covered by variable declaration) + pattern: re(/(\b(?:is|as)\s+)<<0>>/.source, [typeExpression]), + lookbehind: true, + inside: typeInside + }, + { + // Variable, field and parameter declaration + // (Foo bar, Bar baz, Foo[,,] bay, Foo> bax) + pattern: re(/\b<<0>>(?=\s+(?!<<1>>)<<2>>(?:\s*[=,;:{)\]]|\s+in))/.source, [typeExpression, nonContextualKeywords, name]), + inside: typeInside + } + ], + 'keyword': keywords, + // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#literals + 'number': /(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:ul|lu|[dflmu])?\b/i, + 'operator': />>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/, + 'punctuation': /\?\.?|::|[{}[\];(),.:]/ + }); + + Prism.languages.insertBefore('csharp', 'number', { + 'range': { + pattern: /\.\./, + alias: 'operator' + } + }); + + Prism.languages.insertBefore('csharp', 'punctuation', { + 'named-parameter': { + pattern: re(/([(,]\s*)<<0>>(?=\s*:)/.source, [name]), + lookbehind: true, + alias: 'punctuation' } - ], - 'class-name': [ - { - // (Foo bar, Bar baz) - pattern: /\b[A-Z]\w*(?:\.\w+)*\b(?=\s+\w+)/, + }); + + Prism.languages.insertBefore('csharp', 'class-name', { + 'namespace': { + // namespace Foo.Bar {} + // using Foo.Bar; + pattern: re(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source, [name]), + lookbehind: true, inside: { - punctuation: /\./ + 'punctuation': /\./ } }, - { - // [Foo] - pattern: /(\[)[A-Z]\w*(?:\.\w+)*\b/, + 'type-expression': { + // default(Foo), typeof(Foo), sizeof(int) + pattern: re(/(\b(?:default|typeof|sizeof)\s*\(\s*)(?:[^()\s]|\s(?!\s*\))|<<0>>)*(?=\s*\))/.source, [nestedRound]), + lookbehind: true, + alias: 'class-name', + inside: typeInside + }, + 'return-type': { + // Foo ForBar(); Foo IFoo.Bar() => 0 + // int this[int index] => 0; T IReadOnlyList.this[int index] => this[index]; + // int Foo => 0; int Foo { get; set } = 0; + pattern: re(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source, [typeExpression, identifier]), + inside: typeInside, + alias: 'class-name' + }, + 'constructor-invocation': { + // new List> { } + pattern: re(/(\bnew\s+)<<0>>(?=\s*[[({])/.source, [typeExpression]), lookbehind: true, + inside: typeInside, + alias: 'class-name' + }, + /*'explicit-implementation': { + // int IFoo.Bar => 0; void IFoo>.Foo(); + pattern: replace(/\b<<0>>(?=\.<<1>>)/, className, methodOrPropertyDeclaration), + inside: classNameInside, + alias: 'class-name' + },*/ + 'generic-method': { + // foo() + pattern: re(/<<0>>\s*<<1>>(?=\s*\()/.source, [name, generic]), inside: { - punctuation: /\./ + 'function': re(/^<<0>>/.source, [name]), + 'generic': { + pattern: RegExp(generic), + alias: 'class-name', + inside: typeInside + } } }, - { - // class Foo : Bar - pattern: /(\b(?:class|interface)\s+[A-Z]\w*(?:\.\w+)*\s*:\s*)[A-Z]\w*(?:\.\w+)*\b/, + 'type-list': { + // The list of types inherited or of generic constraints + // class Foo : Bar, IList + // where F : Bar, IList + pattern: re( + /\b((?:<<0>>\s+<<1>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>)(?:\s*,\s*(?:<<3>>|<<4>>))*(?=\s*(?:where|[{;]|=>|$))/.source, + [typeDeclarationKeywords, genericName, name, typeExpression, keywords.source] + ), lookbehind: true, inside: { - punctuation: /\./ + 'keyword': keywords, + 'class-name': { + pattern: RegExp(typeExpression), + inside: typeInside + }, + 'punctuation': /,/ } }, - { - // class Foo - pattern: /((?:\b(?:class|interface|new)\s+)|(?:catch\s+\())[A-Z]\w*(?:\.\w+)*\b/, + 'preprocessor': { + pattern: /(^\s*)#.*/m, + lookbehind: true, + alias: 'property', + inside: { + // highlight preprocessor directives as keywords + 'directive': { + pattern: /(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/, + lookbehind: true, + alias: 'keyword' + } + } + } + }); + + // attributes + var regularStringOrCharacter = regularString + '|' + character; + var regularStringCharacterOrComment = replace(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*[\s\S]*?\*\/|<<0>>/.source, [regularStringOrCharacter]); + var roundExpression = nested(replace(/[^"'/()]|<<0>>|\(<>*\)/.source, [regularStringCharacterOrComment]), 2); + + // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/#attribute-targets + var attrTarget = /\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source; + var attr = replace(/<<0>>(?:\s*\(<<1>>*\))?/.source, [identifier, roundExpression]); + + Prism.languages.insertBefore('csharp', 'class-name', { + 'attribute': { + // Attributes + // [Foo], [Foo(1), Bar(2, Prop = "foo")], [return: Foo(1), Bar(2)], [assembly: Foo(Bar)] + pattern: re(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source, [attrTarget, attr]), lookbehind: true, + greedy: true, inside: { - punctuation: /\./ + 'target': { + pattern: re(/^<<0>>(?=\s*:)/.source, [attrTarget]), + alias: 'keyword' + }, + 'attribute-arguments': { + pattern: re(/\(<<0>>*\)/.source, [roundExpression]), + inside: Prism.languages.csharp + }, + 'class-name': { + pattern: RegExp(identifier), + inside: { + 'punctuation': /\./ + } + }, + 'punctuation': /[:,]/ } } - ], - 'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)f?/i, - 'operator': />>=?|<<=?|[-=]>|([-+&|?])\1|~|[-+*/%&|^!=<>]=?/, - 'punctuation': /\?\.?|::|[{}[\];(),.:]/ -}); - -Prism.languages.insertBefore('csharp', 'class-name', { - 'generic-method': { - pattern: /\w+\s*<[^>\r\n]+?>\s*(?=\()/, - inside: { - function: /^\w+/, - 'class-name': { - pattern: /\b[A-Z]\w*(?:\.\w+)*\b/, + }); + + + // string interpolation + var formatString = /:[^}\r\n]+/.source; + // multi line + var mInterpolationRound = nested(replace(/[^"'/()]|<<0>>|\(<>*\)/.source, [regularStringCharacterOrComment]), 2) + var mInterpolation = replace(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source, [mInterpolationRound, formatString]); + // single line + var sInterpolationRound = nested(replace(/[^"'/()]|\/(?!\*)|\/\*.*?\*\/|<<0>>|\(<>*\)/.source, [regularStringOrCharacter]), 2) + var sInterpolation = replace(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source, [sInterpolationRound, formatString]); + + function createInterpolationInside(interpolation, interpolationRound) { + return { + 'interpolation': { + pattern: re(/([^{](?:\{\{)*)<<0>>/.source, [interpolation]), + lookbehind: true, inside: { - punctuation: /\./ + 'format-string': { + pattern: re(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source, [interpolationRound, formatString]), + lookbehind: true, + inside: { + 'punctuation': /^:/ + } + }, + 'punctuation': /^\{|\}$/, + 'expression': { + pattern: /[\s\S]+/, + alias: 'language-csharp', + inside: Prism.languages.csharp + } } }, - keyword: Prism.languages.csharp.keyword, - punctuation: /[<>(),.:]/ - } - }, - 'preprocessor': { - pattern: /(^\s*)#.*/m, - lookbehind: true, - alias: 'property', - inside: { - // highlight preprocessor directives as keywords - 'directive': { - pattern: /(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/, + 'string': /[\s\S]+/ + }; + } + + Prism.languages.insertBefore('csharp', 'string', { + 'interpolation-string': [ + { + pattern: re(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source, [mInterpolation]), + lookbehind: true, + greedy: true, + inside: createInterpolationInside(mInterpolation, mInterpolationRound), + }, + { + pattern: re(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source, [sInterpolation]), lookbehind: true, - alias: 'keyword' + greedy: true, + inside: createInterpolationInside(sInterpolation, sInterpolationRound), } - } - } -}); + ] + }); + +}(Prism)); Prism.languages.dotnet = Prism.languages.cs = Prism.languages.csharp; diff --git a/components/prism-csharp.min.js b/components/prism-csharp.min.js index 3c5dac2434..ddd0da7b2b 100644 --- a/components/prism-csharp.min.js +++ b/components/prism-csharp.min.js @@ -1 +1 @@ -Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(?:abstract|add|alias|as|ascending|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|do|double|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|global|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/,string:[{pattern:/@("|')(?:\1\1|\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*?\1/,greedy:!0}],"class-name":[{pattern:/\b[A-Z]\w*(?:\.\w+)*\b(?=\s+\w+)/,inside:{punctuation:/\./}},{pattern:/(\[)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/(\b(?:class|interface)\s+[A-Z]\w*(?:\.\w+)*\s*:\s*)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/((?:\b(?:class|interface|new)\s+)|(?:catch\s+\())[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}}],number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)f?/i,operator:/>>=?|<<=?|[-=]>|([-+&|?])\1|~|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),Prism.languages.insertBefore("csharp","class-name",{"generic-method":{pattern:/\w+\s*<[^>\r\n]+?>\s*(?=\()/,inside:{function:/^\w+/,"class-name":{pattern:/\b[A-Z]\w*(?:\.\w+)*\b/,inside:{punctuation:/\./}},keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}}),Prism.languages.dotnet=Prism.languages.cs=Prism.languages.csharp; \ No newline at end of file +!function(s){function a(e,s){return e.replace(/<<(\d+)>>/g,function(e,n){return"(?:"+s[+n]+")"})}function t(e,n,s){return RegExp(a(e,n),s||"")}function e(e,n){for(var s=0;s>/g,"(?:"+e+")");return e.replace(/<>/g,"[^\\s\\S]")}var n="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",i="class enum interface struct",r="add alias ascending async await by descending from get global group into join let nameof notnull on orderby partial remove select set unmanaged value when where where",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var d=l(i),p=RegExp(l(n+" "+i+" "+r+" "+o)),c=l(i+" "+r+" "+o),u=l(n+" "+i+" "+o),g=e("<(?:[^<>;=+\\-*/%&|^]|<>)*>",2),b=e("\\((?:[^()]|<>)*\\)",2),h="@?\\b[A-Za-z_]\\w*\\b",f=a("<<0>>(?:\\s*<<1>>)?",[h,g]),m=a("(?!<<0>>)<<1>>(?:\\s*\\.\\s*<<1>>)*",[c,f]),k="\\[\\s*(?:,\\s*)*\\]",y=a("(?:<<0>>|<<1>>)(?:\\s*(?:\\?\\s*)?<<2>>)*(?:\\s*\\?)?",[a("\\(<<0>>+(?:,<<0>>+)+\\)",[a("[^,()<>[\\];=+\\-*/%&|^]|<<0>>|<<1>>|<<2>>",[g,b,k])]),m,k]),w={keyword:p,punctuation:/[<>()?,.:[\]]/},v="'(?:[^\r\\n'\\\\]|\\\\.|\\\\[Uux][\\da-fA-F]{1,8})'",x='"(?:\\\\.|[^\\\\"\r\\n])*"';s.languages.csharp=s.languages.extend("clike",{string:[{pattern:t("(^|[^$\\\\])<<0>>",['@"(?:""|\\\\[\\s\\S]|[^\\\\"])*"(?!")']),lookbehind:!0,greedy:!0},{pattern:t("(^|[^@$\\\\])<<0>>",[x]),lookbehind:!0,greedy:!0},{pattern:RegExp(v),greedy:!0,alias:"character"}],"class-name":[{pattern:t("(\\busing\\s+static\\s+)<<0>>(?=\\s*;)",[m]),lookbehind:!0,inside:w},{pattern:t("(\\busing\\s+<<0>>\\s*=\\s*)<<1>>(?=\\s*;)",[h,y]),lookbehind:!0,inside:w},{pattern:t("(\\busing\\s+)<<0>>(?=\\s*=)",[h]),lookbehind:!0},{pattern:t("(\\b<<0>>\\s+)<<1>>",[d,f]),lookbehind:!0,inside:w},{pattern:t("(\\bcatch\\s*\\(\\s*)<<0>>",[m]),lookbehind:!0,inside:w},{pattern:t("(\\bwhere\\s+)<<0>>",[h]),lookbehind:!0},{pattern:t("(\\b(?:is|as)\\s+)<<0>>",[y]),lookbehind:!0,inside:w},{pattern:t("\\b<<0>>(?=\\s+(?!<<1>>)<<2>>(?:\\s*[=,;:{)\\]]|\\s+in))",[y,u,h]),inside:w}],keyword:p,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:ul|lu|[dflmu])?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),s.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),s.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:t("([(,]\\s*)<<0>>(?=\\s*:)",[h]),lookbehind:!0,alias:"punctuation"}}),s.languages.insertBefore("csharp","class-name",{namespace:{pattern:t("(\\b(?:namespace|using)\\s+)<<0>>(?:\\s*\\.\\s*<<0>>)*(?=\\s*[;{])",[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:t("(\\b(?:default|typeof|sizeof)\\s*\\(\\s*)(?:[^()\\s]|\\s(?!\\s*\\))|<<0>>)*(?=\\s*\\))",[b]),lookbehind:!0,alias:"class-name",inside:w},"return-type":{pattern:t("<<0>>(?=\\s+(?:<<1>>\\s*(?:=>|[({]|\\.\\s*this\\s*\\[)|this\\s*\\[))",[y,m]),inside:w,alias:"class-name"},"constructor-invocation":{pattern:t("(\\bnew\\s+)<<0>>(?=\\s*[[({])",[y]),lookbehind:!0,inside:w,alias:"class-name"},"generic-method":{pattern:t("<<0>>\\s*<<1>>(?=\\s*\\()",[h,g]),inside:{function:t("^<<0>>",[h]),generic:{pattern:RegExp(g),alias:"class-name",inside:w}}},"type-list":{pattern:t("\\b((?:<<0>>\\s+<<1>>|where\\s+<<2>>)\\s*:\\s*)(?:<<3>>|<<4>>)(?:\\s*,\\s*(?:<<3>>|<<4>>))*(?=\\s*(?:where|[{;]|=>|$))",[d,f,h,y,p.source]),lookbehind:!0,inside:{keyword:p,"class-name":{pattern:RegExp(y),inside:w},punctuation:/,/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var $=x+"|"+v,_=a("\\/(?![*/])|\\/\\/[^\r\\n]*[\r\\n]|\\/\\*[\\s\\S]*?\\*\\/|<<0>>",[$]),B=e(a("[^\"'/()]|<<0>>|\\(<>*\\)",[_]),2),E="\\b(?:assembly|event|field|method|module|param|property|return|type)\\b",R=a("<<0>>(?:\\s*\\(<<1>>*\\))?",[m,B]);s.languages.insertBefore("csharp","class-name",{attribute:{pattern:t("((?:^|[^\\s\\w>)?])\\s*\\[\\s*)(?:<<0>>\\s*:\\s*)?<<1>>(?:\\s*,\\s*<<1>>)*(?=\\s*\\])",[E,R]),lookbehind:!0,greedy:!0,inside:{target:{pattern:t("^<<0>>(?=\\s*:)",[E]),alias:"keyword"},"attribute-arguments":{pattern:t("\\(<<0>>*\\)",[B]),inside:s.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var S=":[^}\r\\n]+",P=e(a("[^\"'/()]|<<0>>|\\(<>*\\)",[_]),2),z=a("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[P,S]),j=e(a("[^\"'/()]|\\/(?!\\*)|\\/\\*.*?\\*\\/|<<0>>|\\(<>*\\)",[$]),2),A=a("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[j,S]);function F(e,n){return{interpolation:{pattern:t("([^{](?:\\{\\{)*)<<0>>",[e]),lookbehind:!0,inside:{"format-string":{pattern:t("(^\\{(?:(?![}:])<<0>>)*)<<1>>(?=\\}$)",[n,S]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:s.languages.csharp}}},string:/[\s\S]+/}}s.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:t('(^|[^\\\\])(?:\\$@|@\\$)"(?:""|\\\\[\\s\\S]|\\{\\{|<<0>>|[^\\\\{"])*"',[z]),lookbehind:!0,greedy:!0,inside:F(z,P)},{pattern:t('(^|[^@\\\\])\\$"(?:\\\\.|\\{\\{|<<0>>|[^\\\\"{])*"',[A]),lookbehind:!0,greedy:!0,inside:F(A,j)}]})}(Prism),Prism.languages.dotnet=Prism.languages.cs=Prism.languages.csharp; \ No newline at end of file diff --git a/tests/languages/csharp/attribute_feature.test b/tests/languages/csharp/attribute_feature.test new file mode 100644 index 0000000000..a0647e291a --- /dev/null +++ b/tests/languages/csharp/attribute_feature.test @@ -0,0 +1,258 @@ +[Foo] +[Foo(1, 2)] +[Foo(1, 2, Name = "bar")] +[Foo, Bar] +[Foo("()"), Bar("[]"), Baz] + +[return: MaybeNull] +[assembly: InternalsVisibleTo("Tests")] + +[assembly: Foo] +[module: Foo] +[field: Foo] +[event: Foo] +[method: Foo] +[param: Foo] +[property: Foo] +[return: Foo] +[type: Foo] + +// not attributes + +var a = d +[Foo]; +var b = new Foo?[Count]; +var c = new (int, int)[Count]; + +---------------------------------------------------- + +[ + ["punctuation", "["], + ["attribute", [ + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["class-name", [ + "Foo" + ]], + ["attribute-arguments", [ + ["punctuation", "("], + ["number", "1"], + ["punctuation", ","], + ["number", "2"], + ["punctuation", ")"] + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["class-name", [ + "Foo" + ]], + ["attribute-arguments", [ + ["punctuation", "("], + ["number", "1"], + ["punctuation", ","], + ["number", "2"], + ["punctuation", ","], + " Name ", + ["operator", "="], + ["string", "\"bar\""], + ["punctuation", ")"] + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["class-name", [ + "Foo" + ]], + ["punctuation", ","], + ["class-name", [ + "Bar" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["class-name", [ + "Foo" + ]], + ["attribute-arguments", [ + ["punctuation", "("], + ["string", "\"()\""], + ["punctuation", ")"] + ]], + ["punctuation", ","], + ["class-name", [ + "Bar" + ]], + ["attribute-arguments", [ + ["punctuation", "("], + ["string", "\"[]\""], + ["punctuation", ")"] + ]], + ["punctuation", ","], + ["class-name", [ + "Baz" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "return"], + ["punctuation", ":"], + ["class-name", [ + "MaybeNull" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "assembly"], + ["punctuation", ":"], + ["class-name", [ + "InternalsVisibleTo" + ]], + ["attribute-arguments", [ + ["punctuation", "("], + ["string", "\"Tests\""], + ["punctuation", ")"] + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "assembly"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "module"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "field"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "event"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "method"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "param"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "property"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "return"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["punctuation", "["], + ["attribute", [ + ["target", "type"], + ["punctuation", ":"], + ["class-name", [ + "Foo" + ]] + ]], + ["punctuation", "]"], + ["comment", "// not attributes"], + ["class-name", [ + ["keyword", "var"] + ]], + " a ", + ["operator", "="], + " d\n", + ["punctuation", "["], + "Foo", + ["punctuation", "]"], + ["punctuation", ";"], + ["class-name", [ + ["keyword", "var"] + ]], + " b ", + ["operator", "="], + ["keyword", "new"], + ["constructor-invocation", [ + "Foo", + ["punctuation", "<"], + ["keyword", "int"], + ["punctuation", ">"], + ["punctuation", "?"] + ]], + ["punctuation", "["], + "Count", + ["punctuation", "]"], + ["punctuation", ";"], + ["class-name", [ + ["keyword", "var"] + ]], + " c ", + ["operator", "="], + ["keyword", "new"], + ["constructor-invocation", [ + ["punctuation", "("], + ["keyword", "int"], + ["punctuation", ","], + ["keyword", "int"], + ["punctuation", ")"] + ]], + ["punctuation", "["], + "Count", + ["punctuation", "]"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for class names of attributes. diff --git a/tests/languages/csharp/class-name-declaration_feature.test b/tests/languages/csharp/class-name-declaration_feature.test new file mode 100644 index 0000000000..93410553eb --- /dev/null +++ b/tests/languages/csharp/class-name-declaration_feature.test @@ -0,0 +1,110 @@ +class Foo +interface BarBaz +struct Foo +enum Foo +class Foo +interface Bar + +// not variables +public static RGBColor FromRainbow(Rainbow colorBand) => + colorBand switch + { + Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00), + _ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)), + }; + +---------------------------------------------------- + +[ + ["keyword", "class"], + ["class-name", ["Foo"]], + + ["keyword", "interface"], + ["class-name", ["BarBaz"]], + + ["keyword", "struct"], + ["class-name", ["Foo"]], + + ["keyword", "enum"], + ["class-name", ["Foo"]], + + ["keyword", "class"], + ["class-name", [ + "Foo", + ["punctuation", "<"], + "A", + ["punctuation", ","], + " B", + ["punctuation", ">"] + ]], + + ["keyword", "interface"], + ["class-name", [ + "Bar", + ["punctuation", "<"], + ["keyword", "out"], + " T", + ["punctuation", ">"] + ]], + + ["comment", "// not variables"], + + ["keyword", "public"], + ["keyword", "static"], + ["return-type", [ + "RGBColor" + ]], + ["function", "FromRainbow"], + ["punctuation", "("], + ["class-name", [ + "Rainbow" + ]], + " colorBand", + ["punctuation", ")"], + ["operator", "=>"], + "\n\tcolorBand ", + ["keyword", "switch"], + ["punctuation", "{"], + "\n\t\tRainbow", + ["punctuation", "."], + "Red ", + ["operator", "=>"], + ["keyword", "new"], + ["constructor-invocation", [ + "RGBColor" + ]], + ["punctuation", "("], + ["number", "0xFF"], + ["punctuation", ","], + ["number", "0x00"], + ["punctuation", ","], + ["number", "0x00"], + ["punctuation", ")"], + ["punctuation", ","], + "\n\t\t_ ", + ["operator", "=>"], + ["keyword", "throw"], + ["keyword", "new"], + ["constructor-invocation", [ + "ArgumentException" + ]], + ["punctuation", "("], + ["named-parameter", "message"], + ["punctuation", ":"], + ["string", "\"invalid enum value\""], + ["punctuation", ","], + ["named-parameter", "paramName"], + ["punctuation", ":"], + ["keyword", "nameof"], + ["punctuation", "("], + "colorBand", + ["punctuation", ")"], + ["punctuation", ")"], + ["punctuation", ","], + ["punctuation", "}"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for class names at the class declaration. diff --git a/tests/languages/csharp/class-name-variables-parameters_feature.test b/tests/languages/csharp/class-name-variables-parameters_feature.test new file mode 100644 index 0000000000..9e1c0fc9ba --- /dev/null +++ b/tests/languages/csharp/class-name-variables-parameters_feature.test @@ -0,0 +1,121 @@ +int a; +Foo b; +Foo @new_var; +Foo c = null; +static Foo<(Bar, int)>[,,] d; +void Foo(Foo a, Bar b, Bar[, ] c, Foo<(int, int)> d); +Bar Abc => 0; +Bar.FooBar Abc; + +---------------------------------------------------- + +[ + ["class-name", [ + ["keyword", "int"] + ]], + " a", + ["punctuation", ";"], + ["class-name", [ + "Foo" + ]], + " b", + ["punctuation", ";"], + ["class-name", [ + "Foo" + ]], + " @new_var", + ["punctuation", ";"], + ["class-name", [ + "Foo", + ["punctuation", "<"], + "Bar", + ["punctuation", ">"] + ]], + " c ", + ["operator", "="], + ["keyword", "null"], + ["punctuation", ";"], + ["keyword", "static"], + ["class-name", [ + "Foo", + ["punctuation", "<"], + ["punctuation", "("], + "Bar", + ["punctuation", ","], + ["keyword", "int"], + ["punctuation", ")"], + ["punctuation", ">"], + ["punctuation", "["], + ["punctuation", ","], + ["punctuation", ","], + ["punctuation", "]"] + ]], + " d", + ["punctuation", ";"], + ["return-type", [ + ["keyword", "void"] + ]], + ["function", "Foo"], + ["punctuation", "("], + ["class-name", [ + "Foo" + ]], + " a", + ["punctuation", ","], + ["class-name", [ + "Bar", + ["punctuation", "<"], + "Foo", + ["punctuation", ">"] + ]], + " b", + ["punctuation", ","], + ["class-name", [ + "Bar", + ["punctuation", "["], + ["punctuation", ","], + ["punctuation", "]"] + ]], + " c", + ["punctuation", ","], + ["class-name", [ + "Foo", + ["punctuation", "<"], + ["punctuation", "("], + ["keyword", "int"], + ["punctuation", ","], + ["keyword", "int"], + ["punctuation", ")"], + ["punctuation", ">"] + ]], + " d", + ["punctuation", ")"], + ["punctuation", ";"], + ["return-type", [ + "Bar", + ["punctuation", "<"], + "Foo", + ["punctuation", ">"] + ]], + " Abc ", + ["operator", "=>"], + ["number", "0"], + ["punctuation", ";"], + ["class-name", [ + "Bar", + ["punctuation", "<"], + "Foo", + ["punctuation", ">"], + ["punctuation", "."], + "FooBar", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"] + ]], + " Abc", + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for class names in variables and parameters. diff --git a/tests/languages/csharp/class-name_feature.test b/tests/languages/csharp/class-name_feature.test deleted file mode 100644 index 113982b6fe..0000000000 --- a/tests/languages/csharp/class-name_feature.test +++ /dev/null @@ -1,34 +0,0 @@ -class Foo -interface BarBaz -class Foo : Bar -[Foobar] -void Foo(Bar bar, Baz baz) - ----------------------------------------------------- - -[ - ["keyword", "class"], - ["class-name", ["Foo"]], - ["keyword", "interface"], - ["class-name", ["BarBaz"]], - ["keyword", "class"], - ["class-name", ["Foo"]], - ["punctuation", ":"], - ["class-name", ["Bar"]], - ["punctuation", "["], - ["class-name", ["Foobar"]], - ["punctuation", "]"], - ["keyword", "void"], - ["function", "Foo"], - ["punctuation", "("], - ["class-name", ["Bar"]], - " bar", - ["punctuation", ","], - ["class-name", ["Baz"]], - " baz", - ["punctuation", ")"] -] - ----------------------------------------------------- - -Checks for class names. \ No newline at end of file diff --git a/tests/languages/csharp/constructor-invocation_feature.test b/tests/languages/csharp/constructor-invocation_feature.test new file mode 100644 index 0000000000..eb29e46d07 --- /dev/null +++ b/tests/languages/csharp/constructor-invocation_feature.test @@ -0,0 +1,86 @@ +new Foo(); +new Foo>(); +new Foo>[0]; +new Foo>[] {}; +new Foo> {}; + +---------------------------------------------------- + +[ + ["keyword", "new"], + ["constructor-invocation", ["Foo"]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "new"], + ["constructor-invocation", [ + "Foo", + ["punctuation", "<"], + "A", + ["punctuation", ","], + " B", + ["punctuation", "<"], + "C", + ["punctuation", ">"], + ["punctuation", ">"] + ]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "new"], + ["constructor-invocation", [ + "Foo", + ["punctuation", "<"], + "A", + ["punctuation", ","], + " B", + ["punctuation", "<"], + "C", + ["punctuation", ">"], + ["punctuation", ">"] + ]], + ["punctuation", "["], + ["number", "0"], + ["punctuation", "]"], + ["punctuation", ";"], + + ["keyword", "new"], + ["constructor-invocation", [ + "Foo", + ["punctuation", "<"], + "A", + ["punctuation", ","], + " B", + ["punctuation", "<"], + "C", + ["punctuation", ">"], + ["punctuation", ">"], + ["punctuation", "["], + ["punctuation", "]"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", ";"], + + ["keyword", "new"], + ["constructor-invocation", [ + "Foo", + ["punctuation", "<"], + "A", + ["punctuation", ","], + " B", + ["punctuation", "<"], + "C", + ["punctuation", ">"], + ["punctuation", ">"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for different constructor invocations styles. diff --git a/tests/languages/csharp/for_feature.test b/tests/languages/csharp/for_feature.test new file mode 100644 index 0000000000..4cbc40b3b6 --- /dev/null +++ b/tests/languages/csharp/for_feature.test @@ -0,0 +1,33 @@ +for (Int32 i = 0; i < count; i++) +foreach (Foo e in Elements) + +---------------------------------------------------- + +[ + ["keyword", "for"], + ["punctuation", "("], + ["class-name", ["Int32"]], + " i ", + ["operator", "="], + ["number", "0"], + ["punctuation", ";"], + " i ", + ["operator", "<"], + " count", + ["punctuation", ";"], + " i", + ["operator", "++"], + ["punctuation", ")"], + ["keyword", "foreach"], + ["punctuation", "("], + ["class-name", ["Foo"]], + " e ", + ["keyword", "in"], + " Elements", + ["punctuation", ")"] +] + + +---------------------------------------------------- + +Checks for `for` and `foreach` loops. diff --git a/tests/languages/csharp/generic-constraint_feature.test b/tests/languages/csharp/generic-constraint_feature.test new file mode 100644 index 0000000000..883d279634 --- /dev/null +++ b/tests/languages/csharp/generic-constraint_feature.test @@ -0,0 +1,119 @@ +void abc() where U : struct, IFoo where V : IFoo {} +delegate void F(U u) where U : class, IFoo; +class Foo where T : IFoo {} +readonly struct Foo where T : unmanaged {} + +---------------------------------------------------- + +[ + ["return-type", [ + ["keyword", "void"] + ]], + ["generic-method", [ + ["function", "abc"], + ["generic", [ + ["punctuation", "<"], + "U", + ["punctuation", ","], + " V", + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"], + ["keyword", "where"], + ["class-name", "U"], + ["punctuation", ":"], + ["type-list", [ + ["keyword", "struct"], + ["punctuation", ","], + ["class-name", [ + "IFoo" + ]] + ]], + ["keyword", "where"], + ["class-name", "V"], + ["punctuation", ":"], + ["type-list", [ + ["class-name", [ + "IFoo", + ["punctuation", "<"], + "U", + ["punctuation", ">"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "delegate"], + ["return-type", [ + ["keyword", "void"] + ]], + ["generic-method", [ + ["function", "F"], + ["generic", [ + ["punctuation", "<"], + "U", + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["class-name", [ + "U" + ]], + " u", + ["punctuation", ")"], + ["keyword", "where"], + ["class-name", "U"], + ["punctuation", ":"], + ["type-list", [ + ["keyword", "class"], + ["punctuation", ","], + ["class-name", [ + "IFoo", + ["punctuation", "<"], + "Bar", + ["punctuation", ">"] + ]] + ]], + ["punctuation", ";"], + ["keyword", "class"], + ["class-name", [ + "Foo", + ["punctuation", "<"], + "T", + ["punctuation", ">"] + ]], + ["keyword", "where"], + ["class-name", "T"], + ["punctuation", ":"], + ["type-list", [ + ["class-name", [ + "IFoo" + ]], + "<", + ["keyword", "int"], + ">" + ]], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "readonly"], + ["keyword", "struct"], + ["class-name", [ + "Foo", + ["punctuation", "<"], + "T", + ["punctuation", ">"] + ]], + ["keyword", "where"], + ["class-name", "T"], + ["punctuation", ":"], + ["type-list", [ + ["keyword", "unmanaged"] + ]], + ["punctuation", "{"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Checks for class names and keywords in generic constraints. diff --git a/tests/languages/csharp/generic_feature.test b/tests/languages/csharp/generic_feature.test index 05d3f589a9..32a69dcd87 100644 --- a/tests/languages/csharp/generic_feature.test +++ b/tests/languages/csharp/generic_feature.test @@ -4,25 +4,31 @@ method(); ---------------------------------------------------- [ - ["keyword", "void"], + ["return-type", [ + ["keyword", "void"] + ]], ["generic-method", [ ["function", "method"], - ["punctuation", "<"], - ["class-name", ["T"]], - ["punctuation", ","], - ["class-name", ["U"]], - ["punctuation", ">"] + ["generic", [ + ["punctuation", "<"], + "T", + ["punctuation", ","], + " U", + ["punctuation", ">"] + ]] ]], ["punctuation", "("], ["punctuation", ")"], ["punctuation", ";"], ["generic-method", [ ["function", "method"], - ["punctuation", "<"], - ["keyword", "int"], - ["punctuation", ","], - ["keyword", "char"], - ["punctuation", ">"] + ["generic", [ + ["punctuation", "<"], + ["keyword", "int"], + ["punctuation", ","], + ["keyword", "char"], + ["punctuation", ">"] + ]] ]], ["punctuation", "("], ["punctuation", ")"], @@ -31,4 +37,4 @@ method(); ---------------------------------------------------- -Checks for generic methods \ No newline at end of file +Checks for generic methods diff --git a/tests/languages/csharp/interpolation-string_feature.test b/tests/languages/csharp/interpolation-string_feature.test new file mode 100644 index 0000000000..9e3cdd2170 --- /dev/null +++ b/tests/languages/csharp/interpolation-string_feature.test @@ -0,0 +1,114 @@ +$"Hello, {{ {name} }}! Today is {date.DayOfWeek}, it's {date:HH:mm} now." +$"{a,5} and {b + "" /* foo ":} */:format} {h(a, b)}" + +@$" +" +$@" +" + +$@"{ + 1 + 2 // some comment ":}{} +}" + +---------------------------------------------------- + +[ + ["interpolation-string", [ + ["string", "$\"Hello, {{ "], + ["interpolation", [ + ["punctuation", "{"], + ["expression", [ + "name" + ]], + ["punctuation", "}"] + ]], + ["string", " }}! Today is "], + ["interpolation", [ + ["punctuation", "{"], + ["expression", [ + "date", + ["punctuation", "."], + "DayOfWeek" + ]], + ["punctuation", "}"] + ]], + ["string", ", it's "], + ["interpolation", [ + ["punctuation", "{"], + ["expression", [ + "date" + ]], + ["format-string", [ + ["punctuation", ":"], + "HH:mm" + ]], + ["punctuation", "}"] + ]], + ["string", " now.\""] + ]], + ["interpolation-string", [ + ["string", "$\""], + ["interpolation", [ + ["punctuation", "{"], + ["expression", [ + "a", + ["punctuation", ","], + ["number", "5"] + ]], + ["punctuation", "}"] + ]], + ["string", " and "], + ["interpolation", [ + ["punctuation", "{"], + ["expression", [ + "b ", + ["operator", "+"], + ["string", "\"\""], + ["comment", "/* foo \":} */"] + ]], + ["format-string", [ + ["punctuation", ":"], + "format" + ]], + ["punctuation", "}"] + ]], + ["string", " "], + ["interpolation", [ + ["punctuation", "{"], + ["expression", [ + ["function", "h"], + ["punctuation", "("], + "a", + ["punctuation", ","], + " b", + ["punctuation", ")"] + ]], + ["punctuation", "}"] + ]], + ["string", "\""] + ]], + ["interpolation-string", [ + ["string", "@$\"\n\""] + ]], + ["interpolation-string", [ + ["string", "$@\"\n\""] + ]], + ["interpolation-string", [ + ["string", "$@\""], + ["interpolation", [ + ["punctuation", "{"], + ["expression", [ + ["number", "1"], + ["operator", "+"], + ["number", "2"], + ["comment", "// some comment \":}{}"] + ]], + ["punctuation", "}"] + ]], + ["string", "\""] + ]] +] + +---------------------------------------------------- + +Checks for string interpolation. diff --git a/tests/languages/csharp/issue1365.test b/tests/languages/csharp/issue1365.test index 6aaf3c7169..7829c78002 100644 --- a/tests/languages/csharp/issue1365.test +++ b/tests/languages/csharp/issue1365.test @@ -1,5 +1,5 @@ interface ILogger { - void Init(SomeClass file); + void Init(SomeClass file); void LogInfo(string message); } public class SomeClass : BaseClass {} @@ -8,32 +8,48 @@ public class SomeClass : BaseClass {} [ ["keyword", "interface"], - ["class-name", ["ILogger"]], + ["class-name", [ + "ILogger" + ]], ["punctuation", "{"], - ["keyword", "void"], + ["return-type", [ + ["keyword", "void"] + ]], ["function", "Init"], ["punctuation", "("], - ["class-name", ["SomeClass"]], + ["class-name", [ + "SomeClass" + ]], " file", ["punctuation", ")"], ["punctuation", ";"], - ["keyword", "void"], + ["return-type", [ + ["keyword", "void"] + ]], ["function", "LogInfo"], ["punctuation", "("], - ["keyword", "string"], + ["class-name", [ + ["keyword", "string"] + ]], " message", ["punctuation", ")"], ["punctuation", ";"], ["punctuation", "}"], ["keyword", "public"], ["keyword", "class"], - ["class-name", ["SomeClass"]], + ["class-name", [ + "SomeClass" + ]], ["punctuation", ":"], - ["class-name", ["BaseClass"]], + ["type-list", [ + ["class-name", [ + "BaseClass" + ]] + ]], ["punctuation", "{"], ["punctuation", "}"] ] ---------------------------------------------------- -Checks for class names. See #1365 \ No newline at end of file +Checks for class names. See #1365 diff --git a/tests/languages/csharp/issue1371.test b/tests/languages/csharp/issue1371.test index 1fec4a0580..ddee898406 100644 --- a/tests/languages/csharp/issue1371.test +++ b/tests/languages/csharp/issue1371.test @@ -2,14 +2,14 @@ container.Register(); container.Register(); var container = new Container(f => { - f.For().Use(); + f.For().Use(); }); class LandAnimal { - public void Move() => Run(); } + public void Move() => Run(); } class Dog : LandAnimal { - public new void Move() => Run(); } + public new void Move() => Run(); } class Works : LandAnimal { - public override void Move() => Run(); } + public override void Move() => Run(); } [Required] [RequiredAttribute()] [Range(1, 10)] @@ -21,9 +21,11 @@ class Works : LandAnimal { ["punctuation", "."], ["generic-method", [ ["function", "Register"], - ["punctuation", "<"], - ["class-name", ["Car"]], - ["punctuation", ">"] + ["generic", [ + ["punctuation", "<"], + "Car", + ["punctuation", ">"] + ]] ]], ["punctuation", "("], ["punctuation", ")"], @@ -32,40 +34,50 @@ class Works : LandAnimal { ["punctuation", "."], ["generic-method", [ ["function", "Register"], - ["punctuation", "<"], - ["class-name", ["IJuice"]], - ["punctuation", ","], - ["class-name", ["Juice"]], - ["punctuation", ">"] + ["generic", [ + ["punctuation", "<"], + "IJuice", + ["punctuation", ","], + " Juice", + ["punctuation", ">"] + ]] ]], ["punctuation", "("], ["punctuation", ")"], ["punctuation", ";"], - ["keyword", "var"], + ["class-name", [ + ["keyword", "var"] + ]], " container ", ["operator", "="], ["keyword", "new"], - ["class-name", ["Container"]], + ["constructor-invocation", [ + "Container" + ]], ["punctuation", "("], "f ", ["operator", "=>"], ["punctuation", "{"], - "\r\n f", + "\r\n\tf", ["punctuation", "."], ["generic-method", [ ["function", "For"], - ["punctuation", "<"], - ["class-name", ["IFoo"]], - ["punctuation", ">"] + ["generic", [ + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"] + ]] ]], ["punctuation", "("], ["punctuation", ")"], ["punctuation", "."], ["generic-method", [ ["function", "Use"], - ["punctuation", "<"], - ["class-name", ["Foo"]], - ["punctuation", ">"] + ["generic", [ + ["punctuation", "<"], + "Foo", + ["punctuation", ">"] + ]] ]], ["punctuation", "("], ["punctuation", ")"], @@ -74,10 +86,14 @@ class Works : LandAnimal { ["punctuation", ")"], ["punctuation", ";"], ["keyword", "class"], - ["class-name", ["LandAnimal"]], + ["class-name", [ + "LandAnimal" + ]], ["punctuation", "{"], ["keyword", "public"], - ["keyword", "void"], + ["return-type", [ + ["keyword", "void"] + ]], ["function", "Move"], ["punctuation", "("], ["punctuation", ")"], @@ -88,13 +104,21 @@ class Works : LandAnimal { ["punctuation", ";"], ["punctuation", "}"], ["keyword", "class"], - ["class-name", ["Dog"]], + ["class-name", [ + "Dog" + ]], ["punctuation", ":"], - ["class-name", ["LandAnimal"]], + ["type-list", [ + ["class-name", [ + "LandAnimal" + ]] + ]], ["punctuation", "{"], ["keyword", "public"], ["keyword", "new"], - ["keyword", "void"], + ["return-type", [ + ["keyword", "void"] + ]], ["function", "Move"], ["punctuation", "("], ["punctuation", ")"], @@ -105,13 +129,21 @@ class Works : LandAnimal { ["punctuation", ";"], ["punctuation", "}"], ["keyword", "class"], - ["class-name", ["Works"]], + ["class-name", [ + "Works" + ]], ["punctuation", ":"], - ["class-name", ["LandAnimal"]], + ["type-list", [ + ["class-name", [ + "LandAnimal" + ]] + ]], ["punctuation", "{"], ["keyword", "public"], ["keyword", "override"], - ["keyword", "void"], + ["return-type", [ + ["keyword", "void"] + ]], ["function", "Move"], ["punctuation", "("], ["punctuation", ")"], @@ -122,23 +154,39 @@ class Works : LandAnimal { ["punctuation", ";"], ["punctuation", "}"], ["punctuation", "["], - ["class-name", ["Required"]], + ["attribute", [ + ["class-name", [ + "Required" + ]] + ]], ["punctuation", "]"], ["punctuation", "["], - ["class-name", ["RequiredAttribute"]], - ["punctuation", "("], - ["punctuation", ")"], + ["attribute", [ + ["class-name", [ + "RequiredAttribute" + ]], + ["attribute-arguments", [ + ["punctuation", "("], + ["punctuation", ")"] + ]] + ]], ["punctuation", "]"], ["punctuation", "["], - ["class-name", ["Range"]], - ["punctuation", "("], - ["number", "1"], - ["punctuation", ","], - ["number", "10"], - ["punctuation", ")"], + ["attribute", [ + ["class-name", [ + "Range" + ]], + ["attribute-arguments", [ + ["punctuation", "("], + ["number", "1"], + ["punctuation", ","], + ["number", "10"], + ["punctuation", ")"] + ]] + ]], ["punctuation", "]"] ] ---------------------------------------------------- -Checks for various cases of class names. See #1371 \ No newline at end of file +Checks for various cases of class names. See #1371 diff --git a/tests/languages/csharp/keyword_feature.test b/tests/languages/csharp/keyword_feature.test index e1c37f0a08..75a9f6b695 100644 --- a/tests/languages/csharp/keyword_feature.test +++ b/tests/languages/csharp/keyword_feature.test @@ -8,6 +8,7 @@ await base bool break +by byte case catch @@ -24,11 +25,10 @@ do double dynamic else -enum +enum; event explicit extern -false finally fixed float @@ -42,7 +42,7 @@ group if implicit in -int +int; interface; internal into @@ -51,10 +51,13 @@ join let lock long -namespace +nameof +namespace; new; +notnull null object +on operator orderby out @@ -76,17 +79,17 @@ short sizeof stackalloc static -string -struct +string; +struct; switch this throw -true try typeof uint ulong unchecked +unmanaged unsafe ushort using @@ -95,7 +98,8 @@ var virtual void volatile -where +when +where; while yield @@ -112,6 +116,7 @@ yield ["keyword", "base"], ["keyword", "bool"], ["keyword", "break"], + ["keyword", "by"], ["keyword", "byte"], ["keyword", "case"], ["keyword", "catch"], @@ -128,11 +133,10 @@ yield ["keyword", "double"], ["keyword", "dynamic"], ["keyword", "else"], - ["keyword", "enum"], + ["keyword", "enum"], ["punctuation", ";"], ["keyword", "event"], ["keyword", "explicit"], ["keyword", "extern"], - ["keyword", "false"], ["keyword", "finally"], ["keyword", "fixed"], ["keyword", "float"], @@ -146,7 +150,7 @@ yield ["keyword", "if"], ["keyword", "implicit"], ["keyword", "in"], - ["keyword", "int"], + ["keyword", "int"], ["punctuation", ";"], ["keyword", "interface"], ["punctuation", ";"], ["keyword", "internal"], ["keyword", "into"], @@ -155,10 +159,13 @@ yield ["keyword", "let"], ["keyword", "lock"], ["keyword", "long"], - ["keyword", "namespace"], + ["keyword", "nameof"], + ["keyword", "namespace"], ["punctuation", ";"], ["keyword", "new"], ["punctuation", ";"], + ["keyword", "notnull"], ["keyword", "null"], ["keyword", "object"], + ["keyword", "on"], ["keyword", "operator"], ["keyword", "orderby"], ["keyword", "out"], @@ -180,17 +187,17 @@ yield ["keyword", "sizeof"], ["keyword", "stackalloc"], ["keyword", "static"], - ["keyword", "string"], - ["keyword", "struct"], + ["keyword", "string"], ["punctuation", ";"], + ["keyword", "struct"], ["punctuation", ";"], ["keyword", "switch"], ["keyword", "this"], ["keyword", "throw"], - ["keyword", "true"], ["keyword", "try"], ["keyword", "typeof"], ["keyword", "uint"], ["keyword", "ulong"], ["keyword", "unchecked"], + ["keyword", "unmanaged"], ["keyword", "unsafe"], ["keyword", "ushort"], ["keyword", "using"], @@ -199,11 +206,12 @@ yield ["keyword", "virtual"], ["keyword", "void"], ["keyword", "volatile"], - ["keyword", "where"], + ["keyword", "when"], + ["keyword", "where"], ["punctuation", ";"], ["keyword", "while"], ["keyword", "yield"] ] ---------------------------------------------------- -Checks for all keywords. \ No newline at end of file +Checks for all keywords. diff --git a/tests/languages/csharp/named-parameter_feature.test b/tests/languages/csharp/named-parameter_feature.test new file mode 100644 index 0000000000..7e7560b90f --- /dev/null +++ b/tests/languages/csharp/named-parameter_feature.test @@ -0,0 +1,21 @@ +Foo(abc: 4, xyz: 6); + +---------------------------------------------------- + +[ + ["function", "Foo"], + ["punctuation", "("], + ["named-parameter", "abc"], + ["punctuation", ":"], + ["number", "4"], + ["punctuation", ","], + ["named-parameter", "xyz"], + ["punctuation", ":"], + ["number", "6"], + ["punctuation", ")"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for named method parameters. diff --git a/tests/languages/csharp/namespace_feature.test b/tests/languages/csharp/namespace_feature.test new file mode 100644 index 0000000000..d4c4906756 --- /dev/null +++ b/tests/languages/csharp/namespace_feature.test @@ -0,0 +1,25 @@ +namespace Foo {} +namespace Foo.Bar {} + +---------------------------------------------------- + +[ + ["keyword", "namespace"], + ["namespace", ["Foo"]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "namespace"], + ["namespace", [ + "Foo", + ["punctuation", "."], + "Bar" + ]], + ["punctuation", "{"], + ["punctuation", "}"] +] + + +---------------------------------------------------- + +Checks for namespace declarations. diff --git a/tests/languages/csharp/number_feature.test b/tests/languages/csharp/number_feature.test index 126808037b..4f4d262a4d 100644 --- a/tests/languages/csharp/number_feature.test +++ b/tests/languages/csharp/number_feature.test @@ -1,17 +1,55 @@ 42 3.14159 +3.14159f +3.14159e-23 +.1f +1234L +1234u +700000000000ul +700000000000Lu +0xFFFFFFFFFFFFFFFFul 0xbabe 0XBABE +1_000_000 +1_2_3_4.5_6e-7_8 +0X_BA_BE +0b_1_0000_0000_0000_0000_0000_0000_0000_0000 + +0.06m +0.06M +0.06f +0.06F +0.06d +0.06D ---------------------------------------------------- [ ["number", "42"], ["number", "3.14159"], + ["number", "3.14159f"], + ["number", "3.14159e-23"], + ["number", ".1f"], + ["number", "1234L"], + ["number", "1234u"], + ["number", "700000000000ul"], + ["number", "700000000000Lu"], + ["number", "0xFFFFFFFFFFFFFFFFul"], ["number", "0xbabe"], - ["number", "0XBABE"] + ["number", "0XBABE"], + ["number", "1_000_000"], + ["number", "1_2_3_4.5_6e-7_8"], + ["number", "0X_BA_BE"], + ["number", "0b_1_0000_0000_0000_0000_0000_0000_0000_0000"], + + ["number", "0.06m"], + ["number", "0.06M"], + ["number", "0.06f"], + ["number", "0.06F"], + ["number", "0.06d"], + ["number", "0.06D"] ] ---------------------------------------------------- -Checks for decimal and hexadecimal numbers. \ No newline at end of file +Checks for decimal and hexadecimal numbers. diff --git a/tests/languages/csharp/operator_feature.test b/tests/languages/csharp/operator_feature.test index 4749c38c75..7e74ca4571 100644 --- a/tests/languages/csharp/operator_feature.test +++ b/tests/languages/csharp/operator_feature.test @@ -5,7 +5,7 @@ ! && || -> => = == != < > <= >= -?? +?? ??= ---------------------------------------------------- @@ -52,7 +52,8 @@ ["operator", "<="], ["operator", ">="], - ["operator", "??"] + ["operator", "??"], + ["operator", "??="] ] ---------------------------------------------------- diff --git a/tests/languages/csharp/range_feature.test b/tests/languages/csharp/range_feature.test new file mode 100644 index 0000000000..805fd91b54 --- /dev/null +++ b/tests/languages/csharp/range_feature.test @@ -0,0 +1,42 @@ +list[2..^3]; +list[..^3]; +list[2..]; +list[..]; + +---------------------------------------------------- + +[ + "list", + ["punctuation", "["], + ["number", "2"], + ["range", ".."], + ["operator", "^"], + ["number", "3"], + ["punctuation", "]"], + ["punctuation", ";"], + + "\nlist", + ["punctuation", "["], + ["range", ".."], + ["operator", "^"], + ["number", "3"], + ["punctuation", "]"], + ["punctuation", ";"], + + "\nlist", + ["punctuation", "["], + ["number", "2"], + ["range", ".."], + ["punctuation", "]"], + ["punctuation", ";"], + + "\nlist", + ["punctuation", "["], + ["range", ".."], + ["punctuation", "]"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for ranges. diff --git a/tests/languages/csharp/return-type_feature.test b/tests/languages/csharp/return-type_feature.test new file mode 100644 index 0000000000..9742e85159 --- /dev/null +++ b/tests/languages/csharp/return-type_feature.test @@ -0,0 +1,166 @@ +Foo Bar(); +Foo Bar(); +Foo[,] Bar(); +new Foo[,] Bar(); +(int, long)? Foo(); +(int, long)? Foo => null; +Baz?[,]? Foo { get; set } = null; +int[]? this[int index] => null; +int[]? IInterface.this[int index] => null; + +---------------------------------------------------- + +[ + ["return-type", [ + "Foo" + ]], + ["function", "Bar"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + ["return-type", [ + "Foo", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"] + ]], + ["generic-method", [ + ["function", "Bar"], + ["generic", [ + ["punctuation", "<"], + "A", + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + ["return-type", [ + "Foo", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"], + ["punctuation", "["], + ["punctuation", ","], + ["punctuation", "]"] + ]], + ["generic-method", [ + ["function", "Bar"], + ["generic", [ + ["punctuation", "<"], + "A", + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + ["keyword", "new"], + ["return-type", [ + "Foo", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"], + ["punctuation", "["], + ["punctuation", ","], + ["punctuation", "]"] + ]], + ["generic-method", [ + ["function", "Bar"], + ["generic", [ + ["punctuation", "<"], + "A", + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + ["return-type", [ + ["punctuation", "("], + ["keyword", "int"], + ["punctuation", ","], + ["keyword", "long"], + ["punctuation", ")"], + ["punctuation", "?"] + ]], + ["generic-method", [ + ["function", "Foo"], + ["generic", [ + ["punctuation", "<"], + ["keyword", "int"], + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + ["return-type", [ + ["punctuation", "("], + ["keyword", "int"], + ["punctuation", ","], + ["keyword", "long"], + ["punctuation", ")"], + ["punctuation", "?"] + ]], + " Foo ", + ["operator", "=>"], + ["keyword", "null"], + ["punctuation", ";"], + ["return-type", [ + "Baz", + ["punctuation", "?"], + ["punctuation", "["], + ["punctuation", ","], + ["punctuation", "]"], + ["punctuation", "?"] + ]], + " Foo ", + ["punctuation", "{"], + ["keyword", "get"], + ["punctuation", ";"], + ["keyword", "set"], + ["punctuation", "}"], + ["operator", "="], + ["keyword", "null"], + ["punctuation", ";"], + ["return-type", [ + ["keyword", "int"], + ["punctuation", "["], + ["punctuation", "]"], + ["punctuation", "?"] + ]], + ["keyword", "this"], + ["punctuation", "["], + ["class-name", [ + ["keyword", "int"] + ]], + " index", + ["punctuation", "]"], + ["operator", "=>"], + ["keyword", "null"], + ["punctuation", ";"], + ["return-type", [ + ["keyword", "int"], + ["punctuation", "["], + ["punctuation", "]"], + ["punctuation", "?"] + ]], + " IInterface", + ["punctuation", "."], + ["keyword", "this"], + ["punctuation", "["], + ["class-name", [ + ["keyword", "int"] + ]], + " index", + ["punctuation", "]"], + ["operator", "=>"], + ["keyword", "null"], + ["punctuation", ";"] +] + + +---------------------------------------------------- + +Checks for the return type. diff --git a/tests/languages/csharp/type-expression_feature.test b/tests/languages/csharp/type-expression_feature.test new file mode 100644 index 0000000000..1ef9e28e74 --- /dev/null +++ b/tests/languages/csharp/type-expression_feature.test @@ -0,0 +1,63 @@ +default(int) +default(Foo) +typeof(Foo) +typeof((int, long)) +default(Foo>) +sizeof(int) + +---------------------------------------------------- + +[ + ["keyword", "default"], + ["punctuation", "("], + ["type-expression", [ + ["keyword", "int"] + ]], + ["punctuation", ")"], + ["keyword", "default"], + ["punctuation", "("], + ["type-expression", [ + "Foo" + ]], + ["punctuation", ")"], + ["keyword", "typeof"], + ["punctuation", "("], + ["type-expression", [ + "Foo" + ]], + ["punctuation", ")"], + ["keyword", "typeof"], + ["punctuation", "("], + ["type-expression", [ + ["punctuation", "("], + ["keyword", "int"], + ["punctuation", ","], + ["keyword", "long"], + ["punctuation", ")"] + ]], + ["punctuation", ")"], + ["keyword", "default"], + ["punctuation", "("], + ["type-expression", [ + "Foo", + ["punctuation", "<"], + "Bar", + ["punctuation", ","], + " IFoo", + ["punctuation", "<"], + "Bar", + ["punctuation", ">"], + ["punctuation", ">"] + ]], + ["punctuation", ")"], + ["keyword", "sizeof"], + ["punctuation", "("], + ["type-expression", [ + ["keyword", "int"] + ]], + ["punctuation", ")"] +] + +---------------------------------------------------- + +Checks for class names of type expressions. diff --git a/tests/languages/csharp/type-list_feature.test b/tests/languages/csharp/type-list_feature.test new file mode 100644 index 0000000000..ca44d22ee7 --- /dev/null +++ b/tests/languages/csharp/type-list_feature.test @@ -0,0 +1,153 @@ +class Foo : Bar, T>, IBar, IFoo + where T : class, IBar, IFoo {} + +public delegate ErrorCode GetInfoMethod(H handle, A value, I paramName, + Size_t paramValueSize, IntPtr paramValue, out Size_t paramValueSizeRet) + where H : unmanaged, IInfoHandle where A : unmanaged where I : unmanaged, Enum; + +---------------------------------------------------- + +[ + ["keyword", "class"], + ["class-name", [ + "Foo", + ["punctuation", "<"], + "T", + ["punctuation", ">"] + ]], + ["punctuation", ":"], + ["type-list", [ + ["class-name", [ + "Bar", + ["punctuation", "<"], + "IList", + ["punctuation", "<"], + "Bar", + ["punctuation", ">"], + ["punctuation", ","], + " T", + ["punctuation", ">"] + ]], + ["punctuation", ","], + ["class-name", [ + "IBar", + ["punctuation", "<"], + "Bar", + ["punctuation", ","], + " T", + ["punctuation", ">"] + ]], + ["punctuation", ","], + ["class-name", [ + "IFoo" + ]] + ]], + ["keyword", "where"], + ["class-name", "T"], + ["punctuation", ":"], + ["type-list", [ + ["keyword", "class"], + ["punctuation", ","], + ["class-name", [ + "IBar", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"] + ]], + ["punctuation", ","], + ["class-name", [ + "IFoo", + ["punctuation", "<"], + "Bar", + ["punctuation", ">"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "public"], + ["keyword", "delegate"], + ["return-type", [ + "ErrorCode" + ]], + ["generic-method", [ + ["function", "GetInfoMethod"], + ["generic", [ + ["punctuation", "<"], + "H", + ["punctuation", ","], + " A", + ["punctuation", ","], + " I", + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["class-name", [ + "H" + ]], + " handle", + ["punctuation", ","], + ["class-name", [ + "A" + ]], + ["keyword", "value"], + ["punctuation", ","], + ["class-name", [ + "I" + ]], + " paramName", + ["punctuation", ","], + ["class-name", [ + "Size_t" + ]], + " paramValueSize", + ["punctuation", ","], + ["class-name", [ + "IntPtr" + ]], + " paramValue", + ["punctuation", ","], + ["keyword", "out"], + ["class-name", [ + "Size_t" + ]], + " paramValueSizeRet", + ["punctuation", ")"], + ["keyword", "where"], + ["class-name", "H"], + ["punctuation", ":"], + ["type-list", [ + ["keyword", "unmanaged"], + ["punctuation", ","], + ["class-name", [ + "IInfoHandle", + ["punctuation", "<"], + "A", + ["punctuation", ","], + " I", + ["punctuation", ">"] + ]] + ]], + ["keyword", "where"], + ["class-name", "A"], + ["punctuation", ":"], + ["type-list", [ + ["keyword", "unmanaged"] + ]], + ["keyword", "where"], + ["class-name", "I"], + ["punctuation", ":"], + ["type-list", [ + ["keyword", "unmanaged"], + ["punctuation", ","], + ["class-name", [ + "Enum" + ]] + ]], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for type lists of inheritance or generic constraints. diff --git a/tests/languages/csharp/using-directive_feature.test b/tests/languages/csharp/using-directive_feature.test new file mode 100644 index 0000000000..aa0723e828 --- /dev/null +++ b/tests/languages/csharp/using-directive_feature.test @@ -0,0 +1,81 @@ +using System; +using System.IO; +using static System.Math; +using static Foo.Bar.FooBar; +using FooBar = Foo.Bar; +using FooBar = Foo.Bar.FooBar; + +---------------------------------------------------- + +[ + ["keyword", "using"], + ["namespace", ["System"]], + ["punctuation", ";"], + + ["keyword", "using"], + ["namespace", [ + "System", + ["punctuation", "."], + "IO" + ]], + ["punctuation", ";"], + + ["keyword", "using"], + ["keyword", "static"], + ["class-name", [ + "System", + ["punctuation", "."], + "Math" + ]], + ["punctuation", ";"], + + ["keyword", "using"], + ["keyword", "static"], + ["class-name", [ + "Foo", + ["punctuation", "."], + "Bar", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"], + ["punctuation", "."], + "FooBar", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"] + ]], + ["punctuation", ";"], + + ["keyword", "using"], + ["class-name", "FooBar"], + ["operator", "="], + ["class-name", [ + "Foo", + ["punctuation", "."], + "Bar" + ]], + ["punctuation", ";"], + + ["keyword", "using"], + ["class-name", "FooBar"], + ["operator", "="], + ["class-name", [ + "Foo", + ["punctuation", "."], + "Bar", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"], + ["punctuation", "."], + "FooBar", + ["punctuation", "<"], + "IFoo", + ["punctuation", ">"] + ]], + ["punctuation", ";"] +] + + +---------------------------------------------------- + +Checks for using directives. diff --git a/tests/languages/t4-cs/block_standard_feature.test b/tests/languages/t4-cs/block_standard_feature.test index 1b9a761221..1dc9bd8713 100644 --- a/tests/languages/t4-cs/block_standard_feature.test +++ b/tests/languages/t4-cs/block_standard_feature.test @@ -19,7 +19,9 @@ The number <#= i #> is even. ["content", [ ["keyword", "for"], ["punctuation", "("], - ["keyword", "var"], + ["class-name", [ + ["keyword", "var"] + ]], " i ", ["operator", "="], ["number", "0"], @@ -50,7 +52,9 @@ The number <#= i #> is even. ["block", [ ["expression", [ ["delimiter", "<#="], - ["content", [" i "]], + ["content", [ + " i " + ]], ["delimiter", "#>"] ]] ]],