-
Notifications
You must be signed in to change notification settings - Fork 585
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Teacher Tool: Variable Usage Validator (#9994)
This adds a new validator which can check if variables are both defined and used. The key difference between this and "block-exist" checks for variable_set and variable_get is that we can ensure the names match, and we can ensure it's checking for multiple variables (so variable_get isn't just called X number of times on the same variable, even if variable_set defines X unique variables, and so on...). You can optionally filter by name, but we don't expose this currently in any criteria. You can also used nested validation to ensure a variable is set to something specific (like pick random), but again, we don't have any criteria that currently use this.
- Loading branch information
Showing
5 changed files
with
109 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/// <reference path="../../localtypings/pxtpackage.d.ts" /> | ||
import * as Blockly from "blockly"; | ||
|
||
// Validates that variables are created and used within the workspace. | ||
// Name is optional. If undefined or empty, all variable names are permitted. | ||
// Returns the definition blocks for variables that passed the check. | ||
export function validateVariableUsage({ | ||
usedBlocks, | ||
count, | ||
name, | ||
}: { | ||
usedBlocks: Blockly.Block[]; | ||
count: number; | ||
name?: String; | ||
}): { | ||
passingVarDefinitions: Map<string, Blockly.Block[]>; | ||
passed: boolean; | ||
} { | ||
const varDefinitionBlocks: Map<string, Blockly.Block[]> = new Map(); | ||
const usedVars: Set<string> = new Set(); | ||
|
||
for (const block of usedBlocks) { | ||
if (!block.isEnabled()) { | ||
continue; | ||
} | ||
|
||
const varsUsed = block.getVarModels(); | ||
for (const varModel of varsUsed ?? []) { | ||
const varName = varModel.name; | ||
if (!name || varName === name) { | ||
if (block.type === "variables_set" || block.type === "variables_change") { | ||
// Variable created | ||
if (!varDefinitionBlocks.has(varName)) { | ||
varDefinitionBlocks.set(varName, []); | ||
} | ||
varDefinitionBlocks.get(varName).push(block); | ||
} else { | ||
// Variable used | ||
usedVars.add(varName); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Var passes check if it is both used and defined. | ||
// We return the definition blocks to allow for recursively checking how the var was set. | ||
const passingVarDefinitions = new Map<string, Blockly.Block[]>(); | ||
for (const [varName, definitionBlocks] of varDefinitionBlocks) { | ||
if (usedVars.has(varName)) { | ||
passingVarDefinitions.set(varName, definitionBlocks); | ||
} | ||
} | ||
|
||
return { passingVarDefinitions, passed: passingVarDefinitions.size >= count }; | ||
} |