/// <summary> /// Initializes a new instance of the <see cref="Element" /> class /// from the specified element. /// </summary> /// <param name="e">The element that should be used to create a new instance of the <see cref="Element" /> class.</param> protected Element(Element e) : this() { _location = e._location; _project = e._project; _xmlNode = e._xmlNode; _nsMgr = e._nsMgr; }
/// <summary> /// Returns the <see cref="Location"/> in the XML file for the given node. /// </summary> /// <remarks> /// The <paramref name="node" /> must be from an <see cref="XmlDocument" /> /// that has been added to the map. /// </remarks> public Location GetLocation(XmlNode node) { // check for non-backed documents if (StringUtils.IsNullOrEmpty(node.BaseURI)) { return new Location(null, 0, 0 ); // return null location because we have a fileless node. } // convert URI to absolute URI Uri uri = new Uri(node.BaseURI); string fileName = uri.AbsoluteUri; if (!FileIsMapped(fileName)) { throw new ArgumentException("Xml node has not been mapped."); } // find xpath for node Hashtable map = (Hashtable) _fileMap[fileName]; string xpath = GetXPathFromNode(node); if (!map.ContainsKey(xpath)) { throw new ArgumentException("Xml node has not been mapped."); } TextPosition pos = (TextPosition) map[xpath]; Location location = new Location(fileName, pos.Line, pos.Column); return location; }
/// <summary> /// Expands a <see cref="string" /> from known properties. /// </summary> /// <param name="input">The <see cref="string" /> with replacement tokens.</param> /// <param name="location">The location in the build file. Used to throw more accurate exceptions.</param> /// <returns>The expanded and replaced <see cref="string" />.</returns> public string ExpandProperties(string input, Location location) { return Properties.ExpandProperties(input, location); }
/// <summary> /// Creates a new <see cref="XmlDocument" /> based on the project /// definition. /// </summary> /// <param name="source">The source of the document.<para>Any form that is valid for <see cref="XmlDocument.Load(string)" /> can be used here.</para></param> /// <returns> /// An <see cref="XmlDocument" /> based on the specified project /// definition. /// </returns> private XmlDocument LoadBuildFile(string source) { XmlDocument doc = new XmlDocument(); try { doc.Load(source); } catch (XmlException ex) { Location location = new Location(source, ex.LineNumber, ex.LinePosition); throw new BuildException("Error loading buildfile.", location, ex); } catch (Exception ex) { Location location = new Location(source); throw new BuildException("Error loading buildfile.", location, ex); } return doc; }
/// <summary> /// Initializes a new instance of the <see cref="BuildException" /> class /// with serialized data. /// </summary> /// <param name="info">The <see cref="SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param> /// <param name="context">The <see cref="StreamingContext" /> that contains contextual information about the source or destination.</param> protected BuildException(SerializationInfo info, StreamingContext context) : base(info, context) { _location = info.GetValue("Location", _location.GetType()) as Location; }
/// <summary> /// Initializes a new instance of the <see cref="BuildException" /> class /// with a descriptive message, the location in the build file and an /// instance of the exception that is the cause of the current exception. /// </summary> /// <param name="message">A descriptive message to include with the exception.</param> /// <param name="location">The location in the build file where the exception occured.</param> /// <param name="innerException">A nested exception that is the cause of the current exception.</param> public BuildException(String message, Location location, Exception innerException) : base(message, innerException) { _location = location; }
/// <summary> /// Initializes a new instance of the <see cref="BuildException" /> class /// with a descriptive message and the location in the build file that /// caused the exception. /// </summary> /// <param name="message">A descriptive message to include with the exception.</param> /// <param name="location">The location in the build file where the exception occured.</param> public BuildException(String message, Location location) : base(message) { _location = location; }
/// <summary> /// Evaluates the given expression string and returns the result /// </summary> /// <param name="input"></param> /// <param name="location"></param> /// <param name="state"></param> /// <param name="visiting"></param> /// <returns></returns> private string EvaluateEmbeddedExpressions(string input, Location location, Hashtable state, Stack visiting) { if (input == null) { return null; } if (input.IndexOf('$') < 0) { return input; } try { StringBuilder output = new StringBuilder(input.Length); ExpressionTokenizer tokenizer = new ExpressionTokenizer(); ExpressionEvaluator eval = new ExpressionEvaluator(Project, this, state, visiting); tokenizer.IgnoreWhitespace = false; tokenizer.SingleCharacterMode = true; tokenizer.InitTokenizer(input); while (tokenizer.CurrentToken != ExpressionTokenizer.TokenType.EOF) { if (tokenizer.CurrentToken == ExpressionTokenizer.TokenType.Dollar) { tokenizer.GetNextToken(); if (tokenizer.CurrentToken == ExpressionTokenizer.TokenType.LeftCurlyBrace) { tokenizer.IgnoreWhitespace = true; tokenizer.SingleCharacterMode = false; tokenizer.GetNextToken(); string val = Convert.ToString(eval.Evaluate(tokenizer), CultureInfo.InvariantCulture); output.Append(val); tokenizer.IgnoreWhitespace = false; if (tokenizer.CurrentToken != ExpressionTokenizer.TokenType.RightCurlyBrace) { throw new ExpressionParseException("'}' expected", tokenizer.CurrentPosition.CharIndex); } tokenizer.SingleCharacterMode = true; tokenizer.GetNextToken(); } else { output.Append('$'); if (tokenizer.CurrentToken != ExpressionTokenizer.TokenType.EOF) { output.Append(tokenizer.TokenText); tokenizer.GetNextToken(); } } } else { output.Append(tokenizer.TokenText); tokenizer.GetNextToken(); } } return output.ToString(); } catch (ExpressionParseException ex) { StringBuilder errorMessage = new StringBuilder(); string reformattedInput = input; // replace CR, LF and TAB with a space reformattedInput = reformattedInput.Replace('\n', ' '); reformattedInput = reformattedInput.Replace('\r', ' '); reformattedInput = reformattedInput.Replace('\t', ' '); errorMessage.Append(ex.Message); errorMessage.Append(Environment.NewLine); string label = "Expression: "; errorMessage.Append(label); errorMessage.Append(reformattedInput); int p0 = ex.StartPos; int p1 = ex.EndPos; if (p0 != -1 || p1 != -1) { errorMessage.Append(Environment.NewLine); if (p1 == -1) p1 = p0 + 1; for (int i = 0; i < p0 + label.Length; ++i) errorMessage.Append(' '); for (int i = p0; i < p1; ++i) errorMessage.Append('^'); } throw new BuildException(errorMessage.ToString(), location, ex.InnerException); } }
/// <summary> /// Performs initialization using the given set of properties. /// </summary> internal void Initialize(XmlNode elementNode, PropertyDictionary properties) { if (Project == null) { throw new InvalidOperationException("Element has invalid Project property."); } // save position in buildfile for reporting useful error messages. try { _location = Project.LocationMap.GetLocation(elementNode); } catch (ArgumentException ex) { logger.Warn("Location of Element node could be located.", ex); } InitializeXml(elementNode, properties); // allow inherited classes a chance to do some custom initialization InitializeElement(elementNode); }
private static void ValidatePropertyValue(object value, Location location) { if (value != null) { if (!(value is string)) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1066"), value.GetType()), "value"); } } else { // TODO: verify this // throw new ArgumentException("Property value '" + propertyName + "' must not be null", "value"); return; } }
private static void ValidatePropertyName(string propertyName, Location location) { const string propertyNamePattern = "^[_A-Za-z0-9][_A-Za-z0-9\\-.]*$"; // validate property name if (!Regex.IsMatch(propertyName, propertyNamePattern)) { throw new BuildException(string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1064"), propertyName), location); } if (propertyName.EndsWith("-") || propertyName.EndsWith(".")) { // this additional rule helps simplify the regex pattern throw new BuildException(string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1064"), propertyName), location); } }
/// <summary> /// Expands a <see cref="string" /> from known properties. /// </summary> /// <param name="input">The replacement tokens.</param> /// <param name="location">The <see cref="Location" /> to pass through for any exceptions.</param> /// <param name="state">A mapping from properties to states. The states in question are "VISITING" and "VISITED". Must not be <see langword="null" />.</param> /// <param name="visiting">A stack of properties which are currently being visited. Must not be <see langword="null" />.</param> /// <returns>The expanded and replaced string.</returns> internal string ExpandProperties(string input, Location location, Hashtable state, Stack visiting) { return EvaluateEmbeddedExpressions(input, location, state, visiting); }
/// <summary> /// Expands a <see cref="string" /> from known properties. /// </summary> /// <param name="input">The replacement tokens.</param> /// <param name="location">The <see cref="Location" /> to pass through for any exceptions.</param> /// <returns>The expanded and replaced string.</returns> public string ExpandProperties(string input, Location location) { Hashtable state = new Hashtable(); Stack visiting = new Stack(); return ExpandProperties(input, location, state, visiting); }
/// <summary> /// Initializes a new instance of the <see cref="ValidationException" /> /// class with a descriptive message, the location in the build file and /// an instance of the exception that is the cause of the current /// exception. /// </summary> /// <param name="message">A descriptive message to include with the exception.</param> /// <param name="location">The location in the build file where the exception occured.</param> /// <param name="innerException">A nested exception that is the cause of the current exception.</param> public ValidationException(String message, Location location, Exception innerException) : base(message, location, innerException) { }