private static IMethodSymbol GetContractClassMethod(ITypeSymbol contractClassType, IMethodSymbol baseTypeMethod) { if (baseTypeMethod.ContainingType.TypeKind == TypeKind.Interface) { if (contractClassType is INamedTypeSymbol namedcontractClassType && namedcontractClassType.IsGenericType) { if (baseTypeMethod.ContainingType is INamedTypeSymbol baseNamed && baseNamed.IsGenericType) { var constructed = baseNamed.ConstructedFrom.Construct(namedcontractClassType.TypeArguments.ToArray()); baseTypeMethod = constructed.GetMembers().OfType <IMethodSymbol>().First(o => o.OriginalDefinition.Equals(baseTypeMethod.OriginalDefinition)); } return(contractClassType.FindImplementationForInterfaceMember(baseTypeMethod) as IMethodSymbol); } return(contractClassType.FindImplementationForInterfaceMember(baseTypeMethod) as IMethodSymbol); } else if (baseTypeMethod.ContainingType.TypeKind == TypeKind.Class) { if (contractClassType is INamedTypeSymbol namedcontractClassType && namedcontractClassType.IsGenericType) { return(contractClassType.GetMembers().OfType <IMethodSymbol>().FirstOrDefault(o => o.IsOverride && o.OverriddenMethod.OriginalDefinition.Equals(baseTypeMethod.OriginalDefinition))); } return(contractClassType.GetMembers().OfType <IMethodSymbol>().FirstOrDefault(o => o.IsOverride && o.OverriddenMethod.Equals(baseTypeMethod))); } return(null); }
/// <summary> /// Checks whether the <paramref name="symbol" />'s implementing member for <paramref name="interfaceMember" /> has the /// correct port kind. /// </summary> /// <param name="context">The context in which the analysis should be performed.</param> /// <param name="symbol">The symbol that should be analyzed.</param> /// <param name="compilation">The compilation the symbol is declared in.</param> /// <param name="interfaceMember">The interface member that should be checked.</param> private static void CheckMember(SymbolAnalysisContext context, ITypeSymbol symbol, Compilation compilation, ISymbol interfaceMember) { var implementingMember = symbol.FindImplementationForInterfaceMember(interfaceMember); var interfaceIsRequired = interfaceMember.HasAttribute <RequiredAttribute>(compilation); var interfaceIsProvided = interfaceMember.HasAttribute <ProvidedAttribute>(compilation); var implementationIsRequired = implementingMember.HasAttribute <RequiredAttribute>(compilation) || implementingMember.IsExtern; var implementationIsProvided = implementingMember.HasAttribute <ProvidedAttribute>(compilation) || !implementingMember.IsExtern; // If we can't uniquely classify the port kind of either the interface member or the implementation, // there is another problem that another analyzer deals with. So let's just ignore it here. if ((interfaceIsRequired && interfaceIsProvided) || (implementationIsProvided && implementationIsRequired)) { return; } var location = implementingMember.ContainingType.Equals(symbol) ? implementingMember : symbol; if (interfaceIsRequired && !implementationIsRequired) { _requiredPortImplementedAsProvidedPort.Emit(context, location, implementingMember.ToDisplayString(), interfaceMember.ToDisplayString()); } if (interfaceIsProvided && !implementationIsProvided) { _providedPortImplementedAsRequiredPort.Emit(context, location, implementingMember.ToDisplayString(), interfaceMember.ToDisplayString()); } }
public static ImmutableArray <IMethodSymbol> GetImplementedMethods( this IMethodSymbol method ) { if (method.ExplicitInterfaceImplementations.Length > 0) { return(method.ExplicitInterfaceImplementations); } ITypeSymbol type = method.ContainingType; var result = ImmutableArray.CreateBuilder <IMethodSymbol>(); result.AddRange( type.AllInterfaces .SelectMany(i => i.GetMembers(method.Name).OfType <IMethodSymbol>()) .Where(m => method.Equals(type.FindImplementationForInterfaceMember(m), SymbolEqualityComparer.Default)) );; // Check OverriddenMethod != null instead of IsOverride // because "override void Foo() {}" will have IsOverride == true // even if there isn't a Foo to override if (method.OverriddenMethod != null) { result.Add(method.OverriddenMethod); } return(result.ToImmutable()); }
internal static void GenerateMissingEvents(ClassDeclarationSyntax classDeclaration, ITypeSymbol interfaceType, ITypeSymbol classType, DocumentEditor editor, SyntaxGenerator gen) { foreach (var eventSymbol in interfaceType.GetMembers(). OfType <IEventSymbol>()) { if (classType.FindImplementationForInterfaceMember(eventSymbol) != null) { continue; } editor.AddMember(classDeclaration, GenerateEvent(gen, eventSymbol)); } }
private static bool CanRefactor( TypeSyntax type, ExpressionSyntax expression, ExpressionSyntax accessedExpression, SemanticModel semanticModel, CancellationToken cancellationToken) { ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, cancellationToken); if (typeSymbol?.IsErrorType() == false) { ITypeSymbol expressionTypeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken); if (expressionTypeSymbol?.IsErrorType() == false && !expressionTypeSymbol.IsInterface()) { bool isInterface = typeSymbol.IsInterface(); if (isInterface || typeSymbol.EqualsOrInheritsFrom(expressionTypeSymbol, includeInterfaces: true)) { ISymbol accessedSymbol = semanticModel.GetSymbol(accessedExpression, cancellationToken); INamedTypeSymbol containingType = accessedSymbol?.ContainingType; if (containingType != null) { if (isInterface) { ISymbol implementation = expressionTypeSymbol.FindImplementationForInterfaceMember(accessedSymbol); switch (implementation?.Kind) { case SymbolKind.Property: return(!((IPropertySymbol)implementation).ExplicitInterfaceImplementations.Any(f => f.Equals(accessedSymbol))); case SymbolKind.Method: return(!((IMethodSymbol)implementation).ExplicitInterfaceImplementations.Any(f => f.Equals(accessedSymbol))); } } else { return(expressionTypeSymbol.EqualsOrInheritsFrom(containingType, includeInterfaces: true)); } } } } } return(false); }
internal static void GenerateMissingProperties(ClassDeclarationSyntax classDeclaration, ITypeSymbol interfaceType, ITypeSymbol classType, DocumentEditor editor, SyntaxGenerator gen) { foreach (var propertySymbol in interfaceType.GetMembers(). OfType <IPropertySymbol>()) { if (classType.FindImplementationForInterfaceMember(propertySymbol) != null) { continue; } editor.AddMember(classDeclaration, GenerateProperty(gen, propertySymbol, Constants.ImplementationFieldName)); } }
public static bool IsMemberImplemented(this ITypeSymbol @this, ISymbol member) { ISymbol?implementation = @this.FindImplementationForInterfaceMember(member); if (implementation is null || implementation.IsStatic || !implementation.ContainingType.Equals(@this, SymbolEqualityComparer.Default)) { return(false); } return(implementation switch { IMethodSymbol methodImplementation => methodImplementation.MethodKind == MethodKind.ExplicitInterfaceImplementation, IPropertySymbol propertyImplementation => propertyImplementation.ExplicitInterfaceImplementations.Any(), IEventSymbol eventImplementation => eventImplementation.ExplicitInterfaceImplementations.Any(), _ => false, });
public static IMethodSymbol GetInterfaceImplementation(this ITypeSymbol type, IMethodSymbol interfaceMethod) { if (SymbolEqualityComparer.Default.Equals(type, interfaceMethod.ContainingType)) { return(interfaceMethod); } var result = type.FindImplementationForInterfaceMember(interfaceMethod); if (result == null) { throw new ArgumentNullException(nameof(interfaceMethod)); } return((IMethodSymbol)result); }
private static bool IsExplicitlyImplemented( ITypeSymbol classOrStructType, ISymbol member, out ISymbol typeMember) { if (member != null && member.ContainingType.IsInterfaceType()) { typeMember = classOrStructType?.FindImplementationForInterfaceMember(member); return(typeMember is IPropertySymbol property && property.ExplicitInterfaceImplementations.Length > 0 && property.DeclaredAccessibility == Accessibility.Private); } typeMember = member; return(false); }
private static bool CheckExplicitImplementation(ITypeSymbol typeSymbol, ISymbol symbol) { ISymbol implementation = typeSymbol.FindImplementationForInterfaceMember(symbol); if (implementation == null) { return(false); } switch (implementation.Kind) { case SymbolKind.Property: { foreach (IPropertySymbol propertySymbol in ((IPropertySymbol)implementation).ExplicitInterfaceImplementations) { if (propertySymbol.Equals(symbol)) { return(false); } } break; } case SymbolKind.Method: { foreach (IMethodSymbol methodSymbol in ((IMethodSymbol)implementation).ExplicitInterfaceImplementations) { if (methodSymbol.Equals(symbol)) { return(false); } } break; } default: { Debug.Fail(implementation.Kind.ToString()); return(false); } } return(true); }
internal static void GenerateMissingMethods(ClassDeclarationSyntax classDeclaration, ITypeSymbol interfaceType, ITypeSymbol classType, DocumentEditor editor, SyntaxGenerator gen, SemanticModel model, int minificationLocation, bool includeAsyncAwait) { foreach (var member in interfaceType.GetMembers(). OfType <IMethodSymbol>(). Where(m => m.MethodKind == MethodKind.Ordinary)) { if (classType.FindImplementationForInterfaceMember(member) != null) { continue; } editor.AddMember(classDeclaration, GenerateMethodImplementation(gen, model, minificationLocation, member, Constants.ImplementationFieldName, includeAsyncAwait)); } }
private IEnumerable <CCodeUnit> BuildUnit(ITypeSymbol type, IAssembliesInfoResolver assembliesInfoResolver) { var unit = new CCodeUnit(type); var isNotModule = type.Name != "<Module>"; var isNotInterfaceOrModule = isNotModule && type.TypeKind != TypeKind.Interface; var methodSymbols = type.GetMembers().OfType <IMethodSymbol>().ToList(); var hasStaticConstructor = methodSymbols.Any(m => m.MethodKind == MethodKind.StaticConstructor); foreach (var field in type.GetMembers().OfType <IFieldSymbol>()) { this.BuildField(field, unit, hasStaticConstructor); } foreach (var @event in type.GetMembers().OfType <IEventSymbol>()) { this.BuildField(new FieldImpl(@event), unit, hasStaticConstructor); } if (hasStaticConstructor) { BuildStaticConstructorVariables(type, unit); } if (isNotModule) { ////BuildTypeHolderVariables(type, unit); BuildTypeDescriptorVariables(type, unit); } var constructors = methodSymbols.Where(m => m.MethodKind == MethodKind.Constructor); foreach (var method in constructors) { this.BuildMethod(method, unit); } var finalizationRequired = type.BaseType != null && type.GetMembers().OfType <IMethodSymbol>().Any(m => m.MethodKind == MethodKind.Destructor); var isAtomicType = type.IsAtomicType(); var namedTypeSymbol = (INamedTypeSymbol)type; if (isNotInterfaceOrModule) { unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, debugVersion: true)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, true)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, true, true)); } if (!isAtomicType && type.TypeKind != TypeKind.Interface) { unit.Declarations.Add(new CCodeGetTypeDescriptorDeclaration(namedTypeSymbol)); } if (type.IsPrimitiveValueType() || type.TypeKind == TypeKind.Enum) { unit.Declarations.Add(new CCodeSpecialTypeOrEnumConstructorDeclaration(namedTypeSymbol, false)); } /* * if (type.IsIntPtrType()) * { * unit.Declarations.Add(new CCodeSpecialTypeOrEnumConstructorDeclaration((INamedTypeSymbol)type, true)); * } */ // to support RuntimeType initialization if (type.IsRuntimeType()) { unit.Declarations.Add(new CCodeRuntimeTypeConstructorDeclaration(namedTypeSymbol, true)); } if (type.IsPrimitiveValueType() || type.TypeKind == TypeKind.Enum || type.IsIntPtrType()) { unit.Declarations.Add(new CCodeCastOperatorDeclaration(namedTypeSymbol)); } if (type.TypeKind == TypeKind.Struct) { unit.Declarations.Add(new CCodeArrowOperatorDeclaration(namedTypeSymbol)); } if (isNotInterfaceOrModule) { // add internal infrustructure unit.Declarations.Add(new CCodeGetTypeVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeGetTypeVirtualMethodDefinition(namedTypeSymbol)); unit.Declarations.Add(new CCodeIsTypeVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeIsTypeVirtualMethodDefinition(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetInterfaceVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeGetInterfaceVirtualMethodDefinition(namedTypeSymbol)); if (!type.IsAbstract) { unit.Declarations.Add(new CCodeCloneVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetSizeVirtualMethod(namedTypeSymbol)); } if (type.SpecialType == SpecialType.System_Object) { unit.Declarations.Add(new CCodeHashVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeEqualsVirtualMethod(namedTypeSymbol)); } } if (type.TypeKind == TypeKind.Interface) { unit.Declarations.Add(new CCodeObjectCastOperatorDeclaration(namedTypeSymbol)); } if (type.SpecialType == SpecialType.System_Array) { unit.Declarations.Add(new CCodeNewOperatorPointerDeclaration(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetArrayElementSizeVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeIsPrimitiveTypeArrayVirtualMethod(namedTypeSymbol)); } if (type.TypeKind == TypeKind.Interface) { // add all methods from all interfaces foreach (var method in type.EnumerateInterfaceMethods()) { unit.Declarations.Add(new CCodeMethodDeclaration(type, method)); } } foreach (var method in methodSymbols.Where(m => m.MethodKind != MethodKind.Constructor)) { this.BuildMethod(method, unit); } if (isNotModule) { BuildMethodTableVariables(type, unit); ////BuildRuntimeInfoVariables(type, unit); } if (isNotInterfaceOrModule) { // append interface calls foreach (var interfaceMethod in type.EnumerateInterfaceMethods()) { var method = interfaceMethod; var implementationForInterfaceMember = type.FindImplementationForInterfaceMember(interfaceMethod) as IMethodSymbol; if (implementationForInterfaceMember != null && implementationForInterfaceMember.ExplicitInterfaceImplementations.Any(ei => ei.Equals(method))) { continue; } Debug.Assert(implementationForInterfaceMember != null, "Method for interface can't be found"); unit.Declarations.Add(new CCodeInterfaceMethodAdapterDeclaration(type, interfaceMethod, implementationForInterfaceMember)); unit.Definitions.Add(new CCodeInterfaceMethodAdapterDefinition(type, interfaceMethod, implementationForInterfaceMember)); } } yield return(unit); if (!isNotModule) { yield break; } // return type holder class var typeHolderType = (TypeImpl)TypeImpl.Wrap(type); if (!type.IsAnonymousType()) { typeHolderType.Name = typeHolderType.Name + "__type"; typeHolderType.MetadataName = typeHolderType.MetadataName + "__type"; } else { var namedType = (INamedTypeSymbol)type; typeHolderType.Name = namedType.GetAnonymousTypeName() + "__type"; typeHolderType.MetadataName = namedType.GetAnonymousTypeName() + "__type"; } typeHolderType.BaseType = null; typeHolderType.TypeKind = TypeKind.Struct; typeHolderType.Interfaces = ImmutableArray <INamedTypeSymbol> .Empty; typeHolderType.AllInterfaces = ImmutableArray <INamedTypeSymbol> .Empty; typeHolderType.SpecialType = SpecialType.None; var unitTypeHolder = new CCodeUnit(typeHolderType); BuildTypeHolderVariables(typeHolderType, unitTypeHolder); ////BuildMethodTableVariables(typeHolderType, unitTypeHolder); BuildRuntimeInfoVariables(typeHolderType, type, unitTypeHolder); yield return(unitTypeHolder); }
/// <summary> /// Determines whether the specified invocation target implements <see cref="System.Collections.ICollection"/>. /// </summary> /// <param name="invocationTarget">The invocation target.</param> /// <returns><see langword="true" /> if the specified invocation target implements <see cref="System.Collections.ICollection"/>; otherwise, <see langword="false" />.</returns> internal bool IsICollectionImplementation(ITypeSymbol invocationTarget) => this.ICollectionCountProperty is object && invocationTarget.FindImplementationForInterfaceMember(this.ICollectionCountProperty) is IPropertySymbol countProperty &&
/// <summary> /// Checks whether the <paramref name="symbol" />'s implementing member for <paramref name="interfaceMember" /> has the /// correct port kind. /// </summary> /// <param name="context">The context in which the analysis should be performed.</param> /// <param name="symbol">The symbol that should be analyzed.</param> /// <param name="compilation">The compilation the symbol is declared in.</param> /// <param name="interfaceMember">The interface member that should be checked.</param> private static void CheckMember(SymbolAnalysisContext context, ITypeSymbol symbol, Compilation compilation, ISymbol interfaceMember) { var implementingMember = symbol.FindImplementationForInterfaceMember(interfaceMember); var interfaceIsRequired = interfaceMember.HasAttribute<RequiredAttribute>(compilation); var interfaceIsProvided = interfaceMember.HasAttribute<ProvidedAttribute>(compilation); var implementationIsRequired = implementingMember.HasAttribute<RequiredAttribute>(compilation) || implementingMember.IsExtern; var implementationIsProvided = implementingMember.HasAttribute<ProvidedAttribute>(compilation) || !implementingMember.IsExtern; // If we can't uniquely classify the port kind of either the interface member or the implementation, // there is another problem that another analyzer deals with. So let's just ignore it here. if ((interfaceIsRequired && interfaceIsProvided) || (implementationIsProvided && implementationIsRequired)) return; var location = implementingMember.ContainingType.Equals(symbol) ? implementingMember : symbol; if (interfaceIsRequired && !implementationIsRequired) { _requiredPortImplementedAsProvidedPort.Emit(context, location, implementingMember.ToDisplayString(), interfaceMember.ToDisplayString()); } if (interfaceIsProvided && !implementationIsProvided) { _providedPortImplementedAsRequiredPort.Emit(context, location, implementingMember.ToDisplayString(), interfaceMember.ToDisplayString()); } }
private CCodeUnit BuildUnit(ITypeSymbol type, IAssembliesInfoResolver assembliesInfoResolver) { var unit = new CCodeUnit(type); var methodSymbols = type.GetMembers().OfType <IMethodSymbol>().ToList(); var hasStaticConstructor = methodSymbols.Any(m => m.MethodKind == MethodKind.StaticConstructor); foreach (var field in type.GetMembers().OfType <IFieldSymbol>()) { this.BuildField(field, unit, hasStaticConstructor); } if (hasStaticConstructor) { BuildStaticConstructorVariables(type, unit); } if (type.Name != "<Module>") { BuildTypeHolderVariables(type, unit); } var constructors = methodSymbols.Where(m => m.MethodKind == MethodKind.Constructor); foreach (var method in constructors) { this.BuildMethod(method, unit); } if (type.TypeKind != TypeKind.Interface && type.BaseType == null && type.Name != "<Module>") { unit.Declarations.Add(new CCodeNewOperatorDeclaration((INamedTypeSymbol)type)); unit.Declarations.Add(new CCodeNewOperatorWithSizeDeclaration((INamedTypeSymbol)type)); } if (type.IsPrimitiveValueType() || type.TypeKind == TypeKind.Enum) { unit.Declarations.Add(new CCodeSpecialTypeOrEnumConstructorDeclaration((INamedTypeSymbol)type)); } if (type.IsPrimitiveValueType() || type.TypeKind == TypeKind.Enum || type.IsIntPtrType()) { unit.Declarations.Add(new CCodeCastOperatorDeclaration((INamedTypeSymbol)type)); } if (type.TypeKind == TypeKind.Struct) { unit.Declarations.Add(new CCodeArrowOperatorDeclaration((INamedTypeSymbol)type)); } if (type.Name != "<Module>" && type.TypeKind != TypeKind.Interface) { // add internal infrustructure unit.Declarations.Add(new CCodeGetTypeVirtualMethodDeclaration((INamedTypeSymbol)type)); unit.Definitions.Add(new CCodeGetTypeVirtualMethodDefinition((INamedTypeSymbol)type)); unit.Declarations.Add(new CCodeIsTypeVirtualMethodDeclaration((INamedTypeSymbol)type)); unit.Definitions.Add(new CCodeIsTypeVirtualMethodDefinition((INamedTypeSymbol)type)); unit.Declarations.Add(new CCodeGetInterfaceVirtualMethodDeclaration((INamedTypeSymbol)type)); unit.Definitions.Add(new CCodeGetInterfaceVirtualMethodDefinition((INamedTypeSymbol)type)); if (!type.IsAbstract) { unit.Declarations.Add(new CCodeCloneVirtualMethod((INamedTypeSymbol)type)); } } if (type.TypeKind == TypeKind.Interface) { unit.Declarations.Add(new CCodeObjectCastOperatorDeclaration((INamedTypeSymbol)type)); } if (type.SpecialType == SpecialType.System_Array) { unit.Declarations.Add(new CCodeGetArrayElementSizeVirtualMethod((INamedTypeSymbol)type)); } if (type.TypeKind == TypeKind.Interface) { // add all methods from all interfaces foreach (var method in type.AllInterfaces.SelectMany(i => i.GetMembers().OfType <IMethodSymbol>())) { unit.Declarations.Add(new CCodeMethodDeclaration(method)); } } foreach (var method in methodSymbols.Where(m => m.MethodKind != MethodKind.Constructor)) { this.BuildMethod(method, unit); } if (type.TypeKind != TypeKind.Interface) { // append interface calls foreach (var interfaceMethod in type.AllInterfaces.SelectMany(i => i.GetMembers().OfType <IMethodSymbol>())) { var method = interfaceMethod; var implementationForInterfaceMember = type.FindImplementationForInterfaceMember(interfaceMethod) as IMethodSymbol; if (implementationForInterfaceMember != null && implementationForInterfaceMember.ExplicitInterfaceImplementations.Any(ei => ei.Equals(method))) { continue; } Debug.Assert(implementationForInterfaceMember != null, "Method for interface can't be found"); unit.Declarations.Add(new CCodeInterfaceMethodAdapterDeclaration(interfaceMethod, implementationForInterfaceMember)); unit.Definitions.Add(new CCodeInterfaceMethodAdapterDefinition(type, interfaceMethod, implementationForInterfaceMember)); } } return(unit); }
private static bool ImplementationMissing(ITypeSymbol parentClass, ISymbol i) => parentClass.FindImplementationForInterfaceMember(i) == null;