LaravelTest

Форк
0
304 строки · 9.4 Кб
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("../../mode/sql/sql"));
7
  else if (typeof define == "function" && define.amd) // AMD
8
    define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
9
  else // Plain browser env
10
    mod(CodeMirror);
11
})(function(CodeMirror) {
12
  "use strict";
13

14
  var tables;
15
  var defaultTable;
16
  var keywords;
17
  var identifierQuote;
18
  var CONS = {
19
    QUERY_DIV: ";",
20
    ALIAS_KEYWORD: "AS"
21
  };
22
  var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;
23

24
  function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
25

26
  function getKeywords(editor) {
27
    var mode = editor.doc.modeOption;
28
    if (mode === "sql") mode = "text/x-sql";
29
    return CodeMirror.resolveMode(mode).keywords;
30
  }
31

32
  function getIdentifierQuote(editor) {
33
    var mode = editor.doc.modeOption;
34
    if (mode === "sql") mode = "text/x-sql";
35
    return CodeMirror.resolveMode(mode).identifierQuote || "`";
36
  }
37

38
  function getText(item) {
39
    return typeof item == "string" ? item : item.text;
40
  }
41

42
  function wrapTable(name, value) {
43
    if (isArray(value)) value = {columns: value}
44
    if (!value.text) value.text = name
45
    return value
46
  }
47

48
  function parseTables(input) {
49
    var result = {}
50
    if (isArray(input)) {
51
      for (var i = input.length - 1; i >= 0; i--) {
52
        var item = input[i]
53
        result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
54
      }
55
    } else if (input) {
56
      for (var name in input)
57
        result[name.toUpperCase()] = wrapTable(name, input[name])
58
    }
59
    return result
60
  }
61

62
  function getTable(name) {
63
    return tables[name.toUpperCase()]
64
  }
65

66
  function shallowClone(object) {
67
    var result = {};
68
    for (var key in object) if (object.hasOwnProperty(key))
69
      result[key] = object[key];
70
    return result;
71
  }
72

73
  function match(string, word) {
74
    var len = string.length;
75
    var sub = getText(word).substr(0, len);
76
    return string.toUpperCase() === sub.toUpperCase();
77
  }
78

79
  function addMatches(result, search, wordlist, formatter) {
80
    if (isArray(wordlist)) {
81
      for (var i = 0; i < wordlist.length; i++)
82
        if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
83
    } else {
84
      for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
85
        var val = wordlist[word]
86
        if (!val || val === true)
87
          val = word
88
        else
89
          val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
90
        if (match(search, val)) result.push(formatter(val))
91
      }
92
    }
93
  }
94

95
  function cleanName(name) {
96
    // Get rid name from identifierQuote and preceding dot(.)
97
    if (name.charAt(0) == ".") {
98
      name = name.substr(1);
99
    }
100
    // replace duplicated identifierQuotes with single identifierQuotes
101
    // and remove single identifierQuotes
102
    var nameParts = name.split(identifierQuote+identifierQuote);
103
    for (var i = 0; i < nameParts.length; i++)
104
      nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), "");
105
    return nameParts.join(identifierQuote);
106
  }
107

108
  function insertIdentifierQuotes(name) {
109
    var nameParts = getText(name).split(".");
110
    for (var i = 0; i < nameParts.length; i++)
111
      nameParts[i] = identifierQuote +
112
        // duplicate identifierQuotes
113
        nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +
114
        identifierQuote;
115
    var escaped = nameParts.join(".");
116
    if (typeof name == "string") return escaped;
117
    name = shallowClone(name);
118
    name.text = escaped;
119
    return name;
120
  }
121

122
  function nameCompletion(cur, token, result, editor) {
123
    // Try to complete table, column names and return start position of completion
124
    var useIdentifierQuotes = false;
125
    var nameParts = [];
126
    var start = token.start;
127
    var cont = true;
128
    while (cont) {
129
      cont = (token.string.charAt(0) == ".");
130
      useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);
131

132
      start = token.start;
133
      nameParts.unshift(cleanName(token.string));
134

135
      token = editor.getTokenAt(Pos(cur.line, token.start));
136
      if (token.string == ".") {
137
        cont = true;
138
        token = editor.getTokenAt(Pos(cur.line, token.start));
139
      }
140
    }
141

142
    // Try to complete table names
143
    var string = nameParts.join(".");
144
    addMatches(result, string, tables, function(w) {
145
      return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
146
    });
147

148
    // Try to complete columns from defaultTable
149
    addMatches(result, string, defaultTable, function(w) {
150
      return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
151
    });
152

153
    // Try to complete columns
154
    string = nameParts.pop();
155
    var table = nameParts.join(".");
156

157
    var alias = false;
158
    var aliasTable = table;
159
    // Check if table is available. If not, find table by Alias
160
    if (!getTable(table)) {
161
      var oldTable = table;
162
      table = findTableByAlias(table, editor);
163
      if (table !== oldTable) alias = true;
164
    }
165

166
    var columns = getTable(table);
167
    if (columns && columns.columns)
168
      columns = columns.columns;
169

170
    if (columns) {
171
      addMatches(result, string, columns, function(w) {
172
        var tableInsert = table;
173
        if (alias == true) tableInsert = aliasTable;
174
        if (typeof w == "string") {
175
          w = tableInsert + "." + w;
176
        } else {
177
          w = shallowClone(w);
178
          w.text = tableInsert + "." + w.text;
179
        }
180
        return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
181
      });
182
    }
183

184
    return start;
185
  }
186

187
  function eachWord(lineText, f) {
188
    var words = lineText.split(/\s+/)
189
    for (var i = 0; i < words.length; i++)
190
      if (words[i]) f(words[i].replace(/[`,;]/g, ''))
191
  }
192

193
  function findTableByAlias(alias, editor) {
194
    var doc = editor.doc;
195
    var fullQuery = doc.getValue();
196
    var aliasUpperCase = alias.toUpperCase();
197
    var previousWord = "";
198
    var table = "";
199
    var separator = [];
200
    var validRange = {
201
      start: Pos(0, 0),
202
      end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
203
    };
204

205
    //add separator
206
    var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
207
    while(indexOfSeparator != -1) {
208
      separator.push(doc.posFromIndex(indexOfSeparator));
209
      indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
210
    }
211
    separator.unshift(Pos(0, 0));
212
    separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
213

214
    //find valid range
215
    var prevItem = null;
216
    var current = editor.getCursor()
217
    for (var i = 0; i < separator.length; i++) {
218
      if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
219
        validRange = {start: prevItem, end: separator[i]};
220
        break;
221
      }
222
      prevItem = separator[i];
223
    }
224

225
    if (validRange.start) {
226
      var query = doc.getRange(validRange.start, validRange.end, false);
227

228
      for (var i = 0; i < query.length; i++) {
229
        var lineText = query[i];
230
        eachWord(lineText, function(word) {
231
          var wordUpperCase = word.toUpperCase();
232
          if (wordUpperCase === aliasUpperCase && getTable(previousWord))
233
            table = previousWord;
234
          if (wordUpperCase !== CONS.ALIAS_KEYWORD)
235
            previousWord = word;
236
        });
237
        if (table) break;
238
      }
239
    }
240
    return table;
241
  }
242

243
  CodeMirror.registerHelper("hint", "sql", function(editor, options) {
244
    tables = parseTables(options && options.tables)
245
    var defaultTableName = options && options.defaultTable;
246
    var disableKeywords = options && options.disableKeywords;
247
    defaultTable = defaultTableName && getTable(defaultTableName);
248
    keywords = getKeywords(editor);
249
    identifierQuote = getIdentifierQuote(editor);
250

251
    if (defaultTableName && !defaultTable)
252
      defaultTable = findTableByAlias(defaultTableName, editor);
253

254
    defaultTable = defaultTable || [];
255

256
    if (defaultTable.columns)
257
      defaultTable = defaultTable.columns;
258

259
    var cur = editor.getCursor();
260
    var result = [];
261
    var token = editor.getTokenAt(cur), start, end, search;
262
    if (token.end > cur.ch) {
263
      token.end = cur.ch;
264
      token.string = token.string.slice(0, cur.ch - token.start);
265
    }
266

267
    if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {
268
      search = token.string;
269
      start = token.start;
270
      end = token.end;
271
    } else {
272
      start = end = cur.ch;
273
      search = "";
274
    }
275
    if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {
276
      start = nameCompletion(cur, token, result, editor);
277
    } else {
278
      var objectOrClass = function(w, className) {
279
        if (typeof w === "object") {
280
          w.className = className;
281
        } else {
282
          w = { text: w, className: className };
283
        }
284
        return w;
285
      };
286
    addMatches(result, search, defaultTable, function(w) {
287
        return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table");
288
    });
289
    addMatches(
290
        result,
291
        search,
292
        tables, function(w) {
293
          return objectOrClass(w, "CodeMirror-hint-table");
294
        }
295
    );
296
    if (!disableKeywords)
297
      addMatches(result, search, keywords, function(w) {
298
          return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword");
299
      });
300
  }
301

302
    return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
303
  });
304
});
305

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.