/// <summary> /// Saves the Settings provided into the XmlDocument. /// </summary> /// <param name="document"> /// The root document. /// </param> /// <param name="environment"> /// The environment that StyleCop is running under, if any. /// </param> /// <param name="rootElement"> /// The element to save our settings to. /// </param> /// <param name="settingsToSave"> /// The settings to save. /// </param> private void SaveSettingsIntoXmlDocument(XmlDocument document, StyleCopEnvironment environment, XmlElement rootElement, Settings settingsToSave) { // Get the parent settings if there are any. SettingsMerger merger = new SettingsMerger(settingsToSave, environment); Settings parentSettings = merger.ParentMergedSettings; // Add the global settings if there are any. if (settingsToSave.GlobalSettings != null && settingsToSave.GlobalSettings.Count > 0) { // Get the global settings from the parent. PropertyCollection parentGlobalSettings = null; if (parentSettings != null) { parentGlobalSettings = parentSettings.GlobalSettings; } SavePropertyCollection(rootElement, "GlobalSettings", settingsToSave.GlobalSettings, parentGlobalSettings, true, null); } // Add the parser settings if there are any. if (settingsToSave.ParserSettings.Count > 0) { bool parserSettingsAdded = false; XmlElement parsersNode = document.CreateElement("Parsers"); foreach (AddInPropertyCollection parserSettings in settingsToSave.ParserSettings) { // Add the settings for this parser if there are any. if (parserSettings.Count > 0) { // Create a node for this parser. XmlElement parserNode = document.CreateElement("Parser"); XmlAttribute parserIdAttribute = document.CreateAttribute("ParserId"); parserIdAttribute.Value = parserSettings.AddIn.Id; parserNode.Attributes.Append(parserIdAttribute); // Get the parser settings from the parent. PropertyCollection parentParserSettings = null; if (parentSettings != null) { parentParserSettings = parentSettings.GetAddInSettings(parserSettings.AddIn); } if (SavePropertyCollection(parserNode, "ParserSettings", parserSettings, parentParserSettings, true, null)) { parsersNode.AppendChild(parserNode); parserSettingsAdded = true; } } } if (parserSettingsAdded) { rootElement.AppendChild(parsersNode); } } // Add the analyzer settings if there are any. if (settingsToSave.AnalyzerSettings.Count > 0) { bool analyzerSettingsAdded = false; XmlElement analyzersNode = document.CreateElement("Analyzers"); foreach (AddInPropertyCollection analyzerSettings in settingsToSave.AnalyzerSettings) { // Add the settings for this analyzer if there are any. if (analyzerSettings.Count > 0) { // Create a node for this analzyer. XmlElement analyzerNode = document.CreateElement("Analyzer"); XmlAttribute analyzerIdAttribute = document.CreateAttribute("AnalyzerId"); analyzerIdAttribute.Value = analyzerSettings.AddIn.Id; analyzerNode.Attributes.Append(analyzerIdAttribute); // Get the analyzer settings from the parent. PropertyCollection parentAnalyzerSettings = null; if (parentSettings != null) { parentAnalyzerSettings = parentSettings.GetAddInSettings(analyzerSettings.AddIn); } if (SavePropertyCollection(analyzerNode, "AnalyzerSettings", analyzerSettings, parentAnalyzerSettings, true, null)) { analyzersNode.AppendChild(analyzerNode); analyzerSettingsAdded = true; } } } if (analyzerSettingsAdded) { rootElement.AppendChild(analyzersNode); } } // Add the sourcefilelists settings if there are any. if (settingsToSave.SourceFileLists.Count > 0) { foreach (SourceFileListSettings sourceFileListSettings in settingsToSave.SourceFileLists) { XmlElement sourceFileListNode = document.CreateElement("SourceFileList"); foreach (string sourceFileListSetting in sourceFileListSettings.SourceFiles) { XmlElement sourceFileNode = document.CreateElement("SourceFile"); sourceFileNode.InnerText = sourceFileListSetting; sourceFileListNode.AppendChild(sourceFileNode); } XmlElement settingsNode = document.CreateElement("Settings"); this.SaveSettingsIntoXmlDocument(document, environment, settingsNode, sourceFileListSettings.Settings); sourceFileListNode.AppendChild(settingsNode); rootElement.AppendChild(sourceFileListNode); } } }
/// <summary> /// Saves the given property collection. /// </summary> /// <param name="rootNode"> /// The node to store the property collection beneath. /// </param> /// <param name="nodeName"> /// The name of the new property collection node. /// </param> /// <param name="properties"> /// The property collection to store. /// </param> /// <param name="parentProperties"> /// The corresponding property collection from the parent settings, if any. /// </param> /// <param name="aggregate"> /// Indicates whether the collection is aggregated with the parent collection. /// </param> /// <param name="nodeNameAttribute"> /// An optional name attribute value for the new property node. /// </param> /// <returns> /// Returns true if at least one property was saved. /// </returns> private static bool SavePropertyCollection( XmlNode rootNode, string nodeName, PropertyCollection properties, PropertyCollection parentProperties, bool aggregate, string nodeNameAttribute) { Param.AssertNotNull(rootNode, "rootNode"); Param.AssertValidString(nodeName, "nodeName"); Param.AssertNotNull(properties, "properties"); Param.Ignore(parentProperties); Param.Ignore(aggregate); Param.Ignore(nodeNameAttribute); // If there are no properties in the collection, don't save anything. if (properties.Count == 0) { return(false); } bool propertyWritten = false; // Create the root node for this property collection. Debug.Assert(rootNode.OwnerDocument != null, "The root node has not been attached to a document."); XmlElement rootCollectionNode = rootNode.OwnerDocument.CreateElement(nodeName); if (!string.IsNullOrEmpty(nodeNameAttribute)) { XmlAttribute rootCollectionNodeNameAttribute = rootNode.OwnerDocument.CreateAttribute("Name"); rootCollectionNodeNameAttribute.Value = nodeNameAttribute; rootCollectionNode.Attributes.Append(rootCollectionNodeNameAttribute); } // Add each property in the collection. foreach (PropertyValue property in properties) { bool skip = false; PropertyValue parentProperty = null; if (parentProperties != null) { parentProperty = parentProperties[property.PropertyName]; // If the property also exists in the parent collection, determine whether the local property // is an override. If not, there is no need to add it. if (aggregate && parentProperty != null) { if (!SettingsComparer.IsSettingOverwritten(property, parentProperty)) { skip = true; } } else if (property.IsDefault) { skip = true; } } else if (property.IsDefault) { skip = true; } if (!skip) { // If the property is a rule setting, then add it under the rules section. int index = property.PropertyName.IndexOf('#'); if (index > 0) { propertyWritten |= SaveRuleProperty( rootNode, property, property.PropertyName.Substring(0, index), property.PropertyName.Substring(index + 1, property.PropertyName.Length - index - 1)); } else { // Just save the property value under this add-in's settings since it is // not a rule property. propertyWritten |= SavePropertyValue(rootCollectionNode, property, property.PropertyName); } } } // If at least one property was saved, add the property collection node into the document. if (propertyWritten) { rootNode.AppendChild(rootCollectionNode); } return(propertyWritten); }
/// <summary> /// Loads and stores a string property. /// </summary> /// <param name="propertyName"> /// The name of the property to load. /// </param> /// <param name="propertyNode"> /// The node containing the property. /// </param> /// <param name="properties"> /// The collection in which to store the property. /// </param> /// <param name="propertyDescriptors"> /// The collection of property descriptors. /// </param> private static void LoadStringProperty(string propertyName, XmlNode propertyNode, PropertyCollection properties, PropertyDescriptorCollection propertyDescriptors) { Param.AssertValidString(propertyName, "propertyName"); Param.AssertNotNull(propertyNode, "propertyNode"); Param.AssertNotNull(properties, "properties"); Param.AssertNotNull(propertyDescriptors, "propertyDescriptors"); // Get the property descriptor. PropertyDescriptor <string> descriptor = propertyDescriptors[propertyName] as PropertyDescriptor <string>; if (descriptor != null) { // Create and add the property. properties.Add(new StringProperty(descriptor, propertyNode.InnerText)); } }
/// <summary> /// Loads and stores an integer property. /// </summary> /// <param name="propertyName"> /// The name of the property to load. /// </param> /// <param name="propertyNode"> /// The node containing the property. /// </param> /// <param name="properties"> /// The collection in which to store the property. /// </param> /// <param name="propertyDescriptors"> /// The collection of property descriptors. /// </param> private static void LoadIntProperty(string propertyName, XmlNode propertyNode, PropertyCollection properties, PropertyDescriptorCollection propertyDescriptors) { Param.AssertValidString(propertyName, "propertyName"); Param.AssertNotNull(propertyNode, "propertyNode"); Param.AssertNotNull(properties, "properties"); Param.AssertNotNull(propertyDescriptors, "propertyDescriptors"); // Skip corrupted properties. int value; if (int.TryParse(propertyNode.InnerText, NumberStyles.Any, CultureInfo.InvariantCulture, out value)) { // Get the property descriptor. PropertyDescriptor <int> descriptor = propertyDescriptors[propertyName] as PropertyDescriptor <int>; if (descriptor != null) { // Create and add the property. properties.Add(new IntProperty(descriptor, value)); } } }
/// <summary> /// Loads and stores a boolean property. /// </summary> /// <param name="propertyName"> /// The name of the property to load. /// </param> /// <param name="propertyNode"> /// The node containing the property. /// </param> /// <param name="properties"> /// The collection in which to store the property. /// </param> /// <param name="propertyDescriptors"> /// The collection of property descriptors. /// </param> /// <param name="legacyAnalyzerId"> /// If the settings node comes from a legacy, pre-4.2 analyzer, /// this parameter contains the ID of the legacy analyzer. /// </param> private static void LoadBooleanProperty( string propertyName, XmlNode propertyNode, PropertyCollection properties, PropertyDescriptorCollection propertyDescriptors, string legacyAnalyzerId) { Param.AssertValidString(propertyName, "propertyName"); Param.AssertNotNull(propertyNode, "propertyNode"); Param.AssertNotNull(properties, "properties"); Param.AssertNotNull(propertyDescriptors, "propertyDescriptors"); Param.Ignore(legacyAnalyzerId); // Skip corrupted properties. bool value; if (bool.TryParse(propertyNode.InnerText, out value)) { if (string.IsNullOrEmpty(legacyAnalyzerId)) { AddBooleanProperty(propertyName, value, properties, propertyDescriptors); } else { if (propertyName == "Enabled") { // Enable or disable all rules mapping to the legacy analyzer. ICollection <string> rules = MapAnalyzerToRules(legacyAnalyzerId); if (rules != null) { foreach (string rule in rules) { AddBooleanProperty(rule + "#Enabled", value, properties, propertyDescriptors); } } } else if (legacyAnalyzerId == "Microsoft.SourceAnalysis.CSharp.Documentation") { if (propertyName == "PublicAndProtectedOnly") { AddBooleanProperty("IgnorePrivates", value, properties, propertyDescriptors); AddBooleanProperty("IgnoreInternals", value, properties, propertyDescriptors); } else if (propertyName == "RequireValueTags") { AddOrUpdateLegacyBooleanProperty("PropertyDocumentationMustHaveValue", value, properties, propertyDescriptors); AddOrUpdateLegacyBooleanProperty("PropertyDocumentationMustHaveValueText", value, properties, propertyDescriptors); } else if (propertyName == "RequireCapitalLetter") { AddOrUpdateLegacyBooleanProperty("DocumentationTextMustBeginWithACapitalLetter", value, properties, propertyDescriptors); } else if (propertyName == "RequirePeriod") { AddOrUpdateLegacyBooleanProperty("DocumentationTextMustEndWithAPeriod", value, properties, propertyDescriptors); } else if (propertyName == "RequireProperFormatting") { AddOrUpdateLegacyBooleanProperty("DocumentationTextMustContainWhitespace", value, properties, propertyDescriptors); AddOrUpdateLegacyBooleanProperty("DocumentationMustMeetCharacterPercentage", value, properties, propertyDescriptors); AddOrUpdateLegacyBooleanProperty("DocumentationTextMustMeetMinimumCharacterLength", value, properties, propertyDescriptors); if (!value) { AddOrUpdateLegacyBooleanProperty("DocumentationTextMustEndWithAPeriod", value, properties, propertyDescriptors); AddOrUpdateLegacyBooleanProperty("DocumentationTextMustBeginWithACapitalLetter", value, properties, propertyDescriptors); } } else { AddBooleanProperty(propertyName, value, properties, propertyDescriptors); } } else if (legacyAnalyzerId == "Microsoft.SourceAnalysis.CSharp.FileHeaders") { if (propertyName == "RequireSummary") { AddOrUpdateLegacyBooleanProperty("FileHeaderMustHaveSummary", value, properties, propertyDescriptors); } else { AddBooleanProperty(propertyName, value, properties, propertyDescriptors); } } else { AddBooleanProperty(propertyName, value, properties, propertyDescriptors); } } } }
/// <summary> /// Adds or updates a property to enable or disable a rule depending on the value of a /// legacy property. /// </summary> /// <param name="ruleName"> /// The name of the rule to enable or disable. /// </param> /// <param name="value"> /// The value of the legacy property. /// </param> /// <param name="properties"> /// The collection of properties. /// </param> /// <param name="propertyDescriptors"> /// The collection of property descriptors. /// </param> private static void AddOrUpdateLegacyBooleanProperty(string ruleName, bool value, PropertyCollection properties, PropertyDescriptorCollection propertyDescriptors) { Param.AssertValidString(ruleName, "ruleName"); Param.Ignore(value); Param.AssertNotNull(properties, "properties"); Param.AssertNotNull(propertyDescriptors, "propertyDescriptors"); // Determine whethere is already an Enabled property for this rule. string propertyName = ruleName + "#Enabled"; BooleanProperty property = properties[propertyName] as BooleanProperty; if (property == null) { // Add a new property which enables or disables this rule depending on the // value of the legacy property. AddBooleanProperty(propertyName, value, properties, propertyDescriptors); } else if (!value) { // The rule has already been explictely enabled or disabled. In this case we // never enable the rule, but we may disable it if the legacy property is set to false. property.Value = false; } }