Refactoring script vars and upvars, plus some enhancements

pull/29/head
Bernat Romagosa 2016-12-29 12:19:45 +01:00
rodzic a179d3acf8
commit ce052a8dd5
2 zmienionych plików z 50 dodań i 27 usunięć

Wyświetl plik

@ -663,10 +663,12 @@ SyntaxElementMorph.prototype.getVarNamesDict = function () {
// Variable refactoring // Variable refactoring
SyntaxElementMorph.prototype.refactorVarInStack = function (oldName, newName) { SyntaxElementMorph.prototype.refactorVarInStack = function (oldName, newName, isScriptVar) {
// Rename all oldName var occurrences found in this block stack into newName
// taking care of not being too greedy
if (this instanceof RingMorph if (this instanceof RingMorph
|| (this.selector === 'doDeclareVariables' || (!isScriptVar && this.definesScriptVariable(oldName))) {
&& this.definesScriptVariable(oldName))) {
return; return;
} }
@ -682,7 +684,9 @@ SyntaxElementMorph.prototype.refactorVarInStack = function (oldName, newName) {
this.setContents(newName); this.setContents(newName);
} }
if (this instanceof CustomCommandBlockMorph) { if (this instanceof CustomCommandBlockMorph
&& this.definition.body
&& !contains(this.definition.variableNames, oldName)) {
this.definition.body.expression.refactorVarInStack(oldName, newName); this.definition.body.expression.refactorVarInStack(oldName, newName);
} }
@ -698,6 +702,17 @@ SyntaxElementMorph.prototype.refactorVarInStack = function (oldName, newName) {
} }
}; };
SyntaxElementMorph.prototype.definesScriptVariable = function (name) {
// Returns true if this block is defining either a script local var or
// an upVar called `name`
return ((this.selector === 'doDeclareVariables'
|| (this.blockSpec && this.blockSpec.match('%upvar')))
&& (detect(this.inputs()[0].allInputs(), function (input) {
return (input.selector === 'reportGetVar'
&& input.blockSpec === name)
})));
};
// SyntaxElementMorph drag & drop: // SyntaxElementMorph drag & drop:
SyntaxElementMorph.prototype.reactToGrabOf = function (grabbedMorph) { SyntaxElementMorph.prototype.reactToGrabOf = function (grabbedMorph) {
@ -2369,13 +2384,13 @@ BlockMorph.prototype.userMenu = function () {
'mapToCode' 'mapToCode'
); );
} }
if (this.selector === 'reportGetVar') { }
menu.addLine(); if (this.selector === 'reportGetVar') {
menu.addItem( menu.addLine();
'rename all occurrences...', menu.addItem(
'refactorThisVar' 'rename all occurrences...',
); 'refactorThisVar'
} );
} }
return menu; return menu;
} }
@ -2386,7 +2401,7 @@ BlockMorph.prototype.userMenu = function () {
blck = this.fullCopy(); blck = this.fullCopy();
blck.addShadow(); blck.addShadow();
menu.addItem( menu.addItem(
'rename...', 'rename just here...',
function () { function () {
new DialogBoxMorph( new DialogBoxMorph(
myself, myself,
@ -3048,27 +3063,34 @@ BlockMorph.prototype.codeMappingHeader = function () {
// Variable refactoring // Variable refactoring
BlockMorph.prototype.refactorThisVar = function () { BlockMorph.prototype.refactorThisVar = function () {
// Rename all occurrences of the variable this block is holding, taking care of its
// lexical scope
var oldName = this.blockSpec, var oldName = this.blockSpec,
receiver = this.receiver(), receiver = this.receiver(),
ide = this.parentThatIsA(IDE_Morph), ide = this.parentThatIsA(IDE_Morph),
oldValue, stage; stage = receiver.parentThatIsA(StageMorph),
oldWatcher = receiver.findVariableWatcher(oldName),
oldValue, newWatcher;
new DialogBoxMorph( new DialogBoxMorph(
this, this,
function (newName) { function (newName) {
if (receiver.hasSpriteVariable(oldName)) { if (this.parent instanceof SyntaxElementMorph) {
// script var
this.parentThatIsA(CommandBlockMorph).refactorVarInStack(oldName, newName, true);
} else if (receiver.hasSpriteVariable(oldName)) {
// sprite local var // sprite local var
receiver.refactorVariableInstances(oldName, newName, false); receiver.refactorVariableInstances(oldName, newName, false);
receiver.toggleVariableWatcher(newName, false); receiver.customBlocks.forEach(function (eachBlock) {
eachBlock.definition.body.expression.refactorVarInStack(oldName, newName);
});
} else { } else {
// global var // global var
stage = receiver.parentThatIsA(StageMorph);
oldValue = ide.globalVariables.vars[oldName]; oldValue = ide.globalVariables.vars[oldName];
stage.deleteVariable(oldName); stage.deleteVariable(oldName);
stage.addVariable(newName, true); stage.addVariable(newName, true);
ide.globalVariables.vars[newName] = oldValue; ide.globalVariables.vars[newName] = oldValue;
stage.toggleVariableWatcher(newName, true);
stage.refactorVariableInstances(oldName, newName, true); stage.refactorVariableInstances(oldName, newName, true);
stage.forAllChildren(function (child) { stage.forAllChildren(function (child) {
@ -3077,12 +3099,18 @@ BlockMorph.prototype.refactorThisVar = function () {
} }
}); });
} }
if (oldWatcher && oldWatcher.isVisible) {
newWatcher = stage.toggleVariableWatcher(newName, true);
newWatcher.setPosition(oldWatcher.position());
}
ide.flushBlocksCache('variables'); ide.flushBlocksCache('variables');
ide.refreshPalette(); ide.refreshPalette();
}, },
this this
).prompt( ).prompt(
"Variable name", 'Variable name',
oldName, oldName,
this.world(), this.world(),
this.fullImage(), // pic this.fullImage(), // pic
@ -3090,14 +3118,6 @@ BlockMorph.prototype.refactorThisVar = function () {
); );
}; };
BlockMorph.prototype.definesScriptVariable = function (name) {
return (this.selector === 'doDeclareVariables'
&& detect(this.inputs()[0].allInputs(), function (input) {
return (input.selector === 'reportGetVar'
&& input.blockSpec === name)
}));
};
// BlockMorph drawing // BlockMorph drawing
BlockMorph.prototype.eraseHoles = function (context) { BlockMorph.prototype.eraseHoles = function (context) {

Wyświetl plik

@ -4423,6 +4423,7 @@ SpriteMorph.prototype.toggleVariableWatcher = function (varName, isGlobal) {
stage.add(watcher); stage.add(watcher);
watcher.fixLayout(); watcher.fixLayout();
watcher.keepWithin(stage); watcher.keepWithin(stage);
return watcher;
}; };
SpriteMorph.prototype.showingVariableWatcher = function (varName) { SpriteMorph.prototype.showingVariableWatcher = function (varName) {
@ -4829,6 +4830,8 @@ SpriteMorph.prototype.hasSpriteVariable = function (varName) {
return contains(this.variables.names(), varName); return contains(this.variables.names(), varName);
}; };
// Variable refactoring
SpriteMorph.prototype.refactorVariableInstances = function (oldName, newName, isGlobal) { SpriteMorph.prototype.refactorVariableInstances = function (oldName, newName, isGlobal) {
var oldValue; var oldValue;