source: node_modules/refractor/lang/csharp.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 15.9 KB
Line 
1'use strict'
2
3module.exports = csharp
4csharp.displayName = 'csharp'
5csharp.aliases = ['dotnet', 'cs']
6function csharp(Prism) {
7 ;(function (Prism) {
8 /**
9 * Replaces all placeholders "<<n>>" of given pattern with the n-th replacement (zero based).
10 *
11 * Note: This is a simple text based replacement. Be careful when using backreferences!
12 *
13 * @param {string} pattern the given pattern.
14 * @param {string[]} replacements a list of replacement which can be inserted into the given pattern.
15 * @returns {string} the pattern with all placeholders replaced with their corresponding replacements.
16 * @example replace(/a<<0>>a/.source, [/b+/.source]) === /a(?:b+)a/.source
17 */
18 function replace(pattern, replacements) {
19 return pattern.replace(/<<(\d+)>>/g, function (m, index) {
20 return '(?:' + replacements[+index] + ')'
21 })
22 }
23 /**
24 * @param {string} pattern
25 * @param {string[]} replacements
26 * @param {string} [flags]
27 * @returns {RegExp}
28 */
29 function re(pattern, replacements, flags) {
30 return RegExp(replace(pattern, replacements), flags || '')
31 }
32 /**
33 * Creates a nested pattern where all occurrences of the string `<<self>>` are replaced with the pattern itself.
34 *
35 * @param {string} pattern
36 * @param {number} depthLog2
37 * @returns {string}
38 */
39 function nested(pattern, depthLog2) {
40 for (var i = 0; i < depthLog2; i++) {
41 pattern = pattern.replace(/<<self>>/g, function () {
42 return '(?:' + pattern + ')'
43 })
44 }
45 return pattern.replace(/<<self>>/g, '[^\\s\\S]')
46 } // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
47 var keywordKinds = {
48 // keywords which represent a return or variable type
49 type: 'bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void',
50 // keywords which are used to declare a type
51 typeDeclaration: 'class enum interface record struct',
52 // contextual keywords
53 // ("var" and "dynamic" are missing because they are used like types)
54 contextual:
55 'add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)',
56 // all other keywords
57 other:
58 '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'
59 } // keywords
60 function keywordsToPattern(words) {
61 return '\\b(?:' + words.trim().replace(/ /g, '|') + ')\\b'
62 }
63 var typeDeclarationKeywords = keywordsToPattern(
64 keywordKinds.typeDeclaration
65 )
66 var keywords = RegExp(
67 keywordsToPattern(
68 keywordKinds.type +
69 ' ' +
70 keywordKinds.typeDeclaration +
71 ' ' +
72 keywordKinds.contextual +
73 ' ' +
74 keywordKinds.other
75 )
76 )
77 var nonTypeKeywords = keywordsToPattern(
78 keywordKinds.typeDeclaration +
79 ' ' +
80 keywordKinds.contextual +
81 ' ' +
82 keywordKinds.other
83 )
84 var nonContextualKeywords = keywordsToPattern(
85 keywordKinds.type +
86 ' ' +
87 keywordKinds.typeDeclaration +
88 ' ' +
89 keywordKinds.other
90 ) // types
91 var generic = nested(/<(?:[^<>;=+\-*/%&|^]|<<self>>)*>/.source, 2) // the idea behind the other forbidden characters is to prevent false positives. Same for tupleElement.
92 var nestedRound = nested(/\((?:[^()]|<<self>>)*\)/.source, 2)
93 var name = /@?\b[A-Za-z_]\w*\b/.source
94 var genericName = replace(/<<0>>(?:\s*<<1>>)?/.source, [name, generic])
95 var identifier = replace(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source, [
96 nonTypeKeywords,
97 genericName
98 ])
99 var array = /\[\s*(?:,\s*)*\]/.source
100 var typeExpressionWithoutTuple = replace(
101 /<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,
102 [identifier, array]
103 )
104 var tupleElement = replace(
105 /[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,
106 [generic, nestedRound, array]
107 )
108 var tuple = replace(/\(<<0>>+(?:,<<0>>+)+\)/.source, [tupleElement])
109 var typeExpression = replace(
110 /(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,
111 [tuple, identifier, array]
112 )
113 var typeInside = {
114 keyword: keywords,
115 punctuation: /[<>()?,.:[\]]/
116 } // strings & characters
117 // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#character-literals
118 // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#string-literals
119 var character = /'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source // simplified pattern
120 var regularString = /"(?:\\.|[^\\"\r\n])*"/.source
121 var verbatimString = /@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source
122 Prism.languages.csharp = Prism.languages.extend('clike', {
123 string: [
124 {
125 pattern: re(/(^|[^$\\])<<0>>/.source, [verbatimString]),
126 lookbehind: true,
127 greedy: true
128 },
129 {
130 pattern: re(/(^|[^@$\\])<<0>>/.source, [regularString]),
131 lookbehind: true,
132 greedy: true
133 }
134 ],
135 'class-name': [
136 {
137 // Using static
138 // using static System.Math;
139 pattern: re(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source, [
140 identifier
141 ]),
142 lookbehind: true,
143 inside: typeInside
144 },
145 {
146 // Using alias (type)
147 // using Project = PC.MyCompany.Project;
148 pattern: re(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source, [
149 name,
150 typeExpression
151 ]),
152 lookbehind: true,
153 inside: typeInside
154 },
155 {
156 // Using alias (alias)
157 // using Project = PC.MyCompany.Project;
158 pattern: re(/(\busing\s+)<<0>>(?=\s*=)/.source, [name]),
159 lookbehind: true
160 },
161 {
162 // Type declarations
163 // class Foo<A, B>
164 // interface Foo<out A, B>
165 pattern: re(/(\b<<0>>\s+)<<1>>/.source, [
166 typeDeclarationKeywords,
167 genericName
168 ]),
169 lookbehind: true,
170 inside: typeInside
171 },
172 {
173 // Single catch exception declaration
174 // catch(Foo)
175 // (things like catch(Foo e) is covered by variable declaration)
176 pattern: re(/(\bcatch\s*\(\s*)<<0>>/.source, [identifier]),
177 lookbehind: true,
178 inside: typeInside
179 },
180 {
181 // Name of the type parameter of generic constraints
182 // where Foo : class
183 pattern: re(/(\bwhere\s+)<<0>>/.source, [name]),
184 lookbehind: true
185 },
186 {
187 // Casts and checks via as and is.
188 // as Foo<A>, is Bar<B>
189 // (things like if(a is Foo b) is covered by variable declaration)
190 pattern: re(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source, [
191 typeExpressionWithoutTuple
192 ]),
193 lookbehind: true,
194 inside: typeInside
195 },
196 {
197 // Variable, field and parameter declaration
198 // (Foo bar, Bar baz, Foo[,,] bay, Foo<Bar, FooBar<Bar>> bax)
199 pattern: re(
200 /\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/
201 .source,
202 [typeExpression, nonContextualKeywords, name]
203 ),
204 inside: typeInside
205 }
206 ],
207 keyword: keywords,
208 // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#literals
209 number:
210 /(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,
211 operator: />>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,
212 punctuation: /\?\.?|::|[{}[\];(),.:]/
213 })
214 Prism.languages.insertBefore('csharp', 'number', {
215 range: {
216 pattern: /\.\./,
217 alias: 'operator'
218 }
219 })
220 Prism.languages.insertBefore('csharp', 'punctuation', {
221 'named-parameter': {
222 pattern: re(/([(,]\s*)<<0>>(?=\s*:)/.source, [name]),
223 lookbehind: true,
224 alias: 'punctuation'
225 }
226 })
227 Prism.languages.insertBefore('csharp', 'class-name', {
228 namespace: {
229 // namespace Foo.Bar {}
230 // using Foo.Bar;
231 pattern: re(
232 /(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,
233 [name]
234 ),
235 lookbehind: true,
236 inside: {
237 punctuation: /\./
238 }
239 },
240 'type-expression': {
241 // default(Foo), typeof(Foo<Bar>), sizeof(int)
242 pattern: re(
243 /(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/
244 .source,
245 [nestedRound]
246 ),
247 lookbehind: true,
248 alias: 'class-name',
249 inside: typeInside
250 },
251 'return-type': {
252 // Foo<Bar> ForBar(); Foo IFoo.Bar() => 0
253 // int this[int index] => 0; T IReadOnlyList<T>.this[int index] => this[index];
254 // int Foo => 0; int Foo { get; set } = 0;
255 pattern: re(
256 /<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,
257 [typeExpression, identifier]
258 ),
259 inside: typeInside,
260 alias: 'class-name'
261 },
262 'constructor-invocation': {
263 // new List<Foo<Bar[]>> { }
264 pattern: re(/(\bnew\s+)<<0>>(?=\s*[[({])/.source, [typeExpression]),
265 lookbehind: true,
266 inside: typeInside,
267 alias: 'class-name'
268 },
269 /*'explicit-implementation': {
270// int IFoo<Foo>.Bar => 0; void IFoo<Foo<Foo>>.Foo<T>();
271pattern: replace(/\b<<0>>(?=\.<<1>>)/, className, methodOrPropertyDeclaration),
272inside: classNameInside,
273alias: 'class-name'
274},*/
275 'generic-method': {
276 // foo<Bar>()
277 pattern: re(/<<0>>\s*<<1>>(?=\s*\()/.source, [name, generic]),
278 inside: {
279 function: re(/^<<0>>/.source, [name]),
280 generic: {
281 pattern: RegExp(generic),
282 alias: 'class-name',
283 inside: typeInside
284 }
285 }
286 },
287 'type-list': {
288 // The list of types inherited or of generic constraints
289 // class Foo<F> : Bar, IList<FooBar>
290 // where F : Bar, IList<int>
291 pattern: re(
292 /\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/
293 .source,
294 [
295 typeDeclarationKeywords,
296 genericName,
297 name,
298 typeExpression,
299 keywords.source,
300 nestedRound,
301 /\bnew\s*\(\s*\)/.source
302 ]
303 ),
304 lookbehind: true,
305 inside: {
306 'record-arguments': {
307 pattern: re(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source, [
308 genericName,
309 nestedRound
310 ]),
311 lookbehind: true,
312 greedy: true,
313 inside: Prism.languages.csharp
314 },
315 keyword: keywords,
316 'class-name': {
317 pattern: RegExp(typeExpression),
318 greedy: true,
319 inside: typeInside
320 },
321 punctuation: /[,()]/
322 }
323 },
324 preprocessor: {
325 pattern: /(^[\t ]*)#.*/m,
326 lookbehind: true,
327 alias: 'property',
328 inside: {
329 // highlight preprocessor directives as keywords
330 directive: {
331 pattern:
332 /(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,
333 lookbehind: true,
334 alias: 'keyword'
335 }
336 }
337 }
338 }) // attributes
339 var regularStringOrCharacter = regularString + '|' + character
340 var regularStringCharacterOrComment = replace(
341 /\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,
342 [regularStringOrCharacter]
343 )
344 var roundExpression = nested(
345 replace(/[^"'/()]|<<0>>|\(<<self>>*\)/.source, [
346 regularStringCharacterOrComment
347 ]),
348 2
349 ) // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/#attribute-targets
350 var attrTarget =
351 /\b(?:assembly|event|field|method|module|param|property|return|type)\b/
352 .source
353 var attr = replace(/<<0>>(?:\s*\(<<1>>*\))?/.source, [
354 identifier,
355 roundExpression
356 ])
357 Prism.languages.insertBefore('csharp', 'class-name', {
358 attribute: {
359 // Attributes
360 // [Foo], [Foo(1), Bar(2, Prop = "foo")], [return: Foo(1), Bar(2)], [assembly: Foo(Bar)]
361 pattern: re(
362 /((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/
363 .source,
364 [attrTarget, attr]
365 ),
366 lookbehind: true,
367 greedy: true,
368 inside: {
369 target: {
370 pattern: re(/^<<0>>(?=\s*:)/.source, [attrTarget]),
371 alias: 'keyword'
372 },
373 'attribute-arguments': {
374 pattern: re(/\(<<0>>*\)/.source, [roundExpression]),
375 inside: Prism.languages.csharp
376 },
377 'class-name': {
378 pattern: RegExp(identifier),
379 inside: {
380 punctuation: /\./
381 }
382 },
383 punctuation: /[:,]/
384 }
385 }
386 }) // string interpolation
387 var formatString = /:[^}\r\n]+/.source // multi line
388 var mInterpolationRound = nested(
389 replace(/[^"'/()]|<<0>>|\(<<self>>*\)/.source, [
390 regularStringCharacterOrComment
391 ]),
392 2
393 )
394 var mInterpolation = replace(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source, [
395 mInterpolationRound,
396 formatString
397 ]) // single line
398 var sInterpolationRound = nested(
399 replace(
400 /[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<<self>>*\)/
401 .source,
402 [regularStringOrCharacter]
403 ),
404 2
405 )
406 var sInterpolation = replace(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source, [
407 sInterpolationRound,
408 formatString
409 ])
410 function createInterpolationInside(interpolation, interpolationRound) {
411 return {
412 interpolation: {
413 pattern: re(/((?:^|[^{])(?:\{\{)*)<<0>>/.source, [interpolation]),
414 lookbehind: true,
415 inside: {
416 'format-string': {
417 pattern: re(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source, [
418 interpolationRound,
419 formatString
420 ]),
421 lookbehind: true,
422 inside: {
423 punctuation: /^:/
424 }
425 },
426 punctuation: /^\{|\}$/,
427 expression: {
428 pattern: /[\s\S]+/,
429 alias: 'language-csharp',
430 inside: Prism.languages.csharp
431 }
432 }
433 },
434 string: /[\s\S]+/
435 }
436 }
437 Prism.languages.insertBefore('csharp', 'string', {
438 'interpolation-string': [
439 {
440 pattern: re(
441 /(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,
442 [mInterpolation]
443 ),
444 lookbehind: true,
445 greedy: true,
446 inside: createInterpolationInside(mInterpolation, mInterpolationRound)
447 },
448 {
449 pattern: re(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source, [
450 sInterpolation
451 ]),
452 lookbehind: true,
453 greedy: true,
454 inside: createInterpolationInside(sInterpolation, sInterpolationRound)
455 }
456 ],
457 char: {
458 pattern: RegExp(character),
459 greedy: true
460 }
461 })
462 Prism.languages.dotnet = Prism.languages.cs = Prism.languages.csharp
463 })(Prism)
464}
Note: See TracBrowser for help on using the repository browser.