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));
 }
예제 #2
0
        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;
 }
예제 #4
0
        public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node)
        {
            if (node.Identifier.ToString() == renameFrom.ToString())
                node = node.WithIdentifier(renameTo);

            return base.VisitVariableDeclarator(node);
        }
예제 #5
0
        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.
        }
예제 #6
0
		/// <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)));
		}
예제 #7
0
 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;
 }
예제 #9
0
 /// <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);
 }
예제 #10
0
파일: Rewriter.cs 프로젝트: jthelin/Nake
        public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node)
        {
            var substitution = result.Find(node);

            return substitution != null
                                ? substitution.Substitute()
                                : base.VisitVariableDeclarator(node);
        }
예제 #11
0
        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;
 }
예제 #13
0
        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;
 }
예제 #17
0
        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);
        }
예제 #18
0
        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;
        }
예제 #27
0
        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));
        }
예제 #28
0
            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);
 }
예제 #30
0
        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));
        }
예제 #32
0
        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;
                }
                }
            }
        }
예제 #33
0
 public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node)
 {
     node = (VariableDeclaratorSyntax)base.VisitVariableDeclarator(node);
     Classes.Add(node);
     return(node);
 }
예제 #34
0
        /// <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);
        }
예제 #35
0
 public override void VisitVariableDeclarator(VariableDeclaratorSyntax node)
 {
     this.Found |= node.Identifier.ValueText == this.name;
     base.VisitVariableDeclarator(node);
 }
예제 #36
0
        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));
 }
예제 #40
0
        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));
        }
예제 #41
0
        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);
 }
예제 #44
0
 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();
   }
 }
예제 #46
0
 public SingleLocalDeclarationStatement(VariableDeclarationSyntax declaration, VariableDeclaratorSyntax declarator)
 {
     Declaration = declaration;
     Declarator  = declarator;
 }
예제 #47
0
        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));
        }
예제 #48
0
        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);
        }
예제 #50
0
        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());
        }
예제 #51
0
        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));
        }
예제 #56
0
        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);
        }