File modules/editor/codemirror/addon/tern/tern.min.js
Last commit: Tue May 22 22:39:53 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 // Glue code between CodeMirror and Tern. 5 // 6 // Create a CodeMirror.TernServer to wrap an actual Tern server, 7 // register open documents (CodeMirror.Doc instances) with it, and 8 // call its methods to activate the assisting functions that Tern 9 // provides. 10 // 11 // Options supported (all optional): 12 // * defs: An array of JSON definition data structures. 13 // * plugins: An object mapping plugin names to configuration 14 // options. 15 // * getFile: A function(name, c) that can be used to access files in 16 // the project that haven't been loaded yet. Simply do c(null) to 17 // indicate that a file is not available. 18 // * fileFilter: A function(value, docName, doc) that will be applied 19 // to documents before passing them on to Tern. 20 // * switchToDoc: A function(name, doc) that should, when providing a 21 // multi-file view, switch the view or focus to the named file. 22 // * showError: A function(editor, message) that can be used to 23 // override the way errors are displayed. 24 // * completionTip: Customize the content in tooltips for completions. 25 // Is passed a single argument—the completion's data as returned by 26 // Tern—and may return a string, DOM node, or null to indicate that 27 // no tip should be shown. By default the docstring is shown. 28 // * typeTip: Like completionTip, but for the tooltips shown for type 29 // queries. 30 // * responseFilter: A function(doc, query, request, error, data) that 31 // will be applied to the Tern responses before treating them 32 // 33 // 34 // It is possible to run the Tern server in a web worker by specifying 35 // these additional options: 36 // * useWorker: Set to true to enable web worker mode. You'll probably 37 // want to feature detect the actual value you use here, for example 38 // !!window.Worker. 39 // * workerScript: The main script of the worker. Point this to 40 // wherever you are hosting worker.js from this directory. 41 // * workerDeps: An array of paths pointing (relative to workerScript) 42 // to the Acorn and Tern libraries and any Tern plugins you want to 43 // load. Or, if you minified those into a single script and included 44 // them in the workerScript, simply leave this undefined. 45 46 (function(mod) { 47 if (typeof exports == "object" && typeof module == "object") // CommonJS 48 mod(require("../../lib/codemirror")); 49 else if (typeof define == "function" && define.amd) // AMD 50 define(["../../lib/codemirror"], mod); 51 else // Plain browser env 52 mod(CodeMirror); 53 })(function(CodeMirror) { 54 "use strict"; 55 // declare global: tern 56 57 CodeMirror.TernServer = function(options) { 58 var self = this; 59 this.options = options || {}; 60 var plugins = this.options.plugins || (this.options.plugins = {}); 61 if (!plugins.doc_comment) plugins.doc_comment = true; 62 this.docs = Object.create(null); 63 if (this.options.useWorker) { 64 this.server = new WorkerServer(this); 65 } else { 66 this.server = new tern.Server({ 67 getFile: function(name, c) { return getFile(self, name, c); }, 68 async: true, 69 defs: this.options.defs || [], 70 plugins: plugins 71 }); 72 } 73 this.trackChange = function(doc, change) { trackChange(self, doc, change); }; 74 75 this.cachedArgHints = null; 76 this.activeArgHints = null; 77 this.jumpStack = []; 78 79 this.getHint = function(cm, c) { return hint(self, cm, c); }; 80 this.getHint.async = true; 81 }; 82 83 CodeMirror.TernServer.prototype = { 84 addDoc: function(name, doc) { 85 var data = {doc: doc, name: name, changed: null}; 86 this.server.addFile(name, docValue(this, data)); 87 CodeMirror.on(doc, "change", this.trackChange); 88 return this.docs[name] = data; 89 }, 90 91 delDoc: function(id) { 92 var found = resolveDoc(this, id); 93 if (!found) return; 94 CodeMirror.off(found.doc, "change", this.trackChange); 95 delete this.docs[found.name]; 96 this.server.delFile(found.name); 97 }, 98 99 hideDoc: function(id) { 100 closeArgHints(this); 101 var found = resolveDoc(this, id); 102 if (found && found.changed) sendDoc(this, found); 103 }, 104 105 complete: function(cm) { 106 cm.showHint({hint: this.getHint}); 107 }, 108 109 showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); }, 110 111 showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); }, 112 113 updateArgHints: function(cm) { updateArgHints(this, cm); }, 114 115 jumpToDef: function(cm) { jumpToDef(this, cm); }, 116 117 jumpBack: function(cm) { jumpBack(this, cm); }, 118 119 rename: function(cm) { rename(this, cm); }, 120 121 selectName: function(cm) { selectName(this, cm); }, 122 123 request: function (cm, query, c, pos) { 124 var self = this; 125 var doc = findDoc(this, cm.getDoc()); 126 var request = buildRequest(this, doc, query, pos); 127 var extraOptions = request.query && this.options.queryOptions && this.options.queryOptions[request.query.type] 128 if (extraOptions) for (var prop in extraOptions) request.query[prop] = extraOptions[prop]; 129 130 this.server.request(request, function (error, data) { 131 if (!error && self.options.responseFilter) 132 data = self.options.responseFilter(doc, query, request, error, data); 133 c(error, data); 134 }); 135 }, 136 137 destroy: function () { 138 closeArgHints(this) 139 if (this.worker) { 140 this.worker.terminate(); 141 this.worker = null; 142 } 143 } 144 }; 145 146 var Pos = CodeMirror.Pos; 147 var cls = "CodeMirror-Tern-"; 148 var bigDoc = 250; 149 150 function getFile(ts, name, c) { 151 var buf = ts.docs[name]; 152 if (buf) 153 c(docValue(ts, buf)); 154 else if (ts.options.getFile) 155 ts.options.getFile(name, c); 156 else 157 c(null); 158 } 159 160 function findDoc(ts, doc, name) { 161 for (var n in ts.docs) { 162 var cur = ts.docs[n]; 163 if (cur.doc == doc) return cur; 164 } 165 if (!name) for (var i = 0;; ++i) { 166 n = "[doc" + (i || "") + "]"; 167 if (!ts.docs[n]) { name = n; break; } 168 } 169 return ts.addDoc(name, doc); 170 } 171 172 function resolveDoc(ts, id) { 173 if (typeof id == "string") return ts.docs[id]; 174 if (id instanceof CodeMirror) id = id.getDoc(); 175 if (id instanceof CodeMirror.Doc) return findDoc(ts, id); 176 } 177 178 function trackChange(ts, doc, change) { 179 var data = findDoc(ts, doc); 180 181 var argHints = ts.cachedArgHints; 182 if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) >= 0) 183 ts.cachedArgHints = null; 184 185 var changed = data.changed; 186 if (changed == null) 187 data.changed = changed = {from: change.from.line, to: change.from.line}; 188 var end = change.from.line + (change.text.length - 1); 189 if (change.from.line < changed.to) changed.to = changed.to - (change.to.line - end); 190 if (end >= changed.to) changed.to = end + 1; 191 if (changed.from > change.from.line) changed.from = change.from.line; 192 193 if (doc.lineCount() > bigDoc && change.to - changed.from > 100) setTimeout(function() { 194 if (data.changed && data.changed.to - data.changed.from > 100) sendDoc(ts, data); 195 }, 200); 196 } 197 198 function sendDoc(ts, doc) { 199 ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) { 200 if (error) window.console.error(error); 201 else doc.changed = null; 202 }); 203 } 204 205 // Completion 206 207 function hint(ts, cm, c) { 208 ts.request(cm, {type: "completions", types: true, docs: true, urls: true}, function(error, data) { 209 if (error) return showError(ts, cm, error); 210 var completions = [], after = ""; 211 var from = data.start, to = data.end; 212 if (cm.getRange(Pos(from.line, from.ch - 2), from) == "[\"" && 213 cm.getRange(to, Pos(to.line, to.ch + 2)) != "\"]") 214 after = "\"]"; 215 216 for (var i = 0; i < data.completions.length; ++i) { 217 var completion = data.completions[i], className = typeToIcon(completion.type); 218 if (data.guess) className += " " + cls + "guess"; 219 completions.push({text: completion.name + after, 220 displayText: completion.displayName || completion.name, 221 className: className, 222 data: completion}); 223 } 224 225 var obj = {from: from, to: to, list: completions}; 226 var tooltip = null; 227 CodeMirror.on(obj, "close", function() { remove(tooltip); }); 228 CodeMirror.on(obj, "update", function() { remove(tooltip); }); 229 CodeMirror.on(obj, "select", function(cur, node) { 230 remove(tooltip); 231 var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc; 232 if (content) { 233 tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset, 234 node.getBoundingClientRect().top + window.pageYOffset, content); 235 tooltip.className += " " + cls + "hint-doc"; 236 } 237 }); 238 c(obj); 239 }); 240 } 241 242 function typeToIcon(type) { 243 var suffix; 244 if (type == "?") suffix = "unknown"; 245 else if (type == "number" || type == "string" || type == "bool") suffix = type; 246 else if (/^fn\(/.test(type)) suffix = "fn"; 247 else if (/^\[/.test(type)) suffix = "array"; 248 else suffix = "object"; 249 return cls + "completion " + cls + "completion-" + suffix; 250 } 251 252 // Type queries 253 254 function showContextInfo(ts, cm, pos, queryName, c) { 255 ts.request(cm, queryName, function(error, data) { 256 if (error) return showError(ts, cm, error); 257 if (ts.options.typeTip) { 258 var tip = ts.options.typeTip(data); 259 } else { 260 var tip = elt("span", null, elt("strong", null, data.type || "not found")); 261 if (data.doc) 262 tip.appendChild(document.createTextNode(" — " + data.doc)); 263 if (data.url) { 264 tip.appendChild(document.createTextNode(" ")); 265 var child = tip.appendChild(elt("a", null, "[docs]")); 266 child.href = data.url; 267 child.target = "_blank"; 268 } 269 } 270 tempTooltip(cm, tip, ts); 271 if (c) c(); 272 }, pos); 273 } 274 275 // Maintaining argument hints 276 277 function updateArgHints(ts, cm) { 278 closeArgHints(ts); 279 280 if (cm.somethingSelected()) return; 281 var state = cm.getTokenAt(cm.getCursor()).state; 282 var inner = CodeMirror.innerMode(cm.getMode(), state); 283 if (inner.mode.name != "javascript") return; 284 var lex = inner.state.lexical; 285 if (lex.info != "call") return; 286 287 var ch, argPos = lex.pos || 0, tabSize = cm.getOption("tabSize"); 288 for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) { 289 var str = cm.getLine(line), extra = 0; 290 for (var pos = 0;;) { 291 var tab = str.indexOf("\t", pos); 292 if (tab == -1) break; 293 extra += tabSize - (tab + extra) % tabSize - 1; 294 pos = tab + 1; 295 } 296 ch = lex.column - extra; 297 if (str.charAt(ch) == "(") {found = true; break;} 298 } 299 if (!found) return; 300 301 var start = Pos(line, ch); 302 var cache = ts.cachedArgHints; 303 if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0) 304 return showArgHints(ts, cm, argPos); 305 306 ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) { 307 if (error || !data.type || !(/^fn\(/).test(data.type)) return; 308 ts.cachedArgHints = { 309 start: start, 310 type: parseFnType(data.type), 311 name: data.exprName || data.name || "fn", 312 guess: data.guess, 313 doc: cm.getDoc() 314 }; 315 showArgHints(ts, cm, argPos); 316 }); 317 } 318 319 function showArgHints(ts, cm, pos) { 320 closeArgHints(ts); 321 322 var cache = ts.cachedArgHints, tp = cache.type; 323 var tip = elt("span", cache.guess ? cls + "fhint-guess" : null, 324 elt("span", cls + "fname", cache.name), "("); 325 for (var i = 0; i < tp.args.length; ++i) { 326 if (i) tip.appendChild(document.createTextNode(", ")); 327 var arg = tp.args[i]; 328 tip.appendChild(elt("span", cls + "farg" + (i == pos ? " " + cls + "farg-current" : ""), arg.name || "?")); 329 if (arg.type != "?") { 330 tip.appendChild(document.createTextNode(":\u00a0")); 331 tip.appendChild(elt("span", cls + "type", arg.type)); 332 } 333 } 334 tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")")); 335 if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype)); 336 var place = cm.cursorCoords(null, "page"); 337 var tooltip = ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip) 338 setTimeout(function() { 339 tooltip.clear = onEditorActivity(cm, function() { 340 if (ts.activeArgHints == tooltip) closeArgHints(ts) }) 341 }, 20) 342 } 343 344 function parseFnType(text) { 345 var args = [], pos = 3; 346 347 function skipMatching(upto) { 348 var depth = 0, start = pos; 349 for (;;) { 350 var next = text.charAt(pos); 351 if (upto.test(next) && !depth) return text.slice(start, pos); 352 if (/[{\[\(]/.test(next)) ++depth; 353 else if (/[}\]\)]/.test(next)) --depth; 354 ++pos; 355 } 356 } 357 358 // Parse arguments 359 if (text.charAt(pos) != ")") for (;;) { 360 var name = text.slice(pos).match(/^([^, \(\[\{]+): /); 361 if (name) { 362 pos += name[0].length; 363 name = name[1]; 364 } 365 args.push({name: name, type: skipMatching(/[\),]/)}); 366 if (text.charAt(pos) == ")") break; 367 pos += 2; 368 } 369 370 var rettype = text.slice(pos).match(/^\) -> (.*)$/); 371 372 return {args: args, rettype: rettype && rettype[1]}; 373 } 374 375 // Moving to the definition of something 376 377 function jumpToDef(ts, cm) { 378 function inner(varName) { 379 var req = {type: "definition", variable: varName || null}; 380 var doc = findDoc(ts, cm.getDoc()); 381 ts.server.request(buildRequest(ts, doc, req), function(error, data) { 382 if (error) return showError(ts, cm, error); 383 if (!data.file && data.url) { window.open(data.url); return; } 384 385 if (data.file) { 386 var localDoc = ts.docs[data.file], found; 387 if (localDoc && (found = findContext(localDoc.doc, data))) { 388 ts.jumpStack.push({file: doc.name, 389 start: cm.getCursor("from"), 390 end: cm.getCursor("to")}); 391 moveTo(ts, doc, localDoc, found.start, found.end); 392 return; 393 } 394 } 395 showError(ts, cm, "Could not find a definition."); 396 }); 397 } 398 399 if (!atInterestingExpression(cm)) 400 dialog(cm, "Jump to variable", function(name) { if (name) inner(name); }); 401 else 402 inner(); 403 } 404 405 function jumpBack(ts, cm) { 406 var pos = ts.jumpStack.pop(), doc = pos && ts.docs[pos.file]; 407 if (!doc) return; 408 moveTo(ts, findDoc(ts, cm.getDoc()), doc, pos.start, pos.end); 409 } 410 411 function moveTo(ts, curDoc, doc, start, end) { 412 doc.doc.setSelection(start, end); 413 if (curDoc != doc && ts.options.switchToDoc) { 414 closeArgHints(ts); 415 ts.options.switchToDoc(doc.name, doc.doc); 416 } 417 } 418 419 // The {line,ch} representation of positions makes this rather awkward. 420 function findContext(doc, data) { 421 var before = data.context.slice(0, data.contextOffset).split("\n"); 422 var startLine = data.start.line - (before.length - 1); 423 var start = Pos(startLine, (before.length == 1 ? data.start.ch : doc.getLine(startLine).length) - before[0].length); 424 425 var text = doc.getLine(startLine).slice(start.ch); 426 for (var cur = startLine + 1; cur < doc.lineCount() && text.length < data.context.length; ++cur) 427 text += "\n" + doc.getLine(cur); 428 if (text.slice(0, data.context.length) == data.context) return data; 429 430 var cursor = doc.getSearchCursor(data.context, 0, false); 431 var nearest, nearestDist = Infinity; 432 while (cursor.findNext()) { 433 var from = cursor.from(), dist = Math.abs(from.line - start.line) * 10000; 434 if (!dist) dist = Math.abs(from.ch - start.ch); 435 if (dist < nearestDist) { nearest = from; nearestDist = dist; } 436 } 437 if (!nearest) return null; 438 439 if (before.length == 1) 440 nearest.ch += before[0].length; 441 else 442 nearest = Pos(nearest.line + (before.length - 1), before[before.length - 1].length); 443 if (data.start.line == data.end.line) 444 var end = Pos(nearest.line, nearest.ch + (data.end.ch - data.start.ch)); 445 else 446 var end = Pos(nearest.line + (data.end.line - data.start.line), data.end.ch); 447 return {start: nearest, end: end}; 448 } 449 450 function atInterestingExpression(cm) { 451 var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos); 452 if (tok.start < pos.ch && tok.type == "comment") return false; 453 return /[\w)\]]/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1)); 454 } 455 456 // Variable renaming 457 458 function rename(ts, cm) { 459 var token = cm.getTokenAt(cm.getCursor()); 460 if (!/\w/.test(token.string)) return showError(ts, cm, "Not at a variable"); 461 dialog(cm, "New name for " + token.string, function(newName) { 462 ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) { 463 if (error) return showError(ts, cm, error); 464 applyChanges(ts, data.changes); 465 }); 466 }); 467 } 468 469 function selectName(ts, cm) { 470 var name = findDoc(ts, cm.doc).name; 471 ts.request(cm, {type: "refs"}, function(error, data) { 472 if (error) return showError(ts, cm, error); 473 var ranges = [], cur = 0; 474 var curPos = cm.getCursor(); 475 for (var i = 0; i < data.refs.length; i++) { 476 var ref = data.refs[i]; 477 if (ref.file == name) { 478 ranges.push({anchor: ref.start, head: ref.end}); 479 if (cmpPos(curPos, ref.start) >= 0 && cmpPos(curPos, ref.end) <= 0) 480 cur = ranges.length - 1; 481 } 482 } 483 cm.setSelections(ranges, cur); 484 }); 485 } 486 487 var nextChangeOrig = 0; 488 function applyChanges(ts, changes) { 489 var perFile = Object.create(null); 490 for (var i = 0; i < changes.length; ++i) { 491 var ch = changes[i]; 492 (perFile[ch.file] || (perFile[ch.file] = [])).push(ch); 493 } 494 for (var file in perFile) { 495 var known = ts.docs[file], chs = perFile[file];; 496 if (!known) continue; 497 chs.sort(function(a, b) { return cmpPos(b.start, a.start); }); 498 var origin = "*rename" + (++nextChangeOrig); 499 for (var i = 0; i < chs.length; ++i) { 500 var ch = chs[i]; 501 known.doc.replaceRange(ch.text, ch.start, ch.end, origin); 502 } 503 } 504 } 505 506 // Generic request-building helper 507 508 function buildRequest(ts, doc, query, pos) { 509 var files = [], offsetLines = 0, allowFragments = !query.fullDocs; 510 if (!allowFragments) delete query.fullDocs; 511 if (typeof query == "string") query = {type: query}; 512 query.lineCharPositions = true; 513 if (query.end == null) { 514 query.end = pos || doc.doc.getCursor("end"); 515 if (doc.doc.somethingSelected()) 516 query.start = doc.doc.getCursor("start"); 517 } 518 var startPos = query.start || query.end; 519 520 if (doc.changed) { 521 if (doc.doc.lineCount() > bigDoc && allowFragments !== false && 522 doc.changed.to - doc.changed.from < 100 && 523 doc.changed.from <= startPos.line && doc.changed.to > query.end.line) { 524 files.push(getFragmentAround(doc, startPos, query.end)); 525 query.file = "#0"; 526 var offsetLines = files[0].offsetLines; 527 if (query.start != null) query.start = Pos(query.start.line - -offsetLines, query.start.ch); 528 query.end = Pos(query.end.line - offsetLines, query.end.ch); 529 } else { 530 files.push({type: "full", 531 name: doc.name, 532 text: docValue(ts, doc)}); 533 query.file = doc.name; 534 doc.changed = null; 535 } 536 } else { 537 query.file = doc.name; 538 } 539 for (var name in ts.docs) { 540 var cur = ts.docs[name]; 541 if (cur.changed && cur != doc) { 542 files.push({type: "full", name: cur.name, text: docValue(ts, cur)}); 543 cur.changed = null; 544 } 545 } 546 547 return {query: query, files: files}; 548 } 549 550 function getFragmentAround(data, start, end) { 551 var doc = data.doc; 552 var minIndent = null, minLine = null, endLine, tabSize = 4; 553 for (var p = start.line - 1, min = Math.max(0, p - 50); p >= min; --p) { 554 var line = doc.getLine(p), fn = line.search(/\bfunction\b/); 555 if (fn < 0) continue; 556 var indent = CodeMirror.countColumn(line, null, tabSize); 557 if (minIndent != null && minIndent <= indent) continue; 558 minIndent = indent; 559 minLine = p; 560 } 561 if (minLine == null) minLine = min; 562 var max = Math.min(doc.lastLine(), end.line + 20); 563 if (minIndent == null || minIndent == CodeMirror.countColumn(doc.getLine(start.line), null, tabSize)) 564 endLine = max; 565 else for (endLine = end.line + 1; endLine < max; ++endLine) { 566 var indent = CodeMirror.countColumn(doc.getLine(endLine), null, tabSize); 567 if (indent <= minIndent) break; 568 } 569 var from = Pos(minLine, 0); 570 571 return {type: "part", 572 name: data.name, 573 offsetLines: from.line, 574 text: doc.getRange(from, Pos(endLine, end.line == endLine ? null : 0))}; 575 } 576 577 // Generic utilities 578 579 var cmpPos = CodeMirror.cmpPos; 580 581 function elt(tagname, cls /*, ... elts*/) { 582 var e = document.createElement(tagname); 583 if (cls) e.className = cls; 584 for (var i = 2; i < arguments.length; ++i) { 585 var elt = arguments[i]; 586 if (typeof elt == "string") elt = document.createTextNode(elt); 587 e.appendChild(elt); 588 } 589 return e; 590 } 591 592 function dialog(cm, text, f) { 593 if (cm.openDialog) 594 cm.openDialog(text + ": <input type=text>", f); 595 else 596 f(prompt(text, "")); 597 } 598 599 // Tooltips 600 601 function tempTooltip(cm, content, ts) { 602 if (cm.state.ternTooltip) remove(cm.state.ternTooltip); 603 var where = cm.cursorCoords(); 604 var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content); 605 function maybeClear() { 606 old = true; 607 if (!mouseOnTip) clear(); 608 } 609 function clear() { 610 cm.state.ternTooltip = null; 611 if (tip.parentNode) fadeOut(tip) 612 clearActivity() 613 } 614 var mouseOnTip = false, old = false; 615 CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; }); 616 CodeMirror.on(tip, "mouseout", function(e) { 617 if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) { 618 if (old) clear(); 619 else mouseOnTip = false; 620 } 621 }); 622 setTimeout(maybeClear, ts.options.hintDelay ? ts.options.hintDelay : 1700); 623 var clearActivity = onEditorActivity(cm, clear) 624 } 625 626 function onEditorActivity(cm, f) { 627 cm.on("cursorActivity", f) 628 cm.on("blur", f) 629 cm.on("scroll", f) 630 cm.on("setDoc", f) 631 return function() { 632 cm.off("cursorActivity", f) 633 cm.off("blur", f) 634 cm.off("scroll", f) 635 cm.off("setDoc", f) 636 } 637 } 638 639 function makeTooltip(x, y, content) { 640 var node = elt("div", cls + "tooltip", content); 641 node.style.left = x + "px"; 642 node.style.top = y + "px"; 643 document.body.appendChild(node); 644 return node; 645 } 646 647 function remove(node) { 648 var p = node && node.parentNode; 649 if (p) p.removeChild(node); 650 } 651 652 function fadeOut(tooltip) { 653 tooltip.style.opacity = "0"; 654 setTimeout(function() { remove(tooltip); }, 1100); 655 } 656 657 function showError(ts, cm, msg) { 658 if (ts.options.showError) 659 ts.options.showError(cm, msg); 660 else 661 tempTooltip(cm, String(msg), ts); 662 } 663 664 function closeArgHints(ts) { 665 if (ts.activeArgHints) { 666 if (ts.activeArgHints.clear) ts.activeArgHints.clear() 667 remove(ts.activeArgHints) 668 ts.activeArgHints = null 669 } 670 } 671 672 function docValue(ts, doc) { 673 var val = doc.doc.getValue(); 674 if (ts.options.fileFilter) val = ts.options.fileFilter(val, doc.name, doc.doc); 675 return val; 676 } 677 678 // Worker wrapper 679 680 function WorkerServer(ts) { 681 var worker = ts.worker = new Worker(ts.options.workerScript); 682 worker.postMessage({type: "init", 683 defs: ts.options.defs, 684 plugins: ts.options.plugins, 685 scripts: ts.options.workerDeps}); 686 var msgId = 0, pending = {}; 687 688 function send(data, c) { 689 if (c) { 690 data.id = ++msgId; 691 pending[msgId] = c; 692 } 693 worker.postMessage(data); 694 } 695 worker.onmessage = function(e) { 696 var data = e.data; 697 if (data.type == "getFile") { 698 getFile(ts, data.name, function(err, text) { 699 send({type: "getFile", err: String(err), text: text, id: data.id}); 700 }); 701 } else if (data.type == "debug") { 702 window.console.log(data.message); 703 } else if (data.id && pending[data.id]) { 704 pending[data.id](data.err, data.body); 705 delete pending[data.id]; 706 } 707 }; 708 worker.onerror = function(e) { 709 for (var id in pending) pending[id](e); 710 pending = {}; 711 }; 712 713 this.addFile = function(name, text) { send({type: "add", name: name, text: text}); }; 714 this.delFile = function(name) { send({type: "del", name: name}); }; 715 this.request = function(body, c) { send({type: "req", body: body}, c); }; 716 } 717 });
Downloadmodules/editor/codemirror/addon/tern/tern.min.js
History Tue, 22 May 2018 22:39:53 +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'.