Beispiel #1
0
        private static void AnalyzePositionalArgumentsAndParameters(
            SymbolAnalysisContext context,
            AttributeData attribute,
            ImmutableArray <TypedConstant> attributePositionalArguments,
            ImmutableArray <IParameterSymbol> methodParameters)
        {
            for (var i = 0; i < attributePositionalArguments.Length; i++)
            {
                var attributeArgument = attributePositionalArguments[i];
                var(methodParameterType, methodParameterName, methodParameterParamsType) =
                    TestCaseUsageAnalyzer.GetParameterType(methodParameters, i);

                if (methodParameterType.IsTypeParameterAndDeclaredOnMethod())
                {
                    continue;
                }

                ITypeSymbol?argumentType = attributeArgument.Type;

                var argumentTypeMatchesParameterType = attributeArgument.CanAssignTo(
                    methodParameterType,
                    context.Compilation,
                    allowImplicitConversion: true,
                    allowEnumToUnderlyingTypeConversion: true);

                if (methodParameterParamsType == null && argumentTypeMatchesParameterType)
                {
                    continue;
                }

                if (methodParameterParamsType != null)
                {
                    var argumentTypeMatchesElementType = attributeArgument.CanAssignTo(
                        methodParameterParamsType,
                        context.Compilation,
                        allowImplicitConversion: true,
                        allowEnumToUnderlyingTypeConversion: true);

                    if (argumentTypeMatchesElementType ||
                        (argumentTypeMatchesParameterType && (argumentType != null || !methodParameterParamsType.IsValueType)))
                    {
                        continue;
                    }
                }

                var attributeArgumentSyntax = attribute.GetConstructorArgumentSyntax(i, context.CancellationToken);

                if (attributeArgumentSyntax is null)
                {
                    continue;
                }

                context.ReportDiagnostic(Diagnostic.Create(parameterTypeMismatch,
                                                           attributeArgumentSyntax.GetLocation(),
                                                           i,
                                                           argumentType?.ToDisplayString() ?? "<null>",
                                                           methodParameterName,
                                                           methodParameterType));

                context.CancellationToken.ThrowIfCancellationRequested();
            }
        }
 public static bool IsAbstractClass([NotNullWhen(returnValue: true)] this ITypeSymbol?symbol)
 => symbol?.TypeKind == TypeKind.Class && symbol.IsAbstract;
 public static bool IsNullable([NotNullWhen(returnValue: true)] this ITypeSymbol?symbol)
 => symbol?.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T;
        // Is a protected symbol inside "originalContainingType" accessible from within "within",
        // which much be a named type or an assembly.
        private static bool IsProtectedSymbolAccessible(
            INamedTypeSymbol?withinType,
            IAssemblySymbol withinAssembly,
            ITypeSymbol?throughType,
            INamedTypeSymbol originalContainingType,
            out bool failedThroughTypeCheck)
        {
            failedThroughTypeCheck = false;

            // It is not an error to define protected member in a sealed Script class,
            // it's just a warning. The member behaves like a private one - it is visible
            // in all subsequent submissions.
            if (withinAssembly.IsInteractive && originalContainingType.IsScriptClass)
            {
                return(true);
            }

            if (withinType == null)
            {
                // If we're not within a type, we can't access a protected symbol
                return(false);
            }

            // A protected symbol is accessible if we're (optionally nested) inside the type that it
            // was defined in.

            // NOTE(ericli): It is helpful to consider 'protected' as *increasing* the
            // accessibility domain of a private member, rather than *decreasing* that of a public
            // member. Members are naturally private; the protected, internal and public access
            // modifiers all increase the accessibility domain. Since private members are accessible
            // to nested types, so are protected members.

            // NOTE(cyrusn): We do this check up front as it is very fast and easy to do.
            if (IsNestedWithinOriginalContainingType(withinType, originalContainingType))
            {
                return(true);
            }

            // Protected is really confusing.  Check out 3.5.3 of the language spec "protected access
            // for instance members" to see how it works.  I actually got the code for this from
            // LangCompiler::CheckAccessCore
            {
                var current             = withinType.OriginalDefinition;
                var originalThroughType = throughType?.OriginalDefinition;
                while (current != null)
                {
                    Debug.Assert(current.IsDefinition);

                    if (current.InheritsFromOrImplementsOrEqualsIgnoringConstruction(originalContainingType))
                    {
                        // NOTE(cyrusn): We're continually walking up the 'throughType's inheritance
                        // chain.  We could compute it up front and cache it in a set.  However, i
                        // don't want to allocate memory in this function.  Also, in practice
                        // inheritance chains should be very short.  As such, it might actually be
                        // slower to create and check inside the set versus just walking the
                        // inheritance chain.
                        if (originalThroughType == null ||
                            originalThroughType.InheritsFromOrImplementsOrEqualsIgnoringConstruction(current))
                        {
                            return(true);
                        }
                        else
                        {
                            failedThroughTypeCheck = true;
                        }
                    }

                    // NOTE(cyrusn): The container of an original type is always original.
                    current = current.ContainingType;
                }
            }

            return(false);
        }
Beispiel #5
0
        public IEnumerable <MethodInfo> GetNotImplementedMessages(Accessibility?accessibility = null, ITypeSymbol?returnType = null)
        {
            foreach (var message in GetMessages())
            {
                if (IsImplemented(message))
                {
                    continue;
                }

                if (accessibility.HasValue && !AccessibilityMatch(message, accessibility.Value))
                {
                    continue;
                }

                if (returnType != null && !returnType.Matches(message.ReturnType))
                {
                    continue;
                }

                yield return(message);
            }
        }
 protected abstract bool IsAssignableTo(
     [NotNullWhen(returnValue: true)] ITypeSymbol?fromSymbol,
     [NotNullWhen(returnValue: true)] ITypeSymbol?toSymbol,
     Compilation compilation);
        public bool TryCreate(IOperation operation, [NotNullWhen(returnValue: true)] out AnalysisEntity?analysisEntity)
        {
            if (_analysisEntityMap.TryGetValue(operation, out analysisEntity))
            {
                return(analysisEntity != null);
            }

            analysisEntity = null;
            ISymbol?symbol = null;
            ImmutableArray <AbstractIndex> indices = ImmutableArray <AbstractIndex> .Empty;
            IOperation? instance = null;
            ITypeSymbol?type     = operation.Type;

            switch (operation)
            {
            case ILocalReferenceOperation localReference:
                symbol = localReference.Local;
                break;

            case IParameterReferenceOperation parameterReference:
                symbol = parameterReference.Parameter;
                break;

            case IMemberReferenceOperation memberReference:
                instance = memberReference.Instance;
                GetSymbolAndIndicesForMemberReference(memberReference, ref symbol, ref indices);

                // Workaround for https://github.com/dotnet/roslyn/issues/22736 (IPropertyReferenceExpressions in IAnonymousObjectCreationExpression are missing a receiver).
                if (instance == null &&
                    symbol != null &&
                    memberReference is IPropertyReferenceOperation propertyReference)
                {
                    instance = propertyReference.GetAnonymousObjectCreation();
                }

                break;

            case IArrayElementReferenceOperation arrayElementReference:
                instance = arrayElementReference.ArrayReference;
                indices  = CreateAbstractIndices(arrayElementReference.Indices);
                break;

            case IDynamicIndexerAccessOperation dynamicIndexerAccess:
                instance = dynamicIndexerAccess.Operation;
                indices  = CreateAbstractIndices(dynamicIndexerAccess.Arguments);
                break;

            case IConditionalAccessInstanceOperation conditionalAccessInstance:
                IConditionalAccessOperation?conditionalAccess = conditionalAccessInstance.GetConditionalAccess();
                instance = conditionalAccess?.Operation;
                if (conditionalAccessInstance.Parent is IMemberReferenceOperation memberReferenceParent)
                {
                    GetSymbolAndIndicesForMemberReference(memberReferenceParent, ref symbol, ref indices);
                }
                break;

            case IInstanceReferenceOperation instanceReference:
                if (_getPointsToAbstractValue != null)
                {
                    instance = instanceReference.GetInstance(_getIsInsideAnonymousObjectInitializer());
                    if (instance == null)
                    {
                        // Reference to this or base instance.
                        analysisEntity = _interproceduralCallStack != null && _interproceduralCallStack.Peek().DescendantsAndSelf().Contains(instanceReference) ?
                                         _interproceduralThisOrMeInstanceForCaller :
                                         ThisOrMeInstance;
                    }
                    else
                    {
                        var instanceLocation = _getPointsToAbstractValue(instanceReference);
                        analysisEntity = AnalysisEntity.Create(instanceReference, instanceLocation);
                    }
                }
                break;

            case IConversionOperation conversion:
                return(TryCreate(conversion.Operand, out analysisEntity));

            case IParenthesizedOperation parenthesized:
                return(TryCreate(parenthesized.Operand, out analysisEntity));

            case IArgumentOperation argument:
                return(TryCreate(argument.Value, out analysisEntity));

            case IFlowCaptureOperation flowCapture:
                var isLvalueFlowCapture = _getIsLValueFlowCapture(flowCapture);
                analysisEntity = GetOrCreateForFlowCapture(flowCapture.Id, flowCapture.Value.Type, flowCapture, isLvalueFlowCapture);

                // Store flow capture copy values for simple flow captures of non-flow captured entity.
                // This enables pseudo copy-analysis of values of these two entities in absence of true copy analysis, which is expensive.
                if (!isLvalueFlowCapture &&
                    TryCreate(flowCapture.Value, out var capturedEntity) &&
                    capturedEntity.CaptureId == null &&
                    !_captureIdCopyValueMap.ContainsKey(flowCapture.Id) &&
                    analysisEntity.Type.IsValueType == capturedEntity.Type.IsValueType)
                {
                    // Skip flow capture for conversions unless we know the points to value
                    // for conversion and operand is identical.
                    if (flowCapture.Value is IConversionOperation conversion)
                    {
                        if (_getPointsToAbstractValue == null ||
                            _getPointsToAbstractValue(conversion) != _getPointsToAbstractValue(conversion.Operand))
                        {
                            break;
                        }
                    }

                    var kind      = capturedEntity.Type.IsValueType ? CopyAbstractValueKind.KnownValueCopy : CopyAbstractValueKind.KnownReferenceCopy;
                    var copyValue = new CopyAbstractValue(ImmutableHashSet.Create(analysisEntity, capturedEntity), kind);
                    _captureIdCopyValueMap.Add(flowCapture.Id, copyValue);
                }

                break;

            case IFlowCaptureReferenceOperation flowCaptureReference:
                analysisEntity = GetOrCreateForFlowCapture(flowCaptureReference.Id, flowCaptureReference.Type, flowCaptureReference, flowCaptureReference.IsLValueFlowCaptureReference());
                break;

            case IDeclarationExpressionOperation declarationExpression:
                switch (declarationExpression.Expression)
                {
                case ILocalReferenceOperation localReference:
                    return(TryCreateForSymbolDeclaration(localReference.Local, out analysisEntity));

                case ITupleOperation tupleOperation:
                    return(TryCreate(tupleOperation, out analysisEntity));
                }

                break;

            case IVariableDeclaratorOperation variableDeclarator:
                symbol = variableDeclarator.Symbol;
                type   = variableDeclarator.Symbol.Type;
                break;

            case IDeclarationPatternOperation declarationPattern:
                var declaredLocal = declarationPattern.DeclaredSymbol as ILocalSymbol;
                symbol = declaredLocal;
                type   = declaredLocal?.Type;
                break;

            default:
                break;
            }

            if (symbol != null || !indices.IsEmpty)
            {
                TryCreate(symbol, indices, type !, instance, out analysisEntity);
            }

            _analysisEntityMap[operation] = analysisEntity;
            return(analysisEntity != null);
        }
Beispiel #8
0
 public static bool IsObjectType(this ITypeSymbol?type)
 {
     return(type == null || type.SpecialType == SpecialType.System_Object);
 }
 public ActualApiResponseMetadata(IReturnOperation returnExpression, int statusCode, ITypeSymbol?returnType)
 {
     ReturnOperation = returnExpression;
     _statusCode     = statusCode;
     ReturnType      = returnType;
 }
Beispiel #10
0
        private static bool IsWrongType(BackingFieldOrProperty fieldOrProperty, ArgumentSyntax argument, SyntaxNodeAnalysisContext context, [NotNullWhen(true)] out ITypeSymbol?registeredType)
        {
            if (DependencyProperty.TryGetRegisteredType(fieldOrProperty, context.SemanticModel, context.CancellationToken, out registeredType) &&
                !PropertyMetadata.IsValueValidForRegisteredType(argument.Expression, registeredType, context.SemanticModel, context.CancellationToken))
            {
                if (context.SemanticModel.TryGetType(argument.Expression, context.CancellationToken, out var type))
                {
                    if (type == KnownSymbols.Object)
                    {
                        return(false);
                    }

                    if (registeredType.IsAssignableTo(KnownSymbols.Freezable, context.Compilation) &&
                        type.IsAssignableTo(KnownSymbols.Freezable, context.Compilation))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            return(false);
        }
Beispiel #11
0
            private void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
            {
                var           invocation    = (TInvocationExpressionSyntax)context.Node;
                SemanticModel semanticModel = context.SemanticModel;

                ISymbol symbol = semanticModel.GetSymbolInfo(invocation, context.CancellationToken).Symbol;

                if (symbol == null || symbol.Kind != SymbolKind.Method || !symbol.Name.StartsWith("Register", StringComparison.Ordinal))
                {
                    return;
                }

                var method = (IMethodSymbol)symbol;

                NoteRegisterActionInvocation(method, invocation, semanticModel, context.CancellationToken);

                bool isRegisterSymbolAction         = IsRegisterAction(DiagnosticWellKnownNames.RegisterSymbolActionName, method, _analysisContext, _compilationStartAnalysisContext);
                bool isRegisterSyntaxNodeAction     = IsRegisterAction(DiagnosticWellKnownNames.RegisterSyntaxNodeActionName, method, _analysisContext, _compilationStartAnalysisContext, _codeBlockStartAnalysisContext);
                bool isRegisterCodeBlockStartAction = IsRegisterAction(DiagnosticWellKnownNames.RegisterCodeBlockStartActionName, method, _analysisContext, _compilationStartAnalysisContext);
                bool isRegisterOperationAction      = IsRegisterAction(DiagnosticWellKnownNames.RegisterOperationActionName, method, _analysisContext, _compilationStartAnalysisContext, _operationBlockStartAnalysisContext);

                if (isRegisterSymbolAction || isRegisterSyntaxNodeAction || isRegisterOperationAction)
                {
                    if (method.Parameters.Length == 2 && method.Parameters[1].IsParams)
                    {
                        IEnumerable <SyntaxNode>?arguments = GetArgumentExpressions(invocation);
                        if (arguments != null)
                        {
                            int argumentCount = arguments.Count();
                            if (argumentCount >= 1)
                            {
                                ITypeSymbol type = semanticModel.GetTypeInfo(arguments.First(), context.CancellationToken).ConvertedType;
                                if (type == null || type.Name.Equals(nameof(Action), StringComparison.Ordinal))
                                {
                                    if (argumentCount == 1)
                                    {
                                        DiagnosticDescriptor rule;
                                        if (isRegisterSymbolAction)
                                        {
                                            rule = MissingSymbolKindArgumentRule;
                                        }
                                        else if (isRegisterOperationAction)
                                        {
                                            rule = MissingOperationKindArgumentRule;
                                        }
                                        else
                                        {
                                            rule = MissingSyntaxKindArgumentRule;
                                        }

                                        SyntaxNode invocationExpression = GetInvocationExpression(invocation);
                                        Diagnostic diagnostic           = Diagnostic.Create(rule, invocationExpression.GetLocation());
                                        context.ReportDiagnostic(diagnostic);
                                    }
                                    else if (isRegisterSymbolAction)
                                    {
                                        foreach (SyntaxNode argument in arguments.Skip(1))
                                        {
                                            symbol = semanticModel.GetSymbolInfo(argument, context.CancellationToken).Symbol;
                                            if (symbol != null &&
                                                symbol.Kind == SymbolKind.Field &&
                                                _symbolKind.Equals(symbol.ContainingType) &&
                                                !s_supportedSymbolKinds.Contains(symbol.Name))
                                            {
                                                Diagnostic diagnostic = Diagnostic.Create(UnsupportedSymbolKindArgumentRule, argument.GetLocation(), symbol.Name);
                                                context.ReportDiagnostic(diagnostic);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if (!method.TypeParameters.IsEmpty &&
                    (isRegisterSyntaxNodeAction || isRegisterCodeBlockStartAction))
                {
                    ITypeSymbol?typeArgument = null;
                    if (method.TypeParameters.Length == 1)
                    {
                        if (method.TypeParameters[0].Name == DiagnosticWellKnownNames.TLanguageKindEnumName)
                        {
                            typeArgument = method.TypeArguments[0];
                        }
                    }
                    else
                    {
                        ITypeParameterSymbol typeParam = method.TypeParameters.FirstOrDefault(t => t.Name == DiagnosticWellKnownNames.TLanguageKindEnumName);
                        if (typeParam != null)
                        {
                            int index = method.TypeParameters.IndexOf(typeParam);
                            typeArgument = method.TypeArguments[index];
                        }
                    }

                    if (typeArgument != null &&
                        typeArgument.TypeKind != TypeKind.TypeParameter &&
                        typeArgument.TypeKind != TypeKind.Error &&
                        !IsSyntaxKind(typeArgument))
                    {
                        Location location = typeArgument.Locations[0];
                        if (!location.IsInSource)
                        {
                            SyntaxNode invocationExpression = GetInvocationExpression(invocation);
                            location = invocationExpression.GetLocation();
                        }

                        Diagnostic diagnostic = Diagnostic.Create(InvalidSyntaxKindTypeArgumentRule, location, typeArgument.Name, DiagnosticWellKnownNames.TLanguageKindEnumName, method.Name);
                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
Beispiel #12
0
        public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol?typeArgument, [NotNullWhen(returnValue: true)] INamedTypeSymbol?interfaceType, string interfaceMethodName)
        {
            INamedTypeSymbol?constructedInterface = typeArgument != null?interfaceType?.Construct(typeArgument) : interfaceType;

            return(constructedInterface?.GetMembers(interfaceMethodName).FirstOrDefault() is IMethodSymbol interfaceMethod && method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod)));
        }
Beispiel #13
0
 public static bool IsModuleType([NotNullWhen(returnValue: true)] this ITypeSymbol?symbol)
 {
     return(symbol?.TypeKind == TypeKind.Module);
 }
Beispiel #14
0
 public static bool CanAddNullCheck([NotNullWhen(returnValue: true)] this ITypeSymbol?type)
 => type != null && (type.IsReferenceType || type.IsNullable());
Beispiel #15
0
 internal static bool IsEqualToOrDerivedFrom(ITypeSymbol?type, ITypeSymbol expectedType)
 {
     return(EqualityComparer <ITypeSymbol?> .Default.Equals(type?.OriginalDefinition, expectedType) || IsDerivedFrom(type, expectedType));
 }
Beispiel #16
0
        private static void AddMissingMembersToStatefulMarshaller(DocumentEditor editor, SyntaxNode declaringSyntax, INamedTypeSymbol marshallerType, ITypeSymbol managedType, HashSet <string> missingMemberNames, bool isLinearCollectionMarshaller)
        {
            SyntaxGenerator gen = editor.Generator;

            // Get the methods of the shape so we can use them to determine what types to use in signatures that are not obvious.
            var(_, methods) = StatefulMarshallerShapeHelper.GetShapeForType(marshallerType, managedType, isLinearCollectionMarshaller, editor.SemanticModel.Compilation);
            INamedTypeSymbol spanOfT         = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.System_Span_Metadata) !;
            INamedTypeSymbol readOnlySpanOfT = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.System_ReadOnlySpan_Metadata) !;

            var(typeParameters, _) = marshallerType.GetAllTypeArgumentsIncludingInContainingTypes();

            // Use a lazy factory for the type syntaxes to avoid re-checking the various methods and reconstructing the syntax.
            Lazy <SyntaxNode>  unmanagedTypeSyntax      = new(CreateUnmanagedTypeSyntax, isThreadSafe : false);
            Lazy <ITypeSymbol> managedElementTypeSymbol = new(CreateManagedElementTypeSymbol, isThreadSafe : false);

            List <SyntaxNode> newMembers = new();

            if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.FromManaged))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.FromManaged,
                        parameters: new[] { gen.ParameterDeclaration("managed", gen.TypeExpression(managedType)) },
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.ToUnmanaged))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.ToUnmanaged,
                        returnType: unmanagedTypeSyntax.Value,
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.FromUnmanaged))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.FromUnmanaged,
                        parameters: new[] { gen.ParameterDeclaration("unmanaged", unmanagedTypeSyntax.Value) },
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.ToManaged))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.ToManaged,
                        returnType: gen.TypeExpression(managedType),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.BufferSize))
            {
                newMembers.Add(
                    gen.WithAccessorDeclarations(
                        gen.PropertyDeclaration(ShapeMemberNames.BufferSize,
                                                gen.TypeExpression(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_Int32)),
                                                Accessibility.Public,
                                                DeclarationModifiers.Static),
                        gen.GetAccessorDeclaration(statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource,
                        returnType: gen.TypeExpression(readOnlySpanOfT.Construct(managedElementTypeSymbol.Value)),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination,
                        returnType: gen.TypeExpression(spanOfT.Construct(typeParameters[typeParameters.Length - 1])),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesSource))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesSource,
                        parameters: new[]
                {
                    gen.ParameterDeclaration("numElements", gen.TypeExpression(SpecialType.System_Int32))
                },
                        returnType: gen.TypeExpression(readOnlySpanOfT.Construct(typeParameters[typeParameters.Length - 1])),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination,
                        parameters: new[]
                {
                    gen.ParameterDeclaration("numElements", gen.TypeExpression(SpecialType.System_Int32))
                },
                        returnType: gen.TypeExpression(spanOfT.Construct(managedElementTypeSymbol.Value)),
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            if (missingMemberNames.Contains(ShapeMemberNames.Free))
            {
                newMembers.Add(
                    gen.MethodDeclaration(
                        ShapeMemberNames.Value.Stateful.Free,
                        accessibility: Accessibility.Public,
                        statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }));
            }

            editor.ReplaceNode(declaringSyntax, (declaringSyntax, gen) => gen.AddMembers(declaringSyntax, newMembers));

            SyntaxNode CreateUnmanagedTypeSyntax()
            {
                ITypeSymbol?unmanagedType = null;

                if (methods.ToUnmanaged is not null)
                {
                    unmanagedType = methods.ToUnmanaged.ReturnType;
                }
                else if (methods.FromUnmanaged is not null)
                {
                    unmanagedType = methods.FromUnmanaged.Parameters[0].Type;
                }
                else if (methods.UnmanagedValuesSource is not null)
                {
                    unmanagedType = methods.UnmanagedValuesSource.Parameters[0].Type;
                }
                else if (methods.UnmanagedValuesDestination is not null)
                {
                    unmanagedType = methods.UnmanagedValuesDestination.Parameters[0].Type;
                }

                if (unmanagedType is not null)
                {
                    return(gen.TypeExpression(unmanagedType));
                }
                return(gen.TypeExpression(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_IntPtr)));
            }

            ITypeSymbol CreateManagedElementTypeSymbol()
            {
                if (methods.ManagedValuesSource is not null)
                {
                    return(((INamedTypeSymbol)methods.ManagedValuesSource.ReturnType).TypeArguments[0]);
                }
                if (methods.ManagedValuesDestination is not null)
                {
                    return(((INamedTypeSymbol)methods.ManagedValuesDestination.ReturnType).TypeArguments[0]);
                }

                return(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_IntPtr));
            }
        }
Beispiel #17
0
 internal static bool IsTask([NotNullWhen(true)] ITypeSymbol?typeSymbol) => typeSymbol?.Name == nameof(Task) && typeSymbol.BelongsToNamespace(Namespaces.SystemThreadingTasks);
Beispiel #18
0
 public static bool IsExact([NotNullWhen(true)] this ITypeSymbol?type, string ns0, string name, int arity)
 => type is INamedTypeSymbol nt && nt.Name == name && nt.Arity == arity &&
Beispiel #19
0
        public bool TryCreate(IOperation operation, [NotNullWhen(returnValue: true)] out AnalysisEntity?analysisEntity)
        {
            if (_analysisEntityMap.TryGetValue(operation, out analysisEntity))
            {
                return(analysisEntity != null);
            }

            analysisEntity = null;
            ISymbol?symbol = null;
            ImmutableArray <AbstractIndex> indices = ImmutableArray <AbstractIndex> .Empty;
            IOperation? instance = null;
            ITypeSymbol?type     = operation.Type;

            switch (operation)
            {
            case ILocalReferenceOperation localReference:
                symbol = localReference.Local;
                break;

            case IParameterReferenceOperation parameterReference:
                symbol = parameterReference.Parameter;
                break;

            case IMemberReferenceOperation memberReference:
                instance = memberReference.Instance;
                GetSymbolAndIndicesForMemberReference(memberReference, ref symbol, ref indices);

                // Workaround for https://github.com/dotnet/roslyn/issues/22736 (IPropertyReferenceExpressions in IAnonymousObjectCreationExpression are missing a receiver).
                if (instance == null &&
                    symbol != null &&
                    memberReference is IPropertyReferenceOperation propertyReference)
                {
                    instance = propertyReference.GetAnonymousObjectCreation();
                }

                break;

            case IArrayElementReferenceOperation arrayElementReference:
                instance = arrayElementReference.ArrayReference;
                indices  = CreateAbstractIndices(arrayElementReference.Indices);
                break;

            case IDynamicIndexerAccessOperation dynamicIndexerAccess:
                instance = dynamicIndexerAccess.Operation;
                indices  = CreateAbstractIndices(dynamicIndexerAccess.Arguments);
                break;

            case IConditionalAccessInstanceOperation conditionalAccessInstance:
                IConditionalAccessOperation?conditionalAccess = conditionalAccessInstance.GetConditionalAccess();
                instance = conditionalAccess?.Operation;
                if (conditionalAccessInstance.Parent is IMemberReferenceOperation memberReferenceParent)
                {
                    GetSymbolAndIndicesForMemberReference(memberReferenceParent, ref symbol, ref indices);
                }
                break;

            case IInstanceReferenceOperation instanceReference:
                if (_getPointsToAbstractValue != null)
                {
                    instance = instanceReference.GetInstance(_getIsInsideAnonymousObjectInitializer());
                    if (instance == null)
                    {
                        // Reference to this or base instance.
                        analysisEntity = _interproceduralCallStack != null && _interproceduralCallStack.Peek().DescendantsAndSelf().Contains(instanceReference) ?
                                         _interproceduralThisOrMeInstanceForCaller :
                                         ThisOrMeInstance;
                    }
                    else
                    {
                        var instanceLocation = _getPointsToAbstractValue(instanceReference);
                        analysisEntity = AnalysisEntity.Create(instanceReference, instanceLocation);
                    }
                }
                break;

            case IConversionOperation conversion:
                return(TryCreate(conversion.Operand, out analysisEntity));

            case IParenthesizedOperation parenthesized:
                return(TryCreate(parenthesized.Operand, out analysisEntity));

            case IArgumentOperation argument:
                return(TryCreate(argument.Value, out analysisEntity));

            case IFlowCaptureOperation flowCapture:
                analysisEntity = GetOrCreateForFlowCapture(flowCapture.Id, flowCapture.Value.Type, flowCapture, _getIsLValueFlowCapture(flowCapture));
                break;

            case IFlowCaptureReferenceOperation flowCaptureReference:
                analysisEntity = GetOrCreateForFlowCapture(flowCaptureReference.Id, flowCaptureReference.Type, flowCaptureReference, flowCaptureReference.IsLValueFlowCaptureReference());
                break;

            case IDeclarationExpressionOperation declarationExpression:
                switch (declarationExpression.Expression)
                {
                case ILocalReferenceOperation localReference:
                    return(TryCreateForSymbolDeclaration(localReference.Local, out analysisEntity));

                case ITupleOperation tupleOperation:
                    return(TryCreate(tupleOperation, out analysisEntity));
                }

                break;

            case IVariableDeclaratorOperation variableDeclarator:
                symbol = variableDeclarator.Symbol;
                type   = variableDeclarator.Symbol.Type;
                break;

            case IDeclarationPatternOperation declarationPattern:
                var declaredLocal = declarationPattern.DeclaredSymbol as ILocalSymbol;
                symbol = declaredLocal;
                type   = declaredLocal?.Type;
                break;

            default:
                break;
            }

            if (symbol != null || !indices.IsEmpty)
            {
                TryCreate(symbol, indices, type !, instance, out analysisEntity);
            }

            _analysisEntityMap[operation] = analysisEntity;
            return(analysisEntity != null);
        }
 internal static ExpectedAlternateMethodGroup?GetExpectedAlternateMethodGroup(string operatorName, ITypeSymbol returnType, ITypeSymbol?parameterType)
 {
        // Is a member with declared accessibility "declaredAccessibility" accessible from within
        // "within", which must be a named type or an assembly.
        private static bool IsMemberAccessible(
            INamedTypeSymbol containingType,
            Accessibility declaredAccessibility,
            ISymbol within,
            ITypeSymbol?throughType,
            out bool failedThroughTypeCheck)
        {
            Debug.Assert(within is INamedTypeSymbol || within is IAssemblySymbol);
            Contract.ThrowIfNull(containingType);

            failedThroughTypeCheck = false;

            var originalContainingType = containingType.OriginalDefinition;
            var withinNamedType        = within as INamedTypeSymbol;
            var withinAssembly         = (within as IAssemblySymbol) ?? ((INamedTypeSymbol)within).ContainingAssembly;

            // A nested symbol is only accessible to us if its container is accessible as well.
            if (!IsNamedTypeAccessible(containingType, within))
            {
                return(false);
            }

            switch (declaredAccessibility)
            {
            case Accessibility.NotApplicable:
                // TODO(cyrusn): Is this the right thing to do here?  Should the caller ever be
                // asking about the accessibility of a symbol that has "NotApplicable" as its
                // value?  For now, I'm preserving the behavior of the existing code.  But perhaps
                // we should fail here and require the caller to not do this?
                return(true);

            case Accessibility.Public:
                // Public symbols are always accessible from any context
                return(true);

            case Accessibility.Private:
                // All expressions in the current submission (top-level or nested in a method or
                // type) can access previous submission's private top-level members. Previous
                // submissions are treated like outer classes for the current submission - the
                // inner class can access private members of the outer class.
                if (withinAssembly.IsInteractive && containingType.IsScriptClass)
                {
                    return(true);
                }

                // private members never accessible from outside a type.
                return(withinNamedType != null && IsPrivateSymbolAccessible(withinNamedType, originalContainingType));

            case Accessibility.Internal:
                // An internal type is accessible if we're in the same assembly or we have
                // friend access to the assembly it was defined in.
                return(withinAssembly.IsSameAssemblyOrHasFriendAccessTo(containingType.ContainingAssembly));

            case Accessibility.ProtectedAndInternal:
                if (!withinAssembly.IsSameAssemblyOrHasFriendAccessTo(containingType.ContainingAssembly))
                {
                    // We require internal access.  If we don't have it, then this symbol is
                    // definitely not accessible to us.
                    return(false);
                }

                // We had internal access.  Also have to make sure we have protected access.
                return(IsProtectedSymbolAccessible(withinNamedType, withinAssembly, throughType, originalContainingType, out failedThroughTypeCheck));

            case Accessibility.ProtectedOrInternal:
                if (withinAssembly.IsSameAssemblyOrHasFriendAccessTo(containingType.ContainingAssembly))
                {
                    // If we have internal access to this symbol, then that's sufficient.  no
                    // need to do the complicated protected case.
                    return(true);
                }

                // We don't have internal access.  But if we have protected access then that's
                // sufficient.
                return(IsProtectedSymbolAccessible(withinNamedType, withinAssembly, throughType, originalContainingType, out failedThroughTypeCheck));

            case Accessibility.Protected:
                return(IsProtectedSymbolAccessible(withinNamedType, withinAssembly, throughType, originalContainingType, out failedThroughTypeCheck));

            default:
                throw ExceptionUtilities.UnexpectedValue(declaredAccessibility);
            }
        }
Beispiel #22
0
 public static bool IsDisposable([NotNullWhen(returnValue: true)] this ITypeSymbol?type, [NotNullWhen(returnValue: true)] ITypeSymbol?iDisposableType)
 => iDisposableType != null &&
 (Equals(iDisposableType, type) ||
  type?.AllInterfaces.Contains(iDisposableType) == true);
        /// <summary>
        /// Checks if 'symbol' is accessible from within 'within', which must be a INamedTypeSymbol
        /// or an IAssemblySymbol.  If 'symbol' is accessed off of an expression then
        /// 'throughTypeOpt' is the type of that expression. This is needed to properly do protected
        /// access checks. Sets "failedThroughTypeCheck" to true if this protected check failed.
        /// </summary>
        //// NOTE(cyrusn): I expect this function to be called a lot.  As such, I do not do any memory
        //// allocations in the function itself (including not making any iterators).  This does mean
        //// that certain helper functions that we'd like to call are inlined in this method to
        //// prevent the overhead of returning collections or enumerators.
        private static bool IsSymbolAccessibleCore(
            ISymbol symbol,
            ISymbol within,  // must be assembly or named type symbol
            ITypeSymbol?throughType,
            out bool failedThroughTypeCheck)
        {
            Contract.ThrowIfNull(symbol);
            Contract.ThrowIfNull(within);
            Debug.Assert(within is INamedTypeSymbol || within is IAssemblySymbol);

            failedThroughTypeCheck = false;
            switch (symbol.Kind)
            {
            case SymbolKind.Alias:
                return(IsSymbolAccessibleCore(((IAliasSymbol)symbol).Target, within, throughType, out failedThroughTypeCheck));

            case SymbolKind.ArrayType:
                return(IsSymbolAccessibleCore(((IArrayTypeSymbol)symbol).ElementType, within, null, out failedThroughTypeCheck));

            case SymbolKind.PointerType:
                return(IsSymbolAccessibleCore(((IPointerTypeSymbol)symbol).PointedAtType, within, null, out failedThroughTypeCheck));

            case SymbolKind.FunctionPointerType:
                var funcPtrSignature = ((IFunctionPointerTypeSymbol)symbol).Signature;
                if (!IsSymbolAccessibleCore(funcPtrSignature.ReturnType, within, null, out failedThroughTypeCheck))
                {
                    return(false);
                }

                foreach (var param in funcPtrSignature.Parameters)
                {
                    if (!IsSymbolAccessibleCore(param.Type, within, null, out failedThroughTypeCheck))
                    {
                        return(false);
                    }
                }

                return(true);

            case SymbolKind.NamedType:
                return(IsNamedTypeAccessible((INamedTypeSymbol)symbol, within));

            case SymbolKind.ErrorType:
            case SymbolKind.Discard:
                return(true);

            case SymbolKind.TypeParameter:
            case SymbolKind.Parameter:
            case SymbolKind.Local:
            case SymbolKind.Label:
            case SymbolKind.Namespace:
            case SymbolKind.DynamicType:
            case SymbolKind.Assembly:
            case SymbolKind.NetModule:
            case SymbolKind.RangeVariable:
                // These types of symbols are always accessible (if visible).
                return(true);

            case SymbolKind.Method:
            case SymbolKind.Property:
            case SymbolKind.Field:
            case SymbolKind.Event:
                if (symbol.IsStatic)
                {
                    // static members aren't accessed "through" an "instance" of any type.  So we
                    // null out the "through" instance here.  This ensures that we'll understand
                    // accessing protected statics properly.
                    throughType = null;
                }

                // If this is a synthesized operator of dynamic, it's always accessible.
                if (symbol.IsKind(SymbolKind.Method) &&
                    ((IMethodSymbol)symbol).MethodKind == MethodKind.BuiltinOperator &&
                    symbol.ContainingSymbol.IsKind(SymbolKind.DynamicType))
                {
                    return(true);
                }

                // If it's a synthesized operator on a pointer, use the pointer's PointedAtType.
                // Note: there are currently no synthesized operators on function pointer types. If that
                // ever changes, updated the below assert and fix the code
                Debug.Assert(!(symbol.IsKind(SymbolKind.Method) && ((IMethodSymbol)symbol).MethodKind == MethodKind.BuiltinOperator && symbol.ContainingSymbol.IsKind(SymbolKind.FunctionPointerType)));
                if (symbol.IsKind(SymbolKind.Method) &&
                    ((IMethodSymbol)symbol).MethodKind == MethodKind.BuiltinOperator &&
                    symbol.ContainingSymbol.IsKind(SymbolKind.PointerType))
                {
                    return(IsSymbolAccessibleCore(((IPointerTypeSymbol)symbol.ContainingSymbol).PointedAtType, within, null, out failedThroughTypeCheck));
                }

                return(IsMemberAccessible(symbol.ContainingType, symbol.DeclaredAccessibility, within, throughType, out failedThroughTypeCheck));

            default:
                throw ExceptionUtilities.UnexpectedValue(symbol.Kind);
            }
        }
Beispiel #24
0
 public static bool IsInterfaceType([NotNullWhen(returnValue: true)] this ITypeSymbol?symbol)
 => symbol?.TypeKind == TypeKind.Interface;
Beispiel #25
0
        public static async Task <ImmutableArray <SymbolAndProjectId> > FindImplementationsForInterfaceMemberAsync(
            this SymbolAndProjectId <ITypeSymbol> typeSymbolAndProjectId,
            SymbolAndProjectId interfaceMemberAndProjectId,
            Solution solution,
            CancellationToken cancellationToken)
        {
            // This method can return multiple results.  Consider the case of:
            //
            // interface IGoo<X> { void Goo(X x); }
            //
            // class C : IGoo<int>, IGoo<string> { void Goo(int x); void Goo(string x); }
            //
            // If you're looking for the implementations of IGoo<X>.Goo then you want to find both
            // results in C.

            var arrBuilder = ArrayBuilder <SymbolAndProjectId> .GetInstance();

            var interfaceMember = interfaceMemberAndProjectId.Symbol;

            // TODO(cyrusn): Implement this using the actual code for
            // TypeSymbol.FindImplementationForInterfaceMember
            var typeSymbol = typeSymbolAndProjectId.Symbol;

            if (typeSymbol == null || interfaceMember == null)
            {
                return(arrBuilder.ToImmutableAndFree());
            }

            if (interfaceMember.Kind != SymbolKind.Event &&
                interfaceMember.Kind != SymbolKind.Method &&
                interfaceMember.Kind != SymbolKind.Property)
            {
                return(arrBuilder.ToImmutableAndFree());
            }

            // WorkItem(4843)
            //
            // 'typeSymbol' has to at least implement the interface containing the member.  note:
            // this just means that the interface shows up *somewhere* in the inheritance chain of
            // this type.  However, this type may not actually say that it implements it.  For
            // example:
            //
            // interface I { void Goo(); }
            //
            // class B { }
            //
            // class C : B, I { }
            //
            // class D : C { }
            //
            // D does implement I transitively through C.  However, even if D has a "Goo" method, it
            // won't be an implementation of I.Goo.  The implementation of I.Goo must be from a type
            // that actually has I in it's direct interface chain, or a type that's a base type of
            // that.  in this case, that means only classes C or B.
            var interfaceType = interfaceMember.ContainingType;

            if (!typeSymbol.ImplementsIgnoringConstruction(interfaceType))
            {
                return(arrBuilder.ToImmutableAndFree());
            }

            // We've ascertained that the type T implements some constructed type of the form I<X>.
            // However, we're not precisely sure which constructions of I<X> are being used.  For
            // example, a type C might implement I<int> and I<string>.  If we're searching for a
            // method from I<X> we might need to find several methods that implement different
            // instantiations of that method.
            var originalInterfaceType   = interfaceMember.ContainingType.OriginalDefinition;
            var originalInterfaceMember = interfaceMember.OriginalDefinition;

            var constructedInterfaces = typeSymbol.AllInterfaces.Where(i =>
                                                                       SymbolEquivalenceComparer.Instance.Equals(i.OriginalDefinition, originalInterfaceType));

            // Try to get the compilation for the symbol we're searching for,
            // which can help identify matches with the call to SymbolFinder.OriginalSymbolsMatch.
            // OriginalSymbolMatch allows types to be matched across different assemblies
            // if they are considered to be the same type, which provides a more accurate
            // implementations list for interfaces.
            var typeSymbolProject      = solution.GetProject(typeSymbolAndProjectId.ProjectId);
            var interfaceMemberProject = solution.GetProject(interfaceMemberAndProjectId.ProjectId);

            var typeSymbolCompilation = await GetCompilationOrNullAsync(typeSymbolProject, cancellationToken).ConfigureAwait(false);

            var interfaceMemberCompilation = await GetCompilationOrNullAsync(interfaceMemberProject, cancellationToken).ConfigureAwait(false);

            foreach (var constructedInterface in constructedInterfaces)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var constructedInterfaceMember = constructedInterface.GetMembers().FirstOrDefault(typeSymbol =>
                                                                                                  SymbolFinder.OriginalSymbolsMatch(
                                                                                                      typeSymbol,
                                                                                                      interfaceMember,
                                                                                                      solution,
                                                                                                      typeSymbolCompilation,
                                                                                                      interfaceMemberCompilation,
                                                                                                      cancellationToken));

                if (constructedInterfaceMember == null)
                {
                    continue;
                }

                // Now we need to walk the base type chain, but we start at the first type that actually
                // has the interface directly in its interface hierarchy.
                var seenTypeDeclaringInterface = false;
                for (ITypeSymbol?currentType = typeSymbol; currentType != null; currentType = currentType.BaseType)
                {
                    seenTypeDeclaringInterface = seenTypeDeclaringInterface ||
                                                 currentType.GetOriginalInterfacesAndTheirBaseInterfaces().Contains(interfaceType.OriginalDefinition);

                    if (seenTypeDeclaringInterface)
                    {
                        var result = currentType.FindImplementations(constructedInterfaceMember, solution.Workspace);

                        if (result != null)
                        {
                            arrBuilder.Add(typeSymbolAndProjectId.WithSymbol(result));
                            break;
                        }
                    }
                }
            }

            return(arrBuilder.ToImmutableAndFree());
Beispiel #26
0
 public static bool IsDelegateType([NotNullWhen(returnValue: true)] this ITypeSymbol?symbol)
 => symbol?.TypeKind == TypeKind.Delegate;
 public static bool IsSystemVoid([NotNullWhen(returnValue: true)] this ITypeSymbol?symbol)
 => symbol?.SpecialType == SpecialType.System_Void;
Beispiel #28
0
 public static bool IsStructType([NotNullWhen(returnValue: true)] this ITypeSymbol?symbol)
 => symbol?.TypeKind == TypeKind.Struct;
 public static bool IsEnumType([NotNullWhen(true)] this ITypeSymbol?type)
 => IsEnumType(type, out _);
Beispiel #30
0
 private static bool IsTypeAnObjectArray(ITypeSymbol?typeSymbol)
 {
     return(typeSymbol != null && typeSymbol.TypeKind == TypeKind.Array &&
            ((IArrayTypeSymbol)typeSymbol).ElementType.SpecialType == SpecialType.System_Object);
 }