// ReSharper disable once SuggestBaseTypeForParameter private static string FixAttributeContent(Match m, CompetitionTarget competitionTarget, out bool hasMatch) { var attributeStartText = m.Groups[1].Value; var attributeEndText = m.Groups[3].Value; var attributeWithoutBraces = !attributeStartText.EndsWith("("); var attributeWithoutMinMax = !m.Groups[2].Success; var attributeHasAdditionalContent = !attributeEndText.StartsWith(")"); var result = new StringBuilder(m.Length + 10); result.Append(attributeStartText); if (attributeWithoutBraces) { result.Append('('); AppendMinMax(result, competitionTarget); result.Append(')'); } else { AppendMinMax(result, competitionTarget); if (attributeWithoutMinMax && attributeHasAdditionalContent) { result.Append(", "); } } result.Append(attributeEndText); hasMatch = true; return(result.ToString()); }
// ReSharper disable once SuggestBaseTypeForParameter private static void AppendMinMax(StringBuilder result, CompetitionTarget competitionTarget) { if (!competitionTarget.IgnoreMinRatio) { result.Append(competitionTarget.MinRatioText); result.Append(", "); } // MaxText should be specified even if ignored. result.Append(competitionTarget.MaxRatioText); }
private static bool TryFixBenchmarkAttribute( AnnotateContext annotateContext, string fileName, int firstCodeLine, CompetitionTarget competitionTarget, CompetitionState competitionState) { var sourceFileLines = annotateContext.TryGetFileLines(fileName, competitionState); if (sourceFileLines.Count == 0) { return(false); } bool attributeFixed = false; for (var i = firstCodeLine - 2; i >= 0; i--) { var line = sourceFileLines[i]; if (_breakIfRegex.IsMatch(line)) { break; } bool hasMatch = false; var line2 = _attributeRegex.Replace( line, m => FixAttributeContent(m, competitionTarget, out hasMatch), 1); if (hasMatch) { if (line2 != line) { annotateContext.ReplaceLine(fileName, i, line2); } attributeFixed = true; break; } } return(attributeFixed); }
/// <summary>Adds or updates xml annotation for the competition target.</summary> /// <param name="xmlAnnotationDoc">The xml annotation document that will be updated.</param> /// <param name="competitionTarget">The competition target.</param> public static void AddOrUpdateXmlAnnotation( [NotNull] XDocument xmlAnnotationDoc, [NotNull] CompetitionTarget competitionTarget) { Code.NotNull(xmlAnnotationDoc, nameof(xmlAnnotationDoc)); Code.NotNull(competitionTarget, nameof(competitionTarget)); var competitionName = competitionTarget.Target.GetCompetitionName(xmlAnnotationDoc); var candidateName = competitionTarget.Target.GetCandidateName(); var competition = xmlAnnotationDoc .Element(CompetitionBenchmarksRootNode) .GetOrAddElement(CompetitionNode, competitionName); var candidate = competition.GetOrAddElement(CandidateNode, candidateName); var minText = competitionTarget.IgnoreMinRatio ? null : competitionTarget.MinRatioText; // MaxText should be specified even if ignored. var maxText = competitionTarget.MaxRatioText; candidate.SetAttribute(CompetitionLimitProperties.MinRatio.ToString(), minText); candidate.SetAttribute(CompetitionLimitProperties.MaxRatio.ToString(), maxText); }
private static bool TryFixBenchmarkXmlAnnotation( AnnotateContext annotateContext, string xmlFileName, CompetitionTarget competitionTarget, CompetitionState competitionState) { Code.AssertArgument( competitionTarget.CompetitionMetadata != null, nameof(competitionTarget), "Competition metadata cannot be null for xml annotations."); var xmlAnnotationDoc = annotateContext.TryGetXmlAnnotation( xmlFileName, competitionTarget.CompetitionMetadata.UseFullTypeName, competitionState); if (xmlAnnotationDoc == null) { return(false); } XmlAnnotations.AddOrUpdateXmlAnnotation(xmlAnnotationDoc, competitionTarget); annotateContext.MarkAsChanged(xmlFileName); return(true); }
/// <summary>Fills competition targets with empty metric values.</summary> /// <param name="targets">Competition targets to fill .</param> /// <param name="analysis">State of the analysis.</param> protected virtual void FillTargetsIgnoreAnnotations(List <CompetitionTarget> targets, Analysis analysis) { var ignoreCharacteristic = CompetitionAnnotationMode.IgnoreExistingAnnotationsCharacteristic.FullId; analysis.WriteInfoMessage( $"Existing metric annotations are ignored due to {ignoreCharacteristic} setting."); var metrics = analysis.RunState.Config.GetMetrics().ToArray(); var targetsToFill = analysis.Summary .GetBenchmarkTargets() .Where(t => CheckCompetitionAttribute(t, analysis)); foreach (var target in targetsToFill) { var metricValues = metrics .Where(m => !target.Baseline || !m.IsRelative) .Select(m => new CompetitionMetricValue(m)) .ToArray(); var competitionTarget = new CompetitionTarget(target, metricValues); targets.Add(competitionTarget); } }
private static bool TryUpdate( SourceAnnotationFile sourceCodeFile, CompetitionTarget competitionTarget) { if (!sourceCodeFile.Parsed) { return(false); } var target = competitionTarget.Target; var targetKey = target.Method.MethodHandle; if (!sourceCodeFile.BenchmarkMethods.TryGetValue( targetKey, out var benchmarkMethod)) { return(false); } bool allFixed = true; var metricsByCategory = competitionTarget.MetricValues.GroupBy(m => m.Metric.Category); foreach (var metricGrouping in metricsByCategory.Select(x => x.ToArray())) { var metricAttributes = metricGrouping.Select(m => m.Metric.AttributeType.TypeHandle).ToHashSet(); var attributeAppendLineNumber = benchmarkMethod.AttributeLineNumbers .Where(p => metricAttributes.Contains(p.Key)) .MinOrDefault(p => p.Value, -1); var attributeInsertLineNumber = benchmarkMethod.AttributeLineNumbers .Where(p => metricAttributes.Contains(p.Key)) .MaxOrDefault(p => p.Value, benchmarkMethod.PrimaryAttributeLineNumber); foreach (var metricValue in metricGrouping.Where(m => m.HasUnsavedChanges || m.ValuesRange.IsEmpty)) { var attributeTypeHandle = metricValue.Metric.AttributeType.TypeHandle; if (benchmarkMethod.AttributeLineNumbers.TryGetValue( attributeTypeHandle, out var attributeLineNumber)) { bool updated = TryUpdateLineWithAttribute(sourceCodeFile, attributeLineNumber, metricValue); if (updated && attributeAppendLineNumber <= 0) { attributeAppendLineNumber = attributeLineNumber; } allFixed &= updated; } else { bool inserted = false; if (metricValue.Metric.AnnotateInPlace && attributeAppendLineNumber > 0) { inserted = TryInsertAttributeInPlace( sourceCodeFile, attributeAppendLineNumber, benchmarkMethod, metricValue); } if (!inserted) { attributeInsertLineNumber = InsertLineWithAttribute( sourceCodeFile, attributeInsertLineNumber, benchmarkMethod, metricValue); if (attributeAppendLineNumber <= 0) { attributeAppendLineNumber = attributeInsertLineNumber; } } } } } return(allFixed); }
private static string TryGetAnnotationLocation( [NotNull] CompetitionTarget targetToAnnotate, [NotNull] IMessageLogger messageLogger) => SymbolHelper.TryGetSourcePath(targetToAnnotate.Target, messageLogger);
private static void TrySaveAnnotationCore( CompetitionTarget targetToAnnotate, AnnotationContext annotationContext, List <CompetitionTarget> result, IMessageLogger messageLogger) { var metrics = targetToAnnotate.MetricValues.Where(m => m.HasUnsavedChanges).ToArray(); if (metrics.Length == 0) { return; } var target = targetToAnnotate.Target; var targetKey = new AnnotationTargetKey(target.Method.MethodHandle); var annotationFile = annotationContext.TryGetDocument(targetKey); if (annotationFile == null) { var origin = TryGetAnnotationLocation(targetToAnnotate, messageLogger); if (origin == null) { annotationFile = annotationContext.GetUnknownOriginDocument(); } else { annotationFile = annotationContext.TryGetDocument(origin); if (annotationFile == null) { var soureAnnotationFile = ParseAnnotationFile(target, origin, messageLogger); annotationFile = soureAnnotationFile; annotationContext.AddDocument(annotationFile); foreach (var benchmarkMethod in soureAnnotationFile.BenchmarkMethods.Keys) { var anotherKey = new AnnotationTargetKey(benchmarkMethod); if (!targetKey.Equals(anotherKey)) { annotationContext.AddTargetKey(annotationFile, anotherKey); } } } else if (annotationFile is SourceAnnotationFile) { messageLogger.WriteSetupErrorMessage( target, $"The source file '{annotationFile.Origin}' does not contain code for method."); return; } } annotationContext.AddTargetKey(annotationFile, targetKey); } if (!annotationFile.Parsed) { messageLogger.WriteSetupErrorMessage( $"Could not find XML annotation file {annotationFile.Origin} for the benchmark. Annotations were not saved."); return; } var sourceAnnotationFile = (SourceAnnotationFile)annotationFile; messageLogger.Logger.WriteVerboseHint( $"Method {target.MethodDisplayInfo}: annotating file '{annotationFile.Origin}'"); // TODO: log line??? var annotated = TryUpdate(sourceAnnotationFile, targetToAnnotate); if (!annotated) { messageLogger.WriteSetupErrorMessage( target, $"Could not find annotations in source file '{sourceAnnotationFile.Origin}'."); } else { result.Add(targetToAnnotate); foreach (var metricValue in metrics) { messageLogger.Logger.WriteVerboseHint( $"Method {target.MethodDisplayInfo}: metric {metricValue.Metric} {metricValue} updated."); } } }