js.ide.codebase.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of DevCenter Show documentation
Show all versions of DevCenter Show documentation
Prompto Development Center POM
var isNodeJs = typeof window === 'undefined' && typeof importScripts === 'undefined';
var prompto = prompto;
if(typeof prompto === 'undefined') {
prompto = isNodeJs ?
require("../../../../prompto-javascript/JavaScript-Core/src/test/prompto/parser/PromptoLoader").prompto :
require('prompto/index');
}
/* a function for inferring dialect from file extension */
function inferDialect(path) {
return path.substring(path.length-2, path.length-1).toUpperCase();
}
/* a function for parsing prompto code into declarations */
function parse(input, dialect, listener) {
var klass = prompto.parser[dialect + "CleverParser"];
var parser = new klass(input);
parser.removeErrorListeners();
if(listener)
parser.addErrorListener(listener);
return parser.parse();
}
/* a function for producing code from a declaration object */
function unparse(context, decl, dialect) {
var d = prompto.parser.Dialect[dialect];
var writer = new prompto.utils.CodeWriter(d, context.newChildContext());
if(decl.comments) {
decl.comments.forEach(function (cmt) {
cmt.toDialect(writer);
});
}
decl.toDialect(writer);
return writer.toString();
}
/* a function for translating current input to other dialect */
function translate(context, data, from, to) {
var decls = parse(data, from); // could be cached
var dialect = prompto.parser.Dialect[to];
var writer = new prompto.utils.CodeWriter(dialect, context.newChildContext());
decls.toDialect(writer);
return writer.toString();
}
/* a utility function to sort by field name */
function sortBy(a, f) {
return a.sort(function(i1,i2) {
return (i1[f]>i2[f]) ? 1 : ((i1[f]0;
});
};
/**
* An object which represents the delta between 2 catalogs
* The purpose of this class is to minimize the re-processing in the IDE
* when code is updated. Typically, various scenarios can occur:
* - code body change, this has not impact on the catalog
* - declaration removed
* - declaration added
* - declarations changed, which for global methods adds complexity because
* methods are displayed differently depending on their number of prototypes
* The below code is not optimized. The optimization is to only redisplay what is needed,
* not to optimize the calculation of what needs to be redisplayed.
* This follows the assumption that the number of overloads for a method name is generally very low (< 10).
*/
function Delta() {
this.removed = null;
this.added = null;
return this;
}
Delta.prototype.length = function() {
var length = 0;
if(this.removed)
length += this.removed.length();
if(this.added)
length += this.added.length();
return length;
};
Delta.prototype.getContent = function() {
return { removed : this.removed, added : this.added };
};
Delta.prototype.filterOutDuplicates = function() {
if(!this.removed && !this.added)
return 0;
if(!this.removed)
return this.added.length();
if(!this.added)
return this.removed.length();
var length = this.filterOutDuplicatesInField("attributes");
length += this.filterOutDuplicatesInField("methods");
length += this.filterOutDuplicatesInField("categories");
length += this.filterOutDuplicatesInField("enumerations");
length += this.filterOutDuplicatesInField("tests");
return length;
};
Delta.prototype.filterOutDuplicatesInField = function(field) {
var fn = field==="methods" ? this.filterOutDuplicatesInMethods : this.filterOutDuplicatesInLists;
var length = fn.bind(this)(this.removed[field], this.added[field]);
if(this.removed[field] && !this.removed[field].length)
delete this.removed[field];
if(this.added[field] && !this.added[field].length)
delete this.added[field];
return length;
};
Delta.prototype.filterOutDuplicatesInLists = function(a, b, field) {
if(a && b) {
if(field) {
sortBy(a, field);
sortBy(b, field);
} else {
a.sort();
b.sort();
}
for(var i=0,j=0;ivb) {
j++;
} else {
i++;
}
}
return a.length + b.length;
} else if(a)
return a.length;
else if(b)
return b.length;
else
return 0;
};
Delta.prototype.filterOutDuplicatesInMethods = function(a, b) {
if(a && b) {
sortBy(a, "name");
sortBy(b, "name");
for(var i=0,j=0;ib[j].name) {
j++;
} else {
i++;
}
}
return a.length + b.length;
} else if(a)
return a.length;
else if(b)
return b.length;
else
return 0;
};
Delta.prototype.adjustForMovingProtos = function(context) {
// methods with 1 proto are displayed differently than methods with multiple protos
// if proto cardinality changes from N to 1 or 1 to N, we need to rebuild the corresponding displays
if (this.removed && this.removed.methods) {
this.removed.methods.map(function (method) {
var decl = context.getRegisteredDeclaration(method.name);
if (decl && Object.keys(decl.protos).length === 1) // moved from N to 1
this.adjustMethodForRemovedProtos(method, decl);
}, this);
}
if (this.added && this.added.methods) {
this.added.methods.map(function (method) {
var decl = context.getRegisteredDeclaration(method.name);
if (decl && Object.keys(decl.protos).length - method.protos.length === 1) // moved from 1 to N
this.adjustMethodForAddedProtos(method, decl);
}, this);
}
// cleanup
if (this.removed && this.removed.methods) {
this.removed.methods.map(function (method) {
if(method.proto_to_remove) {
method.protos.push(method.proto_to_remove);
sortBy(method.protos, "proto");
delete method.proto_to_remove;
}
});
}
if (this.added && this.added.methods) {
this.added.methods.map(function (method) {
if(method.proto_to_add) {
method.protos.push(method.proto_to_add);
sortBy(method.protos, "proto");
delete method.proto_to_add;
}
});
}
};
Delta.prototype.adjustMethodForAddedProtos = function(method, decl)
{
var proto = this.findPreExistingProto(method, decl);
if(proto) {
var main = decl.protos[proto].isEligibleAsMain();
var proto_to_move = {proto: proto, main: main};
// add it to the remove list
if(!this.removed)
this.removed = new Catalog();
var removed = this.findOrCreateMethod(this.removed, method.name);
removed.proto_to_remove = proto_to_move;
// add it to the add list
method.proto_to_add = proto_to_move;
}
};
Delta.prototype.findPreExistingProto = function(method, decl) {
for(var proto in decl.protos) {
if(decl.protos.hasOwnProperty(proto)) {
var found = false;
for (var i = 0; !found && i < method.protos.length; i++) {
found = proto === method.protos[i].proto;
}
if (!found)
return proto;
}
}
return null; // TODO throw error?
};
Delta.prototype.adjustMethodForRemovedProtos = function(method, decl) {
// the below will only loop once
for (var proto in decl.protos) {
if (decl.protos.hasOwnProperty(proto)) {
this.adjustMethodForRemovedProto(method, decl, proto);
}
}
};
Delta.prototype.adjustMethodForRemovedProto = function(method, decl, proto) {
var main = decl.protos[proto].isEligibleAsMain();
var proto_to_move = { proto: proto, main: main };
// add it to the remove list
method.proto_to_remove = proto_to_move;
// add it to the added list
if(!this.added)
this.added = new Catalog();
var added = this.findOrCreateMethod(this.added, decl.name);
// avoid adding it twice (it might have just been added)
added.protos.map(function (current) {
if (proto_to_move && proto_to_move.proto === current.proto)
proto_to_move = null; // don't add it
});
// not an existing proto ?
if (proto_to_move)
added.proto_to_add = proto_to_move;
};
Delta.prototype.findOrCreateMethod = function(catalog, name) {
if(!catalog.methods)
catalog.methods = [];
for(var i=0;i