diff --git a/src/Alias.ts b/src/Alias.ts index f18daa6a83..f5b4d77522 100644 --- a/src/Alias.ts +++ b/src/Alias.ts @@ -62,9 +62,13 @@ export function removeAlias(name: string): boolean { return hadAlias; } +export function clearAliases(): void { + Aliases.clear(); + GlobalAliases.clear(); +} + /** * Returns the original string with any aliases substituted in. - * Aliases are only applied to "whole words", one level deep * @param origCommand the original command string */ export function substituteAliases(origCommand: string): string { @@ -79,7 +83,7 @@ export function substituteAliases(origCommand: string): string { * @param currentlyProcessingAliases any aliases that have been applied in the recursive evaluation leading to this point * @return { string } the provided command with all of its referenced aliases evaluated */ -function applyAliases(origCommand: string, depth = 0, currentlyProcessingAliases: string[] = []) { +function applyAliases(origCommand: string, depth = 0, currentlyProcessingAliases: Set = new Set()) { if (!origCommand) { return origCommand; } @@ -93,16 +97,18 @@ function applyAliases(origCommand: string, depth = 0, currentlyProcessingAliases // First get non-global aliases, and recursively apply them // (unless there are any reference loops or the reference chain is too deep) const localAlias = Aliases.get(commandArray[0]); - if (localAlias && !currentlyProcessingAliases.includes(localAlias)) { - const appliedAlias = applyAliases(localAlias, depth + 1, [commandArray[0], ...currentlyProcessingAliases]); + const localrule = commandArray[0] + "->" + localAlias + "(l)"; + if (localAlias && !currentlyProcessingAliases.has(localrule)) { + const appliedAlias = applyAliases(localAlias, depth + 1, new Set([localrule, ...currentlyProcessingAliases])); commandArray.splice(0, 1, ...appliedAlias.split(" ")); } // Once local aliasing is complete (or if none are present) handle any global aliases const processedCommands = commandArray.reduce((resolvedCommandArray: string[], command) => { const globalAlias = GlobalAliases.get(command); - if (globalAlias && !currentlyProcessingAliases.includes(globalAlias)) { - const appliedAlias = applyAliases(globalAlias, depth + 1, [command, ...currentlyProcessingAliases]); + const globalrule = command + "->" + globalAlias + "(g)"; + if (globalAlias && !currentlyProcessingAliases.has(globalrule)) { + const appliedAlias = applyAliases(globalAlias, depth + 1, new Set([globalrule, ...currentlyProcessingAliases])); resolvedCommandArray.push(appliedAlias); } else { // If there is no alias, or if the alias has a circular reference, leave the command as-is diff --git a/test/jest/Alias/Alias.test.ts b/test/jest/Alias/Alias.test.ts index d5f594fb77..059d0cc725 100644 --- a/test/jest/Alias/Alias.test.ts +++ b/test/jest/Alias/Alias.test.ts @@ -1,13 +1,62 @@ -import { substituteAliases, parseAliasDeclaration } from "../../../src/Alias"; +import { substituteAliases, parseAliasDeclaration, clearAliases } from "../../../src/Alias"; describe("substituteAliases Tests", () => { - it("Should gracefully handle recursive local aliases", () => { + beforeEach(() => { + clearAliases(); + }); + it("Should gracefully handle recursive local aliases I", () => { parseAliasDeclaration("recursiveAlias=b"); parseAliasDeclaration("b=c"); parseAliasDeclaration("c=d"); parseAliasDeclaration("d=recursiveAlias"); const result = substituteAliases("recursiveAlias"); - expect(result).toEqual("d"); + expect(result).toEqual("recursiveAlias"); + }); + + it("Should gracefully handle recursive local aliases II", () => { + parseAliasDeclaration("recursiveAlias=recursiveAlias"); + const result = substituteAliases("recursiveAlias"); + expect(result).toEqual("recursiveAlias"); + }); + + it("Should gracefully handle recursive local aliases III", () => { + parseAliasDeclaration('recursiveAlias="recursiveAlias"'); + const result = substituteAliases("recursiveAlias"); + expect(result).toEqual("recursiveAlias"); + }); + + it("Should gracefully handle recursive local aliases IV", () => { + parseAliasDeclaration('recursiveAlias="recursiveAlias -l"'); + const result = substituteAliases("recursiveAlias"); + expect(result).toEqual("recursiveAlias -l"); + }); + + it("Should not substitute quoted commands I", () => { + parseAliasDeclaration("a=b"); + const result = substituteAliases('"a"'); + expect(result).toEqual('"a"'); + }); + + it("Should not substitute quoted commands II", () => { + parseAliasDeclaration("a=b"); + const result = substituteAliases("'a'"); + expect(result).toEqual("'a'"); + }); + + it.skip("Should not substitute quoted commands III", () => { + parseAliasDeclaration("a=b"); + parseAliasDeclaration("b='c'"); + parseAliasDeclaration("c=d"); + const result = substituteAliases("a"); + expect(result).toEqual("'c'"); + }); + + it.skip("Should not substitute quoted commands IV", () => { + parseAliasDeclaration("a=b"); + parseAliasDeclaration('b="c"'); + parseAliasDeclaration("c=d"); + const result = substituteAliases("a"); + expect(result).toEqual('"c"'); }); it("Should only change local aliases if they are the start of the command", () => { @@ -27,7 +76,7 @@ describe("substituteAliases Tests", () => { parseAliasDeclaration("d=a", true); const result = substituteAliases("a b c d"); - expect(result).toEqual("d a b c"); + expect(result).toEqual("a b c d"); }); it("Should gracefully handle recursive mixed local and global aliases", () => { @@ -37,7 +86,7 @@ describe("substituteAliases Tests", () => { parseAliasDeclaration("d=recursiveAlias", false); const result = substituteAliases("recursiveAlias"); - expect(result).toEqual("d"); + expect(result).toEqual("recursiveAlias"); }); it("Should replace chained aliases", () => {