Пример #1
0
        static bool TryGetDiagnostic(MemberAccessExpressionSyntax memberAccessSyntax, ITypeSymbol containingType, SyntaxNode extensionParameter, out Diagnostic diagnostic)
        {
            diagnostic = default(Diagnostic);

            if (memberAccessSyntax.IsKind(SyntaxKind.ThisKeyword) || memberAccessSyntax.IsKind(SyntaxKind.BaseExpression))
            {
                return(false);
            }

            var rightMostName = memberAccessSyntax.Expression.GetRightmostName();

            if (rightMostName == null || rightMostName == extensionParameter)
            {
                return(false);
            }

            var rightMostType = rightMostName.Identifier.Text;

            if (rightMostType == containingType.Name)
            {
                return(false);
            }

            if (CheckCuriouslyRecurringTemplatePattern(containingType, rightMostType))
            {
                return(false);
            }

            diagnostic = Diagnostic.Create(
                descriptor,
                memberAccessSyntax.GetLocation()
                );
            return(true);
        }
Пример #2
0
        private void AnalyzeNodeInvokation(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

            SyntaxToken?identifier = GetMethodCallIdentifier(invocation);

            if (identifier == null)
            {
                return;
            }

            ISymbol methodCallSymbol = context.SemanticModel.GetSymbolInfo(identifier.Value.Parent).Symbol;

            if (methodCallSymbol == null)
            {
                return;
            }

            string typeContainingMethod = methodCallSymbol.ContainingType.ConstructedFrom.ToString();

            if (identifier.Value.ValueText != "Slice" || (typeContainingMethod != "System.Memory<T>" && typeContainingMethod != "System.ReadOnlyMemory<T>"))
            {
                return;
            }

            if (invocation.ArgumentList.Arguments.Count != 1 && invocation.ArgumentList.Arguments.Count != 2)
            {
                return;
            }

            MemberAccessExpressionSyntax parent = invocation.Parent as MemberAccessExpressionSyntax;

            SyntaxToken?secondIdentifier = GetMethodCallIdentifier(parent);

            if (secondIdentifier == null)
            {
                return;
            }

            ISymbol memberAccessSymbol = context.SemanticModel.GetSymbolInfo(secondIdentifier.Value.Parent).Symbol;

            if (memberAccessSymbol == null)
            {
                return;
            }

            string typeContainingMemberAccess = memberAccessSymbol.ContainingType.ConstructedFrom.ToString();

            if (secondIdentifier.Value.ValueText == "Span" && (typeContainingMemberAccess == "System.Memory<T>" || typeContainingMemberAccess == "System.ReadOnlyMemory<T>"))
            {
                context.ReportDiagnostic(Diagnostic.Create(Rule, parent.GetLocation()));
            }
        }
Пример #3
0
        private static ExpressionSyntax Bind(MemberAccessExpressionSyntax node)
        {
            int index = Array.IndexOf(SupportedNumbers, node.Name.Identifier.Text);

            if (index == -1)
            {
                throw new DiagnosticException("Invalid property", node.GetLocation());
            }

            return(SyntaxFactory.LiteralExpression(
                       SyntaxKind.NumericLiteralExpression,
                       SyntaxFactory.Literal(index)
                       ));
        }
Пример #4
0
        private Diagnostic AnalyzeSimpleMemberAccessExpression(SyntaxList <StatementSyntax> statements, MemberAccessExpressionSyntax call, SemanticModel semanticModel)
        {
            var callLineSpan = call.GetLocation().GetLineSpan();

            var noBlankLinesBefore = statements
                                     .Where(_ => HasNoBlankLinesBefore(callLineSpan, _))
                                     .Any(_ => IsCall(_, semanticModel) is false);
            var noBlankLinesAfter = statements
                                    .Where(_ => HasNoBlankLinesAfter(callLineSpan, _))
                                    .Any(_ => IsCall(_, semanticModel) is false);

            if (noBlankLinesBefore || noBlankLinesAfter)
            {
                return(Issue(call, noBlankLinesBefore, noBlankLinesAfter));
            }

            return(null);
        }
Пример #5
0
            private void EvaluateMemberAccessExpression(MemberAccessExpressionSyntax node)
            {
                var typeInfo = semanticModel.GetTypeInfo(node.Expression);
                var name     = typeInfo.Type.Name;

                if (name != "Nullable")
                {
                    return;
                }

                if (node.Name.Identifier.ValueText != "HasValue")
                {
                    return;
                }

                var diagnostic = Diagnostic.Create(Rule, node.GetLocation(), node.Name);

                context.ReportDiagnostic(diagnostic);
            }
        private void Analyze(SyntaxNodeAnalysisContext context)
        {
            MemberAccessExpressionSyntax memberAccessExpressionSyntax = (MemberAccessExpressionSyntax)context.Node;

            if (memberAccessExpressionSyntax == null)
            {
                return;
            }

            if (!memberAccessExpressionSyntax.Name.ToString().Equals(PrivateKeyProperty))
            {
                return;
            }

            ITypeSymbol typeSymbol = context.SemanticModel.GetTypeInfo(memberAccessExpressionSyntax.Expression).Type;

            if (typeSymbol != null && typeSymbol.Name.Equals(ObjectType))
            {
                Diagnostic diagnostic = Diagnostic.Create(Rule, memberAccessExpressionSyntax.GetLocation());
                context.ReportDiagnostic(diagnostic);
            }
        }
        internal static void ValidateMemberAccessInLinqExpression(MemberAccessExpressionSyntax node, EFCodeFirstClassInfo rootQueryableType, SyntaxNodeAnalysisContext context, Dictionary<string, ContextualLinqParameter> parameterNodes, bool treatAsWarning)
        {
            var identifier = (node.Expression as IdentifierNameSyntax);
            var memberName = node?.Name;

            if (identifier != null && memberName != null)
            {
                var identText = identifier?.Identifier.ValueText ?? string.Empty;
                if (!string.IsNullOrEmpty(identText) && parameterNodes.ContainsKey(identText))
                {
                    //TODO: Properties of explicit interface implementations. Does EF recognize these or not?
                    string propName = memberName.Identifier.ValueText;
                    if (rootQueryableType.IsReadOnly(propName))
                    {
                        var diagnostic = Diagnostic.Create(treatAsWarning ? DiagnosticCodes.EFLINQ005 : DiagnosticCodes.EFLINQ002, node.GetLocation(), memberName.Identifier.ValueText, rootQueryableType.Name);
                        context.ReportDiagnostic(diagnostic);
                    }
                    if (rootQueryableType.IsExplicitlyUnmapped(propName))
                    {
                        var diagnostic = Diagnostic.Create(treatAsWarning ? DiagnosticCodes.EFLINQ014 : DiagnosticCodes.EFLINQ013, node.GetLocation(), memberName.Identifier.ValueText, rootQueryableType.Name);
                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
        }
        internal static void ValidateMemberAccessInLinqExpression(MemberAccessExpressionSyntax node, EFCodeFirstClassInfo rootQueryableType, SyntaxNodeAnalysisContext context, Dictionary <string, ContextualLinqParameter> parameterNodes, bool treatAsWarning)
        {
            var identifier = (node.Expression as IdentifierNameSyntax);
            var memberName = node?.Name;

            if (identifier != null && memberName != null)
            {
                var identText = identifier?.Identifier.ValueText ?? string.Empty;
                if (!string.IsNullOrEmpty(identText) && parameterNodes.ContainsKey(identText))
                {
                    //TODO: Properties of explicit interface implementations. Does EF recognize these or not?
                    string propName = memberName.Identifier.ValueText;
                    if (rootQueryableType.IsReadOnly(propName))
                    {
                        var diagnostic = Diagnostic.Create(treatAsWarning ? DiagnosticCodes.EFLINQ005 : DiagnosticCodes.EFLINQ002, node.GetLocation(), memberName.Identifier.ValueText, rootQueryableType.Name);
                        context.ReportDiagnostic(diagnostic);
                    }
                    if (rootQueryableType.IsExplicitlyUnmapped(propName))
                    {
                        var diagnostic = Diagnostic.Create(treatAsWarning ? DiagnosticCodes.EFLINQ014 : DiagnosticCodes.EFLINQ013, node.GetLocation(), memberName.Identifier.ValueText, rootQueryableType.Name);
                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
        }
Пример #9
0
        public static bool TryCreate
        (
            GeneratorContext context,
            MemberAccessExpressionSyntax expressionSyntax,
            ITypeSymbol interfaceType,
            ITypeSymbol implementationType,
            string mode,
            [NotNullWhen(true)] out MemoizerCall?call)
        {
            var interfaceAttributes = interfaceType.GetAttributes();

            if (!context.TryGetInterfaceContext(interfaceType, out var interfaceContext))
            {
                // The Interface could exist in a referenced project which we dont have the interfacesyntax for.. lets check that
                var memoizeAttribute2 = interfaceAttributes.FirstOrDefault(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass, context.CreateMemoizedAttribute));

                if (memoizeAttribute2 == null)
                {
                    context.CreateError("Missing Memoized Attribute", "Interface must have the [CreateMemoizedImplementation] attribute attached", expressionSyntax.Name.GetLocation());
                    call = null;
                    return(false);
                }

                interfaceContext = CreateMemoizeInterfaceContext.CreateFromType(interfaceType, memoizeAttribute2, expressionSyntax.GetLocation());
            }

            var memoizeAttribute = interfaceContext.CreateMemoizedAttributeData;

            if (!TryGetClassName(memoizeAttribute, interfaceType, out var className, out var humanId))
            {
                call = null;
                return(false);
            }

            var memoizerFactory = memoizeAttribute.NamedArguments.FirstOrDefault(x => x.Key == nameof(CreateMemoizedImplementationAttribute.MemoizerFactory)).Value;
            INamedTypeSymbol?memoizerFactoryTypeSymbol = null;

            if (!memoizerFactory.IsNull)
            {
                memoizerFactoryTypeSymbol = memoizerFactory.Value as INamedTypeSymbol;
            }

            if (memoizerFactoryTypeSymbol != null)
            {
                if (!memoizerFactoryTypeSymbol.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, context.MemoizerFactoryInterface)))
                {
                    context.CreateError($"Wrong {nameof(CreateMemoizedImplementationAttribute.MemoizerFactory)} type", $"MemoizerFactory type must implement {nameof(IMemoizerFactory)}", interfaceContext.InterfaceWithAttribute?.GetLocation() ?? expressionSyntax.Name.GetLocation());
                    call = null;
                    return(false);
                }
            }

            var slidingCache = SlidingCache.MaybeCreate(context, interfaceAttributes);

            var members       = interfaceType.GetMembers();
            var methods       = new List <MemoizedMethodMember>(members.Length);
            var methodSymbols = members.OfType <IMethodSymbol>().ToList();

            // TODO Create different ArgKey class name implementations
            // then Check names to see what ArgKey_ class name algo we can use

            foreach (var interfaceMethod in methodSymbols)
            {
                if (MemoizedMethodMember.TryCreate(context, interfaceContext, interfaceMethod, out var methodMember))
                {
                    methods.Add(methodMember);
                }
                else
                {
                    call = null;
                    return(false);
                }
            }

            var @namespace = GetNamespaceFrom(expressionSyntax);

            call = new MemoizerCall(interfaceType, implementationType, className, methods, slidingCache, memoizerFactoryTypeSymbol, humanId, @namespace, mode);

            return(true);
        }
Пример #10
0
        private Location GetMemberInvocationLocation([NotNull] MemberAccessExpressionSyntax memberAccessSyntax)
        {
            SyntaxNode lastChild = memberAccessSyntax.ChildNodes().LastOrDefault();

            return(lastChild != null?lastChild.GetLocation() : memberAccessSyntax.GetLocation());
        }
Пример #11
0
        public override void VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
        {
            var symbol = GetSymbol(node);

            if (symbol is IMethodSymbol methodSymbol)
            {
                base.Visit(node.Expression);
                return;
            }
            else if (symbol is IFieldSymbol fieldSymbol)
            {
                if (TryCallIntrinsicsFunction(new FunctionKey(fieldSymbol), node.Expression, null))
                {
                    return;
                }

                if (!fieldSymbol.IsStatic)
                {
                    var left = WalkAndGetResult(node.Expression) as ShaderOp;
                    if (left.mResultType.mBaseType == OpType.Pointer)
                    {
                        var memberVariableOp = mFrontEnd.GenerateAccessChain(left, fieldSymbol.Name, mContext);
                        mContext.Push(memberVariableOp);
                    }
                    else
                    {
                        var memberVariableOp = mFrontEnd.GenerateCompositeExtract(left, fieldSymbol.Name, mContext);
                        mContext.Push(memberVariableOp);
                    }
                }
                else
                {
                    // Create a constant from enum values (currently only supports ints)
                    if (fieldSymbol.Type.TypeKind == TypeKind.Enum && fieldSymbol.HasConstantValue)
                    {
                        int constantValue = 0;
                        if (fieldSymbol.ConstantValue is int intVal)
                        {
                            constantValue = intVal;
                        }
                        else
                        {
                            mFrontEnd.CurrentProject.SendTranslationError(new ShaderCodeLocation(node.GetLocation()), "Failed to get enum value. Defaulting to 0.");
                        }

                        var constantType = mFrontEnd.mCurrentLibrary.FindType(new TypeKey(fieldSymbol.Type));
                        var constantOp   = mFrontEnd.CreateConstantOp(constantType, constantValue);
                        mContext.Push(constantOp);
                    }
                    else
                    {
                        var staticField = FindStaticField(fieldSymbol);
                        mContext.Push(staticField.InstanceOp);
                    }
                }
                return;
            }
            else if (symbol is IPropertySymbol propertySymbol)
            {
                if (TryCallIntrinsicsFunction(new FunctionKey(propertySymbol.GetMethod), node.Expression, null))
                {
                    return;
                }
                // @JoshD: Handle property getter/setter function calls
            }
            throw new Exception();
        }
Пример #12
0
        public override SyntaxNode VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
        {
            IOperation operation = semanticModel.GetOperation(node, cancellationToken);

            if (operation == null || !operation.IsInvalid)
            {
                return(base.VisitMemberAccessExpression(node));
            }

            // Expression is invalid, might be a late-bound object
            IOperation expression = semanticModel.GetOperation(node.Expression, cancellationToken);

            if (expression.IsInvalid)
            {
                return(base.VisitMemberAccessExpression(node));
            }

            // Find out if it is a late-bound object...
            INamedTypeSymbol type = expression.Type as INamedTypeSymbol;

            if (type == null)
            {
                return(base.VisitMemberAccessExpression(node));
            }

            // ... by finding its Bind method
            object[] arguments = null;

            bool IsValidBindMethod(MethodInfo mi)
            {
                if (!mi.IsStatic || mi.IsAbstract || mi.Name != "Bind")
                {
                    return(false);
                }

                if (!typeof(ExpressionSyntax).IsAssignableFrom(mi.ReturnType))
                {
                    return(false);
                }

                ParameterInfo[] parameters = mi.GetParameters();
                object[]        args       = new object[parameters.Length];

                for (int i = 0; i < parameters.Length; i++)
                {
                    Type paramType = parameters[i].ParameterType;

                    if (paramType.IsAssignableFrom(typeof(MemberAccessExpressionSyntax)))
                    {
                        args[i] = node;
                    }
                    else if (paramType == typeof(IOperation))
                    {
                        args[i] = expression;
                    }
                    else
                    {
                        return(false);
                    }
                }

                arguments = args;
                return(true);
            }

            Type correspondingType = type.GetCorrespondingType();

            if (correspondingType == null)
            {
                return(base.VisitMemberAccessExpression(node));
            }

            MethodInfo bindMethod = correspondingType
                                    .GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
                                    .FirstOrDefault(IsValidBindMethod);

            if (bindMethod == null)
            {
                return(base.VisitMemberAccessExpression(node));
            }

            // We do have a binder!
            // Call the method
            try
            {
                ExpressionSyntax result = bindMethod.Invoke(null, arguments) as ExpressionSyntax;

                return(result == null
                    ? SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)
                    : base.Visit(result));
            }
            catch (Exception e)
            {
                throw new DiagnosticException("Error thrown by binding method.", e, node.GetLocation());
            }
        }