private static PropertyDeclarationSyntax GetSimpleProperty(PropertyDeclarationSyntax property, VariableDeclaratorSyntax variableDeclarator) { var simpleGetSetPropetie = property.WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)), SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)) }))); return variableDeclarator.Initializer == null ? simpleGetSetPropetie : simpleGetSetPropetie.WithInitializer(variableDeclarator.Initializer) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); }
private async Task<Document> UseDeclarationExpression(Document document, ArgumentSyntax argument, VariableDeclaratorSyntax declarator, CancellationToken cancellationToken) { // get variable declaration var declaration = declarator.Parent; // get statement which contains both local declaration statement and method call with out argument var statement = DiagnosticAnalyzer.GetContainingStatement(declaration.Parent); // remove entire local declaration statement or just single variable declaration // depending on how many variables are declared within single local declaration statement var nodeToRemove = declaration.ChildNodes().OfType<VariableDeclaratorSyntax>().Count() > 1 ? declarator : declaration.Parent; var newStatement = statement.RemoveNode(nodeToRemove, SyntaxRemoveOptions.KeepEndOfLine); // get variable type var type = declaration.ChildNodes().First() as TypeSyntax; // create new Declaration Expression using variable type and declarator var newDeclarationExpression = SyntaxFactory.DeclarationExpression(type, declarator); // fix the trivia aroung Declaration Expression var firstToken = newDeclarationExpression.GetFirstToken(); var leadingTrivia = firstToken.LeadingTrivia; var trimmedDeclarationExpression = newDeclarationExpression.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(SyntaxTriviaList.Empty)); // get ArgumentSyntax from newStatement which is equivalent to argument from original syntax tree var newArgument = newStatement.DescendantNodes() .FirstOrDefault(n => n.IsEquivalentTo(argument)); // replace argument with new version, containing Declaration Expression newStatement = newStatement.ReplaceNode(newArgument.ChildNodes().First(), trimmedDeclarationExpression); // get root for current document and replace statement with new version var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(statement, newStatement); // return document with modified syntax return document.WithSyntaxRoot(newRoot); }
private static TypeDeclarationSyntax AddDisposeDeclarationToDisposeMethod(VariableDeclaratorSyntax variableDeclarator, TypeDeclarationSyntax type, INamedTypeSymbol typeSymbol) { var disposableMethod = typeSymbol.GetMembers("Dispose").OfType<IMethodSymbol>().FirstOrDefault(d => d.Arity == 0); var disposeStatement = SyntaxFactory.ParseStatement($"{variableDeclarator.Identifier.ToString()}.Dispose();"); TypeDeclarationSyntax newType; if (disposableMethod == null) { var disposeMethod = SyntaxFactory.MethodDeclaration(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)), "Dispose") .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword))) .WithBody(SyntaxFactory.Block(disposeStatement)) .WithAdditionalAnnotations(Formatter.Annotation); newType = ((dynamic)type).AddMembers(disposeMethod); } else { var existingDisposeMethod = (MethodDeclarationSyntax)disposableMethod.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); if (type.Members.Contains(existingDisposeMethod)) { var newDisposeMethod = existingDisposeMethod.AddBodyStatements(disposeStatement) .WithAdditionalAnnotations(Formatter.Annotation); newType = type.ReplaceNode(existingDisposeMethod, newDisposeMethod); } else { //we will simply anotate the code for now, but ideally we would change another document //for this to work we have to be able to fix more than one doc var fieldDeclaration = variableDeclarator.Parent.Parent; var newFieldDeclaration = fieldDeclaration.WithTrailingTrivia(SyntaxFactory.ParseTrailingTrivia($"//add {disposeStatement.ToString()} to the Dispose method on another file.").AddRange(fieldDeclaration.GetTrailingTrivia())) .WithLeadingTrivia(fieldDeclaration.GetLeadingTrivia()); newType = type.ReplaceNode(fieldDeclaration, newFieldDeclaration); } } return newType; }
public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node) { if (node.Identifier.ToString() == renameFrom.ToString()) node = node.WithIdentifier(renameTo); return base.VisitVariableDeclarator(node); }
internal SourceMemberFieldSymbol( SourceMemberContainerTypeSymbol containingType, VariableDeclaratorSyntax declarator, DeclarationModifiers modifiers, bool modifierErrors, DiagnosticBag diagnostics) : base(containingType, declarator.Identifier.ValueText, declarator.GetReference(), declarator.Identifier.GetLocation()) { this.modifiers = modifiers; this.CheckAccessibility(diagnostics); var location = Location; if (modifierErrors) { // skip the following checks } else if (containingType.IsSealed && (DeclaredAccessibility == Accessibility.Protected || DeclaredAccessibility == Accessibility.ProtectedOrInternal)) { diagnostics.Add(AccessCheck.GetProtectedMemberInSealedTypeError(containingType), location, this); } else if (IsVolatile && IsReadOnly) { diagnostics.Add(ErrorCode.ERR_VolatileAndReadonly, location, this); } else if (containingType.IsStatic && !IsStatic) { diagnostics.Add(ErrorCode.ERR_InstanceMemberInStaticClass, location, this); } // TODO: Consider checking presence of core type System.Runtime.CompilerServices.IsVolatile // if there is a volatile modifier. Perhaps an appropriate error should be reported if the // type isn’t available. }
/// <summary> /// Normalizes the <paramref name="declaration" />. /// </summary> public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax declaration) { var objectCreation = declaration?.Initializer?.Value as ObjectCreationExpressionSyntax; if (objectCreation == null) return declaration; var symbol = SemanticModel.GetDeclaredSymbol(declaration); if (symbol == null) return declaration; ITypeSymbol type; string name; switch (symbol.Kind) { case SymbolKind.Field: var fieldSymbol = ((IFieldSymbol)symbol); type = fieldSymbol.Type; name = fieldSymbol.Name; break; case SymbolKind.Local: var localSymbol = ((ILocalSymbol)symbol); type = localSymbol.Type; name = localSymbol.Name; break; default: return declaration; } var fault = SemanticModel.GetTypeSymbol<Fault>(); if (!type.Equals(fault) && !type.IsDerivedFrom(fault)) return declaration; return declaration.WithInitializer(declaration.Initializer.WithValue(AddNameInitializer(fault, objectCreation, name))); }
protected override void CompileDefaultInitialization(VariableDeclaratorSyntax declarator, TypeSyntax type) { Write("="); Write(Space); Write("("); CompileExpression(type); Write(")0"); }
internal FieldMemberBuilder(NamedTypeSymbol owner, Binder enclosing, FieldDeclarationSyntax declaration, TypeSymbol type, VariableDeclaratorSyntax declarator) : base(enclosing.Location(declarator) as SourceLocation, owner, enclosing) { this.owner = owner; this.declaration = declaration; this.declarator = declarator; this.Type = type; }
/// <summary> /// Returns true if the given expression flows in the target. /// </summary> /// <param name="variable">Variable</param> /// <param name="target">Target</param> /// <param name="syntaxNode">SyntaxNode</param> /// <param name="cfgNode">ControlFlowGraphNode</param> /// <param name="targetSyntaxNode">Target syntaxNode</param> /// <param name="targetCfgNode">Target controlFlowGraphNode</param> /// <param name="model">SemanticModel</param> /// <returns>Boolean</returns> internal static bool FlowsIntoTarget(VariableDeclaratorSyntax variable, ISymbol target, SyntaxNode syntaxNode, ControlFlowGraphNode cfgNode, SyntaxNode targetSyntaxNode, ControlFlowGraphNode targetCfgNode, SemanticModel model) { ISymbol reference = model.GetDeclaredSymbol(variable); return DataFlowAnalysis.FlowsIntoTarget(reference, target, syntaxNode, cfgNode, targetSyntaxNode, targetCfgNode); }
public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node) { var substitution = result.Find(node); return substitution != null ? substitution.Substitute() : base.VisitVariableDeclarator(node); }
private void TypeChecks(TypeSymbol type, BaseFieldDeclarationSyntax fieldSyntax, VariableDeclaratorSyntax declarator, DiagnosticBag diagnostics) { if (type.IsStatic) { // Cannot declare a variable of static type '{0}' diagnostics.Add(ErrorCode.ERR_VarDeclIsStaticClass, this.Location, type); } else if (type.SpecialType == SpecialType.System_Void) { diagnostics.Add(ErrorCode.ERR_FieldCantHaveVoidType, fieldSyntax.Declaration.Type.Location); } else if (type.IsRestrictedType()) { diagnostics.Add(ErrorCode.ERR_FieldCantBeRefAny, fieldSyntax.Declaration.Type.Location, type); } else if (IsConst && !type.CanBeConst()) { SyntaxToken constToken = default(SyntaxToken); foreach (var modifier in fieldSyntax.Modifiers) { if (modifier.CSharpKind() == SyntaxKind.ConstKeyword) { constToken = modifier; break; } } Debug.Assert(constToken.CSharpKind() == SyntaxKind.ConstKeyword); diagnostics.Add(ErrorCode.ERR_BadConstType, constToken.GetLocation(), type); } else { if (ContainingType.TypeKind == TypeKind.Struct && !IsStatic && !IsConst) { var initializerOpt = declarator.Initializer; if (initializerOpt != null) { // '{0}': cannot have instance field initializers in structs diagnostics.Add(ErrorCode.ERR_FieldInitializerInStruct, this.Location, this); } } if (IsVolatile && !type.IsValidVolatileFieldType()) { // '{0}': a volatile field cannot be of the type '{1}' diagnostics.Add(ErrorCode.ERR_VolatileStruct, this.Location, this, type); } } HashSet<DiagnosticInfo> useSiteDiagnostics = null; if (!this.IsNoMoreVisibleThan(type, ref useSiteDiagnostics)) { // Inconsistent accessibility: field type '{1}' is less accessible than field '{0}' diagnostics.Add(ErrorCode.ERR_BadVisFieldType, this.Location, this, type); } diagnostics.Add(this.Location, useSiteDiagnostics); }
internal static BoundStatement AddSequencePoint(VariableDeclaratorSyntax declaratorSyntax, BoundStatement rewrittenStatement) { SyntaxNode node; TextSpan? part; GetBreakpointSpan(declaratorSyntax, out node, out part); var result = BoundSequencePoint.Create(declaratorSyntax, part, rewrittenStatement); result.WasCompilerGenerated = rewrittenStatement.WasCompilerGenerated; return result; }
public static string GetDescription(this VariableDeclarationSyntax declaration, VariableDeclaratorSyntax declarator) { var result = new StringBuilder(); result.Append(declaration.Type.ToStringIgnoringMacroReferences()); result.Append(" "); result.Append(declarator.Identifier.GetFullyQualifiedName()); return result.ToString().Replace(Environment.NewLine, string.Empty); }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { if (node.Ancestors().Any(x => x is FunctionDefinitionSyntax)) CreateTag(node.Identifier, _classificationService.LocalVariableIdentifier); else if (node.Ancestors().Any(x => x is TypeDefinitionSyntax)) CreateTag(node.Identifier, _classificationService.FieldIdentifier); else CreateTag(node.Identifier, _classificationService.GlobalVariableIdentifier); base.VisitVariableDeclarator(node); }
private async Task<Document> MakeParameterAsync(Document document, VariableDeclaratorSyntax typeDecl, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); string varKeyword = string.Empty, varName = string.Empty; //Predefined variable type (string, int, etc...) var preDefType = typeDecl.Parent.ChildNodes().OfType<PredefinedTypeSyntax>().FirstOrDefault(); if (preDefType != null) { varKeyword = preDefType.Keyword.ToString(); var varDecl = typeDecl.Parent.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault(); varName = varDecl?.Identifier.ToString(); } else //var { var identName = typeDecl.Parent.ChildNodes().OfType<IdentifierNameSyntax>().FirstOrDefault(); //Access the semantic model to determine actual type var model = document.GetSemanticModelAsync().Result; var type = model.GetTypeInfo(identName).Type; varKeyword = type.ToMinimalDisplayString(model, typeDecl.SpanStart); var varDecl = typeDecl.Parent.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault(); varName = varDecl?.Identifier.ToString(); } MethodDeclarationSyntax mds = typeDecl.Ancestors().OfType<MethodDeclarationSyntax>().FirstOrDefault(); //Add the existing and new parameters ParameterSyntax ps = SyntaxFactory.Parameter(SyntaxFactory.Identifier(string.Concat(varKeyword, " ", varName))); var newList = SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList<ParameterSyntax>().AddRange( mds.ParameterList.ChildNodes().OfType<ParameterSyntax>()).Add(ps)); var methodNode = typeDecl.Ancestors().OfType<MethodDeclarationSyntax>().FirstOrDefault(); var variableNode = typeDecl.Parent.Parent; var variableParentNode = typeDecl.Parent.Parent.Parent; //Track the nodes we'll be using var newRoot = root.TrackNodes(methodNode, variableNode, variableParentNode); //Remode/replace the variable declaration var trackedVariableParentNode = newRoot.GetCurrentNode(variableParentNode); var trackedVariableNode = newRoot.GetCurrentNode(variableNode); var newVariableParentNode = trackedVariableParentNode.RemoveNode(trackedVariableNode, SyntaxRemoveOptions.KeepNoTrivia); newRoot = newRoot.ReplaceNode(trackedVariableParentNode, newVariableParentNode); //Replace the method parameters var trackedMethodNode = newRoot.GetCurrentNode(methodNode); var newMethodNode = trackedMethodNode.ReplaceNode(trackedMethodNode.ParameterList, newList); newRoot = newRoot.ReplaceNode(trackedMethodNode, newMethodNode); return document.WithSyntaxRoot(newRoot); }
private ReferenceRewriter( SemanticModel semanticModel, VariableDeclaratorSyntax variableDeclarator, ExpressionSyntax expressionToInline, CancellationToken cancellationToken) { _semanticModel = semanticModel; _localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(variableDeclarator, cancellationToken); _variableDeclarator = variableDeclarator; _expressionToInline = expressionToInline; _cancellationToken = cancellationToken; }
internal SourceFixedFieldSymbol( SourceMemberContainerTypeSymbol containingType, VariableDeclaratorSyntax declarator, DeclarationModifiers modifiers, bool modifierErrors, DiagnosticBag diagnostics) : base(containingType, declarator, modifiers, modifierErrors, diagnostics) { // Checked in parser: a fixed field declaration requires a length in square brackets Debug.Assert(this.IsFixed); }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { if (node.ArgumentList != null) { foreach (var arg in node.ArgumentList.Arguments) { Visit(arg.Expression); } } VisitNodeToBind(node.Initializer); }
private static SyntaxNode MakeMultipleFieldsReadonly(SyntaxNode root, FieldDeclarationSyntax fieldDeclaration, VariableDeclaratorSyntax variableToMakeReadonly) { var newDeclaration = fieldDeclaration.Declaration.RemoveNode(variableToMakeReadonly, SyntaxRemoveOptions.KeepEndOfLine); var newFieldDeclaration = fieldDeclaration.WithDeclaration(newDeclaration); var newReadonlyFieldDeclaration = fieldDeclaration.WithDeclaration(SyntaxFactory.VariableDeclaration(fieldDeclaration.Declaration.Type, SyntaxFactory.SeparatedList(new[] { variableToMakeReadonly }))) .WithoutLeadingTrivia() .WithTrailingTrivia(SyntaxFactory.ParseTrailingTrivia("\n")) .AddModifiers(SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword)) .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(fieldDeclaration, new[] { newFieldDeclaration, newReadonlyFieldDeclaration }); return newRoot; }
public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax variable) { // Retrieve the symbol for the variable declarator var field = variable.Parent.Parent as FieldDeclarationSyntax; if (field != null && field.Declaration.Variables.Count == 1) { if (object.Equals(semanticModel.GetDeclaredSymbol(variable), backingField)) { return null; } } return variable; }
internal SourceMemberFieldSymbol( SourceMemberContainerTypeSymbol containingType, VariableDeclaratorSyntax declarator, DeclarationModifiers modifiers, bool modifierErrors, DiagnosticBag diagnostics) : base(containingType, declarator.Identifier.ValueText, declarator.GetReference(), declarator.Identifier.GetLocation()) { _modifiers = modifiers; _hasInitializer = declarator.Initializer != null; this.CheckAccessibility(diagnostics); if (!modifierErrors) { this.ReportModifiersDiagnostics(diagnostics); } }
internal static void GetBreakpointSpan(VariableDeclaratorSyntax declaratorSyntax, out SyntaxNode node, out TextSpan? part) { var declarationSyntax = (VariableDeclarationSyntax)declaratorSyntax.Parent; if (declarationSyntax.Variables.First() == declaratorSyntax) { switch (declarationSyntax.Parent.Kind) { case SyntaxKind.EventFieldDeclaration: case SyntaxKind.FieldDeclaration: var modifiers = ((BaseFieldDeclarationSyntax)declarationSyntax.Parent).Modifiers; GetFirstLocalOrFieldBreakpointSpan(modifiers, declaratorSyntax, out node, out part); break; case SyntaxKind.LocalDeclarationStatement: // only const locals have modifiers and those don't have a sequence point: Debug.Assert(!((LocalDeclarationStatementSyntax)declarationSyntax.Parent).Modifiers.Any()); GetFirstLocalOrFieldBreakpointSpan(default(SyntaxTokenList), declaratorSyntax, out node, out part); break; case SyntaxKind.UsingStatement: case SyntaxKind.FixedStatement: case SyntaxKind.ForStatement: // for ([|int i = 1|]; i < 10; i++) // for ([|int i = 1|], j = 0; i < 10; i++) node = declarationSyntax; part = TextSpan.FromBounds(declarationSyntax.SpanStart, declaratorSyntax.Span.End); break; default: throw ExceptionUtilities.Unreachable; } } else { // int x = 1, [|y = 2|]; // public static int x = 1, [|y = 2|]; // for (int i = 1, [|j = 0|]; i < 10; i++) node = declaratorSyntax; part = null; } }
private static IEnumerable<VariableDeclaratorSyntax> GetConvertedDeclarators(VariableDeclaratorSyntax declarator) { var declarators = declarator.Names.Select(n => SyntaxFactory.VariableDeclarator( SyntaxFactory.SeparatedList(new[] { n }), declarator.AsClause, null)) .ToList(); if (declarator.Initializer != null) { var last = declarators.Last(); last = last.WithInitializer(declarator.Initializer); declarators[declarators.Count - 1] = last; } return declarators.Select(d => d.WithTrailingTrivia(SyntaxFactory.EndOfLineTrivia(Environment.NewLine)) .WithAdditionalAnnotations(Formatter.Annotation)); }
static CodeAction HandleUsingStatement(Document document, Microsoft.CodeAnalysis.Text.TextSpan span, SyntaxNode root, UsingStatementSyntax usingStatement, VariableDeclaratorSyntax variable) { return CodeActionFactory.Create( span, DiagnosticSeverity.Info, "Iterate via 'foreach'", ct => { ForEachStatementSyntax foreachStmt = BuildForeach(SyntaxFactory.IdentifierName(variable.Identifier)); var innerBlock = usingStatement.Statement.EnsureBlock(); var newBlock = innerBlock.WithStatements(innerBlock.Statements.Insert(0, foreachStmt)).WithAdditionalAnnotations(Formatter.Annotation); var newUsing = usingStatement.WithStatement(newBlock); var newRoot = root.ReplaceNode(usingStatement, newUsing.WithTrailingTrivia(usingStatement.GetTrailingTrivia())); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ); }
private static void CheckField(SyntaxNodeAnalysisContext c, VariableDeclaratorSyntax variableDeclarator) { var fieldSymbol = c.SemanticModel.GetDeclaredSymbol(variableDeclarator) as IFieldSymbol; if (fieldSymbol == null) { return; } var fieldName = fieldSymbol.Name; var fieldNameLower = fieldSymbol.Name.ToLower(); var declaringType = fieldSymbol.ContainingType; var baseType = declaringType.BaseType; while (baseType != null && !(baseType is IErrorTypeSymbol)) { var similarFields = baseType.GetMembers() .OfType<IFieldSymbol>() .Where(field => field.DeclaredAccessibility != Accessibility.Private) .Where(field => field.Name.ToLower() == fieldNameLower) .ToList(); if (similarFields.Any(field => field.Name == fieldName)) { c.ReportDiagnostic(Diagnostic.Create(Rule, variableDeclarator.Identifier.GetLocation(), string.Format(MessageMatch, fieldName, baseType.Name))); return; } if (similarFields.Any()) { c.ReportDiagnostic(Diagnostic.Create(Rule, variableDeclarator.Identifier.GetLocation(), string.Format(MessageSimilar, fieldName, baseType.Name, similarFields.First().Name))); return; } baseType = baseType.BaseType; } }
internal static void GetFirstLocalOrFieldBreakpointSpan(SyntaxTokenList modifiers, VariableDeclaratorSyntax declaratorSyntax, out SyntaxNode node, out TextSpan? part) { var declarationSyntax = (VariableDeclarationSyntax)declaratorSyntax.Parent; int start = modifiers.Any() ? modifiers[0].SpanStart : declarationSyntax.SpanStart; int end; if (declarationSyntax.Variables.Count == 1) { // [|int x = 1;|] // [|public static int x = 1;|] end = declarationSyntax.Parent.Span.End; } else { // [|int x = 1|], y = 2; // [|public static int x = 1|], y = 2; end = declaratorSyntax.Span.End; } part = TextSpan.FromBounds(start, end); node = declarationSyntax.Parent; }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { // we take only the first declaration we found // so if this field definition has more than one variable declaration, // skip after the first one if (MixinReference != null) return; var fieldSymbol = (IFieldSymbol)_semantic.GetDeclaredSymbol(node); var typeOfField = fieldSymbol.Type; // type could not be resolved => return here if (typeOfField.TypeKind == TypeKind.Error) return; // also ignore native types (like int, string, double etc...) // we identify them by checking if the types are declared in the runtime itself // if yes, they are system types and we will skip them var module = typeOfField.ContainingModule; if (module != null && module.Name == CommonLanguageRuntimeLibrary) return; var classFactory = new ClassFactory(_semantic); // create the mixin reference, that is the name of the field and the type the field references MixinReference = new MixinReference(fieldSymbol.Name, classFactory.Create(typeOfField)); }
private static SyntaxToken ApplyTriviaFromDeclarationToAssignmentIdentifier(LocalDeclarationStatementSyntax declarationStatement, bool firstVariableToAttachTrivia, VariableDeclaratorSyntax variable) { var identifier = variable.Identifier; var typeSyntax = declarationStatement.Declaration.Type; if (firstVariableToAttachTrivia && typeSyntax != null) { var identifierLeadingTrivia = new SyntaxTriviaList(); if (typeSyntax.HasLeadingTrivia) { identifierLeadingTrivia = identifierLeadingTrivia.AddRange(typeSyntax.GetLeadingTrivia()); } identifierLeadingTrivia = identifierLeadingTrivia.AddRange(identifier.LeadingTrivia); identifier = identifier.WithLeadingTrivia(identifierLeadingTrivia); } return(identifier); }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { this.HandleAssignedValue(node, node.Initializer?.Value); base.VisitVariableDeclarator(node); }
internal static void GetFirstLocalOrFieldBreakpointSpan(SyntaxTokenList modifiers, VariableDeclaratorSyntax declaratorSyntax, out SyntaxNode node, out TextSpan?part) { var declarationSyntax = (VariableDeclarationSyntax)declaratorSyntax.Parent; int start = modifiers.Any() ? modifiers[0].SpanStart : declarationSyntax.SpanStart; int end; if (declarationSyntax.Variables.Count == 1) { // [|int x = 1;|] // [|public static int x = 1;|] end = declarationSyntax.Parent.Span.End; } else { // [|int x = 1|], y = 2; // [|public static int x = 1|], y = 2; end = declaratorSyntax.Span.End; } part = TextSpan.FromBounds(start, end); node = declarationSyntax.Parent; }
static PropertyDeclarationSyntax GeneratePropertyDeclaration(FieldDeclarationSyntax field, VariableDeclaratorSyntax initializer) { var modifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); if (field.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword))) { modifiers = modifiers.Add(SyntaxFactory.Token(SyntaxKind.StaticKeyword)); } string propertyName = NameProposalService.GetNameProposal(initializer.Identifier.ValueText, SyntaxKind.PropertyDeclaration); var block = SyntaxFactory.Block(SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(initializer.Identifier))); return(SyntaxFactory.PropertyDeclaration(field.Declaration.Type, propertyName) .WithModifiers(modifiers) .WithAccessorList( SyntaxFactory.AccessorList(SyntaxFactory.SingletonList( SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, block) )) ).WithAdditionalAnnotations(Formatter.Annotation)); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.MissingXmlCommentForPubliclyVisibleTypeOrMember: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddDocumentationComment)) { break; } CodeAction codeAction = CodeAction.Create( "Add documentation comment", cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); CodeAction codeAction2 = CodeAction.Create( "Add documentation comment (copy from base if available)", cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, cancellationToken), GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable")); context.RegisterCodeFix(codeAction2, diagnostic); break; } case CompilerDiagnosticIdentifiers.MethodReturnTypeMustMatchOverriddenMethodReturnType: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMethodReturnType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType; CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel); break; } case CompilerDiagnosticIdentifiers.PartialMethodsMustHaveVoidReturnType: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMethodReturnType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration; MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken); if (otherPart == null) { break; } CodeAction codeAction = CodeAction.Create( "Change return type to 'void'", cancellationToken => { return(context.Document.Solution().ReplaceNodesAsync( new MethodDeclarationSyntax[] { methodDeclaration, otherPart }, (node, _) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)), cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.MemberTypeMustMatchOverriddenMemberType: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = null; switch (memberDeclaration.Kind()) { case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: { var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = propertySymbol.OverriddenProperty.Type; break; } case SyntaxKind.EventDeclaration: { var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } case SyntaxKind.EventFieldDeclaration: { VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables[0]; var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } } CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel); break; } case CompilerDiagnosticIdentifiers.MissingPartialModifier: case CompilerDiagnosticIdentifiers.PartialMethodMustBeDeclaredInPartialClassOrPartialStruct: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddPartialModifier)) { break; } SyntaxNode node = null; switch (memberDeclaration.Kind()) { case SyntaxKind.MethodDeclaration: { if (memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration)) { node = memberDeclaration.Parent; } break; } case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: { node = memberDeclaration; break; } } Debug.Assert(node != null, memberDeclaration.ToString()); if (node == null) { break; } ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); break; } case CompilerDiagnosticIdentifiers.MemberIsAbstractButItIsContainedInNonAbstractClass: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeContainingClassAbstract)) { break; } if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration)) { break; } ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, memberDeclaration.Parent, SyntaxKind.AbstractKeyword, title: "Make containing class abstract"); break; } case CompilerDiagnosticIdentifiers.StaticConstructorMustBeParameterless: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveParametersFromStaticConstructor)) { break; } var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration; CodeAction codeAction = CodeAction.Create( "Remove parameters", cancellationToken => { ParameterListSyntax parameterList = constructorDeclaration.ParameterList; ParameterListSyntax newParameterList = parameterList .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>)) .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia()) .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia()); ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList); return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ExplicitInterfaceDeclarationCanOnlyBeDeclaredInClassOrStruct: case CompilerDiagnosticIdentifiers.InterfacesCannotContainFields: case CompilerDiagnosticIdentifiers.InterfacesCannotContainOperators: case CompilerDiagnosticIdentifiers.InterfacesCannotDeclareTypes: case CompilerDiagnosticIdentifiers.OnlyClassTypesCanContainDestructors: case CompilerDiagnosticIdentifiers.StructsCannotContainExplicitParameterlessConstructors: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveMemberDeclaration)) { break; } CodeFixRegistrator.RemoveMemberDeclaration(context, diagnostic, memberDeclaration); break; } case CompilerDiagnosticIdentifiers.NameOfDestructorMustMatchNameOfClass: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RenameDestructorToMatchClassName)) { break; } if (!(memberDeclaration is DestructorDeclarationSyntax destructorDeclaration)) { break; } if (!(memberDeclaration.Parent is ClassDeclarationSyntax classDeclaration)) { break; } if (classDeclaration.Identifier.ValueText.Length == 0) { break; } CodeAction codeAction = CodeAction.Create( "Rename destructor to match class name", cancellationToken => { DestructorDeclarationSyntax newNode = destructorDeclaration.WithIdentifier(classDeclaration.Identifier.WithTriviaFrom(destructorDeclaration.Identifier)); return(context.Document.ReplaceNodeAsync(destructorDeclaration, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CannotChangeTupleElementNameWhenOverridingInheritedMember: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RenameTupleElement)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (memberDeclaration is MethodDeclarationSyntax methodDeclaration) { IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken); if (!(methodSymbol.ReturnType is INamedTypeSymbol tupleType)) { break; } if (!tupleType.IsTupleType) { break; } if (!(methodSymbol.OverriddenMethod?.ReturnType is INamedTypeSymbol baseTupleType)) { break; } if (!baseTupleType.IsTupleType) { break; } ImmutableArray <IFieldSymbol> elements = tupleType.TupleElements; ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements; if (elements.Length != baseElements.Length) { break; } int i = 0; while (i < elements.Length) { if (elements[i].Name != baseElements[i].Name) { break; } i++; } if (i == elements.Length) { break; } TupleElementSyntax tupleElement = ((TupleTypeSyntax)methodDeclaration.ReturnType).Elements[i]; CodeAction codeAction = CodeAction.Create( $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'", ct => RenameTupleElementAsync(context.Document, methodDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else if (memberDeclaration is PropertyDeclarationSyntax propertyDeclaration) { IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken); if (!(propertySymbol.Type is INamedTypeSymbol tupleType)) { break; } if (!tupleType.IsTupleType) { break; } if (!(propertySymbol.OverriddenProperty?.Type is INamedTypeSymbol baseTupleType)) { break; } if (!baseTupleType.IsTupleType) { break; } ImmutableArray <IFieldSymbol> elements = tupleType.TupleElements; ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements; if (elements.Length != baseElements.Length) { break; } int i = 0; while (i < elements.Length) { if (elements[i].Name != baseElements[i].Name) { break; } i++; } if (i == elements.Length) { break; } TupleElementSyntax tupleElement = ((TupleTypeSyntax)propertyDeclaration.Type).Elements[i]; CodeAction codeAction = CodeAction.Create( $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'", ct => RenameTupleElementAsync(context.Document, propertyDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.MethodsWithVariableArgumentsAreNotCLSCompliant: case CompilerDiagnosticIdentifiers.ArgumentTypeIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.ReturnTypeIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.TypeOfVariableIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.IdentifierDifferingOnlyInCaseIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.OverloadedMethodDifferingOnlyInRefOrOutOrInArrayRankIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.OverloadedMethodDifferingOnlyByUnnamedArrayTypesIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.IdentifierIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.BaseTypeIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.ArraysAsAttributeArgumentsIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.ConstraintTypeIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.TypeIsNotCLSCompliantBecauseBaseInterfaceIsNotCLSCompliant: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MarkDeclarationAsNonCLSCompliant)) { break; } CodeAction codeAction = CodeAction.Create( $"Mark {CSharpFacts.GetTitle(memberDeclaration)} as non-CLS-compliant", ct => MarkDeclarationAsNonCLSCompliantAsync(context.Document, memberDeclaration, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ExplicitInterfaceDeclarationIsNotMemberOfInterface: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddParameterToExplicitlyImplementedInterfaceMember)) { break; } var context2 = new CommonFixContext( context.Document, GetEquivalenceKey(diagnostic), await context.GetSemanticModelAsync().ConfigureAwait(false), context.CancellationToken); CodeAction codeAction = AddParameterToInterfaceMemberRefactoring.ComputeRefactoringForExplicitImplementation(context2, memberDeclaration); if (codeAction != null) { context.RegisterCodeFix(codeAction, diagnostic); } break; } } } }
public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node) { node = (VariableDeclaratorSyntax)base.VisitVariableDeclarator(node); Classes.Add(node); return(node); }
/// <summary> /// <![CDATA[ /// fixed(int* ptr = &v){ ... } == becomes ===> /// /// pinned ref int pinnedTemp = ref v; // pinning managed ref /// int* ptr = (int*)&pinnedTemp; // unsafe cast to unmanaged ptr /// . . . /// ]]> /// </summary> private BoundStatement InitializeFixedStatementGetPinnable( BoundLocalDeclaration localDecl, LocalSymbol localSymbol, BoundFixedLocalCollectionInitializer fixedInitializer, SyntheticBoundNodeFactory factory, out LocalSymbol pinnedTemp) { TypeSymbol localType = localSymbol.Type; BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression); var initializerType = initializerExpr.Type; var initializerSyntax = initializerExpr.Syntax; var getPinnableMethod = fixedInitializer.GetPinnableOpt; // intervening parens may have been skipped by the binder; find the declarator VariableDeclaratorSyntax declarator = fixedInitializer.Syntax.FirstAncestorOrSelf <VariableDeclaratorSyntax>(); Debug.Assert(declarator != null); // pinned ref int pinnedTemp pinnedTemp = factory.SynthesizedLocal( getPinnableMethod.ReturnType, syntax: declarator, isPinned: true, //NOTE: different from the array and string cases // RefReadOnly to allow referring to readonly variables. (technically we only "read" through the temp anyways) refKind: RefKind.RefReadOnly, kind: SynthesizedLocalKind.FixedReference); BoundExpression callReceiver; int currentConditionalAccessID = 0; bool needNullCheck = !initializerType.IsValueType; if (needNullCheck) { currentConditionalAccessID = _currentConditionalAccessID++; callReceiver = new BoundConditionalReceiver( initializerSyntax, currentConditionalAccessID, initializerType); } else { callReceiver = initializerExpr; } // .GetPinnable() var getPinnableCall = getPinnableMethod.IsStatic ? factory.Call(null, getPinnableMethod, callReceiver) : factory.Call(callReceiver, getPinnableMethod); // temp =ref .GetPinnable() var tempAssignment = factory.AssignmentExpression( factory.Local(pinnedTemp), getPinnableCall, isRef: true); // &pinnedTemp var addr = new BoundAddressOfOperator( factory.Syntax, factory.Local(pinnedTemp), type: fixedInitializer.ElementPointerType); // (int*)&pinnedTemp var pointerValue = factory.Convert( localType, addr, fixedInitializer.ElementPointerTypeConversion); // {pinnedTemp =ref .GetPinnable(), (int*)&pinnedTemp} BoundExpression pinAndGetPtr = factory.Sequence( locals: ImmutableArray <LocalSymbol> .Empty, sideEffects: ImmutableArray.Create <BoundExpression>(tempAssignment), result: pointerValue); if (needNullCheck) { // initializer?.{temp =ref .GetPinnable(), (int*)&pinnedTemp} ?? default; pinAndGetPtr = new BoundLoweredConditionalAccess( initializerSyntax, initializerExpr, hasValueMethodOpt: null, whenNotNull: pinAndGetPtr, whenNullOpt: null, // just return default(T*) currentConditionalAccessID, localType); } // ptr = initializer?.{temp =ref .GetPinnable(), (int*)&pinnedTemp} ?? default; BoundStatement localInit = InstrumentLocalDeclarationIfNecessary(localDecl, localSymbol, factory.Assignment(factory.Local(localSymbol), pinAndGetPtr)); return(localInit); }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { this.Found |= node.Identifier.ValueText == this.name; base.VisitVariableDeclarator(node); }
private static SyntaxNode MakeMultipleFieldsReadonly(SyntaxNode root, FieldDeclarationSyntax fieldDeclaration, VariableDeclaratorSyntax variableToMakeReadonly) { var newDeclaration = fieldDeclaration.Declaration.RemoveNode(variableToMakeReadonly, SyntaxRemoveOptions.KeepEndOfLine); var newFieldDeclaration = fieldDeclaration.WithDeclaration(newDeclaration); var newReadonlyFieldDeclaration = fieldDeclaration.WithDeclaration(SyntaxFactory.VariableDeclaration(fieldDeclaration.Declaration.Type, SyntaxFactory.SeparatedList(new[] { variableToMakeReadonly }))) .WithoutLeadingTrivia() .WithTrailingTrivia(SyntaxFactory.ParseTrailingTrivia("\n")) .AddModifiers(SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword)) .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(fieldDeclaration, new[] { newFieldDeclaration, newReadonlyFieldDeclaration }); return(newRoot); }
private static DeclarationExpressionSyntax GetDeclarationExpression( SourceText sourceText, IdentifierNameSyntax identifier, TypeSyntax newType, VariableDeclaratorSyntax declaratorOpt) { newType = newType.WithoutTrivia().WithAdditionalAnnotations(Formatter.Annotation); var designation = SyntaxFactory.SingleVariableDesignation(identifier.Identifier); if (declaratorOpt != null) { // We're removing a single declarator. Copy any comments it has to the out-var. // // Note: this is tricky due to comment ownership. We want hte comments that logically // belong to the declarator, even if our syntax model attaches them to other tokens. var precedingTrivia = declaratorOpt.GetAllPrecedingTriviaToPreviousToken( sourceText, includePreviousTokenTrailingTriviaOnlyIfOnSameLine: true); if (precedingTrivia.Any(t => t.IsSingleOrMultiLineComment())) { designation = designation.WithPrependedLeadingTrivia(MassageTrivia(precedingTrivia)); } if (declaratorOpt.GetTrailingTrivia().Any(t => t.IsSingleOrMultiLineComment())) { designation = designation.WithAppendedTrailingTrivia(MassageTrivia(declaratorOpt.GetTrailingTrivia())); } } return SyntaxFactory.DeclarationExpression(newType, designation); }
protected static void VerifyModelForDuplicateVariableDeclarationInSameScope(SemanticModel model, VariableDeclaratorSyntax declarator) { var symbol = model.GetDeclaredSymbol(declarator); Assert.Equal(declarator.Identifier.ValueText, symbol.Name); Assert.Equal(declarator, symbol.DeclaringSyntaxReferences.Single().GetSyntax()); Assert.Equal(LocalDeclarationKind.RegularVariable, symbol.GetSymbol <LocalSymbol>().DeclarationKind); Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)declarator)); Assert.NotEqual(symbol, model.LookupSymbols(declarator.SpanStart, name: declarator.Identifier.ValueText).Single()); Assert.True(model.LookupNames(declarator.SpanStart).Contains(declarator.Identifier.ValueText)); }
private ExpressionStatementSyntax CreateDeconstructionStatement( INamedTypeSymbol tupleType, LocalDeclarationStatementSyntax declarationStatement, VariableDeclaratorSyntax variableDeclarator) { // Copy all the tokens/nodes from the existing declaration statement to the new assignment // statement. However, convert the existing declaration over to a "var (x, y)" declaration // or (int x, int y) tuple expression. return(SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, CreateTupleOrDeclarationExpression(tupleType, declarationStatement.Declaration.Type), variableDeclarator.Initializer.EqualsToken, variableDeclarator.Initializer.Value), declarationStatement.SemicolonToken)); }
private static RenameResult RenameSymbol(Document document, SyntaxNode root, SyntaxNode startNode, VariableDeclaratorSyntax declarationNode, string newName) { var identifierToken = declarationNode.Identifier; var methodAnnotation = new SyntaxAnnotation(SELECTED_METHOD_ANNOTATION); var changeDic = new Dictionary <SyntaxNode, SyntaxNode>(); if (startNode != null) { changeDic.Add(startNode, startNode.WithAdditionalAnnotations(methodAnnotation)); } changeDic.Add(declarationNode, declarationNode.WithIdentifier(identifierToken.WithAdditionalAnnotations(RenameAnnotation.Create()))); var annotatedRoot = root.ReplaceNodes(changeDic.Keys, (x, y) => changeDic[x]); var newSolution = RenameSymbol(document, annotatedRoot, identifierToken, methodAnnotation, newName).Result; return(GetNewStartNode(newSolution, document, methodAnnotation, startNode)); }
internal override void TranslateFieldPrefix(ShaderTranslationContext sc, VariableDeclaratorSyntax syntax, MappedField field, int fieldIndex, MappedConstantBuffer cBufferMap) { if (typeof(IShaderResource).IsAssignableFrom(field.Info.FieldType)) { sc.MappedFields.Add(field); } else { // HLSL puts all global, non-const static variables into the $Global constant buffer. if (cBufferMap == null && field.Info.FieldType.DeclaringType == sc.ShaderType) { MappedConstantBuffer cBufferGlobal = null; if (!sc.ConstantBuffers.TryGetValue(GLOBAL_CBUFFER_NAME, out cBufferGlobal)) { cBufferGlobal = Pooling.MappedConstBuffers.Get(); sc.ConstantBuffers.Add(GLOBAL_CBUFFER_NAME, cBufferGlobal); } cBufferGlobal.AddField(field); } if (typeof(IMatrix).IsAssignableFrom(field.Info.FieldType)) { if (field.StructureType == ShaderStructureType.MatrixRowMajor) { sc.Source.Append("row_major "); } if (field.StructureType == ShaderStructureType.MatrixColumnMajor) { sc.Source.Append("column_Major "); } } } foreach (Attribute at in field.Attributes) { switch (at) { case InterpolationAttribute attInterpolation: foreach (InterpolationMode m in InterpolationAttribute.ModeValues) { if (m == InterpolationMode.None) { continue; } if ((attInterpolation.Flags & m) == m) { sc.Source.Append($" {m.ToString().ToLower()}"); } } break; case ComputeGroupSharedAttribute attGroupShared: sc.Source.Append(" groupshared "); break; case GloballyCoherentAttribute attGlobCoherent: if (field.ResourceBaseType == ShaderResourceBaseType.RWBuffer || field.ResourceBaseType == ShaderResourceBaseType.RWTexture) { sc.Source.Append(" globallycoherent "); } break; } } }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { _builder.Add(node); base.VisitVariableDeclarator(node); }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { base.VisitVariableDeclarator(node); Add(node.Identifier); }
private static IEnumerable <IdentifierFieldMapping> GetIdentifierFieldMappings(VariableDeclaratorSyntax variable, INamedTypeSymbol containingType, SemanticModel semanticModel) { return(variable.Initializer.DescendantNodes() .OfType <IdentifierNameSyntax>() .Select(identifier => { var field = semanticModel.GetSymbolInfo(identifier).Symbol as IFieldSymbol; var enclosingSymbol = semanticModel.GetEnclosingSymbol(identifier.SpanStart); return new IdentifierFieldMapping { Identifier = identifier, Field = field, IsRelevant = field != null && !field.IsConst && field.IsStatic && containingType.Equals(field.ContainingType) && enclosingSymbol is IFieldSymbol && enclosingSymbol.ContainingType.Equals(field.ContainingType) }; }) .Where(identifier => identifier.IsRelevant)); }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { if (node.Identifier.ValueText == name_) { Found(); } }
public SingleLocalDeclarationStatement(VariableDeclarationSyntax declaration, VariableDeclaratorSyntax declarator) { Declaration = declaration; Declarator = declarator; }
private static async Task <StatementsInfo> RefactorAsync( Document document, StatementsInfo statementsInfo, StatementSyntax statement, StatementSyntax newStatement, int index, int count, SemanticModel semanticModel, CancellationToken cancellationToken, bool removeReturnStatement) { ReturnStatementSyntax returnStatement = FindReturnStatementBelow(statementsInfo.Statements, index); ExpressionSyntax expression = returnStatement.Expression; ExpressionSyntax newExpression = null; ISymbol symbol = semanticModel.GetSymbol(expression, cancellationToken); if (symbol.IsLocal() && index > 0) { LocalDeclarationStatementSyntax localDeclarationStatement = FindLocalDeclarationStatementAbove(statementsInfo.Statements, index); if (localDeclarationStatement?.ContainsDiagnostics == false && !localDeclarationStatement.SpanOrTrailingTriviaContainsDirectives() && !statement.GetLeadingTrivia().Any(f => f.IsDirective)) { SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = localDeclarationStatement.Declaration.Variables; VariableDeclaratorSyntax declarator = FindVariableDeclarator(semanticModel, symbol, declarators, cancellationToken); if (declarator != null) { ExpressionSyntax value = declarator.Initializer?.Value; if (removeReturnStatement || value != null) { IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false); if (referencedSymbols.First().Locations.Count() == count + 1) { newExpression = value; if (declarators.Count == 1) { statementsInfo = statementsInfo.RemoveNode(localDeclarationStatement, RemoveHelper.GetRemoveOptions(localDeclarationStatement)); index--; } else { statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, RemoveHelper.GetRemoveOptions(declarator))); } returnStatement = FindReturnStatementBelow(statementsInfo.Statements, index); } } } } } if (removeReturnStatement) { statementsInfo = statementsInfo.RemoveNode(returnStatement, RemoveHelper.GetRemoveOptions(returnStatement)); } else if (newExpression != null) { statementsInfo = statementsInfo.ReplaceNode(returnStatement, returnStatement.WithExpression(newExpression.WithTriviaFrom(expression))); } return(statementsInfo.ReplaceNode(statementsInfo.Statements[index], newStatement)); }
public static Task <Document> RefactorAsync(Document document, IfAnalysis ifAnalysis, CancellationToken cancellationToken = default(CancellationToken)) { switch (ifAnalysis.Kind) { case IfAnalysisKind.IfElseToAssignmentWithCoalesceExpression: { return(IfElseToAssignmentWithCoalesceExpressionAsync(document, (IfElseToAssignmentWithCoalesceExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfElseToAssignmentWithConditionalExpression: { return(IfElseToAssignmentWithConditionalExpressionAsync(document, (IfElseToAssignmentWithConditionalExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.AssignmentAndIfElseToAssignmentWithConditionalExpression: { var analysis = (AssignmentAndIfElseToAssignmentWithConditionalExpressionAnalysis)ifAnalysis; ConditionalExpressionSyntax conditionalExpression = CreateConditionalExpression(analysis.IfStatement.Condition, analysis.WhenTrue, analysis.WhenFalse); ExpressionStatementSyntax newStatement = analysis.Statement.ReplaceNode(analysis.Left, conditionalExpression); return(ToAssignmentWithConditionalExpressionAsync(document, analysis, newStatement, cancellationToken)); } case IfAnalysisKind.LocalDeclarationAndIfElseAssignmentWithConditionalExpression: { var analysis = (LocalDeclarationAndIfElseToAssignmentWithConditionalExpressionAnalysis)ifAnalysis; ConditionalExpressionSyntax conditionalExpression = CreateConditionalExpression(analysis.IfStatement.Condition, analysis.WhenTrue, analysis.WhenFalse); VariableDeclaratorSyntax declarator = analysis.Statement.Declaration.Variables[0]; EqualsValueClauseSyntax initializer = declarator.Initializer; EqualsValueClauseSyntax newInitializer = (initializer != null) ? initializer.WithValue(conditionalExpression) : EqualsValueClause(conditionalExpression); LocalDeclarationStatementSyntax newStatement = analysis.Statement.ReplaceNode(declarator, declarator.WithInitializer(newInitializer)); return(ToAssignmentWithConditionalExpressionAsync(document, analysis, newStatement, cancellationToken)); } case IfAnalysisKind.IfElseToAssignmentWithExpression: { return(IfElseToAssignmentWithExpressionAsync(document, (IfElseToAssignmentWithExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfElseToAssignmentWithCondition: { return(IfElseToAssignmentWithConditionAsync(document, (IfElseToAssignmentWithConditionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfElseToReturnWithCoalesceExpression: case IfAnalysisKind.IfElseToYieldReturnWithCoalesceExpression: case IfAnalysisKind.IfReturnToReturnWithCoalesceExpression: { return(IfToReturnWithCoalesceExpressionAsync(document, (IfToReturnWithCoalesceExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfElseToReturnWithConditionalExpression: { return(IfElseToReturnWithConditionalExpressionAsync(document, (IfElseToReturnWithConditionalExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfElseToReturnWithBooleanExpression: { return(IfElseToReturnWithBooleanExpressionAsync(document, (IfElseToReturnWithBooleanExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfElseToReturnWithExpression: case IfAnalysisKind.IfElseToYieldReturnWithExpression: case IfAnalysisKind.IfReturnToReturnWithExpression: { return(IfToReturnWithExpressionAsync(document, (IfToReturnWithExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfElseToYieldReturnWithConditionalExpression: { return(IfElseToYieldReturnWithConditionalExpressionAsync(document, (IfElseToYieldReturnWithConditionalExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfElseToYieldReturnWithBooleanExpression: { return(IfElseToYieldReturnWithBooleanExpressionAsync(document, (IfElseToYieldReturnWithBooleanExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfReturnToReturnWithConditionalExpression: { return(IfReturnToReturnWithConditionalExpressionAsync(document, (IfReturnToReturnWithConditionalExpressionAnalysis)ifAnalysis, cancellationToken)); } case IfAnalysisKind.IfReturnToReturnWithBooleanExpression: { return(IfReturnToReturnWithBooleanExpressionAsync(document, (IfReturnToReturnWithBooleanExpressionAnalysis)ifAnalysis, cancellationToken)); } default: { throw new InvalidOperationException(); } } }
static bool ContainsGetter(SemanticModel model, PropertyDeclarationSyntax property, VariableDeclaratorSyntax declarator) { var symbol = model.GetDeclaredSymbol(declarator); if (property.ExpressionBody != null) { return(model.GetSymbolInfo(property.ExpressionBody.Expression).Symbol == symbol); } var getter = property.AccessorList?.Accessors.FirstOrDefault(a => a.IsKind(SyntaxKind.GetAccessorDeclaration)); if (getter == null || getter.Body?.Statements.Count != 1) { return(false); } #if RE2017 #warning "Check for get => ExpressionBody!" #endif var ret = getter.Body?.Statements.Single() as ReturnStatementSyntax; if (ret == null) { return(false); } return(model.GetSymbolInfo(ret.Expression).Symbol == symbol); }
private async Task <Document> UseAsAsync(Document document, SyntaxNode statement, CancellationToken cancellationToken) { var documentId = document.Id; var projectId = document.Project.Id; var editor = await DocumentEditor.CreateAsync(document, cancellationToken); editor.ReplaceNode(statement, statement.WithAdditionalAnnotations(new SyntaxAnnotation("MyIsStatement"))); // Remove all existing to-rename annotations // This is needed because after renaming one branch in an `if` statement, the extraction is done succesfully but the annotation remains on the extracted declarator // Therefore we have to remove all appropriate annotations so we can start fresh from the new situation // This should only be done for the extracted variable declarator(s): the is-statement is removed so no annotation for that remains var root = await document.GetSyntaxRootAsync(cancellationToken); foreach (var annotatedNode in root.GetAnnotatedNodes("QueueRename")) { editor.ReplaceNode(annotatedNode, annotatedNode.WithoutAnnotations("QueueRename")); } document = editor.GetChangedDocument(); // Editor is created outside the loop so we can apply multiple fixes to one "document" // In our scenario this boils down to applying one fix for every if statement var semanticModel = await document.GetSemanticModelAsync(cancellationToken); editor = await DocumentEditor.CreateAsync(document, cancellationToken); root = await document.GetSyntaxRootAsync(cancellationToken); var isExpression = (BinaryExpressionSyntax)root.GetAnnotatedNodes("MyIsStatement").Single(); var isIdentifier = ((IdentifierNameSyntax)isExpression.Left).Identifier.ValueText; var ifStatement = isExpression.Ancestors().OfType <IfStatementSyntax>().First(); var type = GetRelevantType(isExpression, semanticModel); var newIdentifier = SyntaxFactory.Identifier(GetNewIdentifier(isIdentifier, type, GetOuterIfStatement(ifStatement).Parent)); // We filter out the descendent if statements to avoid executing the code fix on all nested ifs var asExpressions = GetDescendantBinaryAs(ifStatement); var castExpressions = GetDescendantCasts(ifStatement); // First step: we give every eligible expression a custom annotation to indicate the identifiers that need to be renamed foreach (var expression in asExpressions.Concat <ExpressionSyntax>(castExpressions)) { var identifier = default(IdentifierNameSyntax); var binaryExpression = expression as BinaryExpressionSyntax; if (binaryExpression != null) { identifier = binaryExpression.Left as IdentifierNameSyntax; } var castExpression = expression as CastExpressionSyntax; if (castExpression != null) { identifier = castExpression.Expression as IdentifierNameSyntax; } if (identifier != null && identifier.Identifier.ValueText == isIdentifier) { // !!Important!! // We add the annotation on top of the identifier we find but this is *not* the identifier we want to rename // var myVar x = (int) o; // Here we place the annotation on "o" but we want to rename "x" // We can't place it on "x" because VariableDeclarators can't be replaced using DocumentEditor just yet // See https://github.com/dotnet/roslyn/issues/8154 for more info if (identifier.Ancestors().OfType <VariableDeclaratorSyntax>().Any()) { editor.ReplaceNode(identifier, identifier.WithAdditionalAnnotations(new SyntaxAnnotation("QueueRename"))); } } } document = editor.GetChangedDocument(); // Second step: rename all identifiers while (true) { root = await document.GetSyntaxRootAsync(cancellationToken); VariableDeclaratorSyntax nodeToRename = null; foreach (var node in root.GetAnnotatedNodes("QueueRename").Cast <IdentifierNameSyntax>()) { var declarator = node.AncestorsAndSelf().OfType <VariableDeclaratorSyntax>().Single(); // We have to find the first node that isn't renamed yet if (declarator.Identifier.ValueText != newIdentifier.ValueText) { // We only rename the VariableDeclarators that are directly assigned the casted variable in question // If the variable is used in a separate expression, we don't have to rename our declarator if (!IsSurroundedByInvocation(node) && !IsInConditionalExpression(node)) { nodeToRename = declarator; break; } } } if (nodeToRename == null) { break; } var tempSemanticModel = await document.GetSemanticModelAsync(cancellationToken); var nodeToRenameSymbol = tempSemanticModel.GetDeclaredSymbol(nodeToRename); if (nodeToRenameSymbol == null) { break; } var renamedSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, nodeToRenameSymbol, newIdentifier.ValueText, null, cancellationToken); document = renamedSolution.Projects.Single(x => x.Id == projectId).GetDocument(documentId); } // Third step: use the newly created document // We need to recalculate all those things because otherwise there would be discrepancies due to different source documents editor = await DocumentEditor.CreateAsync(document, cancellationToken); semanticModel = await document.GetSemanticModelAsync(cancellationToken); root = await document.GetSyntaxRootAsync(cancellationToken); isExpression = (BinaryExpressionSyntax)root.GetAnnotatedNodes("MyIsStatement").Single(); type = GetRelevantType(isExpression, semanticModel); ifStatement = isExpression.Ancestors().OfType <IfStatementSyntax>().First(); asExpressions = GetDescendantBinaryAs(ifStatement); castExpressions = GetDescendantCasts(ifStatement); var conditionAlreadyReplaced = false; var variableAlreadyExtracted = false; foreach (var asExpression in asExpressions) { var identifier = asExpression.Left as IdentifierNameSyntax; if (identifier == null || identifier.Identifier.ValueText != isIdentifier) { continue; } var castedType = semanticModel.GetTypeInfo(asExpression.Right).Type; if (castedType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { var nullableSyntax = (NullableTypeSyntax)asExpression.Right; var nullableArgument = semanticModel.GetTypeInfo(nullableSyntax.ElementType).Type; if (nullableArgument != type) { continue; } } else { if (castedType != type) { continue; } } // Replace condition if it hasn't happened yet if (!conditionAlreadyReplaced) { ReplaceCondition(newIdentifier.ValueText, isExpression, editor); conditionAlreadyReplaced = true; } // Create as statement before if block if (!variableAlreadyExtracted) { InsertNewVariableDeclaration( asExpression: asExpression, newIdentifier: newIdentifier, nodeLocation: ifStatement, editor: editor); variableAlreadyExtracted = true; } ReplaceIdentifier(asExpression, newIdentifier, editor); // Remove the local variable // If the expression is surrounded by an invocation we just swap the expression for the identifier // e.g.: bool contains = new[] { ""test"", ""test"", ""test"" }.Contains(o as string); if (!IsSurroundedByInvocation(asExpression) && !IsInConditionalExpression(asExpression)) { RemoveLocal(asExpression, editor); } } foreach (var castExpression in castExpressions) { var identifier = castExpression.Expression as IdentifierNameSyntax; if (identifier == null || identifier.Identifier.ValueText != isIdentifier) { continue; } var castedType = semanticModel.GetTypeInfo(castExpression.Type).Type; if (castedType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { var nullableSyntax = (NullableTypeSyntax)castExpression.Type; var nullableArgument = semanticModel.GetTypeInfo(nullableSyntax.ElementType).Type; if (nullableArgument != type) { continue; } } else { if (castedType != type) { continue; } } // Replace condition if it hasn't happened yet if (!conditionAlreadyReplaced) { ReplaceCondition(newIdentifier.ValueText, isExpression, editor); conditionAlreadyReplaced = true; } // Create as statement before if block if (!variableAlreadyExtracted) { var typeToCast = castedType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T || castedType.IsReferenceType ? castExpression.Type : SyntaxFactory.NullableType(castExpression.Type); var newAsClause = SyntaxFactory.BinaryExpression(SyntaxKind.AsExpression, castExpression.Expression, typeToCast); InsertNewVariableDeclaration( asExpression: newAsClause, newIdentifier: newIdentifier, nodeLocation: ifStatement, editor: editor); variableAlreadyExtracted = true; } // If we have a direct cast (yes) and the existing type was a non-nullable value type, we have to add the `.Value` property accessor ourselves // While it is not necessary to add the property access in the case of a nullable collection, we do it anyway because that's a very difficult thing to calculate otherwise // e.g. new double?[] { 5.0, 6.0, 7.0 }.Contains(oAsDouble.Value) // The above can be written with or without `.Value` when the collection is double?[] but requires `.Value` in the case of double[] ReplaceIdentifier(castExpression, newIdentifier, editor, requiresNullableValueAccess: castedType.IsValueType && castedType.OriginalDefinition.SpecialType != SpecialType.System_Nullable_T); // Remove the local variable // If the expression is surrounded by an invocation we just swap the expression for the identifier // e.g.: bool contains = new[] { ""test"", ""test"", ""test"" }.Contains(o as string); if (!IsSurroundedByInvocation(castExpression) && !IsInConditionalExpression(castExpression)) { RemoveLocal(castExpression, editor); } } return(editor.GetChangedDocument()); }
public static void AnalyzeUsingStatement(SyntaxNodeAnalysisContext context) { var usingStatement = (UsingStatementSyntax)context.Node; StatementSyntax statement = usingStatement.Statement; if (statement?.IsKind(SyntaxKind.Block) == true) { var block = (BlockSyntax)statement; StatementSyntax lastStatement = block.Statements.LastOrDefault(); if (lastStatement?.IsKind(SyntaxKind.ExpressionStatement) == true) { var expressionStatement = (ExpressionStatementSyntax)lastStatement; ExpressionSyntax expression = expressionStatement.Expression; if (expression?.IsKind(SyntaxKind.InvocationExpression) == true) { var invocation = (InvocationExpressionSyntax)expression; ExpressionSyntax invocationExpression = invocation.Expression; if (invocationExpression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true) { var memberAccess = (MemberAccessExpressionSyntax)invocationExpression; if (invocation.ArgumentList?.Arguments.Count == 0) { string methodName = memberAccess.Name?.Identifier.ValueText; if (methodName == "Dispose" || methodName == "Close") { ExpressionSyntax memberAccessExpression = memberAccess.Expression; if (memberAccessExpression != null) { ExpressionSyntax usingExpression = usingStatement.Expression; if (usingExpression != null) { if (SyntaxComparer.AreEquivalent(memberAccessExpression, usingExpression)) { ReportDiagnostic(context, expressionStatement, methodName); } } else if (memberAccessExpression.IsKind(SyntaxKind.IdentifierName)) { VariableDeclarationSyntax usingDeclaration = usingStatement.Declaration; if (usingDeclaration != null) { var identifierName = (IdentifierNameSyntax)memberAccessExpression; string name = identifierName.Identifier.ValueText; VariableDeclaratorSyntax declarator = usingDeclaration.Variables.LastOrDefault(); if (declarator != null && declarator.Identifier.ValueText == name) { ISymbol symbol = context.SemanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); if (symbol?.Equals(context.SemanticModel.GetSymbol(identifierName, context.CancellationToken)) == true) { ReportDiagnostic(context, expressionStatement, methodName); } } } } } } } } } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.OverridingMemberCannotChangeAccessModifiers) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeMemberNonStatic) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CannotChangeAccessModifiersWhenOverridingInheritedMember: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.OverridingMemberCannotChangeAccessModifiers)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); OverrideInfo overrideInfo = OverridingMemberCannotChangeAccessModifiersRefactoring.GetOverrideInfo(memberDeclaration, semanticModel, context.CancellationToken); Accessibility newAccessibility = overrideInfo.OverriddenSymbol.DeclaredAccessibility; string title = $"Change accessibility to '{AccessibilityHelper.GetAccessibilityName(newAccessibility)}'"; CodeAction codeAction = CodeAction.Create( title, cancellationToken => OverridingMemberCannotChangeAccessModifiersRefactoring.RefactorAsync(context.Document, memberDeclaration, newAccessibility, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.MissingXmlCommentForPubliclyVisibleTypeOrMember: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment)) { break; } CodeAction codeAction = CodeAction.Create( "Add documentation comment", cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); CodeAction codeAction2 = CodeAction.Create( "Add documentation comment (copy from base if available)", cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, cancellationToken), GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable")); context.RegisterCodeFix(codeAction2, diagnostic); break; } case CompilerDiagnosticIdentifiers.MethodReturnTypeMustMatchOverriddenMethodReturnType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType; if (typeSymbol?.IsErrorType() == false) { TypeSyntax newType = typeSymbol.ToMinimalTypeSyntax(semanticModel, memberDeclaration.SpanStart); CodeAction codeAction = CodeAction.Create( $"Change return type to '{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, memberDeclaration.SpanStart)}'", cancellationToken => MemberTypeMustMatchOverriddenMemberTypeRefactoring.RefactorAsync(context.Document, memberDeclaration, typeSymbol, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.PartialMethodsMustHaveVoidReturnType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration; MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken); if (otherPart == null) { break; } CodeAction codeAction = CodeAction.Create( "Change return type to 'void'", cancellationToken => { return(context.Document.Solution().ReplaceNodesAsync( new MethodDeclarationSyntax[] { methodDeclaration, otherPart }, (node, rewrittenNode) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)), cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.MemberTypeMustMatchOverriddenMemberType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = null; switch (memberDeclaration.Kind()) { case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: { var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = propertySymbol.OverriddenProperty.Type; break; } case SyntaxKind.EventDeclaration: { var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } case SyntaxKind.EventFieldDeclaration: { VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables.First(); var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } } if (typeSymbol?.IsErrorType() == false) { string title = $"Change type to '{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, memberDeclaration.SpanStart)}'"; CodeAction codeAction = CodeAction.Create( title, cancellationToken => MemberTypeMustMatchOverriddenMemberTypeRefactoring.RefactorAsync(context.Document, memberDeclaration, typeSymbol, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.MissingPartialModifier: case CompilerDiagnosticIdentifiers.PartialMethodMustBeDeclaredWithinPartialClassOrPartialStruct: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier)) { break; } CodeAction codeAction = CodeAction.Create( "Add 'partial' modifier", cancellationToken => { if (memberDeclaration.IsKind(SyntaxKind.MethodDeclaration) && memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration)) { return(context.Document.InsertModifierAsync(memberDeclaration.Parent, SyntaxKind.PartialKeyword, ModifierComparer.Instance, cancellationToken)); } else if (memberDeclaration.IsKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration)) { return(context.Document.InsertModifierAsync(memberDeclaration, SyntaxKind.PartialKeyword, ModifierComparer.Instance, cancellationToken)); } return(Task.FromResult(context.Document)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.MemberIsAbstractButItIsContainedInNonAbstractClass: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract)) { break; } if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration)) { break; } CodeAction codeAction = CodeAction.Create( "Make containing class abstract", cancellationToken => context.Document.InsertModifierAsync(memberDeclaration.Parent, SyntaxKind.AbstractKeyword, ModifierComparer.Instance, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ObjectReferenceIsRequiredForNonStaticMember: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeMemberNonStatic)) { break; } SyntaxTokenList modifiers = memberDeclaration.GetModifiers(); Debug.Assert(modifiers.Contains(SyntaxKind.StaticKeyword), memberDeclaration.ToString()); if (!modifiers.Contains(SyntaxKind.StaticKeyword)) { break; } CodeAction codeAction = CodeAction.Create( $"Make containing {memberDeclaration.GetTitle()} non-static", cancellationToken => context.Document.RemoveModifierAsync(memberDeclaration, SyntaxKind.StaticKeyword, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.StaticConstructorMustBeParameterless: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor)) { break; } var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration; CodeAction codeAction = CodeAction.Create( "Remove parameters", cancellationToken => { ParameterListSyntax parameterList = constructorDeclaration.ParameterList; ParameterListSyntax newParameterList = parameterList .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>)) .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia()) .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia()); ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList); return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
private Document Delete(Document document, VariableDeclaratorSyntax node) { var fieldDeclaration = node.FirstAncestorOrSelf<BaseFieldDeclarationSyntax>(); // If we won't have anything left, then just delete the whole declaration if (fieldDeclaration.Declaration.Variables.Count == 1) { return Delete(document, fieldDeclaration); } else { var newFieldDeclaration = fieldDeclaration.RemoveNode(node, SyntaxRemoveOptions.KeepNoTrivia); return document.ReplaceNodeAsync(fieldDeclaration, newFieldDeclaration, CancellationToken.None) .WaitAndGetResult_CodeModel(CancellationToken.None); } }
// // Summary: // Called when the visitor visits a VariableDeclaratorSyntax node. public virtual void VisitVariableDeclarator(VariableDeclaratorSyntax node);
private async Task <ExpressionSyntax> CreateExpressionToInlineAsync( VariableDeclaratorSyntax variableDeclarator, Document document, CancellationToken cancellationToken) { var updatedDocument = document; var expression = SkipRedundantExteriorParentheses(variableDeclarator.Initializer.Value); var semanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(variableDeclarator, cancellationToken); var newExpression = InitializerRewriter.Visit(expression, localSymbol, semanticModel); // If this is an array initializer, we need to transform it into an array creation // expression for inlining. if (newExpression.Kind() == SyntaxKind.ArrayInitializerExpression) { var arrayType = (ArrayTypeSyntax)localSymbol.Type.GenerateTypeSyntax(); var arrayInitializer = (InitializerExpressionSyntax)newExpression; // Add any non-whitespace trailing trivia from the equals clause to the type. var equalsToken = variableDeclarator.Initializer.EqualsToken; if (equalsToken.HasTrailingTrivia) { var trailingTrivia = equalsToken.TrailingTrivia.SkipInitialWhitespace(); if (trailingTrivia.Any()) { arrayType = arrayType.WithTrailingTrivia(trailingTrivia); } } newExpression = SyntaxFactory.ArrayCreationExpression(arrayType, arrayInitializer); } newExpression = newExpression.WithAdditionalAnnotations(InitializerAnnotation); updatedDocument = await updatedDocument.ReplaceNodeAsync(variableDeclarator.Initializer.Value, newExpression, cancellationToken).ConfigureAwait(false); semanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); newExpression = await FindInitializerAsync(updatedDocument, cancellationToken).ConfigureAwait(false); var newVariableDeclarator = await FindDeclaratorAsync(updatedDocument, cancellationToken).ConfigureAwait(false); localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(newVariableDeclarator, cancellationToken); var explicitCastExpression = newExpression.CastIfPossible(localSymbol.Type, newVariableDeclarator.SpanStart, semanticModel); if (explicitCastExpression != newExpression) { updatedDocument = await updatedDocument.ReplaceNodeAsync(newExpression, explicitCastExpression, cancellationToken).ConfigureAwait(false); semanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); newVariableDeclarator = await FindDeclaratorAsync(updatedDocument, cancellationToken).ConfigureAwait(false); } // Now that the variable declarator is normalized, make its initializer // value semantically explicit. newExpression = await Simplifier.ExpandAsync(newVariableDeclarator.Initializer.Value, updatedDocument, cancellationToken : cancellationToken).ConfigureAwait(false); return(newExpression.WithAdditionalAnnotations(ExpressionToInlineAnnotation)); }
private static IEnumerable <VariableDeclaratorSyntax> GetConvertedDeclarators(VariableDeclaratorSyntax declarator) { var declarators = declarator.Names.Select(n => SyntaxFactory.VariableDeclarator( SyntaxFactory.SeparatedList(new[] { n }), declarator.AsClause, null)) .ToList(); if (declarator.Initializer != null) { var last = declarators.Last(); last = last.WithInitializer(declarator.Initializer); declarators[declarators.Count - 1] = last; } return(declarators.Select(d => d.WithTrailingTrivia(SyntaxFactory.EndOfLineTrivia(Environment.NewLine)) .WithAdditionalAnnotations(Formatter.Annotation))); }
public static void ComputeRefactoring( RefactoringContext context, LocalDeclarationStatementSyntax localDeclaration, SemanticModel semanticModel) { if (semanticModel.GetEnclosingSymbol(localDeclaration.SpanStart, context.CancellationToken) is not IMethodSymbol methodSymbol) return; if (methodSymbol.IsImplicitlyDeclared) return; if (!methodSymbol.MethodKind.Is(MethodKind.Ordinary, MethodKind.LocalFunction)) return; if (methodSymbol.PartialImplementationPart != null) methodSymbol = methodSymbol.PartialImplementationPart; SyntaxNode methodOrLocalFunction = methodSymbol.GetSyntax(context.CancellationToken); if (!methodOrLocalFunction.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement)) return; VariableDeclarationSyntax declaration = localDeclaration.Declaration; if (declaration == null) return; VariableDeclaratorSyntax variable = declaration .Variables .FirstOrDefault(f => !f.IsMissing && f.Identifier.Span.Contains(context.Span)); if (variable == null) return; TypeSyntax type = declaration.Type; if (type == null) return; if (type.IsVar) { ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken); if (typeSymbol?.SupportsExplicitDeclaration() == true) { type = typeSymbol.ToTypeSyntax(); } else { return; } } context.RegisterRefactoring( $"Promote '{variable.Identifier.ValueText}' to parameter", ct => { return RefactorAsync( context.Document, methodOrLocalFunction, localDeclaration, type.WithoutTrivia().WithSimplifierAnnotation(), variable, ct); }, RefactoringDescriptors.PromoteLocalVariableToParameter); }
private async Task <Document> InlineTemporaryAsync(Document document, VariableDeclaratorSyntax declarator, CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; // Annotate the variable declarator so that we can get back to it later. var updatedDocument = await document.ReplaceNodeAsync(declarator, declarator.WithAdditionalAnnotations(DefinitionAnnotation), cancellationToken).ConfigureAwait(false); var semanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var variableDeclarator = await FindDeclaratorAsync(updatedDocument, cancellationToken).ConfigureAwait(false); // Create the expression that we're actually going to inline. var expressionToInline = await CreateExpressionToInlineAsync(variableDeclarator, updatedDocument, cancellationToken).ConfigureAwait(false); // Collect the identifier names for each reference. var local = (ILocalSymbol)semanticModel.GetDeclaredSymbol(variableDeclarator, cancellationToken); var symbolRefs = await SymbolFinder.FindReferencesAsync(local, updatedDocument.Project.Solution, cancellationToken).ConfigureAwait(false); var references = symbolRefs.Single(r => Equals(r.Definition, local)).Locations; var syntaxRoot = await updatedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); // Collect the topmost parenting expression for each reference. var nonConflictingIdentifierNodes = references .Select(loc => (IdentifierNameSyntax)syntaxRoot.FindToken(loc.Location.SourceSpan.Start).Parent) .Where(ident => !HasConflict(ident, variableDeclarator)); // Add referenceAnnotations to identifier nodes being replaced. updatedDocument = await updatedDocument.ReplaceNodesAsync( nonConflictingIdentifierNodes, (o, n) => n.WithAdditionalAnnotations(ReferenceAnnotation), cancellationToken).ConfigureAwait(false); semanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); variableDeclarator = await FindDeclaratorAsync(updatedDocument, cancellationToken).ConfigureAwait(false); // Get the annotated reference nodes. nonConflictingIdentifierNodes = await FindReferenceAnnotatedNodesAsync(updatedDocument, cancellationToken).ConfigureAwait(false); var topmostParentingExpressions = nonConflictingIdentifierNodes .Select(ident => GetTopMostParentingExpression(ident)) .Distinct(); var originalInitializerSymbolInfo = semanticModel.GetSymbolInfo(variableDeclarator.Initializer.Value, cancellationToken); // Make each topmost parenting statement or Equals Clause Expressions semantically explicit. updatedDocument = await updatedDocument.ReplaceNodesAsync(topmostParentingExpressions, (o, n) => Simplifier.Expand(n, semanticModel, workspace, cancellationToken: cancellationToken), cancellationToken).ConfigureAwait(false); semanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var semanticModelBeforeInline = semanticModel; variableDeclarator = await FindDeclaratorAsync(updatedDocument, cancellationToken).ConfigureAwait(false); var scope = GetScope(variableDeclarator); var newScope = ReferenceRewriter.Visit(semanticModel, scope, variableDeclarator, expressionToInline, cancellationToken); updatedDocument = await updatedDocument.ReplaceNodeAsync(scope, newScope, cancellationToken).ConfigureAwait(false); semanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); variableDeclarator = await FindDeclaratorAsync(updatedDocument, cancellationToken).ConfigureAwait(false); newScope = GetScope(variableDeclarator); var conflicts = newScope.GetAnnotatedNodesAndTokens(ConflictAnnotation.Kind); var declaratorConflicts = variableDeclarator.GetAnnotatedNodesAndTokens(ConflictAnnotation.Kind); // Note that we only remove the local declaration if there weren't any conflicts, // unless those conflicts are inside the local declaration. if (conflicts.Count() == declaratorConflicts.Count()) { // Certain semantic conflicts can be detected only after the reference rewriter has inlined the expression var newDocument = await DetectSemanticConflicts(updatedDocument, semanticModel, semanticModelBeforeInline, originalInitializerSymbolInfo, cancellationToken).ConfigureAwait(false); if (updatedDocument == newDocument) { // No semantic conflicts, we can remove the definition. updatedDocument = await updatedDocument.ReplaceNodeAsync(newScope, RemoveDeclaratorFromScope(variableDeclarator, newScope), cancellationToken).ConfigureAwait(false); } else { // There were some semantic conflicts, don't remove the definition. updatedDocument = newDocument; } } return(updatedDocument); }
private bool ContainsVariableDeclaration( SyntaxNode scope, VariableDeclaratorSyntax variable) { var variableName = variable.Identifier.ValueText; return scope.DescendantNodes() .OfType<VariableDeclaratorSyntax>() .Where(d => d != variable) .Any(d => d.Identifier.ValueText.Equals(variableName)); }
public static Task<Document> RefactorAsync( Document document, SyntaxNode methodOrLocalFunction, LocalDeclarationStatementSyntax localDeclaration, TypeSyntax type, VariableDeclaratorSyntax variable, CancellationToken cancellationToken = default) { int variableCount = localDeclaration.Declaration.Variables.Count; ExpressionSyntax initializerValue = variable.Initializer?.Value; SyntaxToken identifier = variable.Identifier.WithoutTrivia(); SyntaxNode newNode = methodOrLocalFunction; if (initializerValue != null) { ExpressionStatementSyntax expressionStatement = SimpleAssignmentStatement( IdentifierName(identifier), initializerValue); expressionStatement = expressionStatement.WithFormatterAnnotation(); if (variableCount > 1) { LocalDeclarationStatementSyntax newLocalDeclaration = localDeclaration.RemoveNode( variable, SyntaxRemoveOptions.KeepUnbalancedDirectives); newNode = newNode.ReplaceNode( localDeclaration, new SyntaxNode[] { newLocalDeclaration, expressionStatement }); } else { newNode = newNode.ReplaceNode( localDeclaration, expressionStatement.WithTriviaFrom(localDeclaration)); } } else if (variableCount > 1) { newNode = newNode.RemoveNode(variable, SyntaxRemoveOptions.KeepUnbalancedDirectives); } else { newNode = newNode.RemoveNode(localDeclaration, SyntaxRemoveOptions.KeepUnbalancedDirectives); } ParameterSyntax newParameter = Parameter(type, identifier).WithFormatterAnnotation(); if (newNode is MethodDeclarationSyntax methodDeclaration) { newNode = methodDeclaration.AddParameterListParameters(newParameter); } else { var localFunction = (LocalFunctionStatementSyntax)newNode; newNode = localFunction.AddParameterListParameters(newParameter); } return document.ReplaceNodeAsync(methodOrLocalFunction, newNode, cancellationToken); }