@mirascript/textmate 0.1.83 → 0.1.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.c8rc.json +6 -0
- package/ava.config.js +4 -0
- package/dist/grammar.d.ts.map +1 -1
- package/dist/grammar.js +206 -86
- package/dist/grammar.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mirascript-doc.tmLanguage.json +303 -84
- package/dist/mirascript-template.tmLanguage.json +1 -1
- package/dist/mirascript.tmLanguage.json +1 -1
- package/package.json +7 -7
- package/src/grammar.ts +210 -86
- package/src/index.ts +1 -1
- package/tests/_engine.ts +53 -0
- package/tests/grammar/documentation-comments.ts +157 -0
- package/tests/grammar/documentation-mode.ts +372 -0
- package/tests/grammar/language.ts +59 -0
- package/tests/grammar/strings.ts +35 -0
- package/tests/js-compatibility.ts +22 -0
- package/tests/language.ts +9 -0
- package/tests/tsconfig.json +3 -0
package/src/grammar.ts
CHANGED
|
@@ -11,22 +11,33 @@ import { mirascriptDocLanguage, mirascriptLanguage, mirascriptTemplateLanguage }
|
|
|
11
11
|
|
|
12
12
|
const SCOPE_SUFFIX = 'mira';
|
|
13
13
|
const IDENTIFIER = REG_IDENTIFIER.source;
|
|
14
|
+
const IDENTIFIER_START = String.raw`(?<!\p{XID_Continue})`;
|
|
14
15
|
const IDENTIFIER_END = String.raw`(?!\p{XID_Continue})`;
|
|
15
16
|
const MAX_VERBATIM_LENGTH = 16;
|
|
16
17
|
const BUILT_IN_TYPES = [
|
|
17
18
|
'any',
|
|
18
19
|
'unknown',
|
|
19
20
|
'never',
|
|
21
|
+
|
|
20
22
|
'boolean',
|
|
23
|
+
'true',
|
|
24
|
+
'false',
|
|
25
|
+
|
|
21
26
|
'number',
|
|
22
27
|
'string',
|
|
28
|
+
|
|
23
29
|
'record',
|
|
24
30
|
'array',
|
|
25
31
|
'extern',
|
|
26
32
|
'module',
|
|
33
|
+
|
|
27
34
|
'nil',
|
|
28
35
|
];
|
|
29
36
|
const DOC_CONSTANT_IDENTIFIER = String.raw`(?:@+\p{XID_Continue}+|\p{Lu}[\p{XID_Continue}]*)`;
|
|
37
|
+
const DOC_TAG_NAME = String.raw`[^>\r\n]*[^>\s]`;
|
|
38
|
+
const DOC_TAG_CONTENT = String.raw`(?:module|function|extern)(?:[ \t]+${DOC_TAG_NAME})?`;
|
|
39
|
+
const DOC_FIELD_NAME = String.raw`(?:${IDENTIFIER}|\d+|"(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*')`;
|
|
40
|
+
const DOC_TAG_NUMBER = String.raw`\d[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?[\d_]*\d)?`;
|
|
30
41
|
|
|
31
42
|
/**
|
|
32
43
|
* Escape a literal value for insertion into an Oniguruma regular expression.
|
|
@@ -45,17 +56,6 @@ function alternatives(values: Iterable<string>): string {
|
|
|
45
56
|
.join('|');
|
|
46
57
|
}
|
|
47
58
|
|
|
48
|
-
/**
|
|
49
|
-
* Create a boundary-aware TextMate keyword rule.
|
|
50
|
-
*/
|
|
51
|
-
function keywordRule(values: readonly string[], name: string): { name: string; match: string } | null {
|
|
52
|
-
if (values.length === 0) return null;
|
|
53
|
-
return {
|
|
54
|
-
name: `${name}.${SCOPE_SUFFIX}`,
|
|
55
|
-
match: String.raw`(?<!\p{XID_Continue})(?:${alternatives(values)})${IDENTIFIER_END}`,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
59
|
const numericKeywordSet = new Set<string>(NUMERIC_KEYWORDS);
|
|
60
60
|
const constantKeywords = CONSTANT_KEYWORDS.filter((keyword) => !numericKeywordSet.has(keyword));
|
|
61
61
|
const languageVariables = ['_', 'global'];
|
|
@@ -73,7 +73,7 @@ const classifiedKeywords = new Set([
|
|
|
73
73
|
'type',
|
|
74
74
|
]);
|
|
75
75
|
const otherKeywords = KEYWORDS.filter((keyword) => !classifiedKeywords.has(keyword));
|
|
76
|
-
const mirascriptFenceTags = alternatives([mirascriptLanguage.name, ...
|
|
76
|
+
const mirascriptFenceTags = alternatives([mirascriptLanguage.name, ...mirascriptLanguage.aliases]);
|
|
77
77
|
const documentationMiraFenceBegin = String.raw`^(\s*\*\s?)(\x60{3,})\s*((?i:${mirascriptFenceTags}))?\s*$`;
|
|
78
78
|
const documentationOtherFenceBegin = String.raw`^(\s*\*\s?)(\x60{3,})\s*(\S+)(?:\s+.*)?\s*$`;
|
|
79
79
|
const documentationFenceEnd = String.raw`^(?:(\s*\*\s?)(\2\x60*)\s*$)|(?=\*/)`;
|
|
@@ -300,6 +300,13 @@ function documentationRepository(sourceInclude = '#source') {
|
|
|
300
300
|
* Build the shared repository used by source and template grammars.
|
|
301
301
|
*/
|
|
302
302
|
function sourceRepository(): LanguageRegistration['repository'] {
|
|
303
|
+
/**
|
|
304
|
+
* Create a boundary-aware TextMate keyword rule.
|
|
305
|
+
*/
|
|
306
|
+
const keywordRule = (values: readonly string[], name: string) => ({
|
|
307
|
+
name: `${name}.${SCOPE_SUFFIX}`,
|
|
308
|
+
match: `${IDENTIFIER_START}(?:${alternatives(values)})${IDENTIFIER_END}`,
|
|
309
|
+
});
|
|
303
310
|
const keywordPatterns = [
|
|
304
311
|
keywordRule(NUMERIC_KEYWORDS, 'constant.numeric.language'),
|
|
305
312
|
keywordRule(constantKeywords, 'constant.language'),
|
|
@@ -310,7 +317,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
310
317
|
keywordRule(RESERVED_KEYWORDS, 'keyword.reserved'),
|
|
311
318
|
keywordRule(languageVariables, 'variable.language'),
|
|
312
319
|
keywordRule(otherKeywords, 'keyword.other'),
|
|
313
|
-
]
|
|
320
|
+
];
|
|
314
321
|
|
|
315
322
|
return {
|
|
316
323
|
source: {
|
|
@@ -365,7 +372,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
365
372
|
patterns: [
|
|
366
373
|
{
|
|
367
374
|
name: `meta.function.declaration.${SCOPE_SUFFIX}`,
|
|
368
|
-
begin: String.raw
|
|
375
|
+
begin: String.raw`${IDENTIFIER_START}(fn)(\s+)(${IDENTIFIER})(\s*)(\()`,
|
|
369
376
|
beginCaptures: {
|
|
370
377
|
1: { name: `keyword.declaration.function.${SCOPE_SUFFIX}` },
|
|
371
378
|
3: { name: `entity.name.function.${SCOPE_SUFFIX}` },
|
|
@@ -377,7 +384,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
377
384
|
},
|
|
378
385
|
{
|
|
379
386
|
name: `meta.function.declaration.${SCOPE_SUFFIX}`,
|
|
380
|
-
match: String.raw
|
|
387
|
+
match: String.raw`${IDENTIFIER_START}(fn)(\s+)(${IDENTIFIER})`,
|
|
381
388
|
captures: {
|
|
382
389
|
1: { name: `keyword.declaration.function.${SCOPE_SUFFIX}` },
|
|
383
390
|
3: { name: `entity.name.function.${SCOPE_SUFFIX}` },
|
|
@@ -385,7 +392,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
385
392
|
},
|
|
386
393
|
{
|
|
387
394
|
name: `meta.function.expression.parameters.${SCOPE_SUFFIX}`,
|
|
388
|
-
begin: String.raw
|
|
395
|
+
begin: String.raw`${IDENTIFIER_START}(fn)(\s*)(\()`,
|
|
389
396
|
beginCaptures: {
|
|
390
397
|
1: { name: `keyword.declaration.function.${SCOPE_SUFFIX}` },
|
|
391
398
|
3: { name: `punctuation.section.parameters.begin.${SCOPE_SUFFIX}` },
|
|
@@ -399,7 +406,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
399
406
|
parameters: {
|
|
400
407
|
patterns: [
|
|
401
408
|
{
|
|
402
|
-
match: String.raw
|
|
409
|
+
match: String.raw`${IDENTIFIER_START}(mut)(\s+)(${IDENTIFIER})`,
|
|
403
410
|
captures: {
|
|
404
411
|
1: { name: `keyword.declaration.mutable.${SCOPE_SUFFIX}` },
|
|
405
412
|
3: { name: `variable.emphasis.${SCOPE_SUFFIX}` },
|
|
@@ -407,7 +414,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
407
414
|
},
|
|
408
415
|
{
|
|
409
416
|
name: `keyword.declaration.mutable.${SCOPE_SUFFIX}`,
|
|
410
|
-
match:
|
|
417
|
+
match: `${IDENTIFIER_START}mut${IDENTIFIER_END}`,
|
|
411
418
|
},
|
|
412
419
|
{ name: `keyword.operator.spread.${SCOPE_SUFFIX}`, match: String.raw`\.\.` },
|
|
413
420
|
{ name: `variable.other.constant.emphasis.${SCOPE_SUFFIX}`, match: IDENTIFIER },
|
|
@@ -428,7 +435,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
428
435
|
'module-declarations': {
|
|
429
436
|
patterns: [
|
|
430
437
|
{
|
|
431
|
-
match: String.raw
|
|
438
|
+
match: String.raw`${IDENTIFIER_START}(mod)(\s+)(${IDENTIFIER})`,
|
|
432
439
|
captures: {
|
|
433
440
|
1: { name: `keyword.control.module.${SCOPE_SUFFIX}` },
|
|
434
441
|
3: { name: `entity.name.namespace.${SCOPE_SUFFIX}` },
|
|
@@ -439,7 +446,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
439
446
|
'for-bindings': {
|
|
440
447
|
patterns: [
|
|
441
448
|
{
|
|
442
|
-
match: String.raw
|
|
449
|
+
match: String.raw`${IDENTIFIER_START}(for)(\s+)(mut)(\s+)(${IDENTIFIER})(\s+)(in)${IDENTIFIER_END}`,
|
|
443
450
|
captures: {
|
|
444
451
|
1: { name: `keyword.control.loop.${SCOPE_SUFFIX}` },
|
|
445
452
|
3: { name: `keyword.declaration.mutable.${SCOPE_SUFFIX}` },
|
|
@@ -448,7 +455,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
448
455
|
},
|
|
449
456
|
},
|
|
450
457
|
{
|
|
451
|
-
match: String.raw
|
|
458
|
+
match: String.raw`${IDENTIFIER_START}(for)(\s+)(${IDENTIFIER})(\s+)(in)${IDENTIFIER_END}`,
|
|
452
459
|
captures: {
|
|
453
460
|
1: { name: `keyword.control.loop.${SCOPE_SUFFIX}` },
|
|
454
461
|
3: { name: `variable.other.${SCOPE_SUFFIX}` },
|
|
@@ -509,7 +516,7 @@ function sourceRepository(): LanguageRegistration['repository'] {
|
|
|
509
516
|
patterns: [
|
|
510
517
|
{
|
|
511
518
|
name: `keyword.operator.expression.${SCOPE_SUFFIX}`,
|
|
512
|
-
match: String.raw
|
|
519
|
+
match: String.raw`${IDENTIFIER_START}type${IDENTIFIER_END}(?=\s*\(|\s+${IDENTIFIER})`,
|
|
513
520
|
},
|
|
514
521
|
],
|
|
515
522
|
},
|
|
@@ -664,27 +671,43 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
664
671
|
...documentationRepository('source.mira#source'),
|
|
665
672
|
doc: {
|
|
666
673
|
patterns: [
|
|
674
|
+
{ include: '#tag' },
|
|
667
675
|
{ include: '#global-value' },
|
|
668
676
|
{ include: '#global-constants' },
|
|
669
677
|
{ include: '#inline-parameter' },
|
|
678
|
+
{ include: '#properties' },
|
|
670
679
|
{ include: '#inline-label' },
|
|
680
|
+
{ include: '#binding-value' },
|
|
671
681
|
{ include: '#bindings' },
|
|
672
682
|
{ include: '#function-signatures' },
|
|
673
|
-
{ include: '#properties' },
|
|
674
683
|
{ include: '#generic-types' },
|
|
675
684
|
{ include: '#parameters' },
|
|
676
685
|
{ include: '#return-type' },
|
|
677
|
-
{ include: '#
|
|
686
|
+
{ include: '#tag-comment' },
|
|
678
687
|
{ include: 'source.mira' },
|
|
679
688
|
],
|
|
680
689
|
},
|
|
690
|
+
tag: {
|
|
691
|
+
patterns: [
|
|
692
|
+
{
|
|
693
|
+
name: 'meta.documentation.tag.mira',
|
|
694
|
+
contentName: 'meta.documentation.tag.content.mira',
|
|
695
|
+
begin: `(<)(?=${DOC_TAG_CONTENT}>)`,
|
|
696
|
+
beginCaptures: { 1: { name: 'punctuation.definition.tag.begin.mira' } },
|
|
697
|
+
end: '(>)',
|
|
698
|
+
endCaptures: { 1: { name: 'punctuation.definition.tag.end.mira' } },
|
|
699
|
+
patterns: [{ include: '#tag-content' }],
|
|
700
|
+
},
|
|
701
|
+
],
|
|
702
|
+
},
|
|
681
703
|
'global-value': {
|
|
682
704
|
patterns: [
|
|
683
705
|
{
|
|
706
|
+
name: 'meta.documentation.global-value.mira',
|
|
684
707
|
begin: String.raw`^(\x00)?(\(global\))(\s+)(${IDENTIFIER})(\s*)(=)`,
|
|
685
708
|
beginCaptures: {
|
|
686
709
|
2: { name: 'entity.name.label.mira' },
|
|
687
|
-
4: { name: 'variable.other.
|
|
710
|
+
4: { name: 'variable.other.mira' },
|
|
688
711
|
6: { name: 'keyword.operator.assignment.mira' },
|
|
689
712
|
},
|
|
690
713
|
end: '$',
|
|
@@ -739,7 +762,7 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
739
762
|
bindings: {
|
|
740
763
|
patterns: [
|
|
741
764
|
{
|
|
742
|
-
match: String.raw
|
|
765
|
+
match: String.raw`${IDENTIFIER_START}(let)(\s+)(mut)(\s+)(${IDENTIFIER})`,
|
|
743
766
|
captures: {
|
|
744
767
|
1: { name: 'keyword.declaration.variable.mira' },
|
|
745
768
|
3: { name: 'keyword.declaration.mutable.mira' },
|
|
@@ -747,7 +770,7 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
747
770
|
},
|
|
748
771
|
},
|
|
749
772
|
{
|
|
750
|
-
match: String.raw
|
|
773
|
+
match: String.raw`${IDENTIFIER_START}(let|const)(\s+)(${IDENTIFIER})`,
|
|
751
774
|
captures: {
|
|
752
775
|
1: { name: 'keyword.declaration.variable.mira' },
|
|
753
776
|
3: { name: 'variable.other.constant.mira' },
|
|
@@ -755,10 +778,35 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
755
778
|
},
|
|
756
779
|
],
|
|
757
780
|
},
|
|
781
|
+
'binding-value': {
|
|
782
|
+
patterns: [
|
|
783
|
+
{
|
|
784
|
+
begin: String.raw`${IDENTIFIER_START}(let)(\s+)(mut)(\s+)(${IDENTIFIER})(\s*)(=)`,
|
|
785
|
+
beginCaptures: {
|
|
786
|
+
1: { name: 'keyword.declaration.variable.mira' },
|
|
787
|
+
3: { name: 'keyword.declaration.mutable.mira' },
|
|
788
|
+
5: { name: 'variable.other.readwrite.mira' },
|
|
789
|
+
7: { name: 'keyword.operator.assignment.mira' },
|
|
790
|
+
},
|
|
791
|
+
end: '$',
|
|
792
|
+
patterns: [{ include: '#doc-value' }],
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
begin: String.raw`${IDENTIFIER_START}(let|const)(\s+)(${IDENTIFIER})(\s*)(=)`,
|
|
796
|
+
beginCaptures: {
|
|
797
|
+
1: { name: 'keyword.declaration.variable.mira' },
|
|
798
|
+
3: { name: 'variable.other.constant.mira' },
|
|
799
|
+
5: { name: 'keyword.operator.assignment.mira' },
|
|
800
|
+
},
|
|
801
|
+
end: '$',
|
|
802
|
+
patterns: [{ include: '#doc-value' }],
|
|
803
|
+
},
|
|
804
|
+
],
|
|
805
|
+
},
|
|
758
806
|
'function-signatures': {
|
|
759
807
|
patterns: [
|
|
760
808
|
{
|
|
761
|
-
match: String.raw
|
|
809
|
+
match: String.raw`${IDENTIFIER_START}(?:(pub)(\s+))?(fn)(\s+)(${IDENTIFIER})(?=\s*(?:<|\())`,
|
|
762
810
|
captures: {
|
|
763
811
|
1: { name: 'keyword.control.module.mira' },
|
|
764
812
|
3: { name: 'keyword.declaration.function.mira' },
|
|
@@ -770,22 +818,65 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
770
818
|
properties: {
|
|
771
819
|
patterns: [
|
|
772
820
|
{
|
|
773
|
-
|
|
821
|
+
name: 'meta.documentation.field.mira',
|
|
822
|
+
begin: String.raw`^(\x00)?(?:(\(field\))(\s+))?(${DOC_FIELD_NAME})(\s*)(\??:)(?=[ \t]*/\*[ \t]*<extern[ \t]+(?:(?:async[ \t]+)?function\*?)(?:[ \t]+${DOC_TAG_NAME})?>[ \t]*\*/)`,
|
|
823
|
+
beginCaptures: {
|
|
824
|
+
2: { name: 'entity.name.label.mira' },
|
|
825
|
+
4: { name: 'entity.name.function.mira' },
|
|
826
|
+
6: { name: 'punctuation.separator.type.mira' },
|
|
827
|
+
},
|
|
828
|
+
end: '$',
|
|
829
|
+
patterns: [
|
|
830
|
+
{ include: '#tag-comment' },
|
|
831
|
+
{ include: '#tag' },
|
|
832
|
+
{ include: '#doc-record-value' },
|
|
833
|
+
{ include: '#doc-array-value' },
|
|
834
|
+
{ include: '#type-context' },
|
|
835
|
+
],
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
name: 'meta.documentation.field.mira',
|
|
839
|
+
begin: String.raw`^(\x00)?(?:(\(field\))(\s+))?(${DOC_FIELD_NAME})(\s*)(\??:)(?=[ \t]*/\*[ \t]*<extern[ \t]+class(?:[ \t]+${DOC_TAG_NAME})?>[ \t]*\*/)`,
|
|
774
840
|
beginCaptures: {
|
|
775
|
-
|
|
776
|
-
|
|
841
|
+
2: { name: 'entity.name.label.mira' },
|
|
842
|
+
4: { name: 'entity.name.type.mira' },
|
|
843
|
+
6: { name: 'punctuation.separator.type.mira' },
|
|
777
844
|
},
|
|
778
845
|
end: '$',
|
|
779
|
-
patterns: [
|
|
846
|
+
patterns: [
|
|
847
|
+
{ include: '#tag-comment' },
|
|
848
|
+
{ include: '#tag' },
|
|
849
|
+
{ include: '#doc-record-value' },
|
|
850
|
+
{ include: '#doc-array-value' },
|
|
851
|
+
{ include: '#type-context' },
|
|
852
|
+
],
|
|
853
|
+
},
|
|
854
|
+
{
|
|
855
|
+
name: 'meta.documentation.field.mira',
|
|
856
|
+
begin: String.raw`^(\x00)?(?:(\(field\))(\s+))?(${DOC_FIELD_NAME})(\s*)(\??:)`,
|
|
857
|
+
beginCaptures: {
|
|
858
|
+
2: { name: 'entity.name.label.mira' },
|
|
859
|
+
4: { name: 'variable.other.property.mira' },
|
|
860
|
+
6: { name: 'punctuation.separator.type.mira' },
|
|
861
|
+
},
|
|
862
|
+
end: '$',
|
|
863
|
+
patterns: [
|
|
864
|
+
{ include: '#tag-comment' },
|
|
865
|
+
{ include: '#tag' },
|
|
866
|
+
{ include: '#doc-record-value' },
|
|
867
|
+
{ include: '#doc-array-value' },
|
|
868
|
+
{ include: '#type-context' },
|
|
869
|
+
],
|
|
780
870
|
},
|
|
781
871
|
],
|
|
782
872
|
},
|
|
783
873
|
'doc-value': {
|
|
784
874
|
patterns: [
|
|
785
|
-
{ include: '#
|
|
786
|
-
{ include: '#
|
|
787
|
-
{ include: '#
|
|
875
|
+
{ include: '#tag-properties' },
|
|
876
|
+
{ include: '#tag-comment' },
|
|
877
|
+
{ include: '#tag' },
|
|
788
878
|
{ include: '#doc-record-value' },
|
|
879
|
+
{ include: '#doc-array-value' },
|
|
789
880
|
{ include: 'source.mira' },
|
|
790
881
|
],
|
|
791
882
|
},
|
|
@@ -800,21 +891,28 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
800
891
|
},
|
|
801
892
|
],
|
|
802
893
|
},
|
|
803
|
-
'
|
|
894
|
+
'doc-array-value': {
|
|
895
|
+
patterns: [
|
|
896
|
+
{
|
|
897
|
+
begin: String.raw`\[`,
|
|
898
|
+
beginCaptures: { 0: { name: 'punctuation.section.brackets.begin.mira' } },
|
|
899
|
+
end: String.raw`\]`,
|
|
900
|
+
endCaptures: { 0: { name: 'punctuation.section.brackets.end.mira' } },
|
|
901
|
+
patterns: [{ include: '#doc-value' }],
|
|
902
|
+
},
|
|
903
|
+
],
|
|
904
|
+
},
|
|
905
|
+
'tag-properties': {
|
|
804
906
|
patterns: [
|
|
805
907
|
{
|
|
806
|
-
match: String.raw`(${
|
|
908
|
+
match: String.raw`(${DOC_FIELD_NAME})(\s*)(:)(?=[ \t]*/\*[ \t]*<extern[ \t]+(?:(?:async[ \t]+)?function\*?)(?:[ \t]+${DOC_TAG_NAME})?>[ \t]*\*/)`,
|
|
807
909
|
captures: {
|
|
808
910
|
1: { name: 'entity.name.function.mira' },
|
|
809
911
|
3: { name: 'punctuation.separator.key-value.mira' },
|
|
810
912
|
},
|
|
811
913
|
},
|
|
812
|
-
],
|
|
813
|
-
},
|
|
814
|
-
'extern-class-properties': {
|
|
815
|
-
patterns: [
|
|
816
914
|
{
|
|
817
|
-
match: String.raw`(${
|
|
915
|
+
match: String.raw`(${DOC_FIELD_NAME})(\s*)(:)(?=[ \t]*/\*[ \t]*<extern[ \t]+class(?:[ \t]+${DOC_TAG_NAME})?>[ \t]*\*/)`,
|
|
818
916
|
captures: {
|
|
819
917
|
1: { name: 'entity.name.type.mira' },
|
|
820
918
|
3: { name: 'punctuation.separator.key-value.mira' },
|
|
@@ -822,54 +920,84 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
822
920
|
},
|
|
823
921
|
],
|
|
824
922
|
},
|
|
825
|
-
|
|
923
|
+
'tag-comment': {
|
|
826
924
|
patterns: [
|
|
827
925
|
{
|
|
828
926
|
name: 'comment.block.mira',
|
|
829
|
-
contentName: 'meta.documentation.
|
|
830
|
-
begin: String.raw
|
|
831
|
-
beginCaptures: {
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
},
|
|
853
|
-
{
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
},
|
|
860
|
-
{ name: '
|
|
861
|
-
{ name: '
|
|
862
|
-
|
|
863
|
-
|
|
927
|
+
contentName: 'meta.documentation.tag.mira',
|
|
928
|
+
begin: String.raw`(/\*)([ \t]*)(<)(?=${DOC_TAG_CONTENT}>[ \t]*\*/)`,
|
|
929
|
+
beginCaptures: {
|
|
930
|
+
1: { name: 'punctuation.definition.comment.begin.mira' },
|
|
931
|
+
3: { name: 'punctuation.definition.tag.begin.mira' },
|
|
932
|
+
},
|
|
933
|
+
end: String.raw`(>)([ \t]*)(\*/)`,
|
|
934
|
+
endCaptures: {
|
|
935
|
+
1: { name: 'punctuation.definition.tag.end.mira' },
|
|
936
|
+
3: { name: 'punctuation.definition.comment.end.mira' },
|
|
937
|
+
},
|
|
938
|
+
patterns: [{ include: '#tag-content' }],
|
|
939
|
+
},
|
|
940
|
+
],
|
|
941
|
+
},
|
|
942
|
+
'tag-content': {
|
|
943
|
+
patterns: [
|
|
944
|
+
{
|
|
945
|
+
match: String.raw`(extern)([ \t]+)(?:(async)([ \t]+))?(function)(\*)?(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
|
|
946
|
+
captures: {
|
|
947
|
+
1: { name: 'keyword.declaration.extern.mira' },
|
|
948
|
+
3: { name: 'keyword.js' },
|
|
949
|
+
5: { name: 'keyword.js' },
|
|
950
|
+
6: { name: 'keyword.operator.generator.js' },
|
|
951
|
+
8: { name: 'entity.name.function.js' },
|
|
952
|
+
},
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
match: String.raw`(extern)([ \t]+)(class)(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
|
|
956
|
+
captures: {
|
|
957
|
+
1: { name: 'keyword.declaration.extern.mira' },
|
|
958
|
+
3: { name: 'keyword.js' },
|
|
959
|
+
5: { name: 'entity.name.type.js' },
|
|
960
|
+
},
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
match: String.raw`(extern)([ \t]+)(${DOC_TAG_NAME})(\()(${DOC_TAG_NUMBER})(\))(?=>)`,
|
|
964
|
+
captures: {
|
|
965
|
+
1: { name: 'keyword.declaration.extern.mira' },
|
|
966
|
+
3: { name: 'entity.name.type.js' },
|
|
967
|
+
4: { name: 'punctuation.section.parens.begin.mira' },
|
|
968
|
+
5: { name: 'constant.numeric.mira' },
|
|
969
|
+
6: { name: 'punctuation.section.parens.end.mira' },
|
|
970
|
+
},
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
match: String.raw`(extern)(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
|
|
974
|
+
captures: {
|
|
975
|
+
1: { name: 'keyword.declaration.extern.mira' },
|
|
976
|
+
3: { name: 'entity.name.type.js' },
|
|
977
|
+
},
|
|
978
|
+
},
|
|
979
|
+
{
|
|
980
|
+
match: String.raw`(module)(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
|
|
981
|
+
captures: {
|
|
982
|
+
1: { name: 'keyword.declaration.module.mira' },
|
|
983
|
+
3: { name: 'entity.name.namespace.mira' },
|
|
984
|
+
},
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
match: String.raw`(function)(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
|
|
988
|
+
captures: {
|
|
989
|
+
1: { name: 'keyword.declaration.function.mira' },
|
|
990
|
+
3: { name: 'entity.name.function.mira' },
|
|
991
|
+
},
|
|
864
992
|
},
|
|
865
993
|
],
|
|
866
994
|
},
|
|
867
995
|
'reflection-type': {
|
|
868
996
|
patterns: [
|
|
869
997
|
{
|
|
870
|
-
match: String.raw
|
|
998
|
+
match: String.raw`${IDENTIFIER_START}(type)(\s*)(\()(\s*)(${IDENTIFIER})(\s*)(\))`,
|
|
871
999
|
captures: {
|
|
872
|
-
1: { name: '
|
|
1000
|
+
1: { name: 'support.type.type.mira' },
|
|
873
1001
|
3: { name: 'punctuation.section.parens.begin.mira' },
|
|
874
1002
|
5: { name: 'variable.other.mira' },
|
|
875
1003
|
7: { name: 'punctuation.section.parens.end.mira' },
|
|
@@ -890,7 +1018,7 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
890
1018
|
'function-type': {
|
|
891
1019
|
patterns: [
|
|
892
1020
|
{
|
|
893
|
-
begin: String.raw
|
|
1021
|
+
begin: String.raw`${IDENTIFIER_START}(fn)${IDENTIFIER_END}(?=\s*(?:<|\())`,
|
|
894
1022
|
beginCaptures: { 1: { name: 'support.type.function.mira' } },
|
|
895
1023
|
end: String.raw`(?=\s*(?:,|\)|$))`,
|
|
896
1024
|
patterns: [
|
|
@@ -1013,11 +1141,7 @@ export function createMiraScriptDocGrammar(): LanguageRegistration {
|
|
|
1013
1141
|
{ include: '#reflection-type' },
|
|
1014
1142
|
{
|
|
1015
1143
|
name: 'support.type.builtin.mira',
|
|
1016
|
-
match:
|
|
1017
|
-
},
|
|
1018
|
-
{
|
|
1019
|
-
name: 'constant.language.boolean.mira',
|
|
1020
|
-
match: String.raw`(?<!\p{XID_Continue})(?:true|false)${IDENTIFIER_END}`,
|
|
1144
|
+
match: `${IDENTIFIER_START}(?:${alternatives(BUILT_IN_TYPES)})${IDENTIFIER_END}`,
|
|
1021
1145
|
},
|
|
1022
1146
|
{ name: 'keyword.operator.type.mira', match: '[&|]' },
|
|
1023
1147
|
{ name: 'keyword.operator.spread.mira', match: String.raw`\.\.` },
|
package/src/index.ts
CHANGED
|
@@ -7,4 +7,4 @@ export const mirascriptDoc = createMiraScriptDocGrammar();
|
|
|
7
7
|
|
|
8
8
|
export { mirascriptTemplate as 'mirascript-template', mirascriptDoc as 'mirascript-doc' };
|
|
9
9
|
|
|
10
|
-
export const grammars:
|
|
10
|
+
export const grammars: LanguageRegistration[] = [mirascript, mirascriptTemplate, mirascriptDoc];
|
package/tests/_engine.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createHighlighter, type Highlighter } from 'shiki';
|
|
2
|
+
import { INITIAL, type StateStack } from 'shiki/textmate';
|
|
3
|
+
import test, { type ExecutionContext } from 'ava';
|
|
4
|
+
import { grammars } from '../src/index.ts';
|
|
5
|
+
|
|
6
|
+
let highlighter: Highlighter;
|
|
7
|
+
|
|
8
|
+
test.before(async () => {
|
|
9
|
+
highlighter = await createHighlighter({
|
|
10
|
+
langs: grammars,
|
|
11
|
+
themes: [],
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test.after.always(() => highlighter.dispose());
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Tokenize complete source while preserving TextMate state across lines.
|
|
19
|
+
*/
|
|
20
|
+
export function tokenize(
|
|
21
|
+
code: string,
|
|
22
|
+
language = 'mirascript',
|
|
23
|
+
): Array<{ line: number; text: string; scopes: string[] }> {
|
|
24
|
+
const grammar = highlighter.getLanguage(language);
|
|
25
|
+
let state: StateStack = INITIAL;
|
|
26
|
+
return code.split('\n').flatMap((line, lineIndex) => {
|
|
27
|
+
const result = grammar.tokenizeLine(line, state);
|
|
28
|
+
state = result.ruleStack;
|
|
29
|
+
return result.tokens.map((token) => ({
|
|
30
|
+
line: lineIndex,
|
|
31
|
+
text: line.slice(token.startIndex, token.endIndex),
|
|
32
|
+
scopes: token.scopes,
|
|
33
|
+
}));
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Assert that a selected textual token contains the expected scope.
|
|
39
|
+
*/
|
|
40
|
+
export function expectScope(
|
|
41
|
+
t: ExecutionContext,
|
|
42
|
+
tokens: Array<{ text: string; scopes: string[] }>,
|
|
43
|
+
text: string,
|
|
44
|
+
scope: string,
|
|
45
|
+
occurrence = 0,
|
|
46
|
+
): void {
|
|
47
|
+
const matching = tokens.filter((token) => token.text === text);
|
|
48
|
+
t.true(matching.length > occurrence, `Missing token ${JSON.stringify(text)} #${occurrence}`);
|
|
49
|
+
t.true(
|
|
50
|
+
matching[occurrence].scopes.includes(scope),
|
|
51
|
+
`${JSON.stringify(text)} should include ${scope}; got ${matching[occurrence].scopes.join(', ')}`,
|
|
52
|
+
);
|
|
53
|
+
}
|