Skip to content

Commit a9c1aab

Browse files
committed
added and refined Transitions to plugin explorer
SQUASHED: AUTO-COMMIT-src-components-tools-lively-plugin-explorer.html,AUTO-COMMIT-src-components-tools-lively-plugin-explorer.js,AUTO-COMMIT-src-components-tools-lively-plugin-explorer-playground.js,AUTO-COMMIT-src-external-babel-plugin-locals.js,AUTO-COMMIT-src-external-babel-plugin-transform-react-jsx.js,
1 parent 25bba36 commit a9c1aab

File tree

6 files changed

+191
-25122
lines changed

6 files changed

+191
-25122
lines changed

src/components/tools/lively-plugin-explorer-playground.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export default function (babel) {
33
return {
44
name: "underscore-decorator",
55
visitor: {
6-
/*FunctionDeclaration(path) {
6+
FunctionDeclaration(path) {
77
const nameParts = path.node.id.name.split('_');
88
if (nameParts.length < 2) {
99
return;
@@ -12,7 +12,7 @@ export default function (babel) {
1212

1313
for (const id of nameParts.slice(0, -1).reverse()) {
1414
body = t.callExpression(
15-
t.identifier(id),
15+
t.identifiers(id),
1616
[t.arrowFunctionExpression([], body)])
1717
}
1818

@@ -24,7 +24,11 @@ export default function (babel) {
2424
path.replaceWith(fun);
2525
// not exactly what I want as this does not decorate function declared in the current function
2626
path.stop();
27-
}*/
27+
},
28+
29+
ReturnStatement(path) {
30+
// debugger
31+
}
2832
}
2933
};
3034
}

src/components/tools/lively-plugin-explorer.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@
181181
<div id="bottom" class="pane layout-row">
182182
<div id="tracePane" class="pane tool layout-column">
183183
<b>Transformation Trace</b>
184-
<div class="pane"></div>
184+
<div id="buttonPane" class="pane"></div>
185185
</div>
186186
<lively-separator reverse=true></lively-separator>
187187
<div id="console" class="pane tool layout-column">

src/components/tools/lively-plugin-explorer.js

Lines changed: 129 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -15,67 +15,87 @@ function babelVisitorWrapper(key, nodeType, visitor) {
1515
}
1616

1717
class Transitions {
18-
constructor() {
19-
this._transitions = [];
20-
this.savedTransitions = [];
21-
}
22-
23-
_getProgramParent(path) {
24-
let parent = path;
25-
do {
26-
if (parent.isProgram()) return parent;
27-
} while ((parent = parent.parentPath));
28-
};
29-
30-
getValue() {
31-
return this._transitions;
32-
};
33-
34-
addExitTransition(code) {
35-
this._transitions.push({
36-
code,
37-
pluginAlias: "output",
38-
visitorType: "exit",
39-
size: new Blob([code], { type: "text/plain" }).size,
40-
});
41-
};
42-
43-
wrapPluginVisitorMethod(pluginAlias, visitorType, callback) {
44-
return (...args) => {
45-
// const { code } = generate(this._getProgramParent(args[0]).node);
46-
this.savedTransitions.push({
47-
node: _.cloneDeep(args[0].node),
48-
parent: _.cloneDeep(this._getProgramParent(args[0]).node),
49-
alias: pluginAlias,
50-
type: visitorType
18+
constructor() {
19+
this._transitions = [];
20+
this.savedTransitions = [];
21+
this.selectionTookPlace = false;
22+
this.errorState = null;
23+
}
24+
25+
_getProgramParent(path) {
26+
let parent = path;
27+
do {
28+
if (parent.isProgram()) return parent;
29+
} while ((parent = parent.parentPath));
30+
};
31+
32+
getValue() {
33+
return this._transitions;
34+
};
35+
36+
addEntryTransition(code) {
37+
this._transitions.push({
38+
code,
39+
alias: "Original",
40+
type: "entry",
41+
size: new Blob([code], { type: "text/plain" }).size
5142
})
52-
/*
53-
if (this._transitions.length === 0 || this._transitions[this._transitions.length - 1].code !== code
54-
) {
43+
}
44+
45+
addExitTransition(code) {
5546
this._transitions.push({
56-
code,
57-
pluginAlias,
58-
visitorType,
59-
currentNode: args[0].node.type,
60-
size: new Blob([code], { type: "text/plain" }).size,
47+
code,
48+
alias: "output",
49+
type: "exit",
50+
size: new Blob([code], { type: "text/plain" }).size,
6151
});
62-
}*/
63-
callback.call(this, ...args);
6452
};
65-
};
66-
67-
transform() {
68-
for(const transition of this.savedTransitions) {
69-
const {code} = babel.transformFromAst(transition.parent);
70-
if (this._transitions.length === 0 || this._transitions[this._transitions.length - 1].code !== code) {
53+
54+
wrapPluginVisitorMethod(pluginAlias, visitorType, callback) {
55+
return (...args) => {
56+
try {
57+
callback.call(this, ...args);
58+
59+
this.savedTransitions.push({
60+
node: _.cloneDeep(args[0].node),
61+
parent: _.cloneDeep(this._getProgramParent(args[0]).node),
62+
alias: pluginAlias,
63+
type: visitorType,
64+
})
65+
} catch(e) {
66+
this.errorState = {
67+
error: e,
68+
alias: pluginAlias,
69+
type: visitorType
70+
};
71+
// still want the normal error handling of the plugin explorer
72+
throw e;
73+
}
74+
};
75+
};
76+
77+
selectTransitionsIfNecessary() {
78+
if (!this.selectionTookPlace) {
79+
for (const transition of this.savedTransitions) {
80+
const { code } = babel.transformFromAst(transition.parent);
81+
if (this._transitions.length === 0 || this._transitions[this._transitions.length - 1].code !== code) {
82+
this._transitions.push({
83+
code,
84+
alias: transition.alias,
85+
type: transition.type,
86+
currentNode: transition.node.type,
87+
size: new Blob([code], { type: "text/plain" }).size,
88+
});
89+
}
90+
}
91+
if (this.errorState !== null) {
7192
this._transitions.push({
72-
code,
73-
alias: transition.alias,
74-
type: transition.type,
75-
currentNode: transition.node.type,
76-
size: new Blob([code], { type: "text/plain" }).size,
77-
});
78-
}
93+
code: this.errorState.error.stack,
94+
alias: this.errorState.alias,
95+
type: this.errorState.type
96+
})
97+
}
98+
this.selectionTookPlace = true;
7999
}
80100
}
81101
}
@@ -405,9 +425,40 @@ export default class PluginExplorer extends Morph {
405425
}
406426
}
407427

428+
replaceButtonsWith(buttons) {
429+
const pane = this.get('#buttonPane');
430+
pane.innerHTML = '';
431+
for (const button of buttons) {
432+
pane.appendChild(button);
433+
}
434+
}
435+
436+
updateAndExecute(code) {
437+
this.transformedSourceLCM.value = code;
438+
439+
if (this.autoExecute) this.execute();
440+
if (this.autoRunTests) runTests();
441+
}
442+
443+
setTransitionButtons(transitions) {
444+
this.replaceButtonsWith(transitions.getValue().map((transition, index) => {
445+
const button = document.createElement('button');
446+
button.innerText = `${index}: ${transition.alias}`;
447+
button.addEventListener('click', e => {
448+
// transition.inspect()
449+
this.updateAndExecute(transition.code);
450+
});
451+
button.addEventListener('mouseover', e => {
452+
this.updateAndExecute(transition.code);
453+
});
454+
return button;
455+
}))
456+
}
457+
408458
async updateTransformation(ast) {
409459
const plugin = await this.getPlugin();
410460
let transitions = new Transitions();
461+
transitions.addEntryTransition(this.sourceText);
411462

412463
try {
413464
console.group("PLUGIN TRANSFORMATION");
@@ -432,20 +483,26 @@ export default class PluginExplorer extends Morph {
432483
config.wrapPluginVisitorMethod = transitions.wrapPluginVisitorMethod.bind(transitions);
433484
this.transformationResult = babel.transform(this.sourceText, config);
434485
} else {
435-
this.transformationResult = ast.transformAsAST(plugin, {wrapPluginVisitorMethod: transitions.wrapPluginVisitorMethod.bind(transitions)});
486+
this.transformationResult = ast.transformAsAST(plugin, {
487+
wrapPluginVisitorMethod: transitions.wrapPluginVisitorMethod
488+
.bind(transitions)
489+
});
436490
}
437491

438-
this.transformedSourceLCM.value = this.transformationResult.code;
439-
transitions.addExitTransition(this.transformationResult.code);
492+
// Todo: find in original code how to use
493+
// transitions.addExitTransition(this.transformationResult.code);
494+
495+
this.updateAndExecute(this.transformationResult.code);
440496

441-
if (this.autoExecute) this.execute();
442-
if (this.autoRunTests) runTests();
443-
} catch (err) {
444-
console.error(err);
445-
this.transformedSourceLCM.value = "Error: " + err.message;
497+
transitions.selectTransitionsIfNecessary();
498+
transitions.addExitTransition(this.transformationResult.code);
499+
} catch (e) {
500+
console.error(e);
501+
this.transformedSourceLCM.value = e.stack;
446502
} finally {
447503
console.groupEnd();
448-
transitions.inspect();
504+
transitions.selectTransitionsIfNecessary();
505+
this.setTransitionButtons(transitions);
449506
}
450507
}
451508

@@ -482,7 +539,7 @@ export default class PluginExplorer extends Morph {
482539
this.executionConsole.textContent += "-> " + result;
483540
} catch (e) {
484541
console.error(e);
485-
this.executionConsole.textContent += "Error: " + e
542+
this.executionConsole.textContent += "Error: " + e;
486543
} finally {
487544
console.log = oldLog
488545
console.groupEnd();
@@ -526,8 +583,11 @@ export default class PluginExplorer extends Morph {
526583
//lively.notify(`start ${range.anchor.line} ch ${range.anchor.ch} -> ${start.line} ch ${start.column} / end ${range.head.line} ch ${range.head.ch} -> ${end.line} c ${end.column}`)
527584
if (!start || !end) return;
528585

529-
toTextEditor.setSelection({ line: start.line - 1, ch: start.column - 1 }, { line: end.line - 1, ch: end.column -
530-
1 })
586+
toTextEditor.setSelection({ line: start.line - 1, ch: start.column - 1 }, {
587+
line: end.line - 1,
588+
ch: end.column -
589+
1
590+
})
531591
}
532592

533593
onSourceSelectionChanged(evt) {
@@ -559,7 +619,7 @@ export default class PluginExplorer extends Morph {
559619
this.addEventListener("initialize", () => {
560620
this.loadWorkspace(other.workspace);
561621
this.sourceCM.setValue(other.sourceText);
562-
this.transformedSourceCM.setValue(other.transformedSourceCM.getValue());
622+
this.transformedSourceCM.setValue(other.transformedSourceCM.getValue());
563623
this.transformationResult = other.transformationResult;
564624
this.runsTests = other.runTests;
565625
this.updateAST();

0 commit comments

Comments
 (0)