コード例 #1
0
        public static Pool <CallsWalker> .Pooled GetCallsInContext(IMethodSymbol method, SyntaxNode context, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var pooled = Pool.GetOrCreate();

            pooled.Item.method            = method;
            pooled.Item.semanticModel     = semanticModel;
            pooled.Item.cancellationToken = cancellationToken;
            Constructor.AddRunBefore(context, pooled.Item.ctors, semanticModel, cancellationToken);
            var contextCtor = semanticModel.GetDeclaredSymbolSafe(
                context.FirstAncestorOrSelf <ConstructorDeclarationSyntax>(),
                cancellationToken);

            if (contextCtor != null)
            {
                pooled.Item.ctors.Add(contextCtor).IgnoreReturnValue();
            }

            pooled.Item.contextType = semanticModel.GetDeclaredSymbolSafe(context.FirstAncestor <TypeDeclarationSyntax>(), cancellationToken);
            var type = pooled.Item.contextType;

            while (type != null && type != KnownSymbol.Object)
            {
                foreach (var reference in type.DeclaringSyntaxReferences)
                {
                    pooled.Item.Visit(reference.GetSyntax(cancellationToken));
                }

                type = type.BaseType;
            }

            return(pooled);
        }
コード例 #2
0
        internal static bool IsRunBefore(this ConstructorDeclarationSyntax ctor, ConstructorDeclarationSyntax otherDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (ctor == otherDeclaration)
            {
                return(false);
            }

            var first = semanticModel.GetDeclaredSymbolSafe(ctor, cancellationToken);
            var other = semanticModel.GetDeclaredSymbolSafe(otherDeclaration, cancellationToken);

            return(IsRunBefore(first, other, semanticModel, cancellationToken));
        }
コード例 #3
0
        private static bool AssignedType(ISymbol symbol, SemanticModel semanticModel, CancellationToken cancellationToken, out ITypeSymbol memberType)
        {
            foreach (var reference in symbol.DeclaringSyntaxReferences)
            {
                var node = reference.GetSyntax(cancellationToken);

                if (AssignmentExecutionWalker.SingleForSymbol(
                        symbol,
                        node.FirstAncestor <TypeDeclarationSyntax>(),
                        Search.TopLevel,
                        semanticModel,
                        cancellationToken,
                        out var assignment) &&
                    assignment.Right is IdentifierNameSyntax identifier)
                {
                    var ctor = assignment.FirstAncestor <ConstructorDeclarationSyntax>();
                    if (ctor != null &&
                        ctor.ParameterList != null &&
                        ctor.ParameterList.Parameters.TryFirst(
                            p => p.Identifier.ValueText == identifier.Identifier.ValueText,
                            out var parameter))
                    {
                        memberType = semanticModel.GetDeclaredSymbolSafe(parameter, cancellationToken)?.Type;
                        return(true);
                    }
                }
            }

            memberType = null;
            return(false);
        }
コード例 #4
0
        private static void AddCtorsRecursively(ConstructorDeclarationSyntax ctor, HashSet <IMethodSymbol> ctorsRunBefore, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (ctor.Initializer != null)
            {
                var nestedCtor = semanticModel.GetSymbolSafe(ctor.Initializer, cancellationToken);
                if (nestedCtor == null)
                {
                    return;
                }

                foreach (var reference in nestedCtor.DeclaringSyntaxReferences)
                {
                    var runBefore = (ConstructorDeclarationSyntax)reference.GetSyntax(cancellationToken);
                    ctorsRunBefore.Add(nestedCtor).IgnoreReturnValue();
                    AddCtorsRecursively(runBefore, ctorsRunBefore, semanticModel, cancellationToken);
                }
            }
            else
            {
                var baseType = semanticModel.GetDeclaredSymbolSafe(ctor, cancellationToken)
                               .ContainingType.BaseType;
                if (TryGetDefault(baseType, out IMethodSymbol defaultCtor))
                {
                    foreach (var reference in defaultCtor.DeclaringSyntaxReferences)
                    {
                        ctorsRunBefore.Add(defaultCtor).IgnoreReturnValue();
                        var runBefore = (ConstructorDeclarationSyntax)reference.GetSyntax(cancellationToken);
                        AddCtorsRecursively(runBefore, ctorsRunBefore, semanticModel, cancellationToken);
                    }
                }
            }
        }
コード例 #5
0
        private static bool TryGetAssignedFieldOrProperty(ArgumentSyntax argument, IMethodSymbol method, SemanticModel semanticModel, CancellationToken cancellationToken, out ISymbol member)
        {
            member = null;
            if (method == null)
            {
                return(false);
            }

            if (method.TrySingleDeclaration <BaseMethodDeclarationSyntax>(cancellationToken, out var methodDeclaration) &&
                methodDeclaration.TryGetMatchingParameter(argument, out var paremeter))
            {
                var parameterSymbol = semanticModel.GetDeclaredSymbolSafe(paremeter, cancellationToken);
                if (methodDeclaration.Body.TryGetAssignment(parameterSymbol, semanticModel, cancellationToken, out var assignment))
                {
                    member = semanticModel.GetSymbolSafe(assignment.Left, cancellationToken);
                    if (member is IFieldSymbol ||
                        member is IPropertySymbol)
                    {
                        return(true);
                    }
                }

                if (methodDeclaration is ConstructorDeclarationSyntax ctor &&
                    ctor.Initializer is ConstructorInitializerSyntax initializer &&
                    initializer.ArgumentList != null &&
                    initializer.ArgumentList.Arguments.TrySingle(x => x.Expression is IdentifierNameSyntax identifier && identifier.Identifier.ValueText == paremeter.Identifier.ValueText, out var chainedArgument))
                {
                    var chained = semanticModel.GetSymbolSafe(ctor.Initializer, cancellationToken);
                    return(TryGetAssignedFieldOrProperty(chainedArgument, chained, semanticModel, cancellationToken, out member));
                }
            }

            return(false);
        }
コード例 #6
0
        internal static Pool <ConstructorsWalker> .Pooled Create(TypeDeclarationSyntax context, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var pooled = Pool.GetOrCreate();

            pooled.Item.semanticModel     = semanticModel;
            pooled.Item.cancellationToken = cancellationToken;
            pooled.Item.Visit(context);
            pooled.Item.type = semanticModel.GetDeclaredSymbolSafe(context, cancellationToken) as INamedTypeSymbol;
            if (pooled.Item.type == null)
            {
                return(pooled);
            }

            foreach (var reference in pooled.Item.type.DeclaringSyntaxReferences)
            {
                pooled.Item.Visit(reference.GetSyntax(cancellationToken));
            }

            if (pooled.Item.nonPrivateCtors.Count == 0 &&
                pooled.Item.Default == null)
            {
                if (Constructor.TryGetDefault(pooled.Item.type, out IMethodSymbol @default))
                {
                    foreach (var reference in @default.DeclaringSyntaxReferences)
                    {
                        pooled.Item.Default = (ConstructorDeclarationSyntax)reference.GetSyntax(cancellationToken);
                        pooled.Item.Visit(pooled.Item.Default);
                    }
                }
            }

            return(pooled);
        }
コード例 #7
0
        internal static bool TryGetMatchingParameter(this InvocationExpressionSyntax invocation, ArgumentSyntax argument, SemanticModel semanticModel, CancellationToken cancellationToken, out IParameterSymbol parameter)
        {
            parameter = null;
            if (invocation?.ArgumentList == null)
            {
                return(false);
            }

            if (semanticModel.GetSymbolSafe(invocation, cancellationToken) is IMethodSymbol method)
            {
                foreach (var reference in method.DeclaringSyntaxReferences)
                {
                    if (reference.GetSyntax(cancellationToken) is MethodDeclarationSyntax methodDeclaration)
                    {
                        if (methodDeclaration.TryGetMatchingParameter(argument, out ParameterSyntax parameterSyntax))
                        {
                            parameter = semanticModel.GetDeclaredSymbolSafe(parameterSyntax, cancellationToken);
                            return(parameter != null);
                        }
                    }
                }
            }

            return(false);
        }
        private static bool TryGetField(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken, out IFieldSymbol field)
        {
            field = null;
            var typeDeclaration = node.FirstAncestor <TypeDeclarationSyntax>();

            if (typeDeclaration == null)
            {
                return(false);
            }

            var type = semanticModel.GetDeclaredSymbolSafe(typeDeclaration, cancellationToken);

            if (type == null)
            {
                return(false);
            }

            foreach (var member in type.GetMembers())
            {
                if (member is IFieldSymbol candidateField &&
                    candidateField.Type == KnownSymbol.CompositeDisposable)
                {
                    field = candidateField;
                    return(true);
                }
            }

            return(false);
        }
コード例 #9
0
        private static Fix CreateFix(Diagnostic diagnostic, SyntaxNode syntaxRoot, SemanticModel semanticModel, CancellationToken cancellationToken, SyntaxGenerator syntaxGenerator, bool usesUnderscoreNames)
        {
            var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start);

            if (string.IsNullOrEmpty(token.ValueText))
            {
                return(default(Fix));
            }

            var assignment = syntaxRoot.FindNode(diagnostic.Location.SourceSpan)
                             .FirstAncestorOrSelf <ExpressionSyntax>();
            var typeDeclaration = assignment?.FirstAncestorOrSelf <TypeDeclarationSyntax>();

            if (typeDeclaration == null)
            {
                return(default(Fix));
            }

            if (!diagnostic.Properties.TryGetValue(WPF1012NotifyWhenPropertyChanges.PropertyNameKey, out string property))
            {
                return(default(Fix));
            }

            var type = semanticModel.GetDeclaredSymbolSafe(typeDeclaration, cancellationToken);

            if (PropertyChanged.Helpers.PropertyChanged.TryGetInvoker(type, semanticModel, cancellationToken, out IMethodSymbol invoker) &&
                invoker.Parameters[0].Type == KnownSymbol.String)
            {
                var onPropertyChanged = syntaxGenerator.OnPropertyChanged(property, useCallerMemberName: false, usedUnderscoreNames: usesUnderscoreNames, invoker: invoker);
                return(new Fix(assignment, onPropertyChanged, invoker));
            }

            return(default(Fix));
        }
コード例 #10
0
        internal static ConstructorsWalker Borrow(TypeDeclarationSyntax context, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var walker = Borrow(() => new ConstructorsWalker());

            walker.semanticModel     = semanticModel;
            walker.cancellationToken = cancellationToken;
            walker.Visit(context);
            walker.type = semanticModel.GetDeclaredSymbolSafe(context, cancellationToken) as INamedTypeSymbol;
            if (walker.type == null)
            {
                return(walker);
            }

            foreach (var reference in walker.type.DeclaringSyntaxReferences)
            {
                walker.Visit(reference.GetSyntax(cancellationToken));
            }

            if (walker.nonPrivateCtors.Count == 0 &&
                walker.Default == null)
            {
                if (Constructor.TryGetDefault(walker.type, out var @default))
                {
                    foreach (var reference in @default.DeclaringSyntaxReferences)
                    {
                        walker.Default = (ConstructorDeclarationSyntax)reference.GetSyntax(cancellationToken);
                        walker.Visit(walker.Default);
                    }
                }
            }

            return(walker);
        }
コード例 #11
0
ファイル: SemanticModelExt.cs プロジェクト: forki/Gu.Reactive
 internal static bool IsEither <T1, T2>(this SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken)
     where T1 : ISymbol
     where T2 : ISymbol
 {
     return(semanticModel.GetSymbolSafe(node, cancellationToken).IsEither <T1, T2>() ||
            semanticModel.GetDeclaredSymbolSafe(node, cancellationToken).IsEither <T1, T2>() ||
            semanticModel.GetTypeInfoSafe(node, cancellationToken).Type.IsEither <T1, T2>());
 }
コード例 #12
0
        private static bool TryGetMemberSymbol(MemberDeclarationSyntax member, SemanticModel semanticModel, CancellationToken cancellationToken, out ISymbol symbol)
        {
            if (member is FieldDeclarationSyntax field &&
                field.Declaration.Variables.TryGetSingle(out VariableDeclaratorSyntax declarator))
            {
                symbol = semanticModel.GetDeclaredSymbolSafe(declarator, cancellationToken);
                return(symbol != null);
            }

            if (member is PropertyDeclarationSyntax property)
            {
                symbol = semanticModel.GetDeclaredSymbolSafe(property, cancellationToken);
                return(symbol != null);
            }

            symbol = null;
            return(false);
        }
コード例 #13
0
        private static Fix CreateFix(Diagnostic diagnostic, SyntaxNode syntaxRoot, SemanticModel semanticModel, CancellationToken cancellationToken, bool usesUnderscoreNames)
        {
            var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start);

            if (string.IsNullOrEmpty(token.ValueText) ||
                token.IsMissing)
            {
                return(default(Fix));
            }

            var member = (MemberDeclarationSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan);

            if (member is MethodDeclarationSyntax methodDeclaration)
            {
                var method = semanticModel.GetDeclaredSymbolSafe(methodDeclaration, cancellationToken);
                if (method.Parameters.Length != 1)
                {
                    return(default(Fix));
                }

                var overridden = method.OverriddenMethod;
                var baseCall   = SyntaxFactory.ParseStatement($"base.{overridden.Name}({method.Parameters[0].Name});")
                                 .WithLeadingTrivia(SyntaxFactory.ElasticMarker)
                                 .WithTrailingTrivia(SyntaxFactory.ElasticMarker);
                return(new Fix(baseCall, methodDeclaration));
            }

            if (!TryGetMemberSymbol(member, semanticModel, cancellationToken, out ISymbol memberSymbol))
            {
                return(default(Fix));
            }

            if (Disposable.TryGetDisposeMethod(memberSymbol.ContainingType, Search.TopLevel, out IMethodSymbol disposeMethodSymbol))
            {
                if (disposeMethodSymbol.DeclaredAccessibility == Accessibility.Public &&
                    disposeMethodSymbol.Parameters.Length == 0 &&
                    disposeMethodSymbol.TryGetSingleDeclaration(cancellationToken, out MethodDeclarationSyntax disposeMethodDeclaration))
                {
                    var disposeStatement = CreateDisposeStatement(memberSymbol, semanticModel, cancellationToken, usesUnderscoreNames);
                    return(new Fix(disposeStatement, disposeMethodDeclaration));
                }

                if (disposeMethodSymbol.Parameters.Length == 1 &&
                    disposeMethodSymbol.TryGetSingleDeclaration(cancellationToken, out disposeMethodDeclaration))
                {
                    var parameterType = semanticModel.GetTypeInfoSafe(disposeMethodDeclaration.ParameterList.Parameters[0]?.Type, cancellationToken).Type;
                    if (parameterType == KnownSymbol.Boolean)
                    {
                        var disposeStatement = CreateDisposeStatement(memberSymbol, semanticModel, cancellationToken, usesUnderscoreNames);
                        return(new Fix(disposeStatement, disposeMethodDeclaration));
                    }
                }
            }

            return(default(Fix));
        }
コード例 #14
0
        private static void MakeAutoPropertyNotifyWhenValueChanges(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (Property.IsMutableAutoProperty(propertyDeclaration, out var getter, out var setter))
            {
                if (getter.Body != null ||
                    getter.ContainsSkippedText ||
                    setter.Body != null ||
                    setter.ContainsSkippedText)
                {
                    return;
                }

                var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                var property         = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                var backingField     = editor.AddBackingField(propertyDeclaration, underscoreFields, cancellationToken);
                var fieldAccess      = underscoreFields
                    ? backingField.Name()
                    : $"this.{backingField.Name()}";
                var code = StringBuilderPool.Borrow()
                           .AppendLine($"public Type PropertyName")
                           .AppendLine("{")
                           .AppendLine($"    get => {fieldAccess};")
                           .AppendLine()
                           .AppendLine("    set")
                           .AppendLine("    {")
                           .AppendLine($"        if ({Snippet.EqualityCheck(property.Type, "value", fieldAccess, semanticModel)})")
                           .AppendLine("        {")
                           .AppendLine($"           return;")
                           .AppendLine("        }")
                           .AppendLine()
                           .AppendLine($"        {fieldAccess} = value;")
                           .AppendLine($"        {Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields)}")
                           .AppendLine("    }")
                           .AppendLine("}")
                           .Return();
                var template = ParseProperty(code);
                editor.ReplaceNode(
                    getter,
                    x => x.WithExpressionBody(template.Getter().ExpressionBody)
                    .WithTrailingElasticLineFeed()
                    .WithAdditionalAnnotations(Formatter.Annotation));
                editor.ReplaceNode(
                    setter,
                    x => x.WithBody(template.Setter().Body)
                    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None))
                    .WithAdditionalAnnotations(Formatter.Annotation));
                if (propertyDeclaration.Initializer != null)
                {
                    editor.ReplaceNode(
                        propertyDeclaration,
                        x => x.WithoutInitializer());
                }

                editor.ReplaceNode(propertyDeclaration, x => x.WithAdditionalAnnotations(Formatter.Annotation));
            }
        }
コード例 #15
0
            private static IEnumerable <ISymbol> ReadOnlies(ConstructorDeclarationSyntax ctor, SemanticModel semanticModel, CancellationToken cancellationToken)
            {
                var isStatic = ctor.Modifiers.Any(SyntaxKind.StaticKeyword);
                var typeDeclarationSyntax = (TypeDeclarationSyntax)ctor.Parent;

                foreach (var member in typeDeclarationSyntax.Members)
                {
                    if (member is FieldDeclarationSyntax fieldDeclaration &&
                        fieldDeclaration.Modifiers.Any(SyntaxKind.ReadOnlyKeyword))
                    {
                        var declaration = fieldDeclaration.Declaration;
                        if (declaration.Variables.TryGetSingle(out var variable))
                        {
                            var field = (IFieldSymbol)semanticModel.GetDeclaredSymbolSafe(variable, cancellationToken);
                            if (field.IsReadOnly &&
                                field.IsStatic == isStatic &&
                                variable.Initializer == null)
                            {
                                yield return(field);
                            }
                        }

                        continue;
                    }

                    if (member is PropertyDeclarationSyntax propertyDeclaration &&
                        propertyDeclaration.ExpressionBody == null &&
                        !propertyDeclaration.TryGetSetAccessorDeclaration(out _) &&
                        propertyDeclaration.TryGetGetAccessorDeclaration(out var getter) &&
                        getter.Body == null)
                    {
                        var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                        if (property.IsReadOnly &&
                            property.IsStatic == isStatic &&
                            !property.IsAbstract &&
                            propertyDeclaration.Initializer == null)
                        {
                            yield return(semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken));
                        }
                    }
                }
            }
コード例 #16
0
            private static IEnumerable <string> ReadOnlies(ConstructorDeclarationSyntax ctor, SemanticModel semanticModel, CancellationToken cancellationToken)
            {
                var isStatic = semanticModel.GetDeclaredSymbolSafe(ctor, cancellationToken)
                               .IsStatic;
                var typeDeclarationSyntax = (TypeDeclarationSyntax)ctor.Parent;

                foreach (var member in typeDeclarationSyntax.Members)
                {
                    if (member is FieldDeclarationSyntax fieldDeclaration)
                    {
                        var declaration = fieldDeclaration.Declaration;
                        if (declaration.Variables.TryGetSingle(out VariableDeclaratorSyntax variable))
                        {
                            var field = (IFieldSymbol)semanticModel.GetDeclaredSymbolSafe(variable, cancellationToken);
                            if (field.IsReadOnly && field.IsStatic == isStatic && variable.Initializer == null)
                            {
                                yield return(field.Name);
                            }
                        }

                        continue;
                    }

                    var propertyDeclaration = member as PropertyDeclarationSyntax;
                    if (propertyDeclaration != null &&
                        propertyDeclaration.ExpressionBody == null &&
                        propertyDeclaration.TryGetGetAccessorDeclaration(out AccessorDeclarationSyntax getter) &&
                        getter.Body == null)
                    {
                        var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                        if (property.IsReadOnly &&
                            property.IsStatic == isStatic &&
                            !property.IsAbstract &&
                            propertyDeclaration.Initializer == null)
                        {
                            yield return(propertyDeclaration.Identifier.ValueText);
                        }
                    }
                }
            }
コード例 #17
0
        internal static bool TryGetRegisteredName(ArgumentSyntax callback, SemanticModel semanticModel, CancellationToken cancellationToken, out string registeredName)
        {
            registeredName = null;
            if (callback == null)
            {
                return(false);
            }

            var fieldDeclaration   = callback.FirstAncestorOrSelf <VariableDeclaratorSyntax>();
            var dependencyProperty = semanticModel.GetDeclaredSymbolSafe(fieldDeclaration, cancellationToken) as IFieldSymbol;

            return(DependencyProperty.TryGetRegisteredName(dependencyProperty, semanticModel, cancellationToken, out registeredName));
        }
コード例 #18
0
        internal static bool TryGetDependencyProperty(ObjectCreationExpressionSyntax objectCreation, SemanticModel semanticModel, CancellationToken cancellationToken, out IFieldSymbol dependencyProperty)
        {
            dependencyProperty = null;
            var declarator = objectCreation.FirstAncestorOrSelf <VariableDeclaratorSyntax>();

            if (declarator == null)
            {
                return(false);
            }

            dependencyProperty = semanticModel.GetDeclaredSymbolSafe(declarator, cancellationToken) as IFieldSymbol;
            return(dependencyProperty != null);
        }
コード例 #19
0
        internal static bool Creates(this ObjectCreationExpressionSyntax creation, ConstructorDeclarationSyntax ctor, Search search, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var created    = semanticModel.GetSymbolSafe(creation, cancellationToken) as IMethodSymbol;
            var ctorSymbol = semanticModel.GetDeclaredSymbolSafe(ctor, cancellationToken);

            if (SymbolComparer.Equals(ctorSymbol, created))
            {
                return(true);
            }

            return(search == Search.Recursive &&
                   IsRunBefore(created, ctorSymbol, semanticModel, cancellationToken));
        }
        private static bool TryGetAssignedFieldOrProperty(ArgumentSyntax argument, IMethodSymbol method, SemanticModel semanticModel, CancellationToken cancellationToken, out ISymbol member)
        {
            member = null;
            if (method == null)
            {
                return(false);
            }

            foreach (var reference in method.DeclaringSyntaxReferences)
            {
                var methodDeclaration = reference.GetSyntax(cancellationToken) as BaseMethodDeclarationSyntax;
                if (methodDeclaration == null)
                {
                    continue;
                }

                if (!methodDeclaration.TryGetMatchingParameter(argument, out ParameterSyntax paremeter))
                {
                    continue;
                }

                var parameterSymbol = semanticModel.GetDeclaredSymbolSafe(paremeter, cancellationToken);
                if (methodDeclaration.Body.TryGetAssignment(parameterSymbol, semanticModel, cancellationToken, out AssignmentExpressionSyntax assignment))
                {
                    member = semanticModel.GetSymbolSafe(assignment.Left, cancellationToken);
                    if (member is IFieldSymbol ||
                        member is IPropertySymbol)
                    {
                        return(true);
                    }
                }

                var ctor = reference.GetSyntax(cancellationToken) as ConstructorDeclarationSyntax;
                if (ctor?.Initializer != null)
                {
                    foreach (var arg in ctor.Initializer.ArgumentList.Arguments)
                    {
                        var argSymbol = semanticModel.GetSymbolSafe(arg.Expression, cancellationToken);
                        if (parameterSymbol.Equals(argSymbol))
                        {
                            var chained = semanticModel.GetSymbolSafe(ctor.Initializer, cancellationToken);
                            return(TryGetAssignedFieldOrProperty(arg, chained, semanticModel, cancellationToken, out member));
                        }
                    }
                }
            }

            return(false);
        }
コード例 #21
0
ファイル: Callback.cs プロジェクト: candyzkn/WpfAnalyzers
        internal static bool TryGetRegisteredName(ArgumentSyntax callback, SemanticModel semanticModel, CancellationToken cancellationToken, out string registeredName)
        {
            registeredName = null;
            var invocation   = callback?.FirstAncestorOrSelf <InvocationExpressionSyntax>();
            var memberAccess = invocation?.Expression as MemberAccessExpressionSyntax;

            if (memberAccess == null)
            {
                return(false);
            }

            var method = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol;

            if (method == KnownSymbol.DependencyProperty.OverrideMetadata ||
                method == KnownSymbol.DependencyProperty.AddOwner)
            {
                var dependencyProperty = semanticModel.GetSymbolSafe(memberAccess.Expression, cancellationToken) as IFieldSymbol;
                if (dependencyProperty?.Type != KnownSymbol.DependencyProperty)
                {
                    return(false);
                }

                return(DependencyProperty.TryGetRegisteredName(dependencyProperty, semanticModel, cancellationToken, out registeredName));
            }

            if (method == KnownSymbol.DependencyProperty.Register ||
                method == KnownSymbol.DependencyProperty.RegisterReadOnly ||
                method == KnownSymbol.DependencyProperty.RegisterAttached ||
                method == KnownSymbol.DependencyProperty.RegisterAttachedReadOnly)
            {
                var fieldDeclaration = callback.FirstAncestorOrSelf <VariableDeclaratorSyntax>();
                if (fieldDeclaration == null)
                {
                    return(false);
                }

                var dependencyProperty = semanticModel.GetDeclaredSymbolSafe(fieldDeclaration, cancellationToken) as IFieldSymbol;
                if (dependencyProperty == null)
                {
                    return(false);
                }

                return(DependencyProperty.TryGetRegisteredName(dependencyProperty, semanticModel, cancellationToken, out registeredName));
            }

            return(false);
        }
コード例 #22
0
        internal static void AddRunBefore(SyntaxNode context, HashSet <IMethodSymbol> ctorsRunBefore, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (context == null)
            {
                return;
            }

            var contextCtor = context.FirstAncestorOrSelf <ConstructorDeclarationSyntax>();

            if (contextCtor == null)
            {
                var type = (INamedTypeSymbol)semanticModel.GetDeclaredSymbolSafe(context.FirstAncestorOrSelf <TypeDeclarationSyntax>(), cancellationToken);
                if (type == null)
                {
                    return;
                }

                if (type.Constructors.Length != 0)
                {
                    foreach (var ctor in type.Constructors)
                    {
                        foreach (var reference in ctor.DeclaringSyntaxReferences)
                        {
                            var ctorDeclaration = (ConstructorDeclarationSyntax)reference.GetSyntax(cancellationToken);
                            ctorsRunBefore.Add(ctor).IgnoreReturnValue();
                            AddCtorsRecursively(ctorDeclaration, ctorsRunBefore, semanticModel, cancellationToken);
                        }
                    }
                }
                else
                {
                    if (TryGetDefault(type, out IMethodSymbol ctor))
                    {
                        foreach (var reference in ctor.DeclaringSyntaxReferences)
                        {
                            var ctorDeclaration = (ConstructorDeclarationSyntax)reference.GetSyntax(cancellationToken);
                            ctorsRunBefore.Add(ctor).IgnoreReturnValue();
                            AddCtorsRecursively(ctorDeclaration, ctorsRunBefore, semanticModel, cancellationToken);
                        }
                    }
                }
            }
            else
            {
                AddCtorsRecursively(contextCtor, ctorsRunBefore, semanticModel, cancellationToken);
            }
        }
コード例 #23
0
        private static Task <Document> ApplyImplementINotifyPropertyChangedFixAsync(
            CodeFixContext context,
            SemanticModel semanticModel,
            CancellationToken cancellationToken,
            CompilationUnitSyntax syntaxRoot,
            TypeDeclarationSyntax typeDeclaration)
        {
            var type            = semanticModel.GetDeclaredSymbolSafe(typeDeclaration, cancellationToken);
            var syntaxGenerator = SyntaxGenerator.GetGenerator(context.Document);

            var updated = typeDeclaration.WithINotifyPropertyChangedInterface(syntaxGenerator, type)
                          .WithPropertyChangedEvent(syntaxGenerator)
                          .WithInvoker(syntaxGenerator, type);
            var newRoot = syntaxRoot.ReplaceNode(typeDeclaration, updated)
                          .WithUsings();

            return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot)));
        }
コード例 #24
0
        private static void MakeWithBackingFieldNotify(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();

            if (classDeclaration == null)
            {
                return;
            }

            if (IsSimpleAssignmentOnly(propertyDeclaration, out var setter, out var statement, out var assignment, out _))
            {
                var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                var property         = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                var notifyStatement  = SyntaxFactory
                                       .ParseStatement(Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields))
                                       .WithLeadingTrivia(SyntaxFactory.ElasticMarker)
                                       .WithTrailingTrivia(SyntaxFactory.ElasticMarker)
                                       .WithSimplifiedNames()
                                       .WithAdditionalAnnotations(Formatter.Annotation);
                if (setter.ExpressionBody != null)
                {
                    editor.ReplaceNode(
                        setter,
                        (x, _) =>
                    {
                        var old = (AccessorDeclarationSyntax)x;
                        return(old.WithBody(
                                   SyntaxFactory.Block(
                                       SyntaxFactory.ExpressionStatement(assignment),
                                       notifyStatement))
                               .WithExpressionBody(null)
                               .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)));
                    });
                    editor.FormatNode(propertyDeclaration);
                }
                else if (setter.Body != null)
                {
                    editor.InsertAfter(statement, notifyStatement);
                    editor.FormatNode(propertyDeclaration);
                }
            }
        }
コード例 #25
0
        private static Neighbors GetNeighbors(BasePropertyDeclarationSyntax propertyDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var typeDeclaration = propertyDeclaration.FirstAncestorOrSelf <TypeDeclarationSyntax>();

            if (typeDeclaration == null)
            {
                return(default(Neighbors));
            }

            var isBefore = true;
            BasePropertyDeclarationSyntax before = null;
            BasePropertyDeclarationSyntax after  = null;

            foreach (var member in typeDeclaration.Members)
            {
                var declaration = member as BasePropertyDeclarationSyntax;
                if (declaration == null ||
                    !declaration.IsPropertyOrIndexer())
                {
                    continue;
                }

                if (declaration == propertyDeclaration)
                {
                    isBefore = false;
                    continue;
                }

                if (isBefore)
                {
                    before = declaration;
                }
                else
                {
                    after = declaration;
                    break;
                }
            }

            return(new Neighbors((IPropertySymbol)semanticModel.GetDeclaredSymbolSafe(before, cancellationToken), (IPropertySymbol)semanticModel.GetDeclaredSymbolSafe(after, cancellationToken)));
        }
コード例 #26
0
ファイル: Property.cs プロジェクト: candyzkn/WpfAnalyzers
        internal static bool IsSimplePropertyWithBackingField(PropertyDeclarationSyntax property, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (!(property.TryGetGetAccessorDeclaration(out AccessorDeclarationSyntax getter) &&
                  property.TryGetSetAccessorDeclaration(out AccessorDeclarationSyntax setter)))
            {
                return(false);
            }

            if (getter.Body?.Statements.Count != 1 ||
                setter.Body?.Statements.Count != 1)
            {
                return(false);
            }

            var returnStatement = getter.Body.Statements[0] as ReturnStatementSyntax;
            var assignment      = (setter.Body.Statements[0] as ExpressionStatementSyntax)?.Expression as AssignmentExpressionSyntax;

            if (returnStatement == null ||
                assignment == null)
            {
                return(false);
            }

            var returnedField = semanticModel.GetSymbolSafe(returnStatement.Expression, cancellationToken) as IFieldSymbol;
            var assignedField = semanticModel.GetSymbolSafe(assignment.Left, cancellationToken) as IFieldSymbol;

            if (assignedField == null ||
                returnedField == null)
            {
                return(false);
            }

            var propertySymbol = semanticModel.GetDeclaredSymbolSafe(property, cancellationToken);

            return(assignedField.Equals(returnedField) && assignedField.ContainingType == propertySymbol?.ContainingType);
        }
コード例 #27
0
        private static void MakeWithBackingFieldNotifyWhenValueChanges(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>();

            if (classDeclaration == null)
            {
                return;
            }

            if (propertyDeclaration.TryGetSetter(out var setter))
            {
                if (setter.ExpressionBody != null &&
                    IsSimpleAssignmentOnly(propertyDeclaration, out _, out _, out var assignment, out _))
                {
                    var property         = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                    var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                    var code             = StringBuilderPool.Borrow()
                                           .AppendLine($"public Type PropertyName")
                                           .AppendLine("{")
                                           .AppendLine($"    get => {assignment.Left};")
                                           .AppendLine()
                                           .AppendLine("    set")
                                           .AppendLine("    {")
                                           .AppendLine($"        if ({Snippet.EqualityCheck(property.Type, "value", assignment.Left.ToString(), semanticModel)})")
                                           .AppendLine("        {")
                                           .AppendLine($"           return;")
                                           .AppendLine("        }")
                                           .AppendLine()
                                           .AppendLine($"        {assignment};")
                                           .AppendLine($"        {Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields)}")
                                           .AppendLine("    }")
                                           .AppendLine("}")
                                           .Return();
                    var template = ParseProperty(code);
                    editor.ReplaceNode(
                        setter,
                        (x, _) =>
                    {
                        var old = (AccessorDeclarationSyntax)x;
                        return(old.WithBody(template.Setter().Body)
                               .WithExpressionBody(null)
                               .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)));
                    });
                    editor.FormatNode(propertyDeclaration);
                }

                if (setter.Body?.Statements.Count == 1 &&
                    IsSimpleAssignmentOnly(propertyDeclaration, out _, out var statement, out assignment, out _))
                {
                    var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken);
                    var code     = StringBuilderPool.Borrow()
                                   .AppendLine($"        if ({Snippet.EqualityCheck(property.Type, "value", assignment.Left.ToString(), semanticModel)})")
                                   .AppendLine("        {")
                                   .AppendLine($"           return;")
                                   .AppendLine("        }")
                                   .AppendLine()
                                   .Return();
                    var ifStatement = SyntaxFactory.ParseStatement(code)
                                      .WithSimplifiedNames()
                                      .WithLeadingElasticLineFeed()
                                      .WithTrailingElasticLineFeed()
                                      .WithAdditionalAnnotations(Formatter.Annotation);
                    editor.InsertBefore(
                        statement,
                        ifStatement);
                    var underscoreFields = CodeStyle.UnderscoreFields(semanticModel);
                    var notifyStatement  = SyntaxFactory
                                           .ParseStatement(
                        Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields))
                                           .WithSimplifiedNames()
                                           .WithLeadingElasticLineFeed()
                                           .WithTrailingElasticLineFeed()
                                           .WithAdditionalAnnotations(Formatter.Annotation);
                    editor.InsertAfter(statement, notifyStatement);
                    editor.FormatNode(propertyDeclaration);
                }
            }
        }
コード例 #28
0
 internal static Result IsMemberDisposed(ISymbol member, TypeDeclarationSyntax context, SemanticModel semanticModel, CancellationToken cancellationToken)
 {
     return(IsMemberDisposed(member, semanticModel.GetDeclaredSymbolSafe(context, cancellationToken), semanticModel, cancellationToken));
 }
コード例 #29
0
        internal static bool TryGetConversionTypes(ClassDeclarationSyntax classDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken, out ITypeSymbol sourceType, out ITypeSymbol targetType)
        {
            sourceType = null;
            targetType = null;
            if (classDeclaration.TryFindMethod("Convert", out var convertMethod) &&
                convertMethod.ReturnType is PredefinedTypeSyntax returnType &&
                returnType.Keyword.ValueText == "object" &&
                convertMethod.ParameterList != null &&
                convertMethod.ParameterList.Parameters.Count == 4 &&
                convertMethod.ParameterList.Parameters.TryFirst(out var valueParameter))
            {
                using (var returnValues = ReturnValueWalker.Borrow(convertMethod))
                {
                    using (var returnTypes = PooledSet <ITypeSymbol> .Borrow())
                    {
                        foreach (var returnValue in returnValues.ReturnValues)
                        {
                            AddReturnType(returnTypes, returnValue);
                        }

                        return(returnTypes.TrySingle(out targetType) &&
                               ConversionWalker.TryGetCommonBase(
                                   convertMethod,
                                   semanticModel.GetDeclaredSymbolSafe(valueParameter, cancellationToken),
                                   semanticModel,
                                   cancellationToken,
                                   out sourceType));
                    }
                }
            }

            return(false);

            void AddReturnType(PooledSet <ITypeSymbol> returnTypes, ExpressionSyntax returnValue)
            {
                switch (returnValue)
                {
                case LiteralExpressionSyntax literal when literal.IsKind(SyntaxKind.NullLiteralExpression):
                    break;

                case ConditionalExpressionSyntax ternary:
                    AddReturnType(returnTypes, ternary.WhenTrue);
                    AddReturnType(returnTypes, ternary.WhenFalse);
                    break;

                case BinaryExpressionSyntax coalesce when coalesce.IsKind(SyntaxKind.CoalesceExpression):
                    AddReturnType(returnTypes, coalesce.Left);

                    AddReturnType(returnTypes, coalesce.Right);
                    break;

                case IdentifierNameSyntax _:
                case MemberAccessExpressionSyntax _:
                    var type = semanticModel.GetTypeInfoSafe(returnValue, cancellationToken).Type;
                    if (type == KnownSymbol.Object &&
                        semanticModel.GetSymbolSafe(returnValue, cancellationToken) is ISymbol symbol &&
                        symbol.IsEither <IFieldSymbol, IPropertySymbol>())
                    {
                        switch (symbol)
                        {
                        case IFieldSymbol field:
                            if (field.Type == KnownSymbol.Object &&
                                field.DeclaredAccessibility == Accessibility.Private &&
                                returnValue.FirstAncestor <TypeDeclarationSyntax>() is TypeDeclarationSyntax typeDeclaration)
                            {
                                using (var walker = AssignmentExecutionWalker.Borrow(typeDeclaration, Scope.Instance, semanticModel, cancellationToken))
                                {
                                    foreach (var assignment in walker.Assignments)
                                    {
                                        if (semanticModel.TryGetSymbol(assignment.Left, cancellationToken, out IFieldSymbol assigned) &&
                                            FieldSymbolComparer.Equals(assigned, field))
                                        {
                                            returnTypes.Add(semanticModel.GetTypeInfoSafe(assignment.Right, cancellationToken).Type);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                returnTypes.Add(field.Type);
                            }

                            return;

                        case IPropertySymbol property:
                            returnTypes.Add(property.Type);
                            return;
                        }
                    }
                    else
                    {
                        returnTypes.Add(type);
                    }

                    break;
コード例 #30
0
        internal static Result IsArgumentDisposedByReturnValue(ArgumentSyntax argument, SemanticModel semanticModel, CancellationToken cancellationToken, PooledHashSet <SyntaxNode> visited = null)
        {
            if (argument?.Parent is ArgumentListSyntax argumentList)
            {
                if (argumentList.Parent is InvocationExpressionSyntax invocation &&
                    semanticModel.GetSymbolSafe(invocation, cancellationToken) is IMethodSymbol method)
                {
                    if (method.ContainingType.DeclaringSyntaxReferences.Length == 0)
                    {
                        if (method == KnownSymbol.CompositeDisposable.Add)
                        {
                            return(Result.Yes);
                        }

                        return(method.ReturnsVoid ||
                               !IsAssignableTo(method.ReturnType)
                            ? Result.No
                            : Result.AssumeYes);
                    }

                    if (invocation.TryGetMatchingParameter(argument, semanticModel, cancellationToken, out var parameter))
                    {
                        return(CheckReturnValues(parameter, invocation, semanticModel, cancellationToken, visited));
                    }

                    return(Result.Unknown);
                }

                if (argumentList.Parent is ObjectCreationExpressionSyntax ||
                    argumentList.Parent is ConstructorInitializerSyntax)
                {
                    if (TryGetAssignedFieldOrProperty(argument, semanticModel, cancellationToken, out var member, out var ctor) &&
                        member != null)
                    {
                        var initializer = argument.FirstAncestorOrSelf <ConstructorInitializerSyntax>();
                        if (initializer != null)
                        {
                            if (semanticModel.GetDeclaredSymbolSafe(initializer.Parent, cancellationToken) is IMethodSymbol chainedCtor &&
                                chainedCtor.ContainingType != member.ContainingType)
                            {
                                if (TryGetDelRefMethod(chainedCtor.ContainingType, Search.TopLevel, out var disposeMethod))
                                {
                                    return(IsMemberDisposed(member, disposeMethod, semanticModel, cancellationToken)
                                        ? Result.Yes
                                        : Result.No);
                                }
                            }
                        }

                        return(IsMemberDisposed(member, ctor.ContainingType, semanticModel, cancellationToken));
                    }

                    if (ctor == null)
                    {
                        return(Result.AssumeYes);
                    }

                    if (ctor.ContainingType.DeclaringSyntaxReferences.Length == 0)
                    {
                        return(IsAssignableTo(ctor.ContainingType) ? Result.AssumeYes : Result.No);
                    }

                    return(Result.No);
                }
            }

            return(Result.Unknown);
        }