• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dendrodocs / dotnet-tool / 15993184477

01 Jul 2025 07:49AM UTC coverage: 57.669% (-8.5%) from 66.139%
15993184477

Pull #52

github

web-flow
Merge 247e5cc08 into 5901c209c
Pull Request #52: Add OperationWalker support and fix implicit object creation expressions

183 of 388 branches covered (47.16%)

Branch coverage included in aggregate %.

17 of 110 new or added lines in 2 files covered. (15.45%)

475 of 753 relevant lines covered (63.08%)

0.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/DendroDocs.Tool/Analyzers/OperationBasedInvocationsAnalyzer.cs
1
using Microsoft.CodeAnalysis.Operations;
2

3
namespace DendroDocs.Tool;
4

5
/// <summary>
6
/// OperationWalker-based analyzer for method invocations, providing better support for VB.NET,
7
/// constant values, and implicit object creation expressions.
8
/// 
9
/// Benefits over CSharpSyntaxWalker:
10
/// - Language-agnostic: Works with both C# and VB.NET
11
/// - Better type information: Access to resolved types and constant values
12
/// - Unified object creation: Handles both explicit and implicit object creation seamlessly
13
/// - Enhanced semantic analysis: Works at the operation level rather than syntax level
14
/// 
15
/// Example usage for VB.NET support:
16
/// Instead of needing separate VB-specific syntax walkers, this analyzer can process
17
/// VB.NET code through IOperation, making it language-neutral.
18
/// </summary>
NEW
19
internal class OperationBasedInvocationsAnalyzer(SemanticModel semanticModel, List<Statement> statements) : OperationWalker
×
20
{
21
    // Keep semantic model available for future enhancements
NEW
22
    private readonly SemanticModel _semanticModel = semanticModel;
×
23
    public override void VisitObjectCreation(IObjectCreationOperation operation)
NEW
24
    {
×
NEW
25
        string containingType = operation.Type?.ToDisplayString() ?? string.Empty;
×
NEW
26
        string typeName = operation.Type?.Name ?? string.Empty;
×
27

NEW
28
        var invocation = new InvocationDescription(containingType, typeName);
×
NEW
29
        statements.Add(invocation);
×
30

NEW
31
        foreach (var argument in operation.Arguments)
×
NEW
32
        {
×
NEW
33
            var value = GetConstantValueOrDefault(argument.Value);
×
NEW
34
            var argumentDescription = new ArgumentDescription(argument.Value.Type?.ToDisplayString() ?? string.Empty, value);
×
NEW
35
            invocation.Arguments.Add(argumentDescription);
×
NEW
36
        }
×
37

NEW
38
        if (operation.Initializer != null)
×
NEW
39
        {
×
NEW
40
            foreach (var initializer in operation.Initializer.Initializers)
×
NEW
41
            {
×
NEW
42
                var value = initializer switch
×
NEW
43
                {
×
NEW
44
                    IAssignmentOperation assignment => assignment.Value.Syntax.ToString(),
×
NEW
45
                    _ => initializer.Syntax.ToString()
×
NEW
46
                };
×
47
                
NEW
48
                var argumentDescription = new ArgumentDescription(initializer.Type?.ToDisplayString() ?? string.Empty, value);
×
NEW
49
                invocation.Arguments.Add(argumentDescription);
×
NEW
50
            }
×
NEW
51
        }
×
52

NEW
53
        base.VisitObjectCreation(operation);
×
NEW
54
    }
×
55

56
    public override void VisitInvocation(IInvocationOperation operation)
NEW
57
    {
×
58
        // Check for nameof expression
NEW
59
        if (operation.TargetMethod.Name == "nameof" && operation.Arguments.Length == 1)
×
NEW
60
        {
×
61
            // nameof is compiler sugar, and is actually a method we are not interested in
NEW
62
            return;
×
63
        }
64

NEW
65
        var containingType = operation.TargetMethod.ContainingType?.ToDisplayString() ?? string.Empty;
×
NEW
66
        var methodName = operation.TargetMethod.Name;
×
67

NEW
68
        var invocation = new InvocationDescription(containingType, methodName);
×
NEW
69
        statements.Add(invocation);
×
70

NEW
71
        foreach (var argument in operation.Arguments)
×
NEW
72
        {
×
NEW
73
            var value = GetConstantValueOrDefault(argument.Value);
×
NEW
74
            var argumentDescription = new ArgumentDescription(argument.Value.Type?.ToDisplayString() ?? string.Empty, value);
×
NEW
75
            invocation.Arguments.Add(argumentDescription);
×
NEW
76
        }
×
77

NEW
78
        base.VisitInvocation(operation);
×
NEW
79
    }
×
80

81
    public override void VisitReturn(IReturnOperation operation)
NEW
82
    {
×
NEW
83
        var value = operation.ReturnedValue != null ? GetConstantValueOrDefault(operation.ReturnedValue) : string.Empty;
×
NEW
84
        var returnDescription = new ReturnDescription(value);
×
NEW
85
        statements.Add(returnDescription);
×
86

NEW
87
        base.VisitReturn(operation);
×
NEW
88
    }
×
89

90
    public override void VisitSimpleAssignment(ISimpleAssignmentOperation operation)
NEW
91
    {
×
NEW
92
        var target = operation.Target.Syntax.ToString();
×
NEW
93
        var value = operation.Value.Syntax.ToString();
×
94
        
NEW
95
        var assignmentDescription = new AssignmentDescription(target, "=", value);
×
NEW
96
        statements.Add(assignmentDescription);
×
97

NEW
98
        base.VisitSimpleAssignment(operation);
×
NEW
99
    }
×
100

101
    public override void VisitCompoundAssignment(ICompoundAssignmentOperation operation)
NEW
102
    {
×
NEW
103
        var target = operation.Target.Syntax.ToString();
×
NEW
104
        var value = operation.Value.Syntax.ToString();
×
NEW
105
        var operatorToken = operation.OperatorKind switch
×
NEW
106
        {
×
NEW
107
            BinaryOperatorKind.Add => "+=",
×
NEW
108
            BinaryOperatorKind.Subtract => "-=",
×
NEW
109
            BinaryOperatorKind.Multiply => "*=",
×
NEW
110
            BinaryOperatorKind.Divide => "/=",
×
NEW
111
            BinaryOperatorKind.Remainder => "%=",
×
NEW
112
            BinaryOperatorKind.And => "&=",
×
NEW
113
            BinaryOperatorKind.Or => "|=",
×
NEW
114
            BinaryOperatorKind.ExclusiveOr => "^=",
×
NEW
115
            BinaryOperatorKind.LeftShift => "<<=",
×
NEW
116
            BinaryOperatorKind.RightShift => ">>=",
×
NEW
117
            _ => "="
×
NEW
118
        };
×
119
        
NEW
120
        var assignmentDescription = new AssignmentDescription(target, operatorToken, value);
×
NEW
121
        statements.Add(assignmentDescription);
×
122

NEW
123
        base.VisitCompoundAssignment(operation);
×
NEW
124
    }
×
125

126
    private static string GetConstantValueOrDefault(IOperation operation)
NEW
127
    {
×
NEW
128
        return operation switch
×
NEW
129
        {
×
NEW
130
            ILiteralOperation literal => literal.ConstantValue.Value?.ToString() ?? string.Empty,
×
NEW
131
            IFieldReferenceOperation field when field.Field.IsConst => field.Field.ConstantValue?.ToString() ?? string.Empty,
×
NEW
132
            _ => operation.Syntax.ToString()
×
NEW
133
        };
×
NEW
134
    }
×
135
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc