internal static IEnumerable<ISymbol> GetDeclaredSymbols(SemanticModel semanticModel, MemberDeclarationSyntax memberDeclaration, CancellationToken cancellationToken)
        {
            if (memberDeclaration is FieldDeclarationSyntax)
            {
                return ((FieldDeclarationSyntax)memberDeclaration).Declaration.Variables.Select(
                    v => semanticModel.GetDeclaredSymbol(v, cancellationToken));
            }

            return SpecializedCollections.SingletonEnumerable(
                semanticModel.GetDeclaredSymbol(memberDeclaration, cancellationToken));
        }
        protected override bool TryInitializeState(
            Document document, SemanticModel model, SyntaxNode node, CancellationToken cancellationToken,
            out INamedTypeSymbol classType, out INamedTypeSymbol abstractClassType)
        {
            var baseClassNode = node as TypeSyntax;
            if (baseClassNode != null && baseClassNode.Parent is BaseTypeSyntax &&
                baseClassNode.Parent.IsParentKind(SyntaxKind.BaseList) &&
                ((BaseTypeSyntax)baseClassNode.Parent).Type == baseClassNode)
            {
                if (baseClassNode.Parent.Parent.IsParentKind(SyntaxKind.ClassDeclaration))
                {
                    abstractClassType = model.GetTypeInfo(baseClassNode, cancellationToken).Type as INamedTypeSymbol;
                    cancellationToken.ThrowIfCancellationRequested();

                    if (abstractClassType.IsAbstractClass())
                    {
                        var classDecl = baseClassNode.Parent.Parent.Parent as ClassDeclarationSyntax;
                        classType = model.GetDeclaredSymbol(classDecl, cancellationToken) as INamedTypeSymbol;

                        return classType != null && abstractClassType != null;
                    }
                }
            }

            classType = null;
            abstractClassType = null;
            return false;
        }
Exemplo n.º 3
0
        protected static void VerifyModelForDeclarationPatternDuplicateInSameScope(SemanticModel model, DeclarationPatternSyntax decl)
        {
            var symbol = model.GetDeclaredSymbol(decl);
            Assert.Equal(decl.Identifier.ValueText, symbol.Name);
            Assert.Equal(decl, symbol.DeclaringSyntaxReferences.Single().GetSyntax());
            Assert.Equal(LocalDeclarationKind.PatternVariable, ((LocalSymbol)symbol).DeclarationKind);
            Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)decl));
            Assert.NotEqual(symbol, model.LookupSymbols(decl.SpanStart, name: decl.Identifier.ValueText).Single());
            Assert.True(model.LookupNames(decl.SpanStart).Contains(decl.Identifier.ValueText));

            var type = ((LocalSymbol)symbol).Type;
            if (!decl.Type.IsVar || !type.IsErrorType())
            {
                Assert.Equal(type, model.GetSymbolInfo(decl.Type).Symbol);
            }
        }
        internal override Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, CancellationToken cancellationToken)
        {
            var actions = ImmutableArray.CreateBuilder<CodeAction>();

            // Fix 1: Add a NonSerialized attribute to the field
            var fieldNode = GetFieldDeclarationNode(nodeToFix);
            if (fieldNode != null)
            {
                var generator = SyntaxGenerator.GetGenerator(document);
                var codeAction = new MyDocumentCodeAction(FxCopFixersResources.AddNonSerializedAttribute,
                                                          async ct => await AddNonSerializedAttribute(document, model, root, fieldNode, generator).ConfigureAwait(false));
                actions.Add(codeAction);

                // Fix 2: If the type of the field is defined in source, then add the serializable attribute to the type.
                var fieldSymbol = model.GetDeclaredSymbol(nodeToFix, cancellationToken) as IFieldSymbol;
                var type = fieldSymbol.Type;
                if (type.Locations.Any(l => l.IsInSource))
                {
                    var typeCodeAction = new MySolutionCodeAction(FxCopFixersResources.AddSerializableAttribute,
                                                                  async ct => await AddSerializableAttributeToType(document, model, generator, type, cancellationToken).ConfigureAwait(false));

                    actions.Add(typeCodeAction);
                }
            }

            return Task.FromResult<IEnumerable<CodeAction>>(actions.ToImmutable());
        }
Exemplo n.º 5
0
        internal async override Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, CancellationToken cancellationToken)
        {
            IEnumerable<CodeAction> actions = null;

            // Fix 1: Add a NonSerialized attribute to the field
            var fieldNode = GetFieldDeclarationNode(nodeToFix);
            if (fieldNode != null)
            { 
                var attr = CodeGenerationSymbolFactory.CreateAttributeData(WellKnownTypes.NonSerializedAttribute(model.Compilation));
                var newNode = CodeGenerator.AddAttributes(fieldNode, document.Project.Solution.Workspace, SpecializedCollections.SingletonEnumerable(attr)).WithAdditionalAnnotations(Formatting.Formatter.Annotation);
                var newDocument = document.WithSyntaxRoot(root.ReplaceNode(fieldNode, newNode));
                var codeAction = CodeAction.Create(FxCopFixersResources.AddNonSerializedAttribute, newDocument);
                actions = SpecializedCollections.SingletonEnumerable(codeAction);

                // Fix 2: If the type of the field is defined in source, then add the serializable attribute to the type.
                var fieldSymbol = model.GetDeclaredSymbol(nodeToFix) as IFieldSymbol;
                var type = fieldSymbol.Type;
                if (type.Locations.Any(l => l.IsInSource))
                {
                    var typeDeclNode = type.DeclaringSyntaxReferences.First().GetSyntax();
                    var serializableAttr = CodeGenerationSymbolFactory.CreateAttributeData(WellKnownTypes.SerializableAttribute(model.Compilation));
                    var newTypeDeclNode = CodeGenerator.AddAttributes(typeDeclNode, document.Project.Solution.Workspace, SpecializedCollections.SingletonEnumerable(serializableAttr)).WithAdditionalAnnotations(Formatting.Formatter.Annotation);

                    var documentContainingNode = document.Project.Solution.GetDocument(typeDeclNode.SyntaxTree);
                    var docRoot = await documentContainingNode.GetSyntaxRootAsync(cancellationToken);
                    var newDocumentContainingNode = documentContainingNode.WithSyntaxRoot(docRoot.ReplaceNode(typeDeclNode, newTypeDeclNode));
                    var typeCodeAction = CodeAction.Create(FxCopFixersResources.AddSerializableAttribute, newDocumentContainingNode.Project.Solution);

                    actions = actions.Concat(typeCodeAction);
                }
            }

            return actions;
        }
        private static bool CanRemoveTypeFromParameter(
            SyntaxNode node,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            // We reduce any the parameters that are contained inside ParameterList
            if (node != null && node.IsParentKind(SyntaxKind.ParameterList) && node.Parent.IsParentKind(SyntaxKind.ParenthesizedLambdaExpression))
            {
                var parameterSyntax = (ParameterSyntax)node;
                if (parameterSyntax.Type != null)
                {
                    var annotation = new SyntaxAnnotation();
                    var newParameterSyntax = parameterSyntax.WithType(null).WithAdditionalAnnotations(annotation);

                    var oldLambda = node.FirstAncestorOrSelf<ParenthesizedLambdaExpressionSyntax>();
                    var newLambda = oldLambda.ReplaceNode(parameterSyntax, newParameterSyntax);
                    var speculationAnalyzer = new SpeculationAnalyzer(oldLambda, newLambda, semanticModel, cancellationToken);
                    newParameterSyntax = (ParameterSyntax)speculationAnalyzer.ReplacedExpression.GetAnnotatedNodesAndTokens(annotation).First();

                    var oldSymbol = semanticModel.GetDeclaredSymbol(parameterSyntax, cancellationToken);
                    var newSymbol = speculationAnalyzer.SpeculativeSemanticModel.GetDeclaredSymbol(newParameterSyntax, cancellationToken);
                    if (oldSymbol != null &&
                        newSymbol != null &&
                        oldSymbol.Type == newSymbol.Type)
                    {
                        return !speculationAnalyzer.ReplacementChangesSemantics();
                    }
                }
            }

            return false;
        }
Exemplo n.º 7
0
        public static ISymbol GetDeclaredOriginalSymbol(SyntaxNode syntaxNode,
                                                        SemanticModel semanticModel,
                                                        SemanticModel preportSemanticModel = null)
        {
            if (semanticModel == null && preportSemanticModel == null)
            {
                return(null);
            }

            var symbol = semanticModel?.GetDeclaredSymbol(syntaxNode);

            if (symbol == null && preportSemanticModel != null)
            {
                try
                {
                    symbol = preportSemanticModel.GetDeclaredSymbol(syntaxNode);
                }
                catch (Exception)
                {
                    //When looking for a symbol, and the semantic model is not passed, this generates an error.
                    //We don't log this error because this is an expected behavior when there's no previous semantic models
                }
            }

            return(symbol);
        }
Exemplo n.º 8
0
        protected static void VerifyModelForDeclarationPattern(
            SemanticModel model,
            SingleVariableDesignationSyntax designation,
            bool isShadowed,
            params IdentifierNameSyntax[] references)
        {
            var symbol = model.GetDeclaredSymbol(designation);
            Assert.Equal(designation.Identifier.ValueText, symbol.Name);
            Assert.Equal(designation, symbol.DeclaringSyntaxReferences.Single().GetSyntax());
            Assert.Equal(LocalDeclarationKind.PatternVariable, ((LocalSymbol)symbol).DeclarationKind);
            Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)designation));

            var other = model.LookupSymbols(designation.SpanStart, name: designation.Identifier.ValueText).Single();
            if (isShadowed)
            {
                Assert.NotEqual(symbol, other);
            }
            else
            {
                Assert.Same(symbol, other);
            }

            Assert.True(model.LookupNames(designation.SpanStart).Contains(designation.Identifier.ValueText));

            var decl = (DeclarationPatternSyntax)designation.Parent;
            Assert.True(SyntaxFacts.IsInNamespaceOrTypeContext(decl.Type));
            Assert.True(SyntaxFacts.IsInTypeOnlyContext(decl.Type));

            var local = ((SourceLocalSymbol)symbol);
            var type = local.Type;
            if (type.IsErrorType())
            {
                Assert.Null(model.GetSymbolInfo(decl.Type).Symbol);
            }
            else
            {
                Assert.Equal(type, model.GetSymbolInfo(decl.Type).Symbol);
            }

            foreach (var reference in references)
            {
                Assert.Same(symbol, model.GetSymbolInfo(reference).Symbol);
                Assert.Same(symbol, model.LookupSymbols(reference.SpanStart, name: designation.Identifier.ValueText).Single());
                Assert.True(model.LookupNames(reference.SpanStart).Contains(designation.Identifier.ValueText));
            }
        }
        private static SyntaxNode RemoveFlagsAttribute(Workspace workspace, SemanticModel model, SyntaxNode enumTypeSyntax, INamedTypeSymbol flagsAttributeType, CancellationToken cancellationToken)
        {
            var enumType = model.GetDeclaredSymbol(enumTypeSyntax) as INamedTypeSymbol;
            Contract.ThrowIfNull(enumType);

            var flagsAttribute = enumType.GetAttributes().First(a => a.AttributeClass == flagsAttributeType);
            return CodeGenerator.RemoveAttribute(enumTypeSyntax, workspace, flagsAttribute, CodeGenerationOptions.Default, cancellationToken);
        }
Exemplo n.º 10
0
 internal override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken)
 {
     var classSymbol = (INamedTypeSymbol)model.GetDeclaredSymbol(nodeToFix, cancellationToken);
     var instanceConstructors = classSymbol.InstanceConstructors.Where(t => t.DeclaredAccessibility == Accessibility.Public).Select(t => GetDeclaration(t)).Where(d => d != null).ToList();
     var generator = SyntaxGenerator.GetGenerator(document);
     var newRoot = root.ReplaceNodes(instanceConstructors, (original, rewritten) => generator.WithAccessibility(original, Accessibility.Protected));
     return Task.FromResult(document.WithSyntaxRoot(newRoot));
 }
        private static SyntaxNode RemoveFlagsAttribute(Workspace workspace, SemanticModel model, SyntaxNode enumTypeSyntax, INamedTypeSymbol flagsAttributeType, CancellationToken cancellationToken)
        {
            var enumType = model.GetDeclaredSymbol(enumTypeSyntax, cancellationToken) as INamedTypeSymbol;
            Debug.Assert(enumType != null);

            var flagsAttribute = enumType.GetAttributes().First(a => a.AttributeClass == flagsAttributeType);
            var attributeNode = flagsAttribute.ApplicationSyntaxReference.GetSyntax(cancellationToken);
            var generator = SyntaxGenerator.GetGenerator(workspace, enumTypeSyntax.Language);

            return generator.RemoveNode(enumTypeSyntax, attributeNode);
        }
 private ReferenceRewriter(
     SemanticModel semanticModel,
     VariableDeclaratorSyntax variableDeclarator,
     ExpressionSyntax expressionToInline,
     CancellationToken cancellationToken)
 {
     _semanticModel = semanticModel;
     _localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(variableDeclarator, cancellationToken);
     _variableDeclarator = variableDeclarator;
     _expressionToInline = expressionToInline;
     _cancellationToken = cancellationToken;
 }
Exemplo n.º 13
0
        internal override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, string diagnosticId, CancellationToken cancellationToken)
        {
            var classSymbol = (INamedTypeSymbol)model.GetDeclaredSymbol(nodeToFix);
            var instanceConstructors = classSymbol.InstanceConstructors.Where(t => t.DeclaredAccessibility == Accessibility.Public).Select(t => t.DeclaringSyntaxReferences[0].GetSyntax());
            var workspace = document.Project.Solution.Workspace;
            Func<SyntaxNode, SyntaxNode, SyntaxNode> replacementForNodes = (constructorNode, dummy) =>
                {
                    var newSyntax = CodeGenerator.UpdateDeclarationAccessibility(constructorNode, workspace, Accessibility.Protected, cancellationToken: cancellationToken).WithAdditionalAnnotations(Formatter.Annotation);
                    return newSyntax;
                };

            return Task.FromResult(document.WithSyntaxRoot(root.ReplaceNodes(instanceConstructors, replacementForNodes)));
        }
Exemplo n.º 14
0
        internal static ISymbol GetDeclaredSymbolSafe(this SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken)
        {
            if (node == null)
            {
                return(null);
            }

            var semanticModelFor = semanticModel.SemanticModelFor(node);

            if (semanticModelFor != null)
            {
                return(semanticModelFor.GetDeclaredSymbol(node, cancellationToken));
            }

            return(semanticModel?.GetDeclaredSymbol(node, cancellationToken));
        }
        protected async Task<SyntaxNode> ConvertMethodToAsync(Document document, SemanticModel semanticModel, SyntaxNode methodNode, CancellationToken cancellationToken)
        {
            var methodSymbol = semanticModel.GetDeclaredSymbol(methodNode, cancellationToken) as IMethodSymbol;

            if (methodSymbol.ReturnsVoid)
            {
                return AddAsyncKeyword(methodNode);
            }

            var returnType = methodSymbol.ReturnType;
            var compilation = semanticModel.Compilation;

            var taskSymbol = compilation.GetTypeByMetadataName(SystemThreadingTasksTask);
            var genericTaskSymbol = compilation.GetTypeByMetadataName(SystemThreadingTasksTaskT);
            if (taskSymbol == null)
            {
                return null;
            }

            if (returnType is IErrorTypeSymbol)
            {
                // The return type of the method will not bind.  This could happen for a lot of reasons.
                // The type may not actually exist or the user could just be missing a using/import statement.
                // We're going to try and see if there are any known types that have the same name as 
                // our return type, and then check if those are convertible to Task.  If they are then
                // we assume the user just has a missing using.  If they are not, we wrap the return
                // type in a generic Task.
                var typeName = returnType.Name;
                var syntaxFacts = document.Project.LanguageServices.GetService<ISyntaxFactsService>();
                var results = await SymbolFinder.FindDeclarationsAsync(
                    document.Project, typeName, ignoreCase: syntaxFacts.IsCaseSensitive, filter: SymbolFilter.Type, cancellationToken: cancellationToken).ConfigureAwait(false);

                if (results.OfType<ITypeSymbol>().Any(s => DoesConversionExist(compilation, s, taskSymbol)))
                {
                    return AddAsyncKeyword(methodNode);
                }

                return AddAsyncKeywordAndTaskReturnType(methodNode, returnType, genericTaskSymbol);
            }

            if (DoesConversionExist(compilation, returnType, taskSymbol))
            {
                return AddAsyncKeyword(methodNode);
            }

            return AddAsyncKeywordAndTaskReturnType(methodNode, returnType, genericTaskSymbol);
        }
        private IList<INamespaceSymbol> GetExistingNamespaces(
            SemanticModel semanticModel, NamespaceDeclarationSyntax namespaceDeclaration, CancellationToken cancellationToken)
        {
            var q = from u in namespaceDeclaration.Usings
                    let symbol = semanticModel.GetSymbolInfo(u.Name, cancellationToken).Symbol as INamespaceSymbol
                    where symbol != null && !symbol.IsGlobalNamespace
                    select symbol;

            var usingImports = q.ToList();

            var namespaceSymbol = semanticModel.GetDeclaredSymbol(namespaceDeclaration, cancellationToken) as INamespaceSymbol;
            var namespaceImports = GetContainingNamespacesAndThis(namespaceSymbol).ToList();

            var outerNamespaces = this.GetExistingNamespaces(semanticModel, namespaceDeclaration.Parent, cancellationToken);

            return outerNamespaces.Concat(namespaceImports).Concat(usingImports)
                                  .Distinct()
                                  .OrderBy(INamespaceSymbolExtensions.CompareNamespaces)
                                  .ToList();
        }
Exemplo n.º 17
0
        internal async override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var symbol = model.GetDeclaredSymbol(nodeToFix, cancellationToken);
            var generator = SyntaxGenerator.GetGenerator(document);

            // There was no constructor and so the diagnostic was on the type. Generate a serlialization ctor.
            if (symbol.Kind == SymbolKind.NamedType)
            {
                var typeSymbol = symbol as INamedTypeSymbol;
                var throwStatement = generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException")));

                var ctorDecl = generator.ConstructorDeclaration(
                    typeSymbol.Name,
                    new[]
                    {
                        generator.ParameterDeclaration("serializationInfo", generator.TypeExpression(WellKnownTypes.SerializationInfo(model.Compilation))),
                        generator.ParameterDeclaration("streamingContext", generator.TypeExpression(WellKnownTypes.StreamingContext(model.Compilation)))
                    },
                    typeSymbol.IsSealed ? Accessibility.Private : Accessibility.Protected,
                    statements: new[] { throwStatement });

                var editor = SymbolEditor.Create(document.Project.Solution);
                await editor.EditOneDeclarationAsync(typeSymbol, nodeToFix.GetLocation(), (e, d) => e.AddMember(d, ctorDecl), cancellationToken);
                return editor.GetChangedDocuments().First();
            }
            else if (symbol.Kind == SymbolKind.Method)
            {
                // There is a serialization constructor but with incorrect accessibility. Set that right.
                var methodSymbol = symbol as IMethodSymbol;

                // This would be constructor and can have only one definition.
                Debug.Assert(methodSymbol.IsConstructor() && methodSymbol.DeclaringSyntaxReferences.Count() == 1);
                var declaration = await methodSymbol.DeclaringSyntaxReferences.First().GetSyntaxAsync(cancellationToken);

                var newAccessibility = methodSymbol.ContainingType.IsSealed ? Accessibility.Private : Accessibility.Protected;
                var newDecl = generator.WithAccessibility(declaration, newAccessibility);
                return document.WithSyntaxRoot(root.ReplaceNode(declaration, newDecl));
            }

            return document;
        }
Exemplo n.º 18
0
        internal async override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, string diagnosticId, CancellationToken cancellationToken)
        {
            var syntaxFactoryService = document.GetLanguageService<SyntaxGenerator>();

            var symbol = model.GetDeclaredSymbol(nodeToFix);

            // There was no constructor and so the diagnostic was on the type. Generate a serlialization ctor.
            if (symbol.Kind == SymbolKind.NamedType)
            {
                var typeSymbol = symbol as INamedTypeSymbol;
                var throwStatement = syntaxFactoryService.CreateThrowNotImplementedStatementBlock(model.Compilation);

                var parameters = ImmutableArray.Create(
                    CodeGenerationSymbolFactory.CreateParameterSymbol(WellKnownTypes.SerializationInfo(model.Compilation), "serializationInfo"),
                    CodeGenerationSymbolFactory.CreateParameterSymbol(WellKnownTypes.StreamingContext(model.Compilation), "streamingContext"));

                var ctorSymbol = CodeGenerationSymbolFactory.CreateConstructorSymbol(null,
                                                                                     typeSymbol.IsSealed ? Accessibility.Private : Accessibility.Protected,
                                                                                     new SymbolModifiers(),
                                                                                     typeSymbol.Name,
                                                                                     parameters,
                                                                                     throwStatement);

                return await CodeGenerator.AddMethodDeclarationAsync(document.Project.Solution, typeSymbol, ctorSymbol).ConfigureAwait(false);
            }
            else if (symbol.Kind == SymbolKind.Method)
            {
                // There is a serialization constructor but with incorrect accessibility. Set that right.
                var methodSymbol = symbol as IMethodSymbol;

                // This would be constructor and can have only one definition.
                Debug.Assert(methodSymbol.IsConstructor() && methodSymbol.DeclaringSyntaxReferences.Count() == 1);
                var declaration = await methodSymbol.DeclaringSyntaxReferences.First().GetSyntaxAsync(cancellationToken);

                var newAccessibility = methodSymbol.ContainingType.IsSealed ? Accessibility.Private : Accessibility.Protected;
                var newDecl = CodeGenerator.UpdateDeclarationAccessibility(declaration, document.Project.Solution.Workspace, newAccessibility, cancellationToken: cancellationToken);
                return document.WithSyntaxRoot(root.ReplaceNode(declaration, newDecl));
            }

            return document;
        }
Exemplo n.º 19
0
        public async override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            context.CancellationToken.ThrowIfCancellationRequested();

            var rootTask          = context.Document.GetSyntaxRootAsync(context.CancellationToken);
            var semanticModelTask = context.Document.GetSemanticModelAsync(context.CancellationToken);

            await Task.WhenAll(rootTask, semanticModelTask).ConfigureAwait(false);

            var           root          = rootTask.Result;
            SemanticModel semanticModel = semanticModelTask.Result;

            if (!(root?.FindNode(context.Span) is ClassDeclarationSyntax dacNode))
            {
                return;
            }

            INamedTypeSymbol dacTypeSymbol = semanticModel?.GetDeclaredSymbol(dacNode, context.CancellationToken);

            if (dacTypeSymbol == null || dacTypeSymbol.MemberNames.Contains(TypeNames.ReferentialIntegrity.PrimaryKeyClassName))
            {
                return;
            }

            var pxContext = new PXContext(semanticModel.Compilation, codeAnalysisSettings: null);

            if (pxContext.ReferentialIntegritySymbols.PrimaryKeyOf == null)
            {
                return;
            }

            var codeActionTitle = nameof(Resources.PX1033Fix).GetLocalized().ToString();
            var codeAction      = CodeAction.Create(codeActionTitle,
                                                    cancellation => AddPrimaryKeyDeclarationToDacAsync(context.Document, root, dacNode, pxContext,
                                                                                                       dacTypeSymbol, cancellation),
                                                    equivalenceKey: codeActionTitle);

            context.RegisterCodeFix(codeAction, context.Diagnostics);
        }
        protected override bool TryInitializeState(
            Document document, SemanticModel model, SyntaxNode node, CancellationToken cancellationToken,
            out SyntaxNode classOrStructDecl, out INamedTypeSymbol classOrStructType, out IEnumerable<INamedTypeSymbol> interfaceTypes)
        {
            if (!cancellationToken.IsCancellationRequested)
            {
                var interfaceNode = node as TypeSyntax;
                if (interfaceNode != null && interfaceNode.Parent is BaseTypeSyntax &&
                    interfaceNode.Parent.IsParentKind(SyntaxKind.BaseList) &&
                    ((BaseTypeSyntax)interfaceNode.Parent).Type == interfaceNode)
                {
                    if (interfaceNode.Parent.Parent.IsParentKind(SyntaxKind.ClassDeclaration) ||
                        interfaceNode.Parent.Parent.IsParentKind(SyntaxKind.StructDeclaration))
                    {
                        var interfaceSymbolInfo = model.GetSymbolInfo(interfaceNode, cancellationToken);
                        if (interfaceSymbolInfo.CandidateReason != CandidateReason.WrongArity)
                        {
                            var interfaceType = interfaceSymbolInfo.GetAnySymbol() as INamedTypeSymbol;
                            cancellationToken.ThrowIfCancellationRequested();

                            if (interfaceType != null && interfaceType.TypeKind == TypeKind.Interface)
                            {
                                classOrStructDecl = interfaceNode.Parent.Parent.Parent as TypeDeclarationSyntax;
                                classOrStructType = model.GetDeclaredSymbol(classOrStructDecl, cancellationToken) as INamedTypeSymbol;
                                interfaceTypes = SpecializedCollections.SingletonEnumerable(interfaceType);

                                return interfaceTypes != null && classOrStructType != null;
                            }
                        }
                    }
                }
            }

            classOrStructDecl = null;
            classOrStructType = null;
            interfaceTypes = null;
            return false;
        }
Exemplo n.º 21
0
        private static void VerifyModelForDeconstructionField(SemanticModel model, SingleVariableDesignationSyntax decl, params IdentifierNameSyntax[] references)
        {
            var field = (FieldSymbol)model.GetDeclaredSymbol(decl);
            Assert.Equal(decl.Identifier.ValueText, field.Name);
            Assert.Equal(SymbolKind.Field, ((FieldSymbol)field).Kind);
            Assert.Same(field, model.GetDeclaredSymbol((SyntaxNode)decl));
            Assert.Same(field, model.LookupSymbols(decl.SpanStart, name: decl.Identifier.ValueText).Single());
            Assert.Equal(Accessibility.Private, field.DeclaredAccessibility);
            Assert.True(model.LookupNames(decl.SpanStart).Contains(decl.Identifier.ValueText));

            foreach (var reference in references)
            {
                Assert.Same(field, model.GetSymbolInfo(reference).Symbol);
                Assert.Same(field, model.LookupSymbols(reference.SpanStart, name: decl.Identifier.ValueText).Single());
                Assert.True(model.LookupNames(reference.SpanStart).Contains(decl.Identifier.ValueText));
                Assert.Equal(field.Type, model.GetTypeInfo(reference).Type);
            }
        }
 private void TestAnonymousTypePropertySymbol(SemanticModel model, SyntaxNode node, string name)
 {
     Assert.NotNull(node);
     var symbol = model.GetDeclaredSymbol(node);
     Assert.NotNull(symbol);
     Assert.Equal(name, symbol.ToTestDisplayString());
 }
        static Action AnalyzeActionMethod(
            Compilation compilation,
            SemanticModel semanticModel,
            MethodDeclarationSyntax actionMethodDeclaration,
            Dictionary <string, Compilation> referencedSymbols)
        {
            // Get some symbols by full name.

            var httpGetSymbol = compilation.GetTypeByMetadataName("System.Web.Http.HttpGetAttribute");

            var httpPostSymbol = compilation.GetTypeByMetadataName("System.Web.Http.HttpPostAttribute");

            var httpPutSymbol = compilation.GetTypeByMetadataName("System.Web.Http.HttpPutAttribute");

            var httpDeleteSymbol = compilation.GetTypeByMetadataName("System.Web.Http.HttpDeleteAttribute");

            var routeSymbol = compilation.GetTypeByMetadataName("System.Web.Http.RouteAttribute");

            var fromBodySymbol = compilation.GetTypeByMetadataName("System.Web.Http.FromBodyAttribute");

            var fromUriSymbol = compilation.GetTypeByMetadataName("System.Web.Http.FromUriAttribute");

            var methodSymbol = semanticModel.GetDeclaredSymbol(actionMethodDeclaration);

            var action = new Action
            {
                DocumentationCommentId = methodSymbol.GetDocumentationCommentId(),

                Name = methodSymbol.Name,

                BodyParameters = new List <Parameter>(),

                QueryParameters = new List <Parameter>(),

                RouteParameters = new List <Parameter>(),

                Examples = new List <Example>(),

                Results = new List <Result>()
            };

            // Go through the method's XML comments.

            var methodCommentsXml = methodSymbol.GetDocumentationCommentXml();

            var parameterNotes = new Dictionary <string, XElement>();

            if (!string.IsNullOrWhiteSpace(methodCommentsXml))
            {
                var methodCommentsRoot = XElement.Parse(methodCommentsXml);

                var summary = methodCommentsRoot.Element("summary");

                if (summary != null)
                {
                    foreach (var cref in summary.GetCrefs())
                    {
                        if (!referencedSymbols.ContainsKey(cref))
                        {
                            referencedSymbols.Add(cref, compilation);
                        }
                    }

                    action.Summary = summary.ToMarkup();
                }

                var remarks = methodCommentsRoot.Element("remarks");

                if (remarks != null)
                {
                    foreach (var cref in remarks.GetCrefs())
                    {
                        if (!referencedSymbols.ContainsKey(cref))
                        {
                            referencedSymbols.Add(cref, compilation);
                        }
                    }

                    action.Remarks = remarks.ToMarkup();
                }

                var returns = methodCommentsRoot.Element("returns");

                if (returns != null)
                {
                    foreach (var cref in returns.GetCrefs())
                    {
                        if (!referencedSymbols.ContainsKey(cref))
                        {
                            referencedSymbols.Add(cref, compilation);
                        }
                    }

                    action.Returns = returns.ToMarkup();
                }

                foreach (var example in methodCommentsRoot.Elements("example"))
                {
                    action.Examples.Add(new Example
                    {
                        Label = example.Attribute("label").Value,

                        Content = string
                                  .Concat(example.Nodes())
                                  .NormalizeCodeIndentation()
                    });
                }

                parameterNotes = methodCommentsRoot
                                 .Elements("param")
                                 .ToDictionary(
                    p => p.Attribute("name").Value,
                    p => p);
            }

            var methodName = actionMethodDeclaration.Identifier.ValueText;

            var routeKeys = Enumerable.Empty <string>();

            // Go through the method's attributes.

            foreach (var attributeList in actionMethodDeclaration.AttributeLists)
            {
                foreach (var attribute in attributeList.Attributes)
                {
                    // For each attribute, try to pull a recognized value.

                    var attributeTypeInfo = semanticModel.GetTypeInfo(attribute);

                    if (attributeTypeInfo.Type.MetadataName == httpGetSymbol.MetadataName)
                    {
                        action.Method = "GET";
                    }
                    else if (attributeTypeInfo.Type.MetadataName == httpPostSymbol.MetadataName)
                    {
                        action.Method = "POST";
                    }
                    else if (attributeTypeInfo.Type.MetadataName == httpPutSymbol.MetadataName)
                    {
                        action.Method = "PUT";
                    }
                    else if (attributeTypeInfo.Type.MetadataName == httpDeleteSymbol.MetadataName)
                    {
                        action.Method = "DELETE";
                    }
                    else if (attributeTypeInfo.Type.MetadataName == routeSymbol.MetadataName)
                    {
                        var routeArgument = attribute
                                            .ArgumentList
                                            .Arguments
                                            .Single()
                                            .Expression as LiteralExpressionSyntax;

                        action.Route = routeArgument.Token.ValueText;

                        routeKeys = Regex
                                    .Matches(action.Route, "(?<={)[^}]+(?=})")
                                    .Cast <Match>()
                                    .Select(m => m.Value)
                                    .ToList();
                    }
                }
            }

            // Go through parameters

            foreach (var parameter in actionMethodDeclaration.ParameterList.Parameters)
            {
                var predefinedType = parameter.Type as PredefinedTypeSyntax;

                //var typeName = predefinedType != null ?
                //    predefinedType.Keyword.ValueText :
                //    (parameter.Type as SimpleNameSyntax).Identifier.ValueText;

                var typeInfo = semanticModel.GetTypeInfo(parameter.Type);

                var documentCommentId = typeInfo.Type.GetDocumentationCommentId();

                if (!string.IsNullOrWhiteSpace(documentCommentId) &&
                    !referencedSymbols.ContainsKey(documentCommentId))
                {
                    referencedSymbols.Add(documentCommentId, compilation);
                }

                var parameterType = semanticModel.GetTypeInfo(parameter.Type);

                var parameterName = parameter.Identifier.ValueText;

                var fromBody = false;

                var fromUri = false;

                foreach (var attributeList in parameter.AttributeLists)
                {
                    foreach (var attribute in attributeList.Attributes)
                    {
                        var attributeTypeInfo = semanticModel.GetTypeInfo(attribute);

                        if (attributeTypeInfo.Type.MetadataName == fromBodySymbol.MetadataName)
                        {
                            fromBody = true;
                        }
                        else if (attributeTypeInfo.Type.MetadataName == fromUriSymbol.MetadataName)
                        {
                            fromUri = true;
                        }
                    }
                }

                var outParameter = new Parameter
                {
                    Key = parameterName,

                    TypeName = typeInfo.Type.ToTypeDisplayName(),

                    TypeDocumentCommentId = typeInfo.Type.GetDocumentationCommentId(),

                    Optional = false, // TODO: not this

                    Notes = parameterNotes.ContainsKey(parameterName) ?
                            parameterNotes[parameterName].ToMarkup() :
                            null
                };

                if (routeKeys.Contains(parameterName))
                {
                    action.RouteParameters.Add(outParameter);
                }
                else if (fromUri || parameterType.Type.IsValueType)
                {
                    action.QueryParameters.Add(outParameter);
                }
                else if (fromBody || !parameterType.Type.IsValueType)
                {
                    action.BodyParameters.Add(outParameter);
                }
            }

            var returnStatements = actionMethodDeclaration
                                   .DescendantNodes()
                                   .OfType <ReturnStatementSyntax>()
                                   .ToList();

            foreach (var returnStatement in returnStatements)
            {
                var resultMethodInvocation = returnStatement
                                             .DescendantNodes()
                                             .OfType <InvocationExpressionSyntax>()
                                             .First();

                var invokedMethodSymbol = semanticModel
                                          .GetSymbolInfo(resultMethodInvocation.Expression)
                                          .Symbol as IMethodSymbol;

                var argumentSyntax = resultMethodInvocation
                                     .ArgumentList
                                     .Arguments
                                     .SingleOrDefault();

                var result = new Result
                {
                    Kind = invokedMethodSymbol.Name
                };

                if (argumentSyntax != null)
                {
                    var l = argumentSyntax.DescendantNodes().First();

                    var literalExpression = l as LiteralExpressionSyntax;

                    if (literalExpression != null)
                    {
                        result.ArgumentText = ScrubArgumentText(literalExpression.Token.ValueText);
                    }

                    var argumentSymbol = semanticModel.GetSymbolInfo(argumentSyntax);

                    var argumentTypeInfo = semanticModel.GetTypeInfo(argumentSyntax.Expression);

                    var typeName = argumentTypeInfo.Type.Name;

                    result.ArgumentType = argumentTypeInfo.Type.ToDisplayString();
                }

                action.Results.Add(result);
            }

            return(action);
        }
Exemplo n.º 24
0
        public static void AnalyzeLocalDeclarationStatement(SyntaxNodeAnalysisContext context)
        {
            var localDeclaration = (LocalDeclarationStatementSyntax)context.Node;

            if (localDeclaration.ContainsDiagnostics)
            {
                return;
            }

            if (localDeclaration.SpanOrTrailingTriviaContainsDirectives())
            {
                return;
            }

            if (localDeclaration.IsConst)
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

            if (!localInfo.Success)
            {
                return;
            }

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(localDeclaration.NextStatement());

            if (!assignmentInfo.Success)
            {
                return;
            }

            if (assignmentInfo.Statement.ContainsDiagnostics)
            {
                return;
            }

            if (assignmentInfo.Statement.SpanOrLeadingTriviaContainsDirectives())
            {
                return;
            }

            if (!(assignmentInfo.Left is IdentifierNameSyntax identifierName))
            {
                return;
            }

            string name = identifierName.Identifier.ValueText;

            if (!string.Equals(localInfo.IdentifierText, name, StringComparison.Ordinal))
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            if (!(semanticModel.GetSymbol(identifierName, cancellationToken) is ILocalSymbol localSymbol))
            {
                return;
            }

            if (!localSymbol.Equals(semanticModel.GetDeclaredSymbol(localInfo.Declarator, cancellationToken)))
            {
                return;
            }

            ExpressionSyntax value = localInfo.Value;

            if (value != null)
            {
                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(localInfo.Type, cancellationToken);

                if (typeSymbol == null)
                {
                    return;
                }

                if (!semanticModel.IsDefaultValue(typeSymbol, value, cancellationToken))
                {
                    return;
                }

                if (IsReferenced(localSymbol, assignmentInfo.Right, semanticModel, cancellationToken))
                {
                    return;
                }
            }

            context.ReportDiagnostic(DiagnosticDescriptors.MergeLocalDeclarationWithAssignment, localInfo.Identifier);

            if (value != null)
            {
                context.ReportNode(DiagnosticDescriptors.MergeLocalDeclarationWithAssignmentFadeOut, localInfo.Initializer);
                context.ReportToken(DiagnosticDescriptors.MergeLocalDeclarationWithAssignmentFadeOut, assignmentInfo.OperatorToken);
            }

            context.ReportToken(DiagnosticDescriptors.MergeLocalDeclarationWithAssignmentFadeOut, localDeclaration.SemicolonToken);
            context.ReportNode(DiagnosticDescriptors.MergeLocalDeclarationWithAssignmentFadeOut, assignmentInfo.Left);
        }
        private static IEnumerable<INamedTypeSymbol> GetTypesInFile(SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.NavigationBar_ItemService_GetTypesInFile_CSharp, cancellationToken))
            {
                var types = new HashSet<INamedTypeSymbol>();
                var nodesToVisit = new Stack<SyntaxNode>();

                nodesToVisit.Push(semanticModel.SyntaxTree.GetRoot(cancellationToken));

                while (!nodesToVisit.IsEmpty())
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return SpecializedCollections.EmptyEnumerable<INamedTypeSymbol>();
                    }

                    var node = nodesToVisit.Pop();

                    var type = node.TypeSwitch(
                        (BaseTypeDeclarationSyntax t) => semanticModel.GetDeclaredSymbol(t, cancellationToken),
                        (EnumDeclarationSyntax e) => semanticModel.GetDeclaredSymbol(e, cancellationToken),
                        (DelegateDeclarationSyntax d) => semanticModel.GetDeclaredSymbol(d, cancellationToken));

                    if (type != null)
                    {
                        types.Add((INamedTypeSymbol)type);
                    }

                    if (node is BaseMethodDeclarationSyntax ||
                        node is BasePropertyDeclarationSyntax ||
                        node is BaseFieldDeclarationSyntax ||
                        node is StatementSyntax ||
                        node is ExpressionSyntax)
                    {
                        // quick bail out to prevent us from creating every nodes exist in current file
                        continue;
                    }

                    foreach (var child in node.ChildNodes())
                    {
                        nodesToVisit.Push(child);
                    }
                }

                return types;
            }
        }
Exemplo n.º 26
0
 private static void VerifyModelForDeclarationPatternDuplicateInSameScope(SemanticModel model, DeclarationPatternSyntax decl)
 {
     var symbol = model.GetDeclaredSymbol(decl);
     Assert.Equal(decl.Identifier.ValueText, symbol.Name);
     Assert.Equal(LocalDeclarationKind.PatternVariable, ((LocalSymbol)symbol).DeclarationKind);
     Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)decl));
     Assert.NotEqual(symbol, model.LookupSymbols(decl.SpanStart, name: decl.Identifier.ValueText).Single());
     Assert.True(model.LookupNames(decl.SpanStart).Contains(decl.Identifier.ValueText));
 }
        internal static Accessibility GetDeclaredAccessibility(this BasePropertyDeclarationSyntax syntax, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (syntax == null)
            {
                throw new ArgumentNullException(nameof(syntax));
            }

            if (semanticModel == null)
            {
                throw new ArgumentNullException(nameof(semanticModel));
            }

            AccessLevel accessLevel = GetAccessLevel(syntax.Modifiers);

            if (accessLevel != AccessLevel.NotSpecified)
            {
                return(accessLevel.ToAccessibility());
            }

            PropertyDeclarationSyntax propertyDeclarationSyntax = syntax as PropertyDeclarationSyntax;

            if (propertyDeclarationSyntax != null)
            {
                if (propertyDeclarationSyntax.ExplicitInterfaceSpecifier == null)
                {
                    return(Accessibility.Private);
                }
                else
                {
                    return(Accessibility.Public);
                }
            }

            IndexerDeclarationSyntax indexerDeclarationSyntax = syntax as IndexerDeclarationSyntax;

            if (indexerDeclarationSyntax != null)
            {
                if (indexerDeclarationSyntax.ExplicitInterfaceSpecifier == null)
                {
                    return(Accessibility.Private);
                }
                else
                {
                    return(Accessibility.Public);
                }
            }

            EventDeclarationSyntax eventDeclarationSyntax = syntax as EventDeclarationSyntax;

            if (eventDeclarationSyntax != null)
            {
                if (eventDeclarationSyntax.ExplicitInterfaceSpecifier == null)
                {
                    return(Accessibility.Private);
                }
                else
                {
                    return(Accessibility.Public);
                }
            }

            ISymbol declaredSymbol = semanticModel.GetDeclaredSymbol(syntax, cancellationToken);

            return(declaredSymbol?.DeclaredAccessibility ?? Accessibility.NotApplicable);
        }
Exemplo n.º 28
0
        private static void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext context)
        {
            var property = (PropertyDeclarationSyntax)context.Node;

            if (property.ContainsDiagnostics)
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            IFieldSymbol fieldSymbol = null;

            AccessorDeclarationSyntax getter = null;
            AccessorDeclarationSyntax setter = null;

            ArrowExpressionClauseSyntax expressionBody = property.ExpressionBody;

            if (expressionBody != null)
            {
                IdentifierNameSyntax identifierName = GetIdentifierNameFromExpression(expressionBody.Expression);

                if (identifierName != null)
                {
                    fieldSymbol = GetBackingFieldSymbol(identifierName, semanticModel, cancellationToken);
                }
            }
            else
            {
                getter = property.Getter();

                if (getter != null)
                {
                    setter = property.Setter();

                    if (setter != null)
                    {
                        fieldSymbol = GetBackingFieldSymbol(getter, setter, semanticModel, cancellationToken);
                    }
                    else
                    {
                        IdentifierNameSyntax identifierName = GetIdentifierNameFromGetter(getter);

                        if (identifierName != null)
                        {
                            fieldSymbol = GetBackingFieldSymbol(identifierName, semanticModel, cancellationToken);
                        }
                    }
                }
            }

            if (fieldSymbol == null)
            {
                return;
            }

            var variableDeclarator = (VariableDeclaratorSyntax)fieldSymbol.GetSyntax(cancellationToken);

            if (variableDeclarator.SyntaxTree != property.SyntaxTree)
            {
                return;
            }

            if (variableDeclarator.IsParentKind(SyntaxKind.VariableDeclaration) &&
                variableDeclarator.Parent.Parent is FieldDeclarationSyntax fieldDeclaration &&
                fieldDeclaration.AttributeLists.Any())
            {
                return;
            }

            if (!CheckPreprocessorDirectives(property))
            {
                return;
            }

            if (!CheckPreprocessorDirectives(variableDeclarator))
            {
                return;
            }

            IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(property, cancellationToken);

            if (propertySymbol?.IsStatic != fieldSymbol.IsStatic)
            {
                return;
            }

            if (!propertySymbol.ExplicitInterfaceImplementations.IsDefaultOrEmpty)
            {
                return;
            }

            if (!SymbolEqualityComparer.Default.Equals(propertySymbol.Type, fieldSymbol.Type))
            {
                return;
            }

            if (!SymbolEqualityComparer.Default.Equals(propertySymbol.ContainingType, fieldSymbol.ContainingType))
            {
                return;
            }

            if (setter == null &&
                propertySymbol.IsOverride &&
                propertySymbol.OverriddenProperty?.SetMethod != null)
            {
                return;
            }

            cancellationToken.ThrowIfCancellationRequested();

            foreach (AttributeData attributeData in fieldSymbol.GetAttributes())
            {
                if (attributeData.AttributeClass.HasMetadataName(MetadataNames.System_NonSerializedAttribute))
                {
                    return;
                }
            }

            if (HasStructLayoutAttributeWithExplicitKind(propertySymbol.ContainingType))
            {
                return;
            }

            if (!IsFixableBackingField(property, propertySymbol, fieldSymbol, semanticModel, cancellationToken))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UseAutoProperty, property.Identifier);

            if (property.ExpressionBody != null)
            {
                DiagnosticHelpers.ReportNode(context, DiagnosticRules.UseAutoPropertyFadeOut, property.ExpressionBody);
            }
            else
            {
                if (getter != null)
                {
                    FadeOut(getter);
                }

                if (setter != null)
                {
                    FadeOut(setter);
                }
            }

            void FadeOut(AccessorDeclarationSyntax accessor)
            {
                BlockSyntax body = accessor.Body;

                if (body != null)
                {
                    switch (body.Statements[0])
                    {
                    case ReturnStatementSyntax returnStatement:
                    {
                        DiagnosticHelpers.ReportToken(context, DiagnosticRules.UseAutoPropertyFadeOut, returnStatement.ReturnKeyword);
                        DiagnosticHelpers.ReportNode(context, DiagnosticRules.UseAutoPropertyFadeOut, returnStatement.Expression);
                        break;
                    }

                    case ExpressionStatementSyntax expressionStatement:
                    {
                        DiagnosticHelpers.ReportNode(context, DiagnosticRules.UseAutoPropertyFadeOut, expressionStatement.Expression);
                        break;
                    }
                    }

                    CSharpDiagnosticHelpers.ReportBraces(context, DiagnosticRules.UseAutoPropertyFadeOut, body);
                }
                else
                {
                    DiagnosticHelpers.ReportNode(context, DiagnosticRules.UseAutoPropertyFadeOut, accessor.ExpressionBody);
                }
            }
        }
 public DisposableChecker(ClassDeclarationSyntax classDeclaration, SemanticModel semanticModel)
 {
     this.classDeclaration = classDeclaration;
     this.semanticModel    = semanticModel;
     this.classSymbol      = semanticModel.GetDeclaredSymbol(classDeclaration);
 }
Exemplo n.º 30
0
        protected override void ProcessBlock(Block block, out HashSet <ISymbol> assignedInBlock,
                                             out HashSet <ISymbol> usedInBlock)
        {
            assignedInBlock = new HashSet <ISymbol>(); // Kill (The set of variables that are assigned a value.)
            usedInBlock     = new HashSet <ISymbol>(); // Gen (The set of variables that are used before any assignment.)

            var assignmentLhs = new HashSet <SyntaxNode>();

            foreach (var instruction in block.Instructions.Reverse())
            {
                switch (instruction.Kind())
                {
                case SyntaxKind.IdentifierName:
                    ProcessIdentifier(instruction, assignedInBlock, usedInBlock, assignmentLhs);
                    break;

                case SyntaxKind.SimpleAssignmentExpression:
                    ProcessSimpleAssignment(instruction, assignedInBlock, usedInBlock, assignmentLhs);
                    break;

                case SyntaxKind.VariableDeclarator:
                    ProcessVariableDeclarator((VariableDeclaratorSyntax)instruction, assignedInBlock,
                                              usedInBlock);
                    break;

                case SyntaxKind.AnonymousMethodExpression:
                case SyntaxKind.ParenthesizedLambdaExpression:
                case SyntaxKind.SimpleLambdaExpression:
                case SyntaxKind.QueryExpression:
                    CollectAllCapturedLocal(instruction);
                    break;

                default:
                    break;
                }
            }

            if (block.Instructions.Any())
            {
                return;
            }

            // Variable declaration in a foreach statement is not a VariableDeclarator, so handling it separately:
            if (block is BinaryBranchBlock foreachBlock &&
                foreachBlock.BranchingNode.IsKind(SyntaxKind.ForEachStatement))
            {
                var foreachNode = (ForEachStatementSyntax)foreachBlock.BranchingNode;
                ProcessVariableInForeach(foreachNode, assignedInBlock, usedInBlock);
            }

            // Keep alive the variables declared and used in the using statement until the UsingFinalizerBlock
            if (block is UsingEndBlock usingFinalizerBlock)
            {
                var disposableSymbols = usingFinalizerBlock.Identifiers
                                        .Select(i => semanticModel.GetDeclaredSymbol(i.Parent)
                                                ?? semanticModel.GetSymbolInfo(i.Parent).Symbol)
                                        .WhereNotNull();
                foreach (var disposableSymbol in disposableSymbols)
                {
                    usedInBlock.Add(disposableSymbol);
                }
            }
        }
Exemplo n.º 31
0
        MethodDeclarationSyntax RewriteMethod(MethodDeclarationSyntax inMethodSyntax, SemanticModel semanticModel)
        {
            var inMethodSymbol = semanticModel.GetDeclaredSymbol(inMethodSyntax);

            //Log.LogMessage("Method {0}: {1}", inMethodInfo.Symbol.Name, inMethodInfo.Symbol.);

            var outMethodName = inMethodSyntax.Identifier.Text + "Async";

            _log.Debug("  Rewriting method {0} to {1}", inMethodSymbol.Name, outMethodName);

            // Visit all method invocations inside the method, rewrite them to async if needed
            var rewriter  = new MethodInvocationRewriter(_log, semanticModel, _excludedTypes, _cancellationTokenSymbol, GenerateConfigureAwait);
            var outMethod = (MethodDeclarationSyntax)rewriter.Visit(inMethodSyntax);

            // Method signature
            outMethod = outMethod
                        .WithIdentifier(SyntaxFactory.Identifier(outMethodName))
                        .WithAttributeLists(new SyntaxList <AttributeListSyntax>())
                        .WithModifiers(inMethodSyntax.Modifiers
                                       .Add(SyntaxFactory.Token(SyntaxKind.AsyncKeyword))
                        //.Remove(SyntaxFactory.Token(SyntaxKind.OverrideKeyword))
                        //.Remove(SyntaxFactory.Token(SyntaxKind.NewKeyword))
                                       )
                        // Insert the cancellation token into the parameter list at the right place
                        .WithParameterList(SyntaxFactory.ParameterList(inMethodSyntax.ParameterList.Parameters.Insert(
                                                                           inMethodSyntax.ParameterList.Parameters.TakeWhile(p => p.Default == null && !p.Modifiers.Any(m => m.IsKind(SyntaxKind.ParamsKeyword))).Count(),
                                                                           SyntaxFactory.Parameter(
                                                                               SyntaxFactory.List <AttributeListSyntax>(),
                                                                               SyntaxFactory.TokenList(),
                                                                               SyntaxFactory.ParseTypeName("CancellationToken"),
                                                                               SyntaxFactory.Identifier("cancellationToken"),
                                                                               null
                                                                               ))));

            // Transform return type adding Task<>
            var returnType = inMethodSyntax.ReturnType.ToString();

            outMethod = outMethod.WithReturnType(SyntaxFactory.ParseTypeName(
                                                     returnType == "void" ? "Task" : $"Task<{returnType}>")
                                                 );

            // Remove the override and new attributes. Seems like the clean .Remove above doesn't work...
            for (var i = 0; i < outMethod.Modifiers.Count;)
            {
                var text = outMethod.Modifiers[i].Text;
                if (text == "override" || text == "new")
                {
                    outMethod = outMethod.WithModifiers(outMethod.Modifiers.RemoveAt(i));
                    continue;
                }
                i++;
            }

            var attr = inMethodSymbol.GetAttributes().Single(a => a.AttributeClass.Name == "RewriteAsyncAttribute");

            if (attr.ConstructorArguments.Length > 0 && (bool)attr.ConstructorArguments[0].Value)
            {
                outMethod = outMethod.AddModifiers(SyntaxFactory.Token(SyntaxKind.OverrideKeyword));
            }

            return(outMethod);
        }
Exemplo n.º 32
0
        private static ReduceIfNestingAnalysisResult AnalyzeCore(
            IfStatementSyntax ifStatement,
            SemanticModel semanticModel,
            SyntaxKind jumpKind,
            ReduceIfNestingOptions options,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            if (!statementsInfo.Success)
            {
                return(Fail(ifStatement));
            }

            SyntaxNode node       = statementsInfo.Parent;
            SyntaxNode parent     = node.Parent;
            SyntaxKind parentKind = parent.Kind();

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            if (statementsInfo.IsParentSwitchSection ||
                parentKind == SyntaxKind.SwitchSection)
            {
                SyntaxNode switchSection = (statementsInfo.IsParentSwitchSection) ? node : parent;

                if (!options.AllowSwitchSection())
                {
                    return(Fail(switchSection));
                }

                if (ifStatement != statements.LastButOneOrDefault())
                {
                    return(Fail(switchSection));
                }

                if (!IsFixableJumpStatement(statements.Last(), ref jumpKind))
                {
                    return(Fail(switchSection));
                }

                if (!options.AllowNestedFix() &&
                    IsNestedFix(switchSection.Parent, semanticModel, options, cancellationToken))
                {
                    return(Fail(switchSection));
                }

                return(Success(jumpKind, switchSection));
            }

            if (parentKind.Is(
                    SyntaxKind.ForStatement,
                    SyntaxKind.ForEachStatement,
                    SyntaxKind.DoStatement,
                    SyntaxKind.WhileStatement))
            {
                if (!options.AllowLoop())
                {
                    return(Fail(parent));
                }

                StatementSyntax lastStatement = statements.Last();

                if (ifStatement == lastStatement)
                {
                    jumpKind = SyntaxKind.ContinueStatement;
                }
                else
                {
                    if (ifStatement != statements.LastButOneOrDefault())
                    {
                        return(Fail(parent));
                    }

                    if (!IsFixableJumpStatement(lastStatement, ref jumpKind))
                    {
                        return(Fail(parent));
                    }
                }

                if (!options.AllowNestedFix() &&
                    IsNestedFix(parent.Parent, semanticModel, options, cancellationToken))
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            if (!IsFixable(ifStatement, statements, ref jumpKind))
            {
                return(Fail(node));
            }

            switch (parentKind)
            {
            case SyntaxKind.ConstructorDeclaration:
            case SyntaxKind.DestructorDeclaration:
            case SyntaxKind.SetAccessorDeclaration:
            case SyntaxKind.AddAccessorDeclaration:
            case SyntaxKind.RemoveAccessorDeclaration:
            {
                if (jumpKind == SyntaxKind.None)
                {
                    jumpKind = SyntaxKind.ReturnStatement;
                }
                else if (jumpKind != SyntaxKind.ReturnStatement)
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            case SyntaxKind.OperatorDeclaration:
            case SyntaxKind.ConversionOperatorDeclaration:
            case SyntaxKind.GetAccessorDeclaration:
            {
                if (jumpKind == SyntaxKind.None)
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            case SyntaxKind.MethodDeclaration:
            {
                var methodDeclaration = (MethodDeclarationSyntax)parent;

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                if (methodDeclaration.ReturnsVoid())
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (methodDeclaration.Modifiers.Contains(SyntaxKind.AsyncKeyword) &&
                    semanticModel
                    .GetDeclaredSymbol(methodDeclaration, cancellationToken)?
                    .ReturnType
                    .HasMetadataName(MetadataNames.System_Threading_Tasks_Task) == true)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (semanticModel
                    .GetDeclaredSymbol(methodDeclaration, cancellationToken)?
                    .ReturnType
                    .OriginalDefinition
                    .IsIEnumerableOrIEnumerableOfT() == true &&
                    methodDeclaration.ContainsYield())
                {
                    return(Success(SyntaxKind.YieldBreakStatement, parent));
                }

                break;
            }

            case SyntaxKind.LocalFunctionStatement:
            {
                var localFunction = (LocalFunctionStatementSyntax)parent;

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                if (localFunction.ReturnsVoid())
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (localFunction.Modifiers.Contains(SyntaxKind.AsyncKeyword) &&
                    semanticModel.GetDeclaredSymbol(localFunction, cancellationToken)?
                    .ReturnType
                    .HasMetadataName(MetadataNames.System_Threading_Tasks_Task) == true)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (semanticModel.GetDeclaredSymbol(localFunction, cancellationToken)?
                    .ReturnType
                    .OriginalDefinition
                    .IsIEnumerableOrIEnumerableOfT() == true &&
                    localFunction.ContainsYield())
                {
                    return(Success(SyntaxKind.YieldBreakStatement, parent));
                }

                break;
            }

            case SyntaxKind.AnonymousMethodExpression:
            case SyntaxKind.SimpleLambdaExpression:
            case SyntaxKind.ParenthesizedLambdaExpression:
            {
                var anonymousFunction = (AnonymousFunctionExpressionSyntax)parent;

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                if (!(semanticModel.GetSymbol(anonymousFunction, cancellationToken) is IMethodSymbol methodSymbol))
                {
                    return(Fail(parent));
                }

                if (methodSymbol.ReturnsVoid)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (anonymousFunction.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword &&
                    methodSymbol.ReturnType.HasMetadataName(MetadataNames.System_Threading_Tasks_Task))
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                break;
            }

            case SyntaxKind.IfStatement:
            {
                ifStatement = (IfStatementSyntax)parent;

                if (ifStatement.Parent is ElseClauseSyntax elseClause)
                {
                    if (ifStatement.Else != null)
                    {
                        return(Fail(parent));
                    }

                    if (!options.AllowIfInsideIfElse())
                    {
                        return(Fail(parent));
                    }

                    return(AnalyzeCore(ifStatement.GetTopmostIf(), semanticModel, jumpKind, options, cancellationToken));
                }
                else
                {
                    if (!IsFixable(ifStatement))
                    {
                        return(Fail(parent));
                    }

                    if (!options.AllowNestedFix())
                    {
                        return(Fail(parent));
                    }

                    return(AnalyzeCore(ifStatement, semanticModel, jumpKind, options, cancellationToken));
                }
            }

            case SyntaxKind.ElseClause:
            {
                if (!options.AllowIfInsideIfElse())
                {
                    return(Fail(parent));
                }

                var elseClause = (ElseClauseSyntax)parent;

                return(AnalyzeCore(elseClause.GetTopmostIf(), semanticModel, jumpKind, options, cancellationToken));
            }
            }

            return(Fail(parent));
        }
        /// <summary>
        /// Analyzes the project and returns information about the diagnostics in it.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task <ImmutableList <DocumentationDiagnostic> > GetDiagnosticsAsync()
        {
            var diagnostics = ImmutableList.CreateBuilder <DocumentationDiagnostic>();

            var syntaxTrees = _analyzerCompilation.SyntaxTrees;

            foreach (var syntaxTree in syntaxTrees)
            {
                var match = _diagnosticPathRegex.Match(syntaxTree.FilePath);
                if (!match.Success)
                {
                    continue;
                }

                string shortName       = match.Groups["name"].Value;
                string noCodeFixReason = null;

                // Check if this syntax tree represents a diagnostic
                SyntaxNode syntaxRoot = await syntaxTree.GetRootAsync().ConfigureAwait(false);

                SemanticModel semanticModel   = _analyzerCompilation.GetSemanticModel(syntaxTree);
                SyntaxNode    classSyntaxNode = syntaxRoot.DescendantNodes().FirstOrDefault(x => x.IsKind(SyntaxKind.ClassDeclaration));

                if (classSyntaxNode == null)
                {
                    continue;
                }

                INamedTypeSymbol classSymbol = semanticModel.GetDeclaredSymbol(classSyntaxNode) as INamedTypeSymbol;

                if (!InheritsFrom(classSymbol, _diagnosticAnalyzerTypeSymbol))
                {
                    continue;
                }

                if (classSymbol.IsAbstract)
                {
                    continue;
                }

                IEnumerable <DiagnosticDescriptor> descriptorInfos = GetDescriptor(classSymbol);

                foreach (var descriptorInfo in descriptorInfos)
                {
                    var(codeFixStatus, fixAllStatus) = GetCodeFixAndFixAllStatus(descriptorInfo.Id, classSymbol, out noCodeFixReason);
                    string status = GetStatus(classSymbol, syntaxRoot, semanticModel, descriptorInfo);
                    if (descriptorInfo.CustomTags.Contains(WellKnownDiagnosticTags.NotConfigurable))
                    {
                        continue;
                    }

                    var diagnostic = new DocumentationDiagnostic
                    {
                        Id              = descriptorInfo.Id,
                        Category        = descriptorInfo.Category,
                        Severity        = descriptorInfo.DefaultSeverity.ToString(),
                        Status          = status,
                        Name            = shortName,
                        Title           = descriptorInfo.Title.ToString(),
                        HelpLink        = descriptorInfo.HelpLinkUri,
                        CodeFixStatus   = codeFixStatus,
                        FixAllStatus    = fixAllStatus,
                        NoCodeFixReason = noCodeFixReason,
                    };
                    diagnostics.Add(diagnostic);
                }
            }

            return(diagnostics.ToImmutable());
        }
Exemplo n.º 34
0
        public static IEnumerable <ExpressionSyntax> GetNonNewObjectReturnsForPropertyGet(
            PropertyDeclarationSyntax propertyDeclaration,
            SemanticModel semanticModel,
            KnownSymbols knownSymbols,
            RecursiveState recursiveState1)
        {
            var propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration);

            if (propertySymbol.GetMethod == null)
            {
                yield break;
            }

            if (!propertySymbol.ReturnsByRef && IsCompleteValueType(propertySymbol.Type))
            {
                yield break;
            }

            List <ExpressionSyntax> returnExpressions;

            if (propertyDeclaration.AccessorList != null)
            {
                var getAccessor =
                    propertyDeclaration.AccessorList.Accessors.FirstOrNoValue(x =>
                                                                              x.Keyword.Kind() == SyntaxKind.GetKeyword);

                if (getAccessor.HasNoValue)
                {
                    yield break;
                }

                var getAccessorValue = getAccessor.GetValue();

                returnExpressions =
                    getAccessorValue.ExpressionBody != null
                        ? new List <ExpressionSyntax>()
                {
                    getAccessorValue.ExpressionBody.Expression
                }
                        : getAccessor.GetValue()
                .DescendantNodes()
                .OfType <ReturnStatementSyntax>()
                .Select(x => x.Expression)
                .ToList();
            }
            else if (propertyDeclaration.ExpressionBody != null)
            {
                returnExpressions = new List <ExpressionSyntax>()
                {
                    propertyDeclaration.ExpressionBody.Expression
                };
            }
            else
            {
                yield break;
            }

            foreach (var expression in returnExpressions)
            {
                if (!Utils.IsNewlyCreatedObject(semanticModel, expression, knownSymbols, RecursiveIsNewlyCreatedObjectState.Empty(), recursiveState1))
                {
                    yield return(expression);
                }
            }
        }
Exemplo n.º 35
0
        private static void VerifyModelForOutField(
            SemanticModel model,
            DeclarationExpressionSyntax decl,
            bool duplicate,
            params IdentifierNameSyntax[] references)
        {
            var variableDesignationSyntax = GetVariableDesignation(decl);
            var symbol = model.GetDeclaredSymbol(variableDesignationSyntax);
            Assert.Equal(decl.Identifier().ValueText, symbol.Name);
            Assert.Equal(SymbolKind.Field, symbol.Kind);
            Assert.Equal(variableDesignationSyntax, symbol.DeclaringSyntaxReferences.Single().GetSyntax());
            Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)variableDesignationSyntax));

            var symbols = model.LookupSymbols(decl.SpanStart, name: decl.Identifier().ValueText);
            var names = model.LookupNames(decl.SpanStart);

            if (duplicate)
            {
                Assert.True(symbols.Count() > 1);
                Assert.Contains(symbol, symbols);
            }
            else
            {
                Assert.Same(symbol, symbols.Single());
            }

            Assert.Contains(decl.Identifier().ValueText, names);

            var local = (FieldSymbol)symbol;
            var typeSyntax = decl.Type();

            Assert.True(SyntaxFacts.IsInNamespaceOrTypeContext(typeSyntax));
            Assert.True(SyntaxFacts.IsInTypeOnlyContext(typeSyntax));

            if (typeSyntax.IsVar && local.Type.IsErrorType())
            {
                Assert.Null(model.GetSymbolInfo(typeSyntax).Symbol);
            }
            else
            {
                Assert.Equal(local.Type, model.GetSymbolInfo(typeSyntax).Symbol);
            }

            var declarator = decl.Ancestors().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
            var inFieldDeclaratorArgumentlist = declarator != null && declarator.Parent.Parent.Kind() != SyntaxKind.LocalDeclarationStatement &&
                                           (declarator.ArgumentList?.Contains(decl)).GetValueOrDefault();
            if (inFieldDeclaratorArgumentlist)
            {
                Assert.Null(model.GetSymbolInfo(decl).Symbol);
                Assert.Null(model.GetSymbolInfo(decl).Symbol);
            }
            else
            {
                Assert.Same(symbol, model.GetSymbolInfo(decl).Symbol);
                Assert.Same(symbol, model.GetSymbolInfo(decl).Symbol);
            }

            Assert.Null(model.GetDeclaredSymbol(decl));

            foreach (var reference in references)
            {
                var referenceInfo = model.GetSymbolInfo(reference);
                symbols = model.LookupSymbols(reference.SpanStart, name: decl.Identifier().ValueText);

                if (duplicate)
                {
                    Assert.Null(referenceInfo.Symbol);
                    Assert.Contains(symbol, referenceInfo.CandidateSymbols);
                    Assert.True(symbols.Count() > 1);
                    Assert.Contains(symbol, symbols);
                }
                else
                {
                    Assert.Same(symbol, referenceInfo.Symbol);
                    Assert.Same(symbol, symbols.Single());
                    Assert.Equal(local.Type, model.GetTypeInfo(reference).Type);
                }

                Assert.True(model.LookupNames(reference.SpanStart).Contains(decl.Identifier().ValueText));
            }

            if (!inFieldDeclaratorArgumentlist)
            {
                var dataFlowParent = (ExpressionSyntax)decl.Parent.Parent.Parent;

                if (model.IsSpeculativeSemanticModel)
                {
                    Assert.Throws<NotSupportedException>(() => model.AnalyzeDataFlow(dataFlowParent));
                }
                else
                {
                    var dataFlow = model.AnalyzeDataFlow(dataFlowParent);

                    if (dataFlow.Succeeded)
                    {
                        Assert.False(dataFlow.VariablesDeclared.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.AlwaysAssigned.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.WrittenInside.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.DataFlowsIn.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.ReadInside.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.DataFlowsOut.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.ReadOutside.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.WrittenOutside.Contains(symbol, ReferenceEqualityComparer.Instance));
                    }
                }
            }
        }
Exemplo n.º 36
0
        private static void AnalyzeWhileStatement(SyntaxNodeAnalysisContext context)
        {
            var whileStatement = (WhileStatementSyntax)context.Node;

            ExpressionSyntax condition = whileStatement.Condition;

            if (condition.IsMissing)
            {
                return;
            }

            if (!condition.IsSingleLine())
            {
                return;
            }

            StatementSyntax statement = whileStatement.Statement;

            if (!(statement is BlockSyntax block))
            {
                return;
            }

            SyntaxList <StatementSyntax> innerStatements = block.Statements;

            if (innerStatements.Count <= 1)
            {
                return;
            }

            ExpressionSyntax incrementedExpression = GetIncrementedExpression(innerStatements.Last());

            if (!incrementedExpression.IsKind(SyntaxKind.IdentifierName))
            {
                return;
            }

            SyntaxList <StatementSyntax> outerStatements = SyntaxInfo.StatementListInfo(whileStatement).Statements;

            int index = outerStatements.IndexOf(whileStatement);

            if (index <= 0)
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = GetLocalInfo(outerStatements[index - 1]);

            if (!localInfo.Success)
            {
                return;
            }

            if (index > 1)
            {
                SingleLocalDeclarationStatementInfo localInfo2 = GetLocalInfo(outerStatements[index - 2]);

                if (localInfo2.Success)
                {
                    ExpressionSyntax incrementedExpression2 = GetIncrementedExpression(innerStatements[innerStatements.Count - 2]);

                    if (incrementedExpression2 is IdentifierNameSyntax identifierName2 &&
                        string.Equals(localInfo2.Identifier.ValueText, identifierName2.Identifier.ValueText, StringComparison.Ordinal))
                    {
                        return;
                    }
                }
            }

            var identifierName = (IdentifierNameSyntax)incrementedExpression;

            if (!string.Equals(localInfo.Identifier.ValueText, identifierName.Identifier.ValueText, StringComparison.Ordinal))
            {
                return;
            }

            if (ContainsContinueStatement())
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            ISymbol symbol = semanticModel.GetDeclaredSymbol(localInfo.Declarator, cancellationToken);

            if (symbol?.Kind != SymbolKind.Local)
            {
                return;
            }

            if (IsLocalVariableReferencedAfterWhileStatement())
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseForStatementInsteadOfWhileStatement, whileStatement.WhileKeyword);

            bool ContainsContinueStatement()
            {
                ContainsContinueStatementWalker walker = ContainsContinueStatementWalker.GetInstance();

                walker.ContainsContinueStatement = false;

                var containsContinueStatement = false;

                foreach (StatementSyntax innerStatement in innerStatements)
                {
                    walker.Visit(innerStatement);

                    if (walker.ContainsContinueStatement)
                    {
                        containsContinueStatement = true;
                        break;
                    }
                }

                ContainsContinueStatementWalker.Free(walker);

                return(containsContinueStatement);
            }

            bool IsLocalVariableReferencedAfterWhileStatement()
            {
                ContainsLocalOrParameterReferenceWalker walker = ContainsLocalOrParameterReferenceWalker.GetInstance(symbol, semanticModel, cancellationToken);

                walker.VisitList(outerStatements, index + 1);

                return(ContainsLocalOrParameterReferenceWalker.GetResultAndFree(walker));
            }
        }
Exemplo n.º 37
0
        private static void VerifyModelForOutVarDuplicateInSameScope(SemanticModel model, DeclarationExpressionSyntax decl)
        {
            var variableDesignationSyntax = GetVariableDesignation(decl);
            var symbol = model.GetDeclaredSymbol(variableDesignationSyntax);
            Assert.Equal(decl.Identifier().ValueText, symbol.Name);
            Assert.Equal(variableDesignationSyntax, symbol.DeclaringSyntaxReferences.Single().GetSyntax());
            Assert.Equal(LocalDeclarationKind.RegularVariable, ((LocalSymbol)symbol).DeclarationKind);
            Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)variableDesignationSyntax));
            Assert.NotEqual(symbol, model.LookupSymbols(decl.SpanStart, name: decl.Identifier().ValueText).Single());
            Assert.True(model.LookupNames(decl.SpanStart).Contains(decl.Identifier().ValueText));

            var local = (SourceLocalSymbol)symbol;

            if (decl.Type().IsVar && local.IsVar && local.Type.IsErrorType())
            {
                Assert.Null(model.GetSymbolInfo(decl.Type()).Symbol);
            }
            else
            {
                Assert.Equal(local.Type, model.GetSymbolInfo(decl.Type()).Symbol);
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveThisModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassNonStatic) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveOutModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveRefModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveVirtualModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassUnsealed) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddModifierAbstract) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeMemberReadOnly) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveSealedModifier))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindToken(root, context.Span.Start, out SyntaxToken token))
            {
                return;
            }

            SyntaxNode node = token.Parent;

            if (!CSharpFacts.CanHaveModifiers(node.Kind()))
            {
                node = node.FirstAncestor(f => CSharpFacts.CanHaveModifiers(f.Kind()));
            }

            Debug.Assert(node != null, $"{nameof(node)} is null");

            if (node == null)
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.ModifierIsNotValidForThisItem:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        break;
                    }

                    SyntaxTokenList modifiers = SyntaxInfo.ModifierListInfo(node).Modifiers;

                    if (modifiers.Contains(token))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, token);
                        break;
                    }
                    else if (IsInterfaceMemberOrExplicitInterfaceImplementation(node))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifiers(context, diagnostic, node, modifiers, f =>
                            {
                                switch (f.Kind())
                                {
                                case SyntaxKind.PublicKeyword:
                                case SyntaxKind.ProtectedKeyword:
                                case SyntaxKind.InternalKeyword:
                                case SyntaxKind.PrivateKeyword:
                                case SyntaxKind.StaticKeyword:
                                case SyntaxKind.VirtualKeyword:
                                case SyntaxKind.OverrideKeyword:
                                case SyntaxKind.AbstractKeyword:
                                    {
                                        return(true);
                                    }
                                }

                                return(false);
                            });
                    }
                    else if (node.IsKind(SyntaxKind.IndexerDeclaration))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.StaticKeyword);
                    }
                    else if (node.IsKind(SyntaxKind.PropertyDeclaration))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AsyncKeyword);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.MoreThanOneProtectionModifier:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, token);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.AccessibilityModifiersMayNotBeUsedOnAccessorsInInterface:
                case CompilerDiagnosticIdentifiers.AccessModifiersAreNotAllowedOnStaticConstructors:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveAccessibility(context, diagnostic, node);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.ModifiersCannotBePlacedOnEventAccessorDeclarations:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifiers(context, diagnostic, node);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.OnlyMethodsClassesStructsOrInterfacesMayBePartial:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.PartialKeyword);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.ClassCannotBeBothStaticAndSealed:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.StaticKeyword, additionalKey: nameof(SyntaxKind.StaticKeyword));
                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.SealedKeyword, additionalKey: nameof(SyntaxKind.SealedKeyword));
                    break;
                }

                case CompilerDiagnosticIdentifiers.FieldCanNotBeBothVolatileAndReadOnly:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        break;
                    }

                    var fieldDeclaration = (FieldDeclarationSyntax)node;

                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, fieldDeclaration, SyntaxKind.VolatileKeyword, additionalKey: nameof(SyntaxKind.VolatileKeyword));
                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, fieldDeclaration, SyntaxKind.ReadOnlyKeyword, additionalKey: nameof(SyntaxKind.ReadOnlyKeyword));
                    break;
                }

                case CompilerDiagnosticIdentifiers.NewProtectedMemberDeclaredInSealedClass:
                case CompilerDiagnosticIdentifiers.StaticClassesCannotContainProtectedMembers:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility))
                    {
                        ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrPrivate);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.VirtualOrAbstractmembersCannotBePrivate:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility))
                    {
                        ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrProtected);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.AbstractPropertiesCannotHavePrivateAccessors:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveAccessibility(context, diagnostic, node, additionalKey: CodeFixIdentifiers.RemoveInvalidModifier);
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility))
                    {
                        ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrProtected);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.StaticMemberCannotBeMarkedOverrideVirtualOrAbstract:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        break;
                    }

                    if (!node.IsParentKind(SyntaxKind.ClassDeclaration) ||
                        !((ClassDeclarationSyntax)node.Parent).Modifiers.Contains(SyntaxKind.StaticKeyword))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.StaticKeyword, additionalKey: nameof(SyntaxKind.StaticKeyword));
                    }

                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OverrideKeyword, additionalKey: nameof(SyntaxKind.OverrideKeyword));
                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.VirtualKeyword, additionalKey: nameof(SyntaxKind.VirtualKeyword));
                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AbstractKeyword, additionalKey: nameof(SyntaxKind.AbstractKeyword));
                    break;
                }

                case CompilerDiagnosticIdentifiers.AsyncModifierCanOnlyBeUsedInMethodsThatHaveBody:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AsyncKeyword);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.PartialMethodCannotHaveAccessModifiersOrVirtualAbstractOverrideNewSealedOrExternModifiers:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.RemoveModifiers(context, diagnostic, node, f =>
                        {
                            switch (f.Kind())
                            {
                            case SyntaxKind.PublicKeyword:
                            case SyntaxKind.ProtectedKeyword:
                            case SyntaxKind.InternalKeyword:
                            case SyntaxKind.PrivateKeyword:
                            case SyntaxKind.VirtualKeyword:
                            case SyntaxKind.AbstractKeyword:
                            case SyntaxKind.OverrideKeyword:
                            case SyntaxKind.NewKeyword:
                            case SyntaxKind.SealedKeyword:
                            case SyntaxKind.ExternKeyword:
                                {
                                    return(true);
                                }
                            }

                            return(false);
                        });

                    break;
                }

                case CompilerDiagnosticIdentifiers.ExtensionMethodMustBeStatic:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier))
                    {
                        AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier);
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveThisModifier))
                    {
                        var methodDeclaration = (MethodDeclarationSyntax)node;

                        ParameterSyntax parameter = methodDeclaration.ParameterList.Parameters.First();

                        SyntaxToken modifier = parameter.Modifiers.Find(SyntaxKind.ThisKeyword);

                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, parameter, modifier, additionalKey: CodeFixIdentifiers.RemoveThisModifier);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.ExtensionMethodMustBeDefinedInNonGenericStaticClass:
                {
                    if (!node.IsKind(SyntaxKind.ClassDeclaration))
                    {
                        return;
                    }

                    var classDeclaration = (ClassDeclarationSyntax)node;

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier) &&
                        !classDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword))
                    {
                        AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier);
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveThisModifier))
                    {
                        IEnumerable <ParameterSyntax> thisParameters = classDeclaration.Members
                                                                       .Where(f => f.IsKind(SyntaxKind.MethodDeclaration))
                                                                       .Cast <MethodDeclarationSyntax>()
                                                                       .Select(f => f.ParameterList?.Parameters.FirstOrDefault())
                                                                       .Where(f => f?.Modifiers.Contains(SyntaxKind.ThisKeyword) == true);

                        ModifiersCodeFixRegistrator.RemoveModifier(
                            context,
                            diagnostic,
                            thisParameters,
                            SyntaxKind.ThisKeyword,
                            title: "Remove 'this' modifier from extension methods",
                            additionalKey: CodeFixIdentifiers.RemoveThisModifier);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.NoDefiningDeclarationFoundForImplementingDeclarationOfPartialMethod:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.PartialKeyword);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.MethodHasParameterModifierThisWhichIsNotOnFirstParameter:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveThisModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, token.Parent, token);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotDeclareInstanceMembersInStaticClass:
                case CompilerDiagnosticIdentifiers.StaticClassesCannotHaveInstanceConstructors:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier))
                    {
                        AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier);
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassNonStatic))
                    {
                        var classDeclaration = (ClassDeclarationSyntax)node.Parent;

                        ModifiersCodeFixRegistrator.RemoveModifier(
                            context,
                            diagnostic,
                            classDeclaration,
                            classDeclaration.Modifiers.Find(SyntaxKind.StaticKeyword),
                            title: "Make containing class non-static",
                            additionalKey: CodeFixIdentifiers.MakeContainingClassNonStatic);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.ElementsDefinedInNamespaceCannotBeExplicitlyDeclaredAsPrivateProtectedOrProtectedInternal:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility))
                    {
                        ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternal);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.NamespaceAlreadyContainsDefinition:
                case CompilerDiagnosticIdentifiers.TypeAlreadyContainsDefinition:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier))
                    {
                        break;
                    }

                    if (!node.IsKind(
                            SyntaxKind.ClassDeclaration,
                            SyntaxKind.StructDeclaration,
                            SyntaxKind.InterfaceDeclaration,
                            SyntaxKind.MethodDeclaration))
                    {
                        return;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ISymbol symbol = semanticModel.GetDeclaredSymbol(node, context.CancellationToken);

                    ImmutableArray <SyntaxReference> syntaxReferences = symbol.DeclaringSyntaxReferences;

                    if (syntaxReferences.Length <= 1)
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(
                        context,
                        diagnostic,
                        ImmutableArray.CreateRange(syntaxReferences, f => f.GetSyntax(context.CancellationToken)),
                        SyntaxKind.PartialKeyword);

                    break;
                }

                case CompilerDiagnosticIdentifiers.NoSuitableMethodFoundToOverride:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OverrideKeyword);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.AsyncMethodsCannotHaveRefOrOutParameters:
                case CompilerDiagnosticIdentifiers.IteratorsCannotHaveRefOrOutParameters:
                case CompilerDiagnosticIdentifiers.ReadOnlyFieldCannotBePassedAsRefOrOutValue:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveRefModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.RefKeyword, additionalKey: nameof(SyntaxKind.RefKeyword));
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveOutModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OutKeyword, additionalKey: nameof(SyntaxKind.OutKeyword));
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotHaveInstancePropertyOrFieldInitializersInStruct:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier))
                    {
                        AddStaticModifier(context, diagnostic, node);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.MemberMustDeclareBodyBecauseItIsNotMarkedAbstractExternOrPartial:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddModifierAbstract) &&
                        node.Kind() == SyntaxKind.MethodDeclaration &&
                        (node.Parent as ClassDeclarationSyntax)?.Modifiers.Contains(SyntaxKind.AbstractKeyword) == true)
                    {
                        ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.AbstractKeyword);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.NewVirtualMemberInSealedClass:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveVirtualModifier))
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(
                            context,
                            diagnostic,
                            node,
                            SyntaxKind.VirtualKeyword,
                            additionalKey: CodeFixIdentifiers.RemoveVirtualModifier);
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassUnsealed) &&
                        node.Parent is ClassDeclarationSyntax classDeclaration)
                    {
                        ModifiersCodeFixRegistrator.RemoveModifier(
                            context,
                            diagnostic,
                            classDeclaration,
                            SyntaxKind.SealedKeyword,
                            title: "Make containing class unsealed",
                            additionalKey: CodeFixIdentifiers.MakeContainingClassUnsealed);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.InstanceFieldsOfReadOnlyStructsMustBeReadOnly:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeMemberReadOnly))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.ReadOnlyKeyword);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MemberCannotBeSealedBecauseItIsNotOverride:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveSealedModifier))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    if (semanticModel.GetDiagnostic(
                            CompilerDiagnosticIdentifiers.MemberHidesInheritedMemberToMakeCurrentMethodOverrideThatImplementationAddOverrideKeyword,
                            CSharpUtility.GetIdentifier(node).Span,
                            context.CancellationToken) != null)
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.SealedKeyword);
                    break;
                }
                }
            }
        }
 private static ImmutableArray <ISymbol> GetConstructorParameterSymbols(BaseMethodDeclarationSyntax node, SemanticModel semanticModel) =>
 node.ParameterList.Parameters
 .Select(syntax => (ISymbol)semanticModel.GetDeclaredSymbol(syntax))
 .ToImmutableArray();
Exemplo n.º 40
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out EnumDeclarationSyntax enumDeclaration))
            {
                return;
            }

            Document document = context.Document;

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case DiagnosticIdentifiers.AddNewLineBeforeEnumMember:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Add newline",
                        cancellationToken => AddNewLineBeforeEnumMemberRefactoring.RefactorAsync(document, enumDeclaration, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.SortEnumMembers:
                {
                    CodeAction codeAction = CodeAction.Create(
                        $"Sort '{enumDeclaration.Identifier}' members",
                        cancellationToken => SortEnumMembersAsync(document, enumDeclaration, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.EnumShouldDeclareExplicitValues:
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    INamedTypeSymbol enumSymbol = semanticModel.GetDeclaredSymbol(enumDeclaration, context.CancellationToken);

                    EnumSymbolInfo enumInfo = EnumSymbolInfo.Create(enumSymbol);

                    ImmutableArray <ulong> values = enumInfo
                                                    .Fields
                                                    .Where(f => f.HasValue && ((EnumMemberDeclarationSyntax)f.Symbol.GetSyntax(context.CancellationToken)).EqualsValue != null)
                                                    .Select(f => f.Value)
                                                    .ToImmutableArray();

                    Optional <ulong> optional = FlagsUtility <ulong> .Instance.GetUniquePowerOfTwo(values);

                    if (!optional.HasValue ||
                        !ConvertHelpers.CanConvert(optional.Value, enumSymbol.EnumUnderlyingType.SpecialType))
                    {
                        return;
                    }

                    bool isFlags = enumSymbol.HasAttribute(MetadataNames.System_FlagsAttribute);

                    CodeAction codeAction = CodeAction.Create(
                        "Declare explicit values",
                        ct => DeclareExplicitValueAsync(document, enumDeclaration, enumSymbol, isFlags, useBitShift: false, values, semanticModel, ct),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    if (isFlags)
                    {
                        CodeAction codeAction2 = CodeAction.Create(
                            "Declare explicit values (and use '<<' operator)",
                            ct => DeclareExplicitValueAsync(document, enumDeclaration, enumSymbol, isFlags, useBitShift: true, values, semanticModel, ct),
                            GetEquivalenceKey(diagnostic, "BitShift"));

                        context.RegisterCodeFix(codeAction2, diagnostic);
                    }

                    break;
                }

                case DiagnosticIdentifiers.UseBitShiftOperator:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use '<<' operator",
                        ct => UseBitShiftOperatorAsync(document, enumDeclaration, ct),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
Exemplo n.º 41
0
        public void Execute(SourceGeneratorContext context)
        {
            context.AddSource("MemberAccessAttributes", SourceText.From(attributeText, Encoding.UTF8));

            if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
            {
                return;
            }

            CSharpParseOptions options = (CSharpParseOptions)((CSharpCompilation)context.Compilation).SyntaxTrees[0].Options;

            Compilation compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(attributeText, Encoding.UTF8), options));

            if (!(compilation.GetTypeByMetadataName("MemberAccess.ByIndexAttribute") is { } indexAttributeSymbol))
            {
                return;
            }
            if (!(compilation.GetTypeByMetadataName("MemberAccess.ByNameAttribute") is { } nameAttributeSymbol))
            {
                return;
            }
            if (!(compilation.GetTypeByMetadataName("MemberAccess.EnumerateAttribute") is { } enumerateAttributeSymbol))
            {
                return;
            }

            var buffer = new StringBuilder();

            foreach (var r in receiver.CandidateMethods)
            {
                SemanticModel model = compilation.GetSemanticModel(r.SyntaxTree);

                var flag = getMemberAccessAttribute(model, r);
                if (flag == Flag.None)
                {
                    continue;
                }
                if (r.ParameterList is not {
                } list)
                {
                    continue;
                }
                if (model.GetDeclaredSymbol(r) is not {
                } s)
                {
                    continue;
                }

                var generatedSource = generate(s, list, flag);
                var filename        = getFilename(s);
                context.AddSource(filename, SourceText.From(generatedSource, Encoding.UTF8));
            }

            string getFilename(INamedTypeSymbol type)
            {
                buffer.Clear();

                foreach (var part in type.ContainingNamespace.ToDisplayParts())
                {
                    if (part.Symbol is { Name: var name } && !string.IsNullOrEmpty(name))
                    {
                        buffer.Append(name);
                        buffer.Append('_');
                    }
                }
            public override void VisitToken(SyntaxToken token)
            {
                VisitTriviaList(token.LeadingTrivia);

                if (token.Text == "Foo")
                {
                    Console.WriteLine();
                }

                IEnumerable <ColorizedWord> r = null;

                if (token.IsKeyword())
                {
                    r = Col(token.Text, "Keyword");
                }
                else if (token.IsKind(SyntaxKind.StringLiteralToken))
                {
                    r = Col(token.Text, "StringLiteral");
                }
                else if (token.IsKind(SyntaxKind.CharacterLiteralToken))
                {
                    r = Col(token.Text, "StringLiteral");
                }
                else if (token.IsKind(SyntaxKind.IdentifierToken) && token.Parent is TypeParameterSyntax)
                {
                    r = Col(token.Text, "UserType");
                }
                else if (token.IsKind(SyntaxKind.IdentifierToken) && token.Parent is SimpleNameSyntax)
                {
                    var     name   = token.Parent as SimpleNameSyntax;
                    ISymbol symbol = null;
                    try { symbol = sm?.GetSymbolInfo(name).Symbol; }
                    catch (NullReferenceException) { }
                    // https://github.com/dotnet/roslyn/issues/10023 this might throw NRE, even though it shouldn't...
                    if (symbol?.Kind == SymbolKind.NamedType ||
                        symbol?.Kind == SymbolKind.TypeParameter)
                    {
                        r = Col(token.Text, "UserType");
                    }
                    else if (symbol?.Kind == SymbolKind.Namespace ||
                             symbol?.Kind == SymbolKind.Parameter ||
                             symbol?.Kind == SymbolKind.Local ||
                             symbol?.Kind == SymbolKind.Field ||
                             symbol?.Kind == SymbolKind.Property)
                    {
                        r = Col(token.Text, "PlainText");
                    }
                    else if (name.Identifier.Text == "var")
                    {
                        r = Col(token.Text, "Keyword");
                    }
                    else if (new[] { "C", "T", "U", "V" }.Contains(name.Identifier.Text))
                    {
                        r = Col(token.Text, "UserType");
                    }
                }
                else if (token.IsKind(SyntaxKind.IdentifierToken) && token.Parent is DeclarationStatementSyntax)
                {
                    var name   = token.Parent as DeclarationStatementSyntax;
                    var symbol = sm.GetDeclaredSymbol(name);
                    if (symbol?.Kind == SymbolKind.NamedType)
                    {
                        r = Col(token.Text, "UserType");
                    }
                }

                if (r == null)
                {
                    if ((token.Parent as EnumStatementSyntax)?.Identifier == token)
                    {
                        r = Col(token.Text, "UserType");
                    }
                    else if ((token.Parent as GenericNameSyntax)?.Identifier == token)
                    {
                        if ((token.Parent.Parent as InvocationExpressionSyntax)?.Expression == token.Parent || // e.g. "G<X>(1)"
                            (token.Parent.Parent.Parent as InvocationExpressionSyntax)?.Expression == token.Parent.Parent)    // e.g. e.G<X>(1)
                        {
                            r = Col(token.Text, "PlainText");
                        }
                        else // all other G<A> will assume that G is a type
                        {
                            r = Col(token.Text, "UserType");
                        }
                    }
                    else if (token.Parent.IsKind(SyntaxKind.GenericName))
                    {
                        if (token.Parent.Parent.IsKind(SyntaxKind.SimpleAsClause) || // e.g. "dim x As HashSet" the HashSet
                            token.Parent.Parent.IsKind(SyntaxKind.ObjectCreationExpression))    // e.g. "dim x As New HashSet" or "dim x = New HashSet"
                        {
                            r = Col(token.Text, "UserType");
                        }
                    }
                    else if (token.Parent.IsKind(SyntaxKind.IdentifierName))
                    {
                        if (token.Parent.Parent.IsKind(SyntaxKind.Parameter) ||
                            token.Parent.Parent.IsKind(SyntaxKind.Attribute) ||
                            token.Parent.Parent.IsKind(SyntaxKind.CatchStatement) ||
                            token.Parent.Parent.IsKind(SyntaxKind.ObjectCreationExpression) ||
                            token.Parent.Parent.IsKind(SyntaxKind.SubStatement) ||
                            token.Parent.Parent.IsKind(SyntaxKind.FunctionStatement) ||
                            token.Parent.Parent.IsKind(SyntaxKind.InheritsStatement) || // e.g. "public sealed class BuilderRouteHandler  IRouteHandler" IRouteHandler in this case
                            token.Parent.Parent.IsKind(SyntaxKind.GetTypeExpression) || // e.g. "GetType(BaseBuilder);" BaseBuilder in this case
                            token.Parent.Parent.IsKind(SyntaxKind.SimpleAsClause) || // e.g. "private DbProviderFactory dbProviderFactory;" Or "DbConnection connection = dbProviderFactory.CreateConnection();"
                            token.Parent.Parent.IsKind(SyntaxKind.TypeArgumentList))    // e.g. "DbTypes = New Dictionary();" DbType in this case
                        {
                            r = Col(token.Text, "UserType");
                        }
                        else if ((token.Parent.Parent as CastExpressionSyntax)?.Type == token.Parent || // e.g. "(Foo)x" the Foo
                                 (token.Parent.Parent as TypeConstraintSyntax)?.Type == token.Parent || // e.g. "where T:Foo" the Foo
                                 (token.Parent.Parent as ArrayTypeSyntax)?.ElementType == token.Parent) // e.g. "Foo[]" the Foo
                        {
                            r = Col(token.Text, "UserType");
                        }
                        else if ((token.Parent.Parent.IsKind(SyntaxKind.ForEachStatement) && token.GetNextToken().Kind() != SyntaxKind.CloseParenToken)
                                 //|| (token.Parent.Parent.Parent.IsKind(SyntaxKind.CaseSwitchLabel) && token.GetPreviousToken().Kind() != SyntaxKind.DotToken)
                                 //|| (token.Parent.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression) && token.Parent.Parent.Parent.IsKind(SyntaxKind.Argument) && !token.GetPreviousToken().IsKind(SyntaxKind.DotToken) && token.Text.Length > 0 && !char.IsLower(token.Text[0])) // e.g. "DbTypes.Add("int", DbType.Int32);" DbType in this case
                                 || (token.Parent.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression) && !token.GetPreviousToken().IsKind(SyntaxKind.DotToken) && token.Text.Length > 0 && !char.IsLower(token.Text[0])))
                        {
                            r = Col(token.Text, "UserType");
                        }
                    }
                }

                if (r == null && !string.IsNullOrEmpty(token.Text)) // Empty comes from EndOfFile, OmmittedToken, ...
                {
                    r = Col(token.Text, "PlainText");
                }

                if (r != null)
                {
                    Words.AddRange(r);
                }

                VisitTriviaList(token.TrailingTrivia);
            }
Exemplo n.º 43
0
 public static string GetMemberName <TDeclaration>(this IExpressionBodyHandler <TDeclaration> handler, TDeclaration declaration, SemanticModel semanticModel)
     where TDeclaration : MemberDeclarationSyntax
 => semanticModel.GetDeclaredSymbol(declaration)?.Name
 ?? handler.GetIdentifierName(declaration);
Exemplo n.º 44
0
        public static async Task <Solution> RefactorAsync(
            Document document,
            PropertyDeclarationSyntax propertyDeclaration,
            CancellationToken cancellationToken)
        {
            SyntaxToken propertyIdentifier = propertyDeclaration.Identifier.WithoutTrivia();

            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

            ISymbol fieldSymbol = GetFieldSymbol(propertyDeclaration, semanticModel, cancellationToken);

            var variableDeclarator = (VariableDeclaratorSyntax)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false);

            var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent;

            var fieldDeclaration = (FieldDeclarationSyntax)variableDeclaration.Parent;

            bool isSingleDeclarator = variableDeclaration.Variables.Count == 1;

            Solution solution = document.Solution();

            foreach (DocumentReferenceInfo info in await SyntaxFinder.FindReferencesByDocumentAsync(fieldSymbol, solution, allowCandidate: false, cancellationToken: cancellationToken).ConfigureAwait(false))
            {
                ImmutableArray <SyntaxNode> nodes = info.References;

                if (propertyDeclaration.SyntaxTree == info.SyntaxTree)
                {
                    nodes = nodes.Add(propertyDeclaration);

                    if (isSingleDeclarator)
                    {
                        nodes = nodes.Add(fieldDeclaration);
                    }
                    else
                    {
                        nodes = nodes.Add(variableDeclarator);
                    }
                }

                SyntaxNode newRoot = info.Root.ReplaceNodes(nodes, (node, rewrittenNode) =>
                {
                    switch (node.Kind())
                    {
                    case SyntaxKind.IdentifierName:
                        {
                            return(CreateNewExpression(node, propertyIdentifier, propertySymbol)
                                   .WithTriviaFrom(node)
                                   .WithFormatterAnnotation());
                        }

                    case SyntaxKind.PropertyDeclaration:
                        {
                            return(CreateAutoProperty(propertyDeclaration, variableDeclarator.Initializer));
                        }

                    case SyntaxKind.VariableDeclarator:
                    case SyntaxKind.FieldDeclaration:
                        {
                            return(node.WithAdditionalAnnotations(_removeAnnotation));
                        }

                    default:
                        {
                            Debug.Fail(node.ToString());
                            return(node);
                        }
                    }
                });

                SyntaxNode nodeToRemove = newRoot.GetAnnotatedNodes(_removeAnnotation).FirstOrDefault();

                if (nodeToRemove != null)
                {
                    newRoot = newRoot.RemoveNode(nodeToRemove, SyntaxRemoveOptions.KeepUnbalancedDirectives);
                }

                solution = solution.WithDocumentSyntaxRoot(info.Document.Id, newRoot);
            }

            return(solution);
        }
Exemplo n.º 45
0
        private static void AssertInfoForDeclarationExpressionSyntax(SemanticModel model, DeclarationExpressionSyntax decl)
        {
            var symbolInfo = model.GetSymbolInfo(decl);
            Assert.Null(symbolInfo.Symbol);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Equal(symbolInfo, ((CSharpSemanticModel)model).GetSymbolInfo(decl));

            var typeInfo = model.GetTypeInfo(decl);
            Assert.Null(typeInfo.Type);
            Assert.Null(typeInfo.ConvertedType);
            Assert.Equal(typeInfo, ((CSharpSemanticModel)model).GetTypeInfo(decl));

            var conversion = model.ClassifyConversion(decl, model.Compilation.ObjectType, false);
            Assert.False(conversion.Exists);
            Assert.Equal(conversion, model.ClassifyConversion(decl, model.Compilation.ObjectType, true));
            Assert.Equal(conversion, ((CSharpSemanticModel)model).ClassifyConversion(decl, model.Compilation.ObjectType, false));
            Assert.Equal(conversion, ((CSharpSemanticModel)model).ClassifyConversion(decl, model.Compilation.ObjectType, true));
            Assert.Equal(conversion, model.ClassifyConversion(decl.Position, decl, model.Compilation.ObjectType, false));
            Assert.Equal(conversion, model.ClassifyConversion(decl.Position, decl, model.Compilation.ObjectType, true));
            Assert.Equal(conversion, ((CSharpSemanticModel)model).ClassifyConversion(decl.Position, decl, model.Compilation.ObjectType, false));
            Assert.Equal(conversion, ((CSharpSemanticModel)model).ClassifyConversion(decl.Position, decl, model.Compilation.ObjectType, true));

            Assert.Null(model.GetDeclaredSymbol(decl));
        }
        private static void ExtractVariableDeclarationsBeforeUsing(SemanticModel semanticModel, List <StatementSyntax> beforeUsing, List <StatementSyntax> insideUsing, List <SyntaxNode> nodesToRemove, CancellationToken ct)
        {
            var inUsingDataFlow = semanticModel.AnalyzeDataFlow(insideUsing.First(), insideUsing.Last());

            var declaredVariablesUsedOutside = inUsingDataFlow.ReadOutside.Union(inUsingDataFlow.WrittenOutside)
                                               .Distinct()
                                               .Intersect(inUsingDataFlow.VariablesDeclared)
                                               .Select(x => new { Symbol = x, Declarator = (VariableDeclaratorSyntax)x.DeclaringSyntaxReferences[0].GetSyntax(ct) })
                                               .ToArray();


            for (var i = 0; i < insideUsing.Count; i++)
            {
                var stmt = insideUsing[i];

                var localDeclarationStmt = stmt as LocalDeclarationStatementSyntax;

                if (localDeclarationStmt == null)
                {
                    continue;
                }

                nodesToRemove.Add(localDeclarationStmt);

                var declaredVariables = localDeclarationStmt.Declaration
                                        .Variables.Select(x => new { Symbol = semanticModel.GetDeclaredSymbol(x), Declarator = x })
                                        .ToArray();

                var variablesToMove = declaredVariables
                                      .Intersect(declaredVariablesUsedOutside)
                                      .ToArray();

                if (!variablesToMove.Any())
                {
                    continue;
                }

                var reducedLocalDeclaration = localDeclarationStmt.RemoveNodes(variablesToMove.Select(x => x.Declarator), SyntaxRemoveOptions.AddElasticMarker);

                if (reducedLocalDeclaration.Declaration.Variables.Any())
                {
                    insideUsing[i] = reducedLocalDeclaration;
                }
                else
                {
                    insideUsing.RemoveAt(i);
                    i--;
                }

                foreach (var needAssignment in variablesToMove.Where(x => x.Declarator.Initializer != null))
                {
                    insideUsing.Insert(i + 1, needAssignment.Declarator.InitializerAsAssignment());
                }

                beforeUsing.Add(SyntaxFactory.LocalDeclarationStatement(
                                    SyntaxFactory.VariableDeclaration(
                                        localDeclarationStmt.Declaration.Type,
                                        SyntaxFactory.SeparatedList(variablesToMove.Select(x => x.Declarator.WithInitializer(null)))
                                        )
                                    )
                                .WithAdditionalAnnotations(Formatter.Annotation)
                                );
            }
        }
        protected override IEnumerable <CodeAction> GetActions(Document document, SemanticModel semanticModel, SyntaxNode root, TextSpan span, VariableDeclaratorSyntax node, CancellationToken cancellationToken)
        {
            var variableDeclaration = node.GetAncestor <VariableDeclarationSyntax>();
            var localDeclaration    = node.GetAncestor <LocalDeclarationStatementSyntax>();

            if (node.Initializer == null || node.Parent.Parent != null && node.Parent.Parent.IsKind(SyntaxKind.UsingStatement))
            {
                yield break;
            }

            var symbol = semanticModel.GetDeclaredSymbol(node) as ILocalSymbol;

            if (symbol == null)
            {
                yield break;
            }

            if (!symbol.Type.ImplementsSpecialTypeInterface(SpecialType.System_IDisposable))
            {
                yield break;
            }

            var containingBlock = node.GetAncestor <BlockSyntax>();

            yield return(CodeActionFactory.Create(span, DiagnosticSeverity.Info, "Put inside 'using'", ct =>
            {
                var insideUsing = containingBlock.Statements.SkipWhile(x => x != localDeclaration).Skip(1).ToList();

                ReduceUsingBlock(semanticModel, insideUsing, symbol);

                var nodesToRemove = new List <SyntaxNode>(insideUsing);

                var beforeUsing = new List <StatementSyntax>();

                if (insideUsing.Any())
                {
                    ExtractVariableDeclarationsBeforeUsing(semanticModel, beforeUsing, insideUsing, nodesToRemove, ct);
                }

                if (IsEndingWithDispose(semanticModel, insideUsing, symbol))
                {
                    nodesToRemove.Add(insideUsing.Last());
                    insideUsing.RemoveAt(insideUsing.Count - 1);
                }

                var usingVariableDeclaration = SyntaxFactory.VariableDeclaration(variableDeclaration.Type.WithoutTrivia(), SyntaxFactory.SingletonSeparatedList(node));

                var usingNode = SyntaxFactory.UsingStatement(usingVariableDeclaration, null, SyntaxFactory.Block(insideUsing))
                                .WithAdditionalAnnotations(Formatter.Annotation)
                                .WithPrependedLeadingTrivia(variableDeclaration.GetLeadingTrivia());

                var newRoot = root.TrackNodes(nodesToRemove.Concat(localDeclaration));

                newRoot = newRoot.RemoveNodes(newRoot.GetCurrentNodes <SyntaxNode>(nodesToRemove), SyntaxRemoveOptions.AddElasticMarker);

                newRoot = newRoot.InsertNodesAfter(newRoot.GetCurrentNode(localDeclaration), beforeUsing.Concat(usingNode));

                if (localDeclaration.Declaration.Variables.Count > 1)
                {
                    var remainingVariables = localDeclaration.Declaration.Variables.Except(new[] { node });
                    newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(localDeclaration),
                                                  localDeclaration.WithDeclaration(localDeclaration.Declaration.WithVariables(SyntaxFactory.SeparatedList(remainingVariables)))
                                                  .WithAdditionalAnnotations(Formatter.Annotation));
                }
                else
                {
                    newRoot = newRoot.RemoveNode(newRoot.GetCurrentNode(localDeclaration), SyntaxRemoveOptions.AddElasticMarker);
                }

                return Task.FromResult(document.WithSyntaxRoot(newRoot));
            }));
        }
Exemplo n.º 48
0
        private static async Task <Document> RefactorAsync(
            Document document,
            SyntaxNode node,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            switch (node)
            {
            case MethodDeclarationSyntax methodDeclaration:
            {
                IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, cancellationToken);

                UseAsyncAwaitRewriter rewriter = UseAsyncAwaitRewriter.Create(methodSymbol);

                var newNode = (MethodDeclarationSyntax)rewriter.VisitMethodDeclaration(methodDeclaration);

                newNode = ModifierList <MethodDeclarationSyntax> .Instance.Insert(newNode, SyntaxKind.AsyncKeyword);

                return(await document.ReplaceNodeAsync(methodDeclaration, newNode, cancellationToken).ConfigureAwait(false));
            }

            case LocalFunctionStatementSyntax localFunction:
            {
                IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(localFunction, cancellationToken);

                UseAsyncAwaitRewriter rewriter = UseAsyncAwaitRewriter.Create(methodSymbol);

                var newBody = (BlockSyntax)rewriter.VisitBlock(localFunction.Body);

                LocalFunctionStatementSyntax newNode = localFunction.WithBody(newBody);

                newNode = ModifierList <LocalFunctionStatementSyntax> .Instance.Insert(newNode, SyntaxKind.AsyncKeyword);

                return(await document.ReplaceNodeAsync(localFunction, newNode, cancellationToken).ConfigureAwait(false));
            }

            case SimpleLambdaExpressionSyntax lambda:
            {
                var methodSymbol = (IMethodSymbol)semanticModel.GetSymbol(lambda, cancellationToken);

                UseAsyncAwaitRewriter rewriter = UseAsyncAwaitRewriter.Create(methodSymbol);

                var newBody = (BlockSyntax)rewriter.VisitBlock((BlockSyntax)lambda.Body);

                SimpleLambdaExpressionSyntax newNode = lambda
                                                       .WithBody(newBody)
                                                       .WithAsyncKeyword(Token(SyntaxKind.AsyncKeyword));

                return(await document.ReplaceNodeAsync(lambda, newNode, cancellationToken).ConfigureAwait(false));
            }

            case ParenthesizedLambdaExpressionSyntax lambda:
            {
                var methodSymbol = (IMethodSymbol)semanticModel.GetSymbol(lambda, cancellationToken);

                UseAsyncAwaitRewriter rewriter = UseAsyncAwaitRewriter.Create(methodSymbol);

                var newBody = (BlockSyntax)rewriter.VisitBlock((BlockSyntax)lambda.Body);

                ParenthesizedLambdaExpressionSyntax newNode = lambda
                                                              .WithBody(newBody)
                                                              .WithAsyncKeyword(Token(SyntaxKind.AsyncKeyword));

                return(await document.ReplaceNodeAsync(lambda, newNode, cancellationToken).ConfigureAwait(false));
            }

            case AnonymousMethodExpressionSyntax anonymousMethod:
            {
                var methodSymbol = (IMethodSymbol)semanticModel.GetSymbol(anonymousMethod, cancellationToken);

                UseAsyncAwaitRewriter rewriter = UseAsyncAwaitRewriter.Create(methodSymbol);

                var newBody = (BlockSyntax)rewriter.VisitBlock((BlockSyntax)anonymousMethod.Body);

                AnonymousMethodExpressionSyntax newNode = anonymousMethod
                                                          .WithBody(newBody)
                                                          .WithAsyncKeyword(Token(SyntaxKind.AsyncKeyword));

                return(await document.ReplaceNodeAsync(anonymousMethod, newNode, cancellationToken).ConfigureAwait(false));
            }
            }

            throw new InvalidOperationException();
        }
Exemplo n.º 49
0
        private static void VerifyModelForDeconstruction(SemanticModel model, SingleVariableDesignationSyntax decl, LocalDeclarationKind kind, params IdentifierNameSyntax[] references)
        {
            var symbol = model.GetDeclaredSymbol(decl);
            Assert.Equal(decl.Identifier.ValueText, symbol.Name);
            Assert.Equal(kind, ((LocalSymbol)symbol).DeclarationKind);
            Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)decl));
            Assert.Same(symbol, model.LookupSymbols(decl.SpanStart, name: decl.Identifier.ValueText).Single());
            Assert.True(model.LookupNames(decl.SpanStart).Contains(decl.Identifier.ValueText));

            var local = (SourceLocalSymbol)symbol;
            var typeSyntax = GetTypeSyntax(decl);
            if (local.IsVar && local.Type.IsErrorType())
            {
                Assert.Null(model.GetSymbolInfo(typeSyntax).Symbol);
            }
            else
            {
                if (typeSyntax != null)
                {
                    Assert.Equal(local.Type, model.GetSymbolInfo(typeSyntax).Symbol);
                }
            }

            foreach (var reference in references)
            {
                Assert.Same(symbol, model.GetSymbolInfo(reference).Symbol);
                Assert.Same(symbol, model.LookupSymbols(reference.SpanStart, name: decl.Identifier.ValueText).Single());
                Assert.True(model.LookupNames(reference.SpanStart).Contains(decl.Identifier.ValueText));
                Assert.Equal(local.Type, model.GetTypeInfo(reference).Type);
            }
        }
Exemplo n.º 50
0
        public static void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext context)
        {
            var property = (PropertyDeclarationSyntax)context.Node;

            if (property.ContainsDiagnostics)
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            IFieldSymbol fieldSymbol = null;

            AccessorDeclarationSyntax getter = null;
            AccessorDeclarationSyntax setter = null;

            ArrowExpressionClauseSyntax expressionBody = property.ExpressionBody;

            if (expressionBody != null)
            {
                fieldSymbol = GetBackingFieldSymbol(expressionBody, semanticModel, cancellationToken);
            }
            else
            {
                getter = property.Getter();

                if (getter != null)
                {
                    setter = property.Setter();

                    if (setter != null)
                    {
                        fieldSymbol = GetBackingFieldSymbol(getter, setter, semanticModel, cancellationToken);
                    }
                    else
                    {
                        fieldSymbol = GetBackingFieldSymbol(getter, semanticModel, cancellationToken);
                    }
                }
            }

            if (fieldSymbol == null)
            {
                return;
            }

            var variableDeclarator = (VariableDeclaratorSyntax)fieldSymbol.GetSyntax(cancellationToken);

            if (variableDeclarator.SyntaxTree != property.SyntaxTree)
            {
                return;
            }

            IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(property, cancellationToken);

            if (propertySymbol == null)
            {
                return;
            }

            if (!propertySymbol.ExplicitInterfaceImplementations.IsDefaultOrEmpty)
            {
                return;
            }

            if (propertySymbol.IsStatic != fieldSymbol.IsStatic)
            {
                return;
            }

            if (!propertySymbol.Type.Equals(fieldSymbol.Type))
            {
                return;
            }

            if (propertySymbol.ContainingType?.Equals(fieldSymbol.ContainingType) != true)
            {
                return;
            }

            if (setter == null &&
                propertySymbol.IsOverride &&
                propertySymbol.OverriddenProperty?.SetMethod != null)
            {
                return;
            }

            if (HasStructLayoutAttributeWithExplicitKind(propertySymbol.ContainingType, context.Compilation))
            {
                return;
            }

            if (IsBackingFieldUsedInRefOrOutArgument(context, fieldSymbol, property))
            {
                return;
            }

            if (!CheckPreprocessorDirectives(property, variableDeclarator))
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.UseAutoProperty, property.Identifier);

            if (property.ExpressionBody != null)
            {
                context.ReportNode(DiagnosticDescriptors.UseAutoPropertyFadeOut, property.ExpressionBody);
            }
            else
            {
                if (getter != null)
                {
                    FadeOutBodyOrExpressionBody(context, getter);
                }

                if (setter != null)
                {
                    FadeOutBodyOrExpressionBody(context, setter);
                }
            }
        }
Exemplo n.º 51
0
        private static void VerifyModelNotSupported(
            SemanticModel model,
            DeclarationExpressionSyntax decl,
            params IdentifierNameSyntax[] references)
        {
            var variableDeclaratorSyntax = GetVariableDesignation(decl);
            Assert.Null(model.GetDeclaredSymbol(variableDeclaratorSyntax));
            Assert.Null(model.GetDeclaredSymbol((SyntaxNode)variableDeclaratorSyntax));
            var identifierText = decl.Identifier().ValueText;
            Assert.False(model.LookupSymbols(decl.SpanStart, name: identifierText).Any());

            Assert.False(model.LookupNames(decl.SpanStart).Contains(identifierText));
            Assert.Null(model.GetSymbolInfo(decl.Type()).Symbol);

            Assert.Null(model.GetSymbolInfo(decl).Symbol);
            Assert.Null(model.GetTypeInfo(decl).Type);
            Assert.Null(model.GetDeclaredSymbol(decl));
            VerifyModelNotSupported(model, references);
        }
Exemplo n.º 52
0
        public ISymbol GetDeclaredSymbol(SemanticModel semanticModel, SyntaxToken token, CancellationToken cancellationToken)
        {
            var location = token.GetLocation();
            var q = from node in token.GetAncestors<SyntaxNode>()
                    let symbol = semanticModel.GetDeclaredSymbol(node, cancellationToken)
                    where symbol != null && symbol.Locations.Contains(location)
                    select symbol;

            return q.FirstOrDefault();
        }
Exemplo n.º 53
0
        private static void VerifyModelForOutVar(
            SemanticModel model,
            DeclarationExpressionSyntax decl,
            bool isDelegateCreation,
            bool isExecutableCode,
            bool isShadowed,
            bool verifyDataFlow = true,
            params IdentifierNameSyntax[] references)
        {
            var variableDeclaratorSyntax = GetVariableDesignation(decl);
            var symbol = model.GetDeclaredSymbol(variableDeclaratorSyntax);
            Assert.NotNull(symbol);
            Assert.Equal(decl.Identifier().ValueText, symbol.Name);
            Assert.Equal(variableDeclaratorSyntax, symbol.DeclaringSyntaxReferences.Single().GetSyntax());
            Assert.Equal(LocalDeclarationKind.RegularVariable, ((LocalSymbol)symbol).DeclarationKind);
            Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)variableDeclaratorSyntax));

            if (isShadowed)
            {
                Assert.NotEqual(symbol, model.LookupSymbols(decl.SpanStart, name: decl.Identifier().ValueText).Single());
            }
            else
            {
                Assert.Same(symbol, model.LookupSymbols(decl.SpanStart, name: decl.Identifier().ValueText).Single());
            }

            Assert.True(model.LookupNames(decl.SpanStart).Contains(decl.Identifier().ValueText));

            var local = (SourceLocalSymbol)symbol;
            var typeSyntax = decl.Type();

            Assert.True(SyntaxFacts.IsInNamespaceOrTypeContext(typeSyntax));
            Assert.True(SyntaxFacts.IsInTypeOnlyContext(typeSyntax));

            if (typeSyntax.IsVar && local.IsVar && local.Type.IsErrorType())
            {
                Assert.Null(model.GetSymbolInfo(typeSyntax).Symbol);
            }
            else
            {
                Assert.Equal(local.Type, model.GetSymbolInfo(typeSyntax).Symbol);
            }

            Assert.Same(symbol, model.GetSymbolInfo(decl).Symbol);
            Assert.Equal(local.Type, model.GetTypeInfo(decl).Type);
            Assert.Null(model.GetDeclaredSymbol(decl));

            foreach (var reference in references)
            {
                Assert.Same(symbol, model.GetSymbolInfo(reference).Symbol);
                Assert.Same(symbol, model.LookupSymbols(reference.SpanStart, name: decl.Identifier().ValueText).Single());
                Assert.True(model.LookupNames(reference.SpanStart).Contains(decl.Identifier().ValueText));
                Assert.Equal(local.Type, model.GetTypeInfo(reference).Type);
            }

            if (verifyDataFlow)
            {
                VerifyDataFlow(model, decl, isDelegateCreation, isExecutableCode, references, symbol);
            }
        }
Exemplo n.º 54
0
        private static async Task <Document> DeclareExplicitValueAsync(
            Document document,
            EnumDeclarationSyntax enumDeclaration,
            INamedTypeSymbol enumSymbol,
            bool isFlags,
            bool useBitShift,
            ImmutableArray <ulong> values,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            List <ulong> reservedValues = values.ToList();

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> members = enumDeclaration.Members;

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> newMembers = members;

            for (int i = 0; i < members.Count; i++)
            {
                if (members[i].EqualsValue == null)
                {
                    IFieldSymbol fieldSymbol = semanticModel.GetDeclaredSymbol(members[i], cancellationToken);

                    ulong?value = null;

                    if (isFlags)
                    {
                        Optional <ulong> optional = FlagsUtility <ulong> .Instance.GetUniquePowerOfTwo(reservedValues);

                        if (optional.HasValue &&
                            ConvertHelpers.CanConvert(optional.Value, enumSymbol.EnumUnderlyingType.SpecialType))
                        {
                            value = optional.Value;
                        }
                    }
                    else
                    {
                        value = SymbolUtility.GetEnumValueAsUInt64(fieldSymbol.ConstantValue, enumSymbol);
                    }

                    if (value != null)
                    {
                        reservedValues.Add(value.Value);

                        ExpressionSyntax expression;

                        if (useBitShift &&
                            value.Value > 1)
                        {
                            var power = (int)Math.Log(Convert.ToDouble(value.Value), 2);

                            expression = LeftShiftExpression(NumericLiteralExpression(1), NumericLiteralExpression(power));
                        }
                        else
                        {
                            expression = NumericLiteralExpression(value.Value, enumSymbol.EnumUnderlyingType.SpecialType);
                        }

                        EqualsValueClauseSyntax equalsValue = EqualsValueClause(expression);

                        EnumMemberDeclarationSyntax newMember = members[i].WithEqualsValue(equalsValue);

                        newMembers = newMembers.ReplaceAt(i, newMember);
                    }
                }
            }

            EnumDeclarationSyntax newEnumDeclaration = enumDeclaration.WithMembers(newMembers);

            return(await document.ReplaceNodeAsync(enumDeclaration, newEnumDeclaration, cancellationToken).ConfigureAwait(false));
        }
Exemplo n.º 55
0
        private static void VerifyModelForDeclarationPattern(SemanticModel model, DeclarationPatternSyntax decl, params IdentifierNameSyntax[] references)
        {
            var symbol = model.GetDeclaredSymbol(decl);
            Assert.Equal(decl.Identifier.ValueText, symbol.Name);
            Assert.Equal(LocalDeclarationKind.PatternVariable, ((LocalSymbol)symbol).DeclarationKind);
            Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)decl));
            Assert.Same(symbol, model.LookupSymbols(decl.SpanStart, name: decl.Identifier.ValueText).Single());
            Assert.True(model.LookupNames(decl.SpanStart).Contains(decl.Identifier.ValueText));

            foreach (var reference in references)
            {
                Assert.Same(symbol, model.GetSymbolInfo(reference).Symbol);
                Assert.Same(symbol, model.LookupSymbols(reference.SpanStart, name: decl.Identifier.ValueText).Single());
                Assert.True(model.LookupNames(reference.SpanStart).Contains(decl.Identifier.ValueText));
            }
        }
Exemplo n.º 56
0
        public virtual async Task <IList <DtoRules> > GetProjectAllDtoRules(Project project, IList <Project> allSourceProjects = null)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            IList <DtoRules> allDtoRules = new List <DtoRules>();

            foreach (Document doc in project.Documents)
            {
                if (!doc.SupportsSemanticModel)
                {
                    continue;
                }

                SemanticModel semanticModel = await doc.GetSemanticModelAsync();

                SyntaxNode root = await doc.GetSyntaxRootAsync();

                List <ClassDeclarationSyntax> allDtoRulesClasses = new List <ClassDeclarationSyntax>();

                foreach (ClassDeclarationSyntax classDeclarationSyntax in root.DescendantNodes()
                         .OfType <ClassDeclarationSyntax>())
                {
                    if (classDeclarationSyntax.BaseList == null)
                    {
                        continue;
                    }

                    bool isDtoRules = classDeclarationSyntax.BaseList.Types.Select(t => t.Type)
                                      .Select(t => semanticModel.GetSymbolInfo(t).Symbol?.OriginalDefinition?.ToString())
                                      .Any(t => t == "Bit.Owin.DtoRules.DtoRules<TDto>");

                    if (isDtoRules == true)
                    {
                        isDtoRules = semanticModel.GetDeclaredSymbol(classDeclarationSyntax)
                                     .GetAttributes()
                                     .Any(att => att.AttributeClass.Name == "AutoGenerateAttribute");
                    }

                    if (isDtoRules == true)
                    {
                        allDtoRulesClasses.Add(classDeclarationSyntax);
                    }
                }

                if (!allDtoRulesClasses.Any())
                {
                    continue;
                }

                foreach (ClassDeclarationSyntax dtoRulesClassDec in allDtoRulesClasses)
                {
                    INamedTypeSymbol dtoRuleSymbol = (INamedTypeSymbol)semanticModel.GetDeclaredSymbol(dtoRulesClassDec);

                    DtoRules dtoRules = new DtoRules
                    {
                        DtoRulesSymbol   = dtoRuleSymbol,
                        Name             = dtoRuleSymbol.Name,
                        ClassDeclaration = dtoRulesClassDec,
                        DtoSymbol        = (dtoRuleSymbol.BaseType.TypeArguments).ExtendedSingle($"Looking for dto of {dtoRuleSymbol.Name}"),
                        DtoRulesDocument = doc,
                        SemanticModel    = semanticModel,
                        ClassSyntaxTree  = dtoRulesClassDec.SyntaxTree
                    };

                    dtoRules.ClassRootNode = (CompilationUnitSyntax)dtoRules.ClassSyntaxTree.GetRoot();

                    allDtoRules.Add(dtoRules);
                }
            }

            return(allDtoRules);
        }
Exemplo n.º 57
0
        private static void VerifySpeculativeSemanticModelForMethodBody(BlockSyntax blockStatement, SemanticModel speculativeModel)
        {
            var localDecl = (LocalDeclarationStatementSyntax)blockStatement.Statements[0];
            var declarator = localDecl.Declaration.Variables.First();
            var local = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(local);
            Assert.Equal("z", local.Name);
            Assert.Equal(SymbolKind.Local, local.Kind);
            Assert.Equal("Int32", ((LocalSymbol)local).Type.Name);

            var typeInfo = speculativeModel.GetTypeInfo(localDecl.Declaration.Type);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("Int32", typeInfo.Type.Name);

            var call = (InvocationExpressionSyntax)((ExpressionStatementSyntax)blockStatement.Statements[1]).Expression;
            var arg = call.ArgumentList.Arguments[0].Expression;
            var info = speculativeModel.GetSymbolInfo(arg);
            Assert.NotNull(info.Symbol);
            Assert.Equal("z", info.Symbol.Name);
            Assert.Equal(SymbolKind.Local, info.Symbol.Kind);

            // Shouldn't bind to local y in the original method as we are replacing the method body.
            var call2 = (InvocationExpressionSyntax)((ExpressionStatementSyntax)((BlockSyntax)blockStatement).Statements[2]).Expression;
            var arg2 = call2.ArgumentList.Arguments[0].Expression;
            var info2 = speculativeModel.GetSymbolInfo(arg2);
            Assert.Null(info2.Symbol);
        }
Exemplo n.º 58
0
        /// <summary>
        /// 一つのメソッド定義を解析
        /// </summary>
        /// <param name="methodBlock">メソッド定義</param>
        /// <param name="model">セマンティックモデル</param>
        /// <param name="nameSpace">呼び出し元クラスの属する名前空間</param>
        /// <param name="className">呼び出し元クラス名</param>
        /// <param name="indent">インデント(省略可能)</param>
        private static ClassMethodInfo GetMethodDeclaration(MethodDeclarationSyntax methodBlock, SemanticModel model,
                                                            string nameSpace, string className)
        {
            StringBuilder str = new StringBuilder();

            try
            {
                var symbol = model.GetDeclaredSymbol(methodBlock);

                str.Append("Method Declaration: ");
                str.Append("\t");

                if (symbol != null)
                {
                    str.Append(symbol.ContainingType);
                }
                else
                {
                    str.Append(nameSpace + "." + className);
                }

                str.Append("\t");
                str.Append(methodBlock.Identifier.Text);

                str.Append(methodBlock.ParameterList);
                str.Append("\t");

                string modifier = methodBlock.Modifiers.ToString();
                str.Append(modifier);
                str.Append("\t");

                int lineCount = 0;
                using (StringReader sReader = new StringReader(methodBlock.WithoutTrivia().ToFullString()))
                {
                    string line;
                    while ((line = sReader.ReadLine()) != null)
                    {
                        if (line != string.Empty &&
                            !string.IsNullOrWhiteSpace(line) &&
                            !line.Trim().StartsWith("//"))
                        {
                            lineCount++;
                        }
                    }
                }

                str.Append(lineCount);
                //Console.WriteLine((indent ?? string.Empty) + str);

                IEnumerable <ClassMethodInfo> children = GetCallingMethods(methodBlock, model, nameSpace, className);

                ClassMethodInfo result = new ClassMethodInfo();
                result.ClassName  = symbol.ContainingType.ToString();
                result.MethodName = symbol.OriginalDefinition.ToString();
                result.LineCount  = lineCount;
                result.Children.AddRange(children);

                return(result);
            }
            catch (Exception ex)
            {
                List <string> errorReport = new List <string>();
                errorReport.Add($"AnalyzingNamespace: {nameSpace}");
                errorReport.Add($"AnalyzingClass: {className}");
                errorReport.Add($"AnalyzingMethod: {methodBlock.Identifier.Text}");

                WriteExceptionLog(new ApplicationException("[" + string.Join(",", errorReport) + "]", ex));
            }

            return(null);
        }
Exemplo n.º 59
0
        public void Execute(GeneratorExecutionContext context)
        {
#if DEBUG
            //if (!Debugger.IsAttached) Debugger.Launch();
#endif
            if (!(context.Compilation is CSharpCompilation compilation))
            {
                return;
            }
            if (!(context.ParseOptions is CSharpParseOptions parseOptions))
            {
                return;
            }

            // check if required types exists.
            if (!(compilation.GetTypeByMetadataName("System.ReadOnlySpan`1") is { } readOnlySpanSymbol))
            {
                return;
            }
            if (!(compilation.GetTypeByMetadataName("System.Runtime.CompilerServices.Unsafe") is { } unsafeSymbol))
            {
                return;
            }
            if (!(compilation.GetTypeByMetadataName("System.Runtime.InteropServices.MemoryMarshal") is { } memoryMarshalSymbol))
            {
                return;
            }

            SourceText attributeSourceText = constractSourceText(new PrimitiveStaticDataAttributeTemplate().TransformText());
            context.AddSource(PrimitiveStaticDataAttributeTemplate.TypeFullName, attributeSourceText);

            try
            {
                compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(attributeSourceText, options: parseOptions));

                INamedTypeSymbol attrSymbol = compilation.GetTypeByMetadataName(PrimitiveStaticDataAttributeTemplate.TypeFullName) !;

                var candidateMethodSyntaxes = compilation.
                                              SyntaxTrees.
                                              SelectMany(tree => tree.GetRoot().DescendantNodes()).
                                              OfType <MethodDeclarationSyntax>().
                                              Where(method => method.IsExtendedPartial() &&
                                                    method.Modifiers.Any(SyntaxKind.StaticKeyword) &&
                                                    method.AttributeLists.Count > 0 &&
                                                    method.ParentNodes().OfType <TypeDeclarationSyntax>().All(type => type.Modifiers.Any(SyntaxKind.PartialKeyword)));

                foreach (var methodSyntax in candidateMethodSyntaxes)
                {
                    SemanticModel semantic = compilation.GetSemanticModel(methodSyntax.SyntaxTree);

                    if (!(semantic.GetDeclaredSymbol(methodSyntax) is { } methodSymbol) ||
                        methodSymbol.MethodKind != MethodKind.Ordinary ||
                        methodSymbol.PartialImplementationPart is not null ||
                        !equalsSymbol(methodSymbol.ReturnType.OriginalDefinition, readOnlySpanSymbol))
                    {
                        continue;
                    }

                    var returnSpanType = (INamedTypeSymbol)methodSymbol.ReturnType;
                    if (!isPrimitiveType(returnSpanType.TypeArguments[0]))
                    {
                        continue;
                    }

                    foreach (AttributeData attr in methodSymbol.GetReturnTypeAttributes())
                    {
                        if (!equalsSymbol(attr.AttributeClass, attrSymbol) ||
                            attr.ConstructorArguments.Length < 1)
                        {
                            continue;
                        }

                        TypedConstant arg1 = attr.ConstructorArguments[0];

                        bool             argIsSingleByteValues = false;
                        IArrayTypeSymbol arraySymbol;
                        object[]         values = default !;
Exemplo n.º 60
0
        protected static void VerifyModelForDeclarationField(
            SemanticModel model,
            SingleVariableDesignationSyntax designation,
            bool duplicate,
            params IdentifierNameSyntax[] references)
        {
            var symbol = model.GetDeclaredSymbol(designation);

            Assert.Equal(designation.Identifier.ValueText, symbol.Name);
            Assert.Equal(SymbolKind.Field, symbol.Kind);
            Assert.Equal(designation, symbol.DeclaringSyntaxReferences.Single().GetSyntax());
            Assert.Same(symbol, model.GetDeclaredSymbol((SyntaxNode)designation));

            var symbols = model.LookupSymbols(designation.SpanStart, name: designation.Identifier.ValueText);
            var names   = model.LookupNames(designation.SpanStart);

            if (duplicate)
            {
                Assert.True(symbols.Count() > 1);
                Assert.Contains(symbol, symbols);
            }
            else
            {
                Assert.Same(symbol, symbols.Single());
            }

            Assert.Contains(designation.Identifier.ValueText, names);

            var local = (IFieldSymbol)symbol;

            switch (designation.Parent)
            {
            case DeclarationPatternSyntax decl:
                var typeSyntax = decl.Type;

                Assert.True(SyntaxFacts.IsInNamespaceOrTypeContext(typeSyntax));
                Assert.True(SyntaxFacts.IsInTypeOnlyContext(typeSyntax));

                var type = local.Type;
                if (typeSyntax.IsVar && type.IsErrorType())
                {
                    Assert.Null(model.GetSymbolInfo(typeSyntax).Symbol);
                }
                else
                {
                    Assert.Equal(type, model.GetSymbolInfo(typeSyntax).Symbol);
                }

                AssertTypeInfo(model, decl.Type, type);
                break;

            case var parent:
                Assert.True(parent is VarPatternSyntax);
                break;
            }

            var declarator = designation.Ancestors().OfType <VariableDeclaratorSyntax>().FirstOrDefault();
            var inFieldDeclaratorArgumentlist = declarator != null && declarator.Parent.Parent.Kind() != SyntaxKind.LocalDeclarationStatement &&
                                                (declarator.ArgumentList?.Contains(designation)).GetValueOrDefault();

            // this is a declaration site, not a use site.
            Assert.Null(model.GetSymbolInfo(designation).Symbol);
            Assert.Null(model.GetSymbolInfo(designation).Symbol);

            foreach (var reference in references)
            {
                var referenceInfo = model.GetSymbolInfo(reference);
                symbols = model.LookupSymbols(reference.SpanStart, name: designation.Identifier.ValueText);

                if (duplicate)
                {
                    Assert.Null(referenceInfo.Symbol);
                    Assert.Contains(symbol, referenceInfo.CandidateSymbols);
                    Assert.True(symbols.Count() > 1);
                    Assert.Contains(symbol, symbols);
                }
                else
                {
                    Assert.Same(symbol, referenceInfo.Symbol);
                    Assert.Same(symbol, symbols.Single());
                    Assert.Equal(local.Type, model.GetTypeInfo(reference).Type);
                }

                Assert.True(model.LookupNames(reference.SpanStart).Contains(designation.Identifier.ValueText));
            }

            if (!inFieldDeclaratorArgumentlist)
            {
                var dataFlowParent = designation.FirstAncestorOrSelf <ExpressionSyntax>();

                if (model.IsSpeculativeSemanticModel)
                {
                    Assert.Throws <NotSupportedException>(() => model.AnalyzeDataFlow(dataFlowParent));
                }
                else
                {
                    var dataFlow = model.AnalyzeDataFlow(dataFlowParent);

                    if (dataFlow.Succeeded)
                    {
                        Assert.False(dataFlow.VariablesDeclared.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.AlwaysAssigned.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.WrittenInside.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.DataFlowsIn.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.ReadInside.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.DataFlowsOut.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.ReadOutside.Contains(symbol, ReferenceEqualityComparer.Instance));
                        Assert.False(dataFlow.WrittenOutside.Contains(symbol, ReferenceEqualityComparer.Instance));
                    }
                }
            }
        }