LaravelTest
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) {5if (typeof exports == "object" && typeof module == "object") // CommonJS6mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));7else if (typeof define == "function" && define.amd) // AMD8define(["../../lib/codemirror", "../../mode/sql/sql"], mod);9else // Plain browser env10mod(CodeMirror);11})(function(CodeMirror) {12"use strict";13
14var tables;15var defaultTable;16var keywords;17var identifierQuote;18var CONS = {19QUERY_DIV: ";",20ALIAS_KEYWORD: "AS"21};22var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;23
24function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }25
26function getKeywords(editor) {27var mode = editor.doc.modeOption;28if (mode === "sql") mode = "text/x-sql";29return CodeMirror.resolveMode(mode).keywords;30}31
32function getIdentifierQuote(editor) {33var mode = editor.doc.modeOption;34if (mode === "sql") mode = "text/x-sql";35return CodeMirror.resolveMode(mode).identifierQuote || "`";36}37
38function getText(item) {39return typeof item == "string" ? item : item.text;40}41
42function wrapTable(name, value) {43if (isArray(value)) value = {columns: value}44if (!value.text) value.text = name45return value46}47
48function parseTables(input) {49var result = {}50if (isArray(input)) {51for (var i = input.length - 1; i >= 0; i--) {52var item = input[i]53result[getText(item).toUpperCase()] = wrapTable(getText(item), item)54}55} else if (input) {56for (var name in input)57result[name.toUpperCase()] = wrapTable(name, input[name])58}59return result60}61
62function getTable(name) {63return tables[name.toUpperCase()]64}65
66function shallowClone(object) {67var result = {};68for (var key in object) if (object.hasOwnProperty(key))69result[key] = object[key];70return result;71}72
73function match(string, word) {74var len = string.length;75var sub = getText(word).substr(0, len);76return string.toUpperCase() === sub.toUpperCase();77}78
79function addMatches(result, search, wordlist, formatter) {80if (isArray(wordlist)) {81for (var i = 0; i < wordlist.length; i++)82if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))83} else {84for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {85var val = wordlist[word]86if (!val || val === true)87val = word88else89val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text90if (match(search, val)) result.push(formatter(val))91}92}93}94
95function cleanName(name) {96// Get rid name from identifierQuote and preceding dot(.)97if (name.charAt(0) == ".") {98name = name.substr(1);99}100// replace duplicated identifierQuotes with single identifierQuotes101// and remove single identifierQuotes102var nameParts = name.split(identifierQuote+identifierQuote);103for (var i = 0; i < nameParts.length; i++)104nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), "");105return nameParts.join(identifierQuote);106}107
108function insertIdentifierQuotes(name) {109var nameParts = getText(name).split(".");110for (var i = 0; i < nameParts.length; i++)111nameParts[i] = identifierQuote +112// duplicate identifierQuotes113nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +114identifierQuote;115var escaped = nameParts.join(".");116if (typeof name == "string") return escaped;117name = shallowClone(name);118name.text = escaped;119return name;120}121
122function nameCompletion(cur, token, result, editor) {123// Try to complete table, column names and return start position of completion124var useIdentifierQuotes = false;125var nameParts = [];126var start = token.start;127var cont = true;128while (cont) {129cont = (token.string.charAt(0) == ".");130useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);131
132start = token.start;133nameParts.unshift(cleanName(token.string));134
135token = editor.getTokenAt(Pos(cur.line, token.start));136if (token.string == ".") {137cont = true;138token = editor.getTokenAt(Pos(cur.line, token.start));139}140}141
142// Try to complete table names143var string = nameParts.join(".");144addMatches(result, string, tables, function(w) {145return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;146});147
148// Try to complete columns from defaultTable149addMatches(result, string, defaultTable, function(w) {150return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;151});152
153// Try to complete columns154string = nameParts.pop();155var table = nameParts.join(".");156
157var alias = false;158var aliasTable = table;159// Check if table is available. If not, find table by Alias160if (!getTable(table)) {161var oldTable = table;162table = findTableByAlias(table, editor);163if (table !== oldTable) alias = true;164}165
166var columns = getTable(table);167if (columns && columns.columns)168columns = columns.columns;169
170if (columns) {171addMatches(result, string, columns, function(w) {172var tableInsert = table;173if (alias == true) tableInsert = aliasTable;174if (typeof w == "string") {175w = tableInsert + "." + w;176} else {177w = shallowClone(w);178w.text = tableInsert + "." + w.text;179}180return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;181});182}183
184return start;185}186
187function eachWord(lineText, f) {188var words = lineText.split(/\s+/)189for (var i = 0; i < words.length; i++)190if (words[i]) f(words[i].replace(/[`,;]/g, ''))191}192
193function findTableByAlias(alias, editor) {194var doc = editor.doc;195var fullQuery = doc.getValue();196var aliasUpperCase = alias.toUpperCase();197var previousWord = "";198var table = "";199var separator = [];200var validRange = {201start: Pos(0, 0),202end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)203};204
205//add separator206var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);207while(indexOfSeparator != -1) {208separator.push(doc.posFromIndex(indexOfSeparator));209indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);210}211separator.unshift(Pos(0, 0));212separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));213
214//find valid range215var prevItem = null;216var current = editor.getCursor()217for (var i = 0; i < separator.length; i++) {218if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {219validRange = {start: prevItem, end: separator[i]};220break;221}222prevItem = separator[i];223}224
225if (validRange.start) {226var query = doc.getRange(validRange.start, validRange.end, false);227
228for (var i = 0; i < query.length; i++) {229var lineText = query[i];230eachWord(lineText, function(word) {231var wordUpperCase = word.toUpperCase();232if (wordUpperCase === aliasUpperCase && getTable(previousWord))233table = previousWord;234if (wordUpperCase !== CONS.ALIAS_KEYWORD)235previousWord = word;236});237if (table) break;238}239}240return table;241}242
243CodeMirror.registerHelper("hint", "sql", function(editor, options) {244tables = parseTables(options && options.tables)245var defaultTableName = options && options.defaultTable;246var disableKeywords = options && options.disableKeywords;247defaultTable = defaultTableName && getTable(defaultTableName);248keywords = getKeywords(editor);249identifierQuote = getIdentifierQuote(editor);250
251if (defaultTableName && !defaultTable)252defaultTable = findTableByAlias(defaultTableName, editor);253
254defaultTable = defaultTable || [];255
256if (defaultTable.columns)257defaultTable = defaultTable.columns;258
259var cur = editor.getCursor();260var result = [];261var token = editor.getTokenAt(cur), start, end, search;262if (token.end > cur.ch) {263token.end = cur.ch;264token.string = token.string.slice(0, cur.ch - token.start);265}266
267if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {268search = token.string;269start = token.start;270end = token.end;271} else {272start = end = cur.ch;273search = "";274}275if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {276start = nameCompletion(cur, token, result, editor);277} else {278var objectOrClass = function(w, className) {279if (typeof w === "object") {280w.className = className;281} else {282w = { text: w, className: className };283}284return w;285};286addMatches(result, search, defaultTable, function(w) {287return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table");288});289addMatches(290result,291search,292tables, function(w) {293return objectOrClass(w, "CodeMirror-hint-table");294}295);296if (!disableKeywords)297addMatches(result, search, keywords, function(w) {298return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword");299});300}301
302return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};303});304});305