// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #if HAS_IOPERATION using System; using System.Collections.Immutable; namespace Microsoft.CodeAnalysis.CodeMetrics { public abstract partial class CodeAnalysisMetricData { private sealed class MethodMetricData : CodeAnalysisMetricData { internal MethodMetricData( IMethodSymbol symbol, int maintainabilityIndex, ComputationalComplexityMetrics computationalComplexityMetrics, ImmutableHashSet<INamedTypeSymbol> coupledNamedTypes, long linesOfCode, int cyclomaticComplexity, int? depthOfInheritance) : base(symbol, maintainabilityIndex, computationalComplexityMetrics, coupledNamedTypes, linesOfCode, cyclomaticComplexity, depthOfInheritance, children: ImmutableArray<CodeAnalysisMetricData>.Empty) { } internal static MethodMetricData Compute(IMethodSymbol method, CodeMetricsAnalysisContext context) { var coupledTypesBuilder = ImmutableHashSet.CreateBuilder<INamedTypeSymbol>(); ImmutableArray<SyntaxReference> declarations = method.DeclaringSyntaxReferences; long linesOfCode = MetricsHelper.GetLinesOfCode(declarations, method, context); (int cyclomaticComplexity, ComputationalComplexityMetrics computationalComplexityMetrics) = MetricsHelper.ComputeCoupledTypesAndComplexityExcludingMemberDecls(declarations, method, coupledTypesBuilder, context); MetricsHelper.AddCoupledNamedTypes(coupledTypesBuilder, context.WellKnownTypeProvider, method.Parameters); if (!method.ReturnsVoid) { MetricsHelper.AddCoupledNamedTypes(coupledTypesBuilder, context.WellKnownTypeProvider, method.ReturnType); } int? depthOfInheritance = null; int maintainabilityIndex = CalculateMaintainabilityIndex(computationalComplexityMetrics, cyclomaticComplexity); MetricsHelper.RemoveContainingTypes(method, coupledTypesBuilder); if (cyclomaticComplexity == 0) { // Empty method, such as auto-generated accessor. cyclomaticComplexity = 1; } return new MethodMetricData(method, maintainabilityIndex, computationalComplexityMetrics, coupledTypesBuilder.ToImmutable(), linesOfCode, cyclomaticComplexity, depthOfInheritance); } private static int CalculateMaintainabilityIndex(ComputationalComplexityMetrics computationalComplexityMetrics, int cyclomaticComplexity) { double computationalComplexityVolume = Math.Max(0.0, Math.Log(computationalComplexityMetrics.Volume)); //avoid Log(0) = -Infinity double logEffectiveLinesOfCode = Math.Max(0.0, Math.Log(computationalComplexityMetrics.EffectiveLinesOfCode)); //avoid Log(0) = -Infinity return MetricsHelper.NormalizeAndRoundMaintainabilityIndex(171 - 5.2 * computationalComplexityVolume - 0.23 * cyclomaticComplexity - 16.2 * logEffectiveLinesOfCode); } } } } #endif |