private static void BuildErrors( ModValidationResult result, StringBuilder builder ) { foreach ( var modError in result.ModErrors ) { builder.AppendLine( modError ); } foreach ( var fileValidationErrors in result.XmlErrors ) { if ( fileValidationErrors.Errors.Count > 0 ) { builder.AppendLine( fileValidationErrors.Path ); builder.AppendLine( String.Format( "{0} error(s) found.", fileValidationErrors.Errors.Count ) ); foreach ( var error in fileValidationErrors.Errors ) { builder.AppendLine( String.Format( "Line {0}, Position: {1} -- {2}", error.LineNumber, error.LinePosition, XmlErrorTranslator.Translate( error.Message ) ) ); } builder.AppendLine(); } } }
private static void AddRequirementErrors(ModValidationResult result, ContentFile modFile) { //we already loaded and used XSD validation on mod.xml annd exited if it had malformed XML, so it's safe to just load it here. //However we are not sure their "expansion" attributes exist or are integers. using (var modXml = modFile.OpenRead()) { XDocument doc = XDocument.Load(modXml); var requireElements = doc.Root.Elements("require", true); //Need nullables to support left joins. List <int?> statedRequirements = new List <int?>(); List <int?> knownRequirements = result.ExpansionNumbersUsed.Select(p => new Nullable <int>(p)).ToList(); foreach (var element in requireElements) { var expansion = element.GetIntAttribute("expansion"); if (expansion != null) { statedRequirements.Add(expansion.Value); } } //distinct list in case they repeat themselves. statedRequirements = statedRequirements.Distinct().ToList(); //left join to find missing requirements. var missingRequirements = from knownRequirement in knownRequirements join statedRequirement in statedRequirements on knownRequirement equals statedRequirement into statedRequirementGroup from statedRequirement in statedRequirementGroup.DefaultIfEmpty() where statedRequirement == null select knownRequirement; result.ModErrors.AddRange( missingRequirements.Select( p => String.Format("Expansion {0} is used by your mod, but you didn't include <require expansion=\"{0}\"/> in mod.xml", p) ) ); //the opposite left join to find overstated requirements. var overstatedRequirements = from overStatedRequirement in statedRequirements join knownRequirement in knownRequirements on overStatedRequirement equals knownRequirement into knownRequirementGroup from knownRequirement in knownRequirementGroup.DefaultIfEmpty() where knownRequirement == null select overStatedRequirement; result.ModErrors.AddRange( overstatedRequirements.Select( p => String.Format("You have <require expansion=\"{0}\"/> in mod.xml, but expansion {0} is not used by your mod.", p) ) ); } }
/// <summary> /// Performs mod structure validation, XML and XSD validation, resource validation and expansion requirement validation. /// </summary> /// <returns></returns> public ModValidationResult Validate() { ModValidationResult result = new ModValidationResult(); var modFolder = mod.GetDirectory(@"mod"); if (modFolder == null) { result.ModErrors.Add("The required folder, 'mod', was not found."); return(result); } var modFile = modFolder.GetFile("mod.xml"); if (modFile == null) { result.ModErrors.Add("The required file, 'mod/mod.xml', was not found."); return(result); } var xmlFiles = modFolder.EnumerateXmlFiles(DredmorInfo.XmlFilesToValidate, SearchOption.TopDirectoryOnly); XsdValidator xsd = new XsdValidator(); result.XmlErrors = xsd.Validate(xmlFiles, true); if (!result.IsValid && result.XmlErrors.Any(p => p.XmlExceptionOccurred)) { return(result); } resources.LoadResources(mod); result.XmlErrors.AddRange( XmlResourceValidator.Validate( xmlFiles.Where(p => p.Name.ToLower() != "mod.xml"), resources, ExpansionResourcesUsed ) .Where(p => p.Errors.Count > 0) ); result.ExpansionResourcedUsed = ExpansionResourcesUsed; result.ExpansionNumbersUsed = ExpansionResourcesUsed.Animations.Select(p => p.ExpansionNumber) .Concat(result.ExpansionResourcedUsed.Files.Select(p => p.ExpansionNumber)) .Concat(result.ExpansionResourcedUsed.ContentResources.Select(p => p.ExpansionNumber)) .Distinct() .OrderBy(p => p) .ToList(); AddRequirementErrors(result, modFile); return(result); }
/// <summary> /// Performs mod structure validation, XML and XSD validation, resource validation and expansion requirement validation. /// </summary> /// <returns></returns> public ModValidationResult Validate() { ModValidationResult result = new ModValidationResult(); var modFolder = mod.GetDirectory( @"mod" ); if ( modFolder == null ) { result.ModErrors.Add( "The required folder, 'mod', was not found." ); return result; } var modFile = modFolder.GetFile( "mod.xml" ); if ( modFile == null ) { result.ModErrors.Add( "The required file, 'mod/mod.xml', was not found." ); return result; } var xmlFiles = modFolder.EnumerateXmlFiles( DredmorInfo.XmlFilesToValidate, SearchOption.TopDirectoryOnly ); XsdValidator xsd = new XsdValidator(); result.XmlErrors = xsd.Validate( xmlFiles, true ); if ( !result.IsValid && result.XmlErrors.Any( p => p.XmlExceptionOccurred ) ) { return result; } resources.LoadResources( mod ); result.XmlErrors.AddRange( XmlResourceValidator.Validate( xmlFiles.Where( p => p.Name.ToLower() != "mod.xml" ), resources, ExpansionResourcesUsed ) .Where( p => p.Errors.Count > 0 ) ); result.ExpansionResourcedUsed = ExpansionResourcesUsed; result.ExpansionNumbersUsed = ExpansionResourcesUsed.Animations.Select( p => p.ExpansionNumber ) .Concat( result.ExpansionResourcedUsed.Files.Select( p => p.ExpansionNumber ) ) .Concat( result.ExpansionResourcedUsed.ContentResources.Select( p => p.ExpansionNumber ) ) .Distinct() .OrderBy( p => p ) .ToList(); AddRequirementErrors( result, modFile ); return result; }
private static void AddRequirementErrors( ModValidationResult result, ContentFile modFile ) { //we already loaded and used XSD validation on mod.xml annd exited if it had malformed XML, so it's safe to just load it here. //However we are not sure their "expansion" attributes exist or are integers. using ( var modXml = modFile.OpenRead() ) { XDocument doc = XDocument.Load( modXml ); var requireElements = doc.Root.Elements( "require", true ); //Need nullables to support left joins. List<int?> statedRequirements = new List<int?>(); List<int?> knownRequirements = result.ExpansionNumbersUsed.Select( p => new Nullable<int>( p ) ).ToList(); foreach ( var element in requireElements ) { var expansion = element.GetIntAttribute( "expansion" ); if ( expansion != null ) { statedRequirements.Add( expansion.Value ); } } //distinct list in case they repeat themselves. statedRequirements = statedRequirements.Distinct().ToList(); //left join to find missing requirements. var missingRequirements = from knownRequirement in knownRequirements join statedRequirement in statedRequirements on knownRequirement equals statedRequirement into statedRequirementGroup from statedRequirement in statedRequirementGroup.DefaultIfEmpty() where statedRequirement == null select knownRequirement; result.ModErrors.AddRange( missingRequirements.Select( p => String.Format( "Expansion {0} is used by your mod, but you didn't include <require expansion=\"{0}\"/> in mod.xml", p ) ) ); //the opposite left join to find overstated requirements. var overstatedRequirements = from overStatedRequirement in statedRequirements join knownRequirement in knownRequirements on overStatedRequirement equals knownRequirement into knownRequirementGroup from knownRequirement in knownRequirementGroup.DefaultIfEmpty() where knownRequirement == null select overStatedRequirement; result.ModErrors.AddRange( overstatedRequirements.Select( p => String.Format( "You have <require expansion=\"{0}\"/> in mod.xml, but expansion {0} is not used by your mod.", p ) ) ); } }
private void WriteExpansionsUsed( ModValidationResult result ) { if ( result.ExpansionNumbersUsed != null ) { this.expansionNumbers.Text = String.Join( ", ", result.ExpansionNumbersUsed ); } }
private void WriteErrors( ModValidationResult result ) { if ( result.ModErrors.Count == 0 && result.XmlErrors.Count == 0 ) { WriteHeading( "No errors! Congratulations!" ); } else { foreach ( var modError in result.ModErrors ) { WriteHeading( modError ); output.AppendText( Environment.NewLine ); output.AppendText( Environment.NewLine ); } foreach ( var fileValidationErrors in result.XmlErrors.Where( p => p.Errors.Count > 0 ) ) { WriteHeading( fileValidationErrors.Path ); WriteSubheading( fileValidationErrors.Errors.Count ); WriteErrors( fileValidationErrors.Errors ); output.AppendText( Environment.NewLine ); output.AppendText( Environment.NewLine ); } } }