File modules/editor/codemirror/addon/hint/sql-hint.min.js
Last commit: Tue May 22 22:39:49 2018 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 // Distributed under an MIT license: http://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 doublicated 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 // doublicate 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 var query = doc.getRange(validRange.start, validRange.end, false); 226 227 for (var i = 0; i < query.length; i++) { 228 var lineText = query[i]; 229 eachWord(lineText, function(word) { 230 var wordUpperCase = word.toUpperCase(); 231 if (wordUpperCase === aliasUpperCase && getTable(previousWord)) 232 table = previousWord; 233 if (wordUpperCase !== CONS.ALIAS_KEYWORD) 234 previousWord = word; 235 }); 236 if (table) break; 237 } 238 return table; 239 } 240 241 CodeMirror.registerHelper("hint", "sql", function(editor, options) { 242 tables = parseTables(options && options.tables) 243 var defaultTableName = options && options.defaultTable; 244 var disableKeywords = options && options.disableKeywords; 245 defaultTable = defaultTableName && getTable(defaultTableName); 246 keywords = getKeywords(editor); 247 identifierQuote = getIdentifierQuote(editor); 248 249 if (defaultTableName && !defaultTable) 250 defaultTable = findTableByAlias(defaultTableName, editor); 251 252 defaultTable = defaultTable || []; 253 254 if (defaultTable.columns) 255 defaultTable = defaultTable.columns; 256 257 var cur = editor.getCursor(); 258 var result = []; 259 var token = editor.getTokenAt(cur), start, end, search; 260 if (token.end > cur.ch) { 261 token.end = cur.ch; 262 token.string = token.string.slice(0, cur.ch - token.start); 263 } 264 265 if (token.string.match(/^[.`"\w@]\w*$/)) { 266 search = token.string; 267 start = token.start; 268 end = token.end; 269 } else { 270 start = end = cur.ch; 271 search = ""; 272 } 273 if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) { 274 start = nameCompletion(cur, token, result, editor); 275 } else { 276 addMatches(result, search, tables, function(w) {return w;}); 277 addMatches(result, search, defaultTable, function(w) {return w;}); 278 if (!disableKeywords) 279 addMatches(result, search, keywords, function(w) {return w.toUpperCase();}); 280 } 281 282 return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)}; 283 }); 284 });
Downloadmodules/editor/codemirror/addon/hint/sql-hint.min.js
History Tue, 22 May 2018 22:39:49 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.