From e06e52aa2a8d4e9d1a64c0eee23cc3b40e880160 Mon Sep 17 00:00:00 2001 From: RunDevelopment Date: Fri, 29 May 2020 16:03:32 +0200 Subject: [PATCH] C#: Improved pattern matching --- components/prism-csharp.js | 7 +- components/prism-csharp.min.js | 2 +- ...ass-name-variables-parameters_feature.test | 86 +++ tests/languages/csharp/keyword_feature.test | 6 + tests/languages/csharp/switch_feature.test | 582 ++++++++++++++++++ 5 files changed, 679 insertions(+), 4 deletions(-) create mode 100644 tests/languages/csharp/switch_feature.test diff --git a/components/prism-csharp.js b/components/prism-csharp.js index a03c7dbe86..564c39339a 100644 --- a/components/prism-csharp.js +++ b/components/prism-csharp.js @@ -47,7 +47,7 @@ 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', + contextual: 'add alias and ascending async await by descending from get global group into join let nameof not notnull on or 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' }; @@ -68,6 +68,7 @@ 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 typeExpressionWithoutTuple = replace(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source, [identifier, array]); 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]); @@ -150,14 +151,14 @@ // 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]), + pattern: re(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source, [typeExpressionWithoutTuple]), 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]), + pattern: re(/\b<<0>>(?=\s+(?!<<1>>)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source, [typeExpression, nonContextualKeywords, name]), inside: typeInside } ], diff --git a/components/prism-csharp.min.js b/components/prism-csharp.min.js index e5eeb3f717..25b6f6d605 100644 --- a/components/prism-csharp.min.js +++ b/components/prism-csharp.min.js @@ -1 +1 @@ -!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,function(){return"(?:"+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>>",['@"(?:""|\\\\[^]|[^\\\\"])*"(?!")']),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),greedy:!0,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]|/\\*(?:[^*]|\\*(?!/))*\\*/|<<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 P=":[^}\r\n]+",z=e(a("[^\"'/()]|<<0>>|\\(<>*\\)",[_]),2),S=a("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[z,P]),j=e(a("[^\"'/()]|/(?!\\*)|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>|\\(<>*\\)",[$]),2),A=a("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[j,P]);function F(e,n){return{interpolation:{pattern:t("([^{](?:\\{\\{)*)<<0>>",[e]),lookbehind:!0,inside:{"format-string":{pattern:t("(^\\{(?:(?![}:])<<0>>)*)<<1>>(?=\\}$)",[n,P]),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('(^|[^\\\\])(?:\\$@|@\\$)"(?:""|\\\\[^]|\\{\\{|<<0>>|[^\\\\{"])*"',[S]),lookbehind:!0,greedy:!0,inside:F(S,z)},{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 +!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,function(){return"(?:"+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",r="class enum interface struct",i="add alias and ascending async await by descending from get global group into join let nameof not notnull on or 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(r),p=RegExp(l(n+" "+r+" "+i+" "+o)),c=l(r+" "+i+" "+o),u=l(n+" "+r+" "+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>>(?:\\s*(?:\\?\\s*)?<<1>>)*(?:\\s*\\?)?",[m,k]),w=a("(?:<<0>>|<<1>>)(?:\\s*(?:\\?\\s*)?<<2>>)*(?:\\s*\\?)?",[a("\\(<<0>>+(?:,<<0>>+)+\\)",[a("[^,()<>[\\];=+\\-*/%&|^]|<<0>>|<<1>>|<<2>>",[g,b,k])]),m,k]),v={keyword:p,punctuation:/[<>()?,.:[\]]/},x="'(?:[^\r\n'\\\\]|\\\\.|\\\\[Uux][\\da-fA-F]{1,8})'",$='"(?:\\\\.|[^\\\\"\r\n])*"';s.languages.csharp=s.languages.extend("clike",{string:[{pattern:t("(^|[^$\\\\])<<0>>",['@"(?:""|\\\\[^]|[^\\\\"])*"(?!")']),lookbehind:!0,greedy:!0},{pattern:t("(^|[^@$\\\\])<<0>>",[$]),lookbehind:!0,greedy:!0},{pattern:RegExp(x),greedy:!0,alias:"character"}],"class-name":[{pattern:t("(\\busing\\s+static\\s+)<<0>>(?=\\s*;)",[m]),lookbehind:!0,inside:v},{pattern:t("(\\busing\\s+<<0>>\\s*=\\s*)<<1>>(?=\\s*;)",[h,w]),lookbehind:!0,inside:v},{pattern:t("(\\busing\\s+)<<0>>(?=\\s*=)",[h]),lookbehind:!0},{pattern:t("(\\b<<0>>\\s+)<<1>>",[d,f]),lookbehind:!0,inside:v},{pattern:t("(\\bcatch\\s*\\(\\s*)<<0>>",[m]),lookbehind:!0,inside:v},{pattern:t("(\\bwhere\\s+)<<0>>",[h]),lookbehind:!0},{pattern:t("(\\b(?:is(?:\\s+not)?|as)\\s+)<<0>>",[y]),lookbehind:!0,inside:v},{pattern:t("\\b<<0>>(?=\\s+(?!<<1>>)<<2>>(?:\\s*[=,;:{)\\]]|\\s+(?:in|when)\\b))",[w,u,h]),inside:v}],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:v},"return-type":{pattern:t("<<0>>(?=\\s+(?:<<1>>\\s*(?:=>|[({]|\\.\\s*this\\s*\\[)|this\\s*\\[))",[w,m]),inside:v,alias:"class-name"},"constructor-invocation":{pattern:t("(\\bnew\\s+)<<0>>(?=\\s*[[({])",[w]),lookbehind:!0,inside:v,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:v}}},"type-list":{pattern:t("\\b((?:<<0>>\\s+<<1>>|where\\s+<<2>>)\\s*:\\s*)(?:<<3>>|<<4>>)(?:\\s*,\\s*(?:<<3>>|<<4>>))*(?=\\s*(?:where|[{;]|=>|$))",[d,f,h,w,p.source]),lookbehind:!0,inside:{keyword:p,"class-name":{pattern:RegExp(w),greedy:!0,inside:v},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,B=a("/(?![*/])|//[^\r\n]*[\r\n]|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>",[_]),E=e(a("[^\"'/()]|<<0>>|\\(<>*\\)",[B]),2),R="\\b(?:assembly|event|field|method|module|param|property|return|type)\\b",P=a("<<0>>(?:\\s*\\(<<1>>*\\))?",[m,E]);s.languages.insertBefore("csharp","class-name",{attribute:{pattern:t("((?:^|[^\\s\\w>)?])\\s*\\[\\s*)(?:<<0>>\\s*:\\s*)?<<1>>(?:\\s*,\\s*<<1>>)*(?=\\s*\\])",[R,P]),lookbehind:!0,greedy:!0,inside:{target:{pattern:t("^<<0>>(?=\\s*:)",[R]),alias:"keyword"},"attribute-arguments":{pattern:t("\\(<<0>>*\\)",[E]),inside:s.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var z=":[^}\r\n]+",S=e(a("[^\"'/()]|<<0>>|\\(<>*\\)",[B]),2),j=a("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[S,z]),A=e(a("[^\"'/()]|/(?!\\*)|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>|\\(<>*\\)",[_]),2),F=a("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[A,z]);function U(e,n){return{interpolation:{pattern:t("([^{](?:\\{\\{)*)<<0>>",[e]),lookbehind:!0,inside:{"format-string":{pattern:t("(^\\{(?:(?![}:])<<0>>)*)<<1>>(?=\\}$)",[n,z]),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('(^|[^\\\\])(?:\\$@|@\\$)"(?:""|\\\\[^]|\\{\\{|<<0>>|[^\\\\{"])*"',[j]),lookbehind:!0,greedy:!0,inside:U(j,S)},{pattern:t('(^|[^@\\\\])\\$"(?:\\\\.|\\{\\{|<<0>>|[^\\\\"{])*"',[F]),lookbehind:!0,greedy:!0,inside:U(F,A)}]})}(Prism),Prism.languages.dotnet=Prism.languages.cs=Prism.languages.csharp; \ No newline at end of file diff --git a/tests/languages/csharp/class-name-variables-parameters_feature.test b/tests/languages/csharp/class-name-variables-parameters_feature.test index 9e1c0fc9ba..53b93c85ca 100644 --- a/tests/languages/csharp/class-name-variables-parameters_feature.test +++ b/tests/languages/csharp/class-name-variables-parameters_feature.test @@ -7,6 +7,14 @@ void Foo(Foo a, Bar b, Bar[, ] c, Foo<(int, int)> d); Bar Abc => 0; Bar.FooBar Abc; +if (foo is Bar) +if (foo is not Bar) +if (foo is null) +if (foo is not null) +if (t is (int, string)) +if ((e1, e2) is (0, int i) or (int i, 0)) +var baz = foo as Bar; + ---------------------------------------------------- [ @@ -113,6 +121,84 @@ Bar.FooBar Abc; ["punctuation", ">"] ]], " Abc", + ["punctuation", ";"], + + ["keyword", "if"], + ["punctuation", "("], + "foo ", + ["keyword", "is"], + ["class-name", [ + "Bar" + ]], + ["punctuation", ")"], + ["keyword", "if"], + ["punctuation", "("], + "foo ", + ["keyword", "is"], + ["keyword", "not"], + ["class-name", [ + "Bar" + ]], + ["punctuation", ")"], + ["keyword", "if"], + ["punctuation", "("], + "foo ", + ["keyword", "is"], + ["keyword", "null"], + ["punctuation", ")"], + ["keyword", "if"], + ["punctuation", "("], + "foo ", + ["keyword", "is"], + ["keyword", "not"], + ["keyword", "null"], + ["punctuation", ")"], + ["keyword", "if"], + ["punctuation", "("], + "t ", + ["keyword", "is"], + ["punctuation", "("], + ["keyword", "int"], + ["punctuation", ","], + ["keyword", "string"], + ["punctuation", ")"], + ["punctuation", ")"], + ["keyword", "if"], + ["punctuation", "("], + ["punctuation", "("], + "e1", + ["punctuation", ","], + " e2", + ["punctuation", ")"], + ["keyword", "is"], + ["punctuation", "("], + ["number", "0"], + ["punctuation", ","], + ["class-name", [ + ["keyword", "int"] + ]], + " i", + ["punctuation", ")"], + ["keyword", "or"], + ["punctuation", "("], + ["class-name", [ + ["keyword", "int"] + ]], + " i", + ["punctuation", ","], + ["number", "0"], + ["punctuation", ")"], + ["punctuation", ")"], + ["class-name", [ + ["keyword", "var"] + ]], + " baz ", + ["operator", "="], + " foo ", + ["keyword", "as"], + ["class-name", [ + "Bar" + ]], ["punctuation", ";"] ] diff --git a/tests/languages/csharp/keyword_feature.test b/tests/languages/csharp/keyword_feature.test index 75a9f6b695..1769b30b0e 100644 --- a/tests/languages/csharp/keyword_feature.test +++ b/tests/languages/csharp/keyword_feature.test @@ -1,6 +1,7 @@ abstract add alias +and as ascending async @@ -54,11 +55,13 @@ long nameof namespace; new; +not notnull null object on operator +or orderby out override @@ -109,6 +112,7 @@ yield ["keyword", "abstract"], ["keyword", "add"], ["keyword", "alias"], + ["keyword", "and"], ["keyword", "as"], ["keyword", "ascending"], ["keyword", "async"], @@ -162,11 +166,13 @@ yield ["keyword", "nameof"], ["keyword", "namespace"], ["punctuation", ";"], ["keyword", "new"], ["punctuation", ";"], + ["keyword", "not"], ["keyword", "notnull"], ["keyword", "null"], ["keyword", "object"], ["keyword", "on"], ["keyword", "operator"], + ["keyword", "or"], ["keyword", "orderby"], ["keyword", "out"], ["keyword", "override"], diff --git a/tests/languages/csharp/switch_feature.test b/tests/languages/csharp/switch_feature.test new file mode 100644 index 0000000000..a9ff987424 --- /dev/null +++ b/tests/languages/csharp/switch_feature.test @@ -0,0 +1,582 @@ +public static decimal CalculateToll(object vehicle) => + vehicle switch + { + DeliveryTruck t when t.GrossWeightClass > 5000 => 10.00m + 5.00m, + DeliveryTruck t when t.GrossWeightClass < 3000 => 10.00m - 2.00m, + DeliveryTruck _ => 10.00m, + _ => throw new ArgumentException("Not a known vehicle type", nameof(vehicle)) + }; + +DeliveryTruck t when t.GrossWeightClass switch +{ + > 5000 => 10.00m + 5.00m, + < 3000 => 10.00m - 2.00m, + _ => 10.00m, +}, +DeliveryTruck t when t.GrossWeightClass switch +{ + < 3000 => 10.00m - 2.00m, + >= 3000 and <= 5000 => 10.00m, + > 5000 => 10.00m + 5.00m, +}, + +switch (DateTime.Now.DayOfWeek) +{ + case DayOfWeek.Sunday: + case DayOfWeek.Saturday: + Console.WriteLine("The weekend"); + break; + case DayOfWeek.Monday: + Console.WriteLine("The first day of the work week."); + break; + case DayOfWeek.Friday: + Console.WriteLine("The last day of the work week."); + break; + default: + Console.WriteLine("The middle of the work week."); + break; +} + +switch (str) +{ + case "1": + case "small": + cost += 25; + break; + case "2": + case "medium": + cost += 25; + goto case "1"; + case "3": + case "large": + cost += 50; + goto case "1"; + default: + Console.WriteLine("Invalid selection. Please select 1, 2, or 3."); + break; +} + +switch (sh) +{ + // Note that this code never evaluates to true. + case Shape shape when shape == null: + break; + case null: + break; + case Rectangle r when r.Length == r.Width && r.Area > 0: + break; + default: + break; +} + +switch (coll) +{ + case Array arr: + break; + case IEnumerable ieInt: + break; + case object o: + break; + default: + break; +} + +bool IsValidPercentage(object x) => x is + >= 0 and <= 100 or // integer tests + >= 0F and <= 100F or // float tests + >= 0D and <= 100D; // double tests + +bool isSmallByte(object o) => o is byte and < 100; + +case (0, int x): +case (int x, 0): + Console.WriteLine(x); + +case < 2: break; +case 0 or 1 or 2 or 3 or 4 or 5: break; + +int x = b switch { <100 => 0, 100 => 1, 101 => 2, >101 => 3 }; + +---------------------------------------------------- + +[ + ["keyword", "public"], + ["keyword", "static"], + ["return-type", [ + ["keyword", "decimal"] + ]], + ["function", "CalculateToll"], + ["punctuation", "("], + ["class-name", [ + ["keyword", "object"] + ]], + " vehicle", + ["punctuation", ")"], + ["operator", "=>"], + "\n\tvehicle ", + ["keyword", "switch"], + ["punctuation", "{"], + ["class-name", [ + "DeliveryTruck" + ]], + " t ", + ["keyword", "when"], + " t", + ["punctuation", "."], + "GrossWeightClass ", + ["operator", ">"], + ["number", "5000"], + ["operator", "=>"], + ["number", "10.00m"], + ["operator", "+"], + ["number", "5.00m"], + ["punctuation", ","], + ["class-name", [ + "DeliveryTruck" + ]], + " t ", + ["keyword", "when"], + " t", + ["punctuation", "."], + "GrossWeightClass ", + ["operator", "<"], + ["number", "3000"], + ["operator", "=>"], + ["number", "10.00m"], + ["operator", "-"], + ["number", "2.00m"], + ["punctuation", ","], + ["return-type", [ + "DeliveryTruck" + ]], + " _ ", + ["operator", "=>"], + ["number", "10.00m"], + ["punctuation", ","], + "\n\t\t_ ", + ["operator", "=>"], + ["keyword", "throw"], + ["keyword", "new"], + ["constructor-invocation", [ + "ArgumentException" + ]], + ["punctuation", "("], + ["string", "\"Not a known vehicle type\""], + ["punctuation", ","], + ["keyword", "nameof"], + ["punctuation", "("], + "vehicle", + ["punctuation", ")"], + ["punctuation", ")"], + ["punctuation", "}"], + ["punctuation", ";"], + ["class-name", [ + "DeliveryTruck" + ]], + " t ", + ["keyword", "when"], + " t", + ["punctuation", "."], + "GrossWeightClass ", + ["keyword", "switch"], + ["punctuation", "{"], + ["operator", ">"], + ["number", "5000"], + ["operator", "=>"], + ["number", "10.00m"], + ["operator", "+"], + ["number", "5.00m"], + ["punctuation", ","], + ["operator", "<"], + ["number", "3000"], + ["operator", "=>"], + ["number", "10.00m"], + ["operator", "-"], + ["number", "2.00m"], + ["punctuation", ","], + "\n\t_ ", + ["operator", "=>"], + ["number", "10.00m"], + ["punctuation", ","], + ["punctuation", "}"], + ["punctuation", ","], + ["class-name", [ + "DeliveryTruck" + ]], + " t ", + ["keyword", "when"], + " t", + ["punctuation", "."], + "GrossWeightClass ", + ["keyword", "switch"], + ["punctuation", "{"], + ["operator", "<"], + ["number", "3000"], + ["operator", "=>"], + ["number", "10.00m"], + ["operator", "-"], + ["number", "2.00m"], + ["punctuation", ","], + ["operator", ">="], + ["number", "3000"], + ["keyword", "and"], + ["operator", "<="], + ["number", "5000"], + ["operator", "=>"], + ["number", "10.00m"], + ["punctuation", ","], + ["operator", ">"], + ["number", "5000"], + ["operator", "=>"], + ["number", "10.00m"], + ["operator", "+"], + ["number", "5.00m"], + ["punctuation", ","], + ["punctuation", "}"], + ["punctuation", ","], + ["keyword", "switch"], + ["punctuation", "("], + "DateTime", + ["punctuation", "."], + "Now", + ["punctuation", "."], + "DayOfWeek", + ["punctuation", ")"], + ["punctuation", "{"], + ["keyword", "case"], + " DayOfWeek", + ["punctuation", "."], + "Sunday", + ["punctuation", ":"], + ["keyword", "case"], + " DayOfWeek", + ["punctuation", "."], + "Saturday", + ["punctuation", ":"], + "\n\t\tConsole", + ["punctuation", "."], + ["function", "WriteLine"], + ["punctuation", "("], + ["string", "\"The weekend\""], + ["punctuation", ")"], + ["punctuation", ";"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "case"], + " DayOfWeek", + ["punctuation", "."], + "Monday", + ["punctuation", ":"], + "\n\t\tConsole", + ["punctuation", "."], + ["function", "WriteLine"], + ["punctuation", "("], + ["string", "\"The first day of the work week.\""], + ["punctuation", ")"], + ["punctuation", ";"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "case"], + " DayOfWeek", + ["punctuation", "."], + "Friday", + ["punctuation", ":"], + "\n\t\tConsole", + ["punctuation", "."], + ["function", "WriteLine"], + ["punctuation", "("], + ["string", "\"The last day of the work week.\""], + ["punctuation", ")"], + ["punctuation", ";"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "default"], + ["punctuation", ":"], + "\n\t\tConsole", + ["punctuation", "."], + ["function", "WriteLine"], + ["punctuation", "("], + ["string", "\"The middle of the work week.\""], + ["punctuation", ")"], + ["punctuation", ";"], + ["keyword", "break"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "switch"], + ["punctuation", "("], + "str", + ["punctuation", ")"], + ["punctuation", "{"], + ["keyword", "case"], + ["string", "\"1\""], + ["punctuation", ":"], + ["keyword", "case"], + ["string", "\"small\""], + ["punctuation", ":"], + "\n\t\tcost ", + ["operator", "+="], + ["number", "25"], + ["punctuation", ";"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "case"], + ["string", "\"2\""], + ["punctuation", ":"], + ["keyword", "case"], + ["string", "\"medium\""], + ["punctuation", ":"], + "\n\t\tcost ", + ["operator", "+="], + ["number", "25"], + ["punctuation", ";"], + ["keyword", "goto"], + ["keyword", "case"], + ["string", "\"1\""], + ["punctuation", ";"], + ["keyword", "case"], + ["string", "\"3\""], + ["punctuation", ":"], + ["keyword", "case"], + ["string", "\"large\""], + ["punctuation", ":"], + "\n\t\tcost ", + ["operator", "+="], + ["number", "50"], + ["punctuation", ";"], + ["keyword", "goto"], + ["keyword", "case"], + ["string", "\"1\""], + ["punctuation", ";"], + ["keyword", "default"], + ["punctuation", ":"], + "\n\t\tConsole", + ["punctuation", "."], + ["function", "WriteLine"], + ["punctuation", "("], + ["string", "\"Invalid selection. Please select 1, 2, or 3.\""], + ["punctuation", ")"], + ["punctuation", ";"], + ["keyword", "break"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "switch"], + ["punctuation", "("], + "sh", + ["punctuation", ")"], + ["punctuation", "{"], + ["comment", "// Note that this code never evaluates to true."], + ["keyword", "case"], + ["class-name", [ + "Shape" + ]], + " shape ", + ["keyword", "when"], + " shape ", + ["operator", "=="], + ["keyword", "null"], + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "case"], + ["keyword", "null"], + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "case"], + ["class-name", [ + "Rectangle" + ]], + " r ", + ["keyword", "when"], + " r", + ["punctuation", "."], + "Length ", + ["operator", "=="], + " r", + ["punctuation", "."], + "Width ", + ["operator", "&&"], + " r", + ["punctuation", "."], + "Area ", + ["operator", ">"], + ["number", "0"], + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "default"], + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "switch"], + ["punctuation", "("], + "coll", + ["punctuation", ")"], + ["punctuation", "{"], + ["keyword", "case"], + ["class-name", [ + "Array" + ]], + " arr", + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "case"], + ["class-name", [ + "IEnumerable", + ["punctuation", "<"], + ["keyword", "int"], + ["punctuation", ">"] + ]], + " ieInt", + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "case"], + ["class-name", [ + ["keyword", "object"] + ]], + " o", + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "default"], + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["punctuation", "}"], + ["return-type", [ + ["keyword", "bool"] + ]], + ["function", "IsValidPercentage"], + ["punctuation", "("], + ["class-name", [ + ["keyword", "object"] + ]], + " x", + ["punctuation", ")"], + ["operator", "=>"], + " x ", + ["keyword", "is"], + ["operator", ">="], + ["number", "0"], + ["keyword", "and"], + ["operator", "<="], + ["number", "100"], + ["keyword", "or"], + ["comment", "// integer tests"], + ["operator", ">="], + ["number", "0F"], + ["keyword", "and"], + ["operator", "<="], + ["number", "100F"], + ["keyword", "or"], + ["comment", "// float tests"], + ["operator", ">="], + ["number", "0D"], + ["keyword", "and"], + ["operator", "<="], + ["number", "100D"], + ["punctuation", ";"], + ["comment", "// double tests"], + ["return-type", [ + ["keyword", "bool"] + ]], + ["function", "isSmallByte"], + ["punctuation", "("], + ["class-name", [ + ["keyword", "object"] + ]], + " o", + ["punctuation", ")"], + ["operator", "=>"], + " o ", + ["keyword", "is"], + ["class-name", [ + ["keyword", "byte"] + ]], + ["keyword", "and"], + ["operator", "<"], + ["number", "100"], + ["punctuation", ";"], + ["keyword", "case"], + ["punctuation", "("], + ["number", "0"], + ["punctuation", ","], + ["class-name", [ + ["keyword", "int"] + ]], + " x", + ["punctuation", ")"], + ["punctuation", ":"], + ["keyword", "case"], + ["punctuation", "("], + ["class-name", [ + ["keyword", "int"] + ]], + " x", + ["punctuation", ","], + ["number", "0"], + ["punctuation", ")"], + ["punctuation", ":"], + "\n\tConsole", + ["punctuation", "."], + ["function", "WriteLine"], + ["punctuation", "("], + "x", + ["punctuation", ")"], + ["punctuation", ";"], + ["keyword", "case"], + ["operator", "<"], + ["number", "2"], + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["keyword", "case"], + ["number", "0"], + ["keyword", "or"], + ["number", "1"], + ["keyword", "or"], + ["number", "2"], + ["keyword", "or"], + ["number", "3"], + ["keyword", "or"], + ["number", "4"], + ["keyword", "or"], + ["number", "5"], + ["punctuation", ":"], + ["keyword", "break"], + ["punctuation", ";"], + ["class-name", [ + ["keyword", "int"] + ]], + " x ", + ["operator", "="], + " b ", + ["keyword", "switch"], + ["punctuation", "{"], + ["operator", "<"], + ["number", "100"], + ["operator", "=>"], + ["number", "0"], + ["punctuation", ","], + ["number", "100"], + ["operator", "=>"], + ["number", "1"], + ["punctuation", ","], + ["number", "101"], + ["operator", "=>"], + ["number", "2"], + ["punctuation", ","], + ["operator", ">"], + ["number", "101"], + ["operator", "=>"], + ["number", "3"], + ["punctuation", "}"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for switch statements and expressions.