internal override Expression ResolveEntityNames(ParserContext parser) { this.Root = this.Root.ResolveEntityNames(parser); this.Index = this.Index.ResolveEntityNames(parser); if (this.Root is CompileTimeDictionary) { // Swap out this bracketed expression with a fixed constant. CompileTimeDictionary root = (CompileTimeDictionary)this.Root; if (root.Type == "var") { if (this.Index is StringConstant) { string index = ((StringConstant)this.Index).Value; if (parser.BuildContext.TopLevelAssembly.BuildVariableLookup.ContainsKey(index)) { BuildVarCanonicalized buildVar = parser.BuildContext.TopLevelAssembly.BuildVariableLookup[index]; switch (buildVar.Type) { case VarType.INT: return(new IntegerConstant(this.FirstToken, buildVar.IntValue, this.Owner)); case VarType.FLOAT: return(new FloatConstant(this.FirstToken, buildVar.FloatValue, this.Owner)); case VarType.STRING: return(new StringConstant(this.FirstToken, buildVar.StringValue, this.Owner)); case VarType.BOOLEAN: return(new BooleanConstant(this.FirstToken, buildVar.BoolValue, this.Owner)); default: throw new System.Exception("This should not happen."); // invalid types filtered during build context construction. } } else { return(new NullConstant(this.FirstToken, this.Owner)); // TODO: strict mode that enforces this. There are two ways this could be done: // 1) $var['foo'] vs $optional['foo'] // 2) <strictvars>true</strictvars> // I kind of prefer #1. // throw new ParserException(this.Index, "The build variable with id '" + index + "' is not defined for this target."); } } } else { throw new System.Exception("Unknown compile time dictionary type."); } } return(this); }
private static Dictionary<string, BuildVarCanonicalized> GenerateBuildVars(BuildItem root, BuildItem target, string targetName) { Dictionary<string, BuildVar> firstPass = new Dictionary<string, BuildVar>(); if (root.Var != null) { foreach (BuildVar rootVar in root.Var) { if (rootVar.Id == null) { throw new InvalidOperationException("Build file contains a <var> without an id attribute."); } firstPass.Add(rootVar.Id, rootVar); } } if (target.Var != null) { foreach (BuildVar targetVar in target.Var) { if (targetVar.Id == null) { throw new InvalidOperationException("Build file target contains a <var> without an id attribute."); } firstPass[targetVar.Id] = targetVar; } } Dictionary<string, BuildVarCanonicalized> output = new Dictionary<string, BuildVarCanonicalized>(); foreach (BuildVar rawElement in firstPass.Values) { string id = rawElement.Id; string value = rawElement.Value; int intValue = 0; double floatValue = 0; bool boolValue = false; VarType type = VarType.BOOLEAN; switch ((rawElement.Type ?? "string").ToLowerInvariant()) { case "int": case "integer": type = VarType.INT; break; case "float": case "double": type = VarType.FLOAT; break; case "bool": case "boolean": type = VarType.BOOLEAN; break; case "string": type = VarType.STRING; break; default: throw new InvalidOperationException("Build file variable '" + id + "' contains an unrecognized type: '" + rawElement.Type + "'. Types must be 'string', 'integer', 'boolean', or 'float'."); } int score = (rawElement.EnvironmentVarValue != null ? 1 : 0) + (rawElement.Value != null ? 1 : 0); if (score != 1) { throw new InvalidOperationException("Build file variable '" + id + "' must contain either a <value> or a <env> content element but not both."); } if (value == null) { value = System.Environment.GetEnvironmentVariable(rawElement.EnvironmentVarValue); if (value == null) { throw new InvalidOperationException("Build file varaible '" + id + "' references an environment variable that is not set: '" + rawElement.EnvironmentVarValue + "'"); } value = DoReplacement(targetName, value.Trim()); } switch (type) { case VarType.INT: if (!int.TryParse(value, out intValue)) { throw new InvalidOperationException("Build file variable: '" + id + "' contains an invalid integer value."); } break; case VarType.FLOAT: if (!double.TryParse(value, out floatValue)) { throw new InvalidOperationException("Build file variable: '" + id + "' contains an invalid float value."); } break; case VarType.BOOLEAN: switch (value.ToLowerInvariant()) { case "0": case "no": case "false": case "f": case "n": boolValue = false; break; case "1": case "true": case "t": case "yes": case "y": boolValue = true; break; default: throw new InvalidOperationException("Build file variable: '" + id + "' contains an invalid boolean valud."); } break; case VarType.STRING: break; default: break; } output[id] = new BuildVarCanonicalized() { ID = id, Type = type, StringValue = value, IntValue = intValue, FloatValue = floatValue, BoolValue = boolValue }; } return output; }
private static Dictionary <string, BuildVarCanonicalized> GenerateBuildVars(BuildItem root, BuildItem target, string targetName) { Dictionary <string, BuildVar> firstPass = new Dictionary <string, BuildVar>(); if (root.Var != null) { foreach (BuildVar rootVar in root.Var) { if (rootVar.Id == null) { throw new InvalidOperationException("Build file contains a <var> without an id attribute."); } firstPass.Add(rootVar.Id, rootVar); } } if (target.Var != null) { foreach (BuildVar targetVar in target.Var) { if (targetVar.Id == null) { throw new InvalidOperationException("Build file target contains a <var> without an id attribute."); } firstPass[targetVar.Id] = targetVar; } } Dictionary <string, BuildVarCanonicalized> output = new Dictionary <string, BuildVarCanonicalized>(); foreach (BuildVar rawElement in firstPass.Values) { string id = rawElement.Id; string value = rawElement.Value; int intValue = 0; double floatValue = 0; bool boolValue = false; VarType type = VarType.BOOLEAN; switch ((rawElement.Type ?? "string").ToLowerInvariant()) { case "int": case "integer": type = VarType.INT; break; case "float": case "double": type = VarType.FLOAT; break; case "bool": case "boolean": type = VarType.BOOLEAN; break; case "string": type = VarType.STRING; break; default: throw new InvalidOperationException("Build file variable '" + id + "' contains an unrecognized type: '" + rawElement.Type + "'. Types must be 'string', 'integer', 'boolean', or 'float'."); } int score = (rawElement.EnvironmentVarValue != null ? 1 : 0) + (rawElement.Value != null ? 1 : 0); if (score != 1) { throw new InvalidOperationException("Build file variable '" + id + "' must contain either a <value> or a <env> content element but not both."); } if (value == null) { value = System.Environment.GetEnvironmentVariable(rawElement.EnvironmentVarValue); if (value == null) { throw new InvalidOperationException("Build file varaible '" + id + "' references an environment variable that is not set: '" + rawElement.EnvironmentVarValue + "'"); } value = DoReplacement(targetName, value.Trim()); } switch (type) { case VarType.INT: if (!int.TryParse(value, out intValue)) { throw new InvalidOperationException("Build file variable: '" + id + "' contains an invalid integer value."); } break; case VarType.FLOAT: if (!double.TryParse(value, out floatValue)) { throw new InvalidOperationException("Build file variable: '" + id + "' contains an invalid float value."); } break; case VarType.BOOLEAN: switch (value.ToLowerInvariant()) { case "0": case "no": case "false": case "f": case "n": boolValue = false; break; case "1": case "true": case "t": case "yes": case "y": boolValue = true; break; default: throw new InvalidOperationException("Build file variable: '" + id + "' contains an invalid boolean valud."); } break; case VarType.STRING: break; default: break; } output[id] = new BuildVarCanonicalized() { ID = id, Type = type, StringValue = value, IntValue = intValue, FloatValue = floatValue, BoolValue = boolValue }; } return(output); }