Arquivos
deepforge/src/visualizers/panels/ClassCodeEditor/ClassCodeEditorControl.js
T

150 linhas
4.8 KiB
JavaScript

/*globals define */
/*jshint browser: true*/
define([
'panels/TextEditor/TextEditorControl',
'deepforge/lua',
'underscore',
'text!./DefaultCodeTemplate.ejs'
], function (
TextEditorControl,
lua,
_,
CODE_TEMPLATE
) {
'use strict';
var ClassCodeEditorControl,
getBoilerplate = _.template(CODE_TEMPLATE);
ClassCodeEditorControl = function (options) {
options.attributeName = 'code';
TextEditorControl.call(this, options);
};
_.extend(
ClassCodeEditorControl.prototype,
TextEditorControl.prototype
);
// input/output updates are actually activeNode updates
ClassCodeEditorControl.prototype._onUpdate = function (id) {
if (id === this._currentNodeId) {
TextEditorControl.prototype._onUpdate.call(this, id);
}
};
ClassCodeEditorControl.prototype._getObjectDescriptor = function (nodeId) {
var desc = TextEditorControl.prototype._getObjectDescriptor.call(this, nodeId),
node = this._client.getNode(nodeId),
ownCode = node.getOwnAttribute(this.ATTRIBUTE_NAME);
// If the 'text' attribute is not set, and it's not inheriting anything
if (!desc.text && ownCode === undefined) {
desc.text = getBoilerplate(desc);
}
return desc;
};
ClassCodeEditorControl.prototype.saveTextFor = function (id, text) {
// On save, update the node's name
// For now, simply use regex to grab the returned name
var i = text.lastIndexOf('return') + 7,
returned = text.substring(i),
match = returned.match(/[a-zA-Z0-9_]+/),
node = this._client.getNode(id),
nodeName = node.getAttribute('name'),
baseName = null,
basePath,
name,
ast;
if (match) {
name = match[0];
}
// Check if the base needs to be updated
try {
ast = lua.parser.parse(text);
lua.codegen.traverse(curr => {
// Check for inheritance of the given type
if (curr.type === 'expr.call') {
var object = curr.func.self.val,
method = curr.func.key.val,
child,
base;
if (object === 'torch' && method === 'class') {
child = curr.args[0];
base = curr.args[1];
// If the first argument is the given class, get the base
if (child.type === 'const.string' && child.val === name) {
if (base && base.type === 'const.string') {
baseName = base.val;
}
}
}
}
})(ast);
// Get the base path from the base name
basePath = this.getBasePathFromName(baseName);
if (!basePath) {
this._logger.warn(`Could not find base type matching the name ${baseName}`);
}
} catch(e) {
this._logger.warn(`Invalid lua code. Parser failed: ${e}`);
}
this._client.startTransaction(`Updating class "${name || nodeName}"`);
if (name) {
this._client.setAttributes(id, 'name', name);
}
if (basePath) {
this._client.setBase(id, basePath);
} else { // Set base back to 'Complex'
while (node && (node.getAttribute('name') !== 'Complex' ||
node.isAbstract() !== true)) {
node = this._client.getNode(node.getBaseId());
}
if (node) { // node is the base class type
this._client.setBase(id, node.getId());
} else {
this._logger.warn(`Could not find the base class type from ${id}`);
}
}
TextEditorControl.prototype.saveTextFor.call(this, id, text, true);
this._client.completeTransaction();
};
ClassCodeEditorControl.prototype.getBasePathFromName = function (baseName) {
var metanodes = this._client.getAllMetaNodes(),
nameMatches = [],
classNode,
i;
for (i = metanodes.length; i--;) {
if (metanodes[i].getAttribute('name') === baseName) {
nameMatches.push(metanodes[i]);
}
if (metanodes[i].getAttribute('name') === 'Complex') {
classNode = metanodes[i];
}
}
for (i = nameMatches.length; i--;) {
if (this._client.isTypeOf(nameMatches[i].getId(), classNode.getId())) {
return nameMatches[i].getId();
}
}
return null;
};
return ClassCodeEditorControl;
});