scripts/CodeMirror/mode/dart/dart.js (view raw)
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: https://codemirror.net/LICENSE
3
4(function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"), require("../clike/clike"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror", "../clike/clike"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11})(function(CodeMirror) {
12 "use strict";
13
14 var keywords = ("this super static final const abstract class extends external factory " +
15 "implements mixin get native set typedef with enum throw rethrow " +
16 "assert break case continue default in return new deferred async await covariant " +
17 "try catch finally do else for if switch while import library export " +
18 "part of show hide is as extension on yield late required").split(" ");
19 var blockKeywords = "try catch finally do else for if switch while".split(" ");
20 var atoms = "true false null".split(" ");
21 var builtins = "void bool num int double dynamic var String Null Never".split(" ");
22
23 function set(words) {
24 var obj = {};
25 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
26 return obj;
27 }
28
29 function pushInterpolationStack(state) {
30 (state.interpolationStack || (state.interpolationStack = [])).push(state.tokenize);
31 }
32
33 function popInterpolationStack(state) {
34 return (state.interpolationStack || (state.interpolationStack = [])).pop();
35 }
36
37 function sizeInterpolationStack(state) {
38 return state.interpolationStack ? state.interpolationStack.length : 0;
39 }
40
41 CodeMirror.defineMIME("application/dart", {
42 name: "clike",
43 keywords: set(keywords),
44 blockKeywords: set(blockKeywords),
45 builtin: set(builtins),
46 atoms: set(atoms),
47 hooks: {
48 "@": function(stream) {
49 stream.eatWhile(/[\w\$_\.]/);
50 return "meta";
51 },
52
53 // custom string handling to deal with triple-quoted strings and string interpolation
54 "'": function(stream, state) {
55 return tokenString("'", stream, state, false);
56 },
57 "\"": function(stream, state) {
58 return tokenString("\"", stream, state, false);
59 },
60 "r": function(stream, state) {
61 var peek = stream.peek();
62 if (peek == "'" || peek == "\"") {
63 return tokenString(stream.next(), stream, state, true);
64 }
65 return false;
66 },
67
68 "}": function(_stream, state) {
69 // "}" is end of interpolation, if interpolation stack is non-empty
70 if (sizeInterpolationStack(state) > 0) {
71 state.tokenize = popInterpolationStack(state);
72 return null;
73 }
74 return false;
75 },
76
77 "/": function(stream, state) {
78 if (!stream.eat("*")) return false
79 state.tokenize = tokenNestedComment(1)
80 return state.tokenize(stream, state)
81 },
82 token: function(stream, _, style) {
83 if (style == "variable") {
84 // Assume uppercase symbols are classes using variable-2
85 var isUpper = RegExp('^[_$]*[A-Z][a-zA-Z0-9_$]*$','g');
86 if (isUpper.test(stream.current())) {
87 return 'variable-2';
88 }
89 }
90 }
91 }
92 });
93
94 function tokenString(quote, stream, state, raw) {
95 var tripleQuoted = false;
96 if (stream.eat(quote)) {
97 if (stream.eat(quote)) tripleQuoted = true;
98 else return "string"; //empty string
99 }
100 function tokenStringHelper(stream, state) {
101 var escaped = false;
102 while (!stream.eol()) {
103 if (!raw && !escaped && stream.peek() == "$") {
104 pushInterpolationStack(state);
105 state.tokenize = tokenInterpolation;
106 return "string";
107 }
108 var next = stream.next();
109 if (next == quote && !escaped && (!tripleQuoted || stream.match(quote + quote))) {
110 state.tokenize = null;
111 break;
112 }
113 escaped = !raw && !escaped && next == "\\";
114 }
115 return "string";
116 }
117 state.tokenize = tokenStringHelper;
118 return tokenStringHelper(stream, state);
119 }
120
121 function tokenInterpolation(stream, state) {
122 stream.eat("$");
123 if (stream.eat("{")) {
124 // let clike handle the content of ${...},
125 // we take over again when "}" appears (see hooks).
126 state.tokenize = null;
127 } else {
128 state.tokenize = tokenInterpolationIdentifier;
129 }
130 return null;
131 }
132
133 function tokenInterpolationIdentifier(stream, state) {
134 stream.eatWhile(/[\w_]/);
135 state.tokenize = popInterpolationStack(state);
136 return "variable";
137 }
138
139 function tokenNestedComment(depth) {
140 return function (stream, state) {
141 var ch
142 while (ch = stream.next()) {
143 if (ch == "*" && stream.eat("/")) {
144 if (depth == 1) {
145 state.tokenize = null
146 break
147 } else {
148 state.tokenize = tokenNestedComment(depth - 1)
149 return state.tokenize(stream, state)
150 }
151 } else if (ch == "/" && stream.eat("*")) {
152 state.tokenize = tokenNestedComment(depth + 1)
153 return state.tokenize(stream, state)
154 }
155 }
156 return "comment"
157 }
158 }
159
160 CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));
161
162 // This is needed to make loading through meta.js work.
163 CodeMirror.defineMode("dart", function(conf) {
164 return CodeMirror.getMode(conf, "application/dart");
165 }, "clike");
166});