mirror of
				https://github.com/MindWorkAI/AI-Studio.git
				synced 2025-11-04 06:40:20 +00:00 
			
		
		
		
	Added this usage rule & code fix
This commit is contained in:
		
							parent
							
								
									60b58648ca
								
							
						
					
					
						commit
						db9bb8f487
					
				@ -2,9 +2,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### New Rules
 | 
					### New Rules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 Rule ID   | Category | Severity | Notes                  
 | 
					 Rule ID   | Category | Severity | Notes                       
 | 
				
			||||||
-----------|----------|----------|------------------------
 | 
					-----------|----------|----------|-----------------------------
 | 
				
			||||||
 MWAIS0001 | Usage    | Error    | ProviderAccessAnalyzer
 | 
					 MWAIS0001 | Usage    | Error    | ProviderAccessAnalyzer      
 | 
				
			||||||
 MWAIS0002 | Naming | Error | ConstStaticAnalyzer
 | 
					 MWAIS0002 | Naming   | Error    | ConstStaticAnalyzer         
 | 
				
			||||||
 MWAIS0003 | Naming | Error | UnderscorePrefixAnalyzer
 | 
					 MWAIS0003 | Naming   | Error    | UnderscorePrefixAnalyzer    
 | 
				
			||||||
 MWAIS0004 | Usage | Error | RandomInstantiationAnalyzer
 | 
					 MWAIS0004 | Usage    | Error    | RandomInstantiationAnalyzer 
 | 
				
			||||||
 | 
					 MWAIS0005 | Usage    | Error    | ThisUsageAnalyzer           
 | 
				
			||||||
@ -6,4 +6,5 @@ public static class Identifier
 | 
				
			|||||||
    public const string CONST_STATIC_ANALYZER = $"{Tools.ID_PREFIX}0002";
 | 
					    public const string CONST_STATIC_ANALYZER = $"{Tools.ID_PREFIX}0002";
 | 
				
			||||||
    public const string UNDERSCORE_PREFIX_ANALYZER = $"{Tools.ID_PREFIX}0003";
 | 
					    public const string UNDERSCORE_PREFIX_ANALYZER = $"{Tools.ID_PREFIX}0003";
 | 
				
			||||||
    public const string RANDOM_INSTANTIATION_ANALYZER = $"{Tools.ID_PREFIX}0004";
 | 
					    public const string RANDOM_INSTANTIATION_ANALYZER = $"{Tools.ID_PREFIX}0004";
 | 
				
			||||||
 | 
					    public const string THIS_USAGE_ANALYZER = $"{Tools.ID_PREFIX}0005";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -0,0 +1,236 @@
 | 
				
			|||||||
 | 
					using System.Collections.Immutable;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CSharp;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CSharp.Syntax;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.Diagnostics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace SourceCodeRules.UsageAnalyzers;
 | 
				
			||||||
 | 
					#pragma warning disable RS1038
 | 
				
			||||||
 | 
					[DiagnosticAnalyzer(LanguageNames.CSharp)]
 | 
				
			||||||
 | 
					#pragma warning restore RS1038
 | 
				
			||||||
 | 
					public sealed class ThisUsageAnalyzer : DiagnosticAnalyzer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private const string DIAGNOSTIC_ID = Identifier.THIS_USAGE_ANALYZER;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static readonly string TITLE = "`this.` must be used";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static readonly string MESSAGE_FORMAT = "`this.` must be used to access variables, methods, and properties";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static readonly string DESCRIPTION = MESSAGE_FORMAT;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private const string CATEGORY = "Usage";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static readonly DiagnosticDescriptor RULE = new(DIAGNOSTIC_ID, TITLE, MESSAGE_FORMAT, CATEGORY, DiagnosticSeverity.Error, isEnabledByDefault: true, description: DESCRIPTION);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [RULE];
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public override void Initialize(AnalysisContext context)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
 | 
				
			||||||
 | 
					        context.EnableConcurrentExecution();
 | 
				
			||||||
 | 
					        context.RegisterSyntaxNodeAction(this.AnalyzeIdentifier, SyntaxKind.IdentifierName);
 | 
				
			||||||
 | 
					        context.RegisterSyntaxNodeAction(this.AnalyzeGenericName, SyntaxKind.GenericName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private void AnalyzeGenericName(SyntaxNodeAnalysisContext context)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var genericNameSyntax = (GenericNameSyntax)context.Node;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Skip if already part of a 'this' expression
 | 
				
			||||||
 | 
					        if (IsAccessedThroughThis(genericNameSyntax))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        if (IsWithinInitializer(genericNameSyntax))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (IsPartOfMemberAccess(genericNameSyntax))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Get symbol info for the generic name
 | 
				
			||||||
 | 
					        var symbolInfo = context.SemanticModel.GetSymbolInfo(genericNameSyntax);
 | 
				
			||||||
 | 
					        var symbol = symbolInfo.Symbol;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (symbol == null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        // Skip static methods
 | 
				
			||||||
 | 
					        if (symbol.IsStatic)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        // Skip local functions
 | 
				
			||||||
 | 
					        if (symbol is IMethodSymbol methodSymbol && IsLocalFunction(methodSymbol))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Get the containing type of the current context
 | 
				
			||||||
 | 
					        var containingSymbol = context.ContainingSymbol;
 | 
				
			||||||
 | 
					        var currentType = containingSymbol?.ContainingType;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // If we're in a static context, allow accessing members without this
 | 
				
			||||||
 | 
					        if (IsInStaticContext(containingSymbol))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (symbol is IMethodSymbol)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var containingType = symbol.ContainingType;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // If the symbol is a member of the current type or a base type, then require this
 | 
				
			||||||
 | 
					            if (currentType != null && (SymbolEqualityComparer.Default.Equals(containingType, currentType) || 
 | 
				
			||||||
 | 
					                                        IsBaseTypeOf(containingType, currentType)))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var diagnostic = Diagnostic.Create(RULE, genericNameSyntax.Identifier.GetLocation());
 | 
				
			||||||
 | 
					                context.ReportDiagnostic(diagnostic);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private void AnalyzeIdentifier(SyntaxNodeAnalysisContext context)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var identifierNameSyntax = (IdentifierNameSyntax)context.Node;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Skip if this identifier is part of a generic name - we'll handle that separately
 | 
				
			||||||
 | 
					        if (identifierNameSyntax.Parent is GenericNameSyntax)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Skip if already part of a 'this' expression
 | 
				
			||||||
 | 
					        if (IsAccessedThroughThis(identifierNameSyntax))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        if (IsWithinInitializer(identifierNameSyntax))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (IsPartOfMemberAccess(identifierNameSyntax))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Also skip if it's part of static import statements
 | 
				
			||||||
 | 
					        if (IsPartOfUsingStaticDirective(identifierNameSyntax))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        // Skip if it's part of a namespace or type name
 | 
				
			||||||
 | 
					        if (IsPartOfNamespaceOrTypeName(identifierNameSyntax))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Get symbol info
 | 
				
			||||||
 | 
					        var symbolInfo = context.SemanticModel.GetSymbolInfo(identifierNameSyntax);
 | 
				
			||||||
 | 
					        var symbol = symbolInfo.Symbol;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (symbol == null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        // Skip local variables, parameters, and range variables
 | 
				
			||||||
 | 
					        if (symbol.Kind is SymbolKind.Local or SymbolKind.Parameter or SymbolKind.RangeVariable or SymbolKind.TypeParameter)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        // Skip types and namespaces
 | 
				
			||||||
 | 
					        if (symbol.Kind is SymbolKind.NamedType or SymbolKind.Namespace)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Explicitly check if this is a local function
 | 
				
			||||||
 | 
					        if (symbol is IMethodSymbol methodSymbol && IsLocalFunction(methodSymbol))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        // Get the containing type of the current context
 | 
				
			||||||
 | 
					        var containingSymbol = context.ContainingSymbol;
 | 
				
			||||||
 | 
					        var currentType = containingSymbol?.ContainingType;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // If we're in a static context, allow accessing members without this
 | 
				
			||||||
 | 
					        if (IsInStaticContext(containingSymbol))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        // Now check if the symbol is an instance member of the current class
 | 
				
			||||||
 | 
					        if (symbol is IFieldSymbol or IPropertySymbol or IMethodSymbol or IEventSymbol)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Skip static members
 | 
				
			||||||
 | 
					            if (symbol.IsStatic)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            // Skip constants
 | 
				
			||||||
 | 
					            if (symbol is IFieldSymbol { IsConst: true })
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            var containingType = symbol.ContainingType;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // If the symbol is a member of the current type or a base type, then require this
 | 
				
			||||||
 | 
					            if (currentType != null && (SymbolEqualityComparer.Default.Equals(containingType, currentType) || 
 | 
				
			||||||
 | 
					                                        IsBaseTypeOf(containingType, currentType)))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var diagnostic = Diagnostic.Create(RULE, identifierNameSyntax.GetLocation());
 | 
				
			||||||
 | 
					                context.ReportDiagnostic(diagnostic);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static bool IsLocalFunction(IMethodSymbol methodSymbol) => methodSymbol.MethodKind is MethodKind.LocalFunction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static bool IsBaseTypeOf(INamedTypeSymbol baseType, INamedTypeSymbol derivedType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var currentType = derivedType.BaseType;
 | 
				
			||||||
 | 
					        while (currentType != null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (SymbolEqualityComparer.Default.Equals(currentType, baseType))
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            currentType = currentType.BaseType;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static bool IsInStaticContext(ISymbol? containingSymbol) => containingSymbol?.IsStatic is true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static bool IsAccessedThroughThis(SyntaxNode node)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (node.Parent is MemberAccessExpressionSyntax memberAccess)
 | 
				
			||||||
 | 
					            if (memberAccess.Expression is ThisExpressionSyntax && memberAccess.Name == node)
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static bool IsWithinInitializer(SyntaxNode node)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (var current = node.Parent; current != null; current = current.Parent)
 | 
				
			||||||
 | 
					            if (current is InitializerExpressionSyntax)
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static bool IsPartOfMemberAccess(SyntaxNode node)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Check if the node is part of a member access expression where the expression is not 'this':
 | 
				
			||||||
 | 
					        if (node.Parent is MemberAccessExpressionSyntax memberAccess)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // If the member access expression is 'this', it's allowed:
 | 
				
			||||||
 | 
					            if (memberAccess.Expression is ThisExpressionSyntax)
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // If the member access expression is something else (e.g., instance.Member), skip:
 | 
				
			||||||
 | 
					            if (memberAccess.Name == node)
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Also check for conditional access expressions (e.g., instance?.Member):
 | 
				
			||||||
 | 
					        if (node.Parent is ConditionalAccessExpressionSyntax)
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static bool IsPartOfUsingStaticDirective(SyntaxNode node)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (var current = node.Parent; current != null; current = current.Parent)
 | 
				
			||||||
 | 
					            if (current is UsingDirectiveSyntax)
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static bool IsPartOfNamespaceOrTypeName(SyntaxNode node)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Check if a node is part of a namespace, class, or type declaration:
 | 
				
			||||||
 | 
					        if (node.Parent is NameSyntax && node.Parent is not MemberAccessExpressionSyntax)
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					using System.Collections.Immutable;
 | 
				
			||||||
 | 
					using System.Composition;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CodeActions;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CodeFixes;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CSharp;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CSharp.Syntax;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace SourceCodeRules.UsageCodeFixes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ThisUsageCodeFixProvider)), Shared]
 | 
				
			||||||
 | 
					public class ThisUsageCodeFixProvider : CodeFixProvider
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private const string TITLE = "Add 'this.' prefix";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public sealed override ImmutableArray<string> FixableDiagnosticIds => [Identifier.THIS_USAGE_ANALYZER];
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
 | 
				
			||||||
 | 
					        if (root == null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        var diagnostic = context.Diagnostics.First();
 | 
				
			||||||
 | 
					        var diagnosticSpan = diagnostic.Location.SourceSpan;
 | 
				
			||||||
 | 
					        var node = root.FindNode(diagnosticSpan);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (node is IdentifierNameSyntax identifierNode)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            context.RegisterCodeFix(
 | 
				
			||||||
 | 
					                CodeAction.Create(
 | 
				
			||||||
 | 
					                    title: TITLE,
 | 
				
			||||||
 | 
					                    createChangedDocument: c => AddThisPrefixAsync(context.Document, identifierNode, c),
 | 
				
			||||||
 | 
					                    equivalenceKey: nameof(ThisUsageCodeFixProvider)),
 | 
				
			||||||
 | 
					                diagnostic);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (node is GenericNameSyntax genericNameNode)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            context.RegisterCodeFix(
 | 
				
			||||||
 | 
					                CodeAction.Create(
 | 
				
			||||||
 | 
					                    title: TITLE,
 | 
				
			||||||
 | 
					                    createChangedDocument: c => AddThisPrefixAsync(context.Document, genericNameNode, c),
 | 
				
			||||||
 | 
					                    equivalenceKey: nameof(ThisUsageCodeFixProvider)),
 | 
				
			||||||
 | 
					                diagnostic);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static async Task<Document> AddThisPrefixAsync(Document document, SyntaxNode node, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var root = await document.GetSyntaxRootAsync(cancellationToken);
 | 
				
			||||||
 | 
					        if (root == null)
 | 
				
			||||||
 | 
					            return document;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        var thisExpression = SyntaxFactory.ThisExpression();
 | 
				
			||||||
 | 
					        var leadingTrivia = node.GetLeadingTrivia();
 | 
				
			||||||
 | 
					        var memberAccessExpression = SyntaxFactory.MemberAccessExpression(
 | 
				
			||||||
 | 
					                SyntaxKind.SimpleMemberAccessExpression,
 | 
				
			||||||
 | 
					                thisExpression.WithLeadingTrivia(leadingTrivia), 
 | 
				
			||||||
 | 
					                ((SimpleNameSyntax)node).WithLeadingTrivia(SyntaxTriviaList.Empty))
 | 
				
			||||||
 | 
					            .WithTrailingTrivia(node.GetTrailingTrivia());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var newRoot = root.ReplaceNode(node, memberAccessExpression);
 | 
				
			||||||
 | 
					        return document.WithSyntaxRoot(newRoot);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user