177 lines
5.4 KiB
JavaScript
177 lines
5.4 KiB
JavaScript
define("xace/views/_AceMultiDocs", [
|
|
"dcl/dcl",
|
|
"xdojo/declare",
|
|
"module",
|
|
"xace/base_handler",
|
|
"xace/complete_util"
|
|
],function (dcl,declare,module,baseLanguageHandler,completeUtil){
|
|
|
|
var analysisCache = {}; // path => {identifier: 3, ...}
|
|
var globalWordIndex = {}; // word => frequency
|
|
var globalWordFiles = {}; // word => [path]
|
|
var precachedPath;
|
|
var precachedDoc;
|
|
|
|
var completer = module.exports = Object.create(baseLanguageHandler);
|
|
|
|
completer.handlesLanguage = function(language) {
|
|
return true;
|
|
};
|
|
|
|
completer.handlesEditor = function() {
|
|
return this.HANDLES_ANY;
|
|
};
|
|
|
|
completer.getMaxFileSizeSupported = function() {
|
|
return 1000 * 1000;
|
|
};
|
|
|
|
function frequencyAnalyzer(path, text, identDict, fileDict) {
|
|
var identifiers = text.split(/[^a-zA-Z_0-9\$]+/);
|
|
for (var i = 0; i < identifiers.length; i++) {
|
|
var ident = identifiers[i];
|
|
if (!ident)
|
|
continue;
|
|
|
|
if (Object.prototype.hasOwnProperty.call(identDict, ident)) {
|
|
identDict[ident]++;
|
|
fileDict[ident][path] = true;
|
|
}
|
|
else {
|
|
identDict[ident] = 1;
|
|
fileDict[ident] = {};
|
|
fileDict[ident][path] = true;
|
|
}
|
|
}
|
|
return identDict;
|
|
}
|
|
|
|
function removeDocumentFromCache(path) {
|
|
var analysis = analysisCache[path];
|
|
if (!analysis) return;
|
|
|
|
for (var id in analysis) {
|
|
globalWordIndex[id] -= analysis[id];
|
|
delete globalWordFiles[id][path];
|
|
if (globalWordIndex[id] === 0) {
|
|
delete globalWordIndex[id];
|
|
delete globalWordFiles[id];
|
|
}
|
|
}
|
|
delete analysisCache[path];
|
|
}
|
|
|
|
function analyzeDocument(path, allCode) {
|
|
if (!analysisCache[path]) {
|
|
if (allCode.size > 80 * 10000) {
|
|
delete analysisCache[path];
|
|
return;
|
|
}
|
|
// Delay this slightly, because in Firefox document.value is not immediately filled
|
|
analysisCache[path] = frequencyAnalyzer(path, allCode, {}, {});
|
|
// may be a bit redundant to do this twice, but alright...
|
|
frequencyAnalyzer(path, allCode, globalWordIndex, globalWordFiles);
|
|
}
|
|
}
|
|
|
|
completer.onDocumentOpen = function(path, doc, oldPath, callback) {
|
|
if (!analysisCache[path]) {
|
|
analyzeDocument(path, doc.getValue());
|
|
}
|
|
callback();
|
|
};
|
|
|
|
completer.addDocument = function(path, value) {
|
|
if (!analysisCache[path]) {
|
|
analyzeDocument(path, value);
|
|
}
|
|
|
|
};
|
|
|
|
completer.onDocumentClose = function(path, callback) {
|
|
removeDocumentFromCache(path);
|
|
if (path == precachedPath)
|
|
precachedDoc = null;
|
|
callback();
|
|
};
|
|
|
|
completer.analyze = function(doc, ast, callback, minimalAnalysis) {
|
|
if (precachedDoc && this.path !== precachedPath) {
|
|
removeDocumentFromCache(precachedPath);
|
|
analyzeDocument(precachedPath, precachedDoc);
|
|
precachedDoc = null;
|
|
}
|
|
precachedPath = this.path;
|
|
precachedDoc = doc;
|
|
callback();
|
|
};
|
|
|
|
completer.complete = function(editor, fullAst, pos, currentNode, callback) {
|
|
|
|
var doc = editor.getSession();
|
|
var line = doc.getLine(pos.row);
|
|
var identifier = completeUtil.retrievePrecedingIdentifier(line, pos.column, this.$getIdentifierRegex());
|
|
var identDict = globalWordIndex;
|
|
|
|
var allIdentifiers = [];
|
|
for (var ident in identDict) {
|
|
allIdentifiers.push(ident);
|
|
}
|
|
var matches = completeUtil.findCompletions(identifier, allIdentifiers);
|
|
|
|
var currentPath = this.path;
|
|
matches = matches.filter(function(m) {
|
|
return !globalWordFiles[m][currentPath];
|
|
});
|
|
|
|
matches = matches.slice(0, 100); // limits results for performance
|
|
|
|
callback(matches.filter(function(m) {
|
|
return !m.match(/^[0-9$_\/]/);
|
|
}).map(function(m) {
|
|
var path = Object.keys(globalWordFiles[m])[0] || "[unknown]";
|
|
var pathParts = path.split("/");
|
|
var foundInFile = pathParts[pathParts.length-1];
|
|
return {
|
|
name: m,
|
|
value: m,
|
|
icon: null,
|
|
score: identDict[m],
|
|
meta: foundInFile,
|
|
priority: 0,
|
|
isGeneric: true
|
|
};
|
|
}));
|
|
};
|
|
|
|
completer.getCompletions=function (editor, session, pos, prefix, callback) {
|
|
var completions = null;
|
|
var _c = function(_completions){
|
|
completions = _completions;
|
|
};
|
|
completer.complete(editor,null,pos,null,_c);
|
|
callback(null,completions);
|
|
};
|
|
|
|
var Module = dcl(null,{
|
|
|
|
declaredClass:"xide.views._AceMultiDocs",
|
|
didAddMCompleter:false,
|
|
multiFileCompleter:null,
|
|
addFileCompleter:function(){
|
|
var compl = null;
|
|
if(!this.didAddMCompleter) {
|
|
compl = completer;
|
|
this.multiFileCompleter= compl;
|
|
var langTools = ace.require("ace/ext/language_tools");
|
|
langTools.addCompleter(compl);
|
|
this.didAddMCompleter=true;
|
|
}
|
|
return compl;
|
|
}
|
|
});
|
|
|
|
Module.completer = completer;
|
|
|
|
return Module;
|
|
}); |