Exemple #1
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;

            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(span.Start);

            if (!token.Span.IntersectsWith(span))
            {
                return;
            }

            var service = document.GetRequiredLanguageService <IImplementInterfaceService>();
            var model   = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var options = ImplementTypeOptions.From(document.Project);

            var actions = token.Parent.GetAncestorsOrThis <TypeSyntax>()
                          .Where(_interfaceName)
                          .Select(n => service.GetCodeActions(document, options, model, n, cancellationToken))
                          .FirstOrDefault(a => !a.IsEmpty);

            if (actions.IsDefaultOrEmpty)
            {
                return;
            }

            context.RegisterFixes(actions, context.Diagnostics);
        }
 public static ImplementInterfaceCodeAction CreateImplementRemainingExplicitlyCodeAction(
     AbstractImplementInterfaceService service,
     Document document,
     ImplementTypeOptions options,
     State state)
 {
     return(new ImplementInterfaceCodeAction(service, document, options, state, explicitly: true, abstractly: false, onlyRemaining: true, throughMember: null));
 }
        private IEnumerable <CodeAction> GetActions(Document document, ImplementTypeOptions options, State state)
        {
            if (state == null)
            {
                yield break;
            }

            if (state.MembersWithoutExplicitOrImplicitImplementationWhichCanBeImplicitlyImplemented.Length > 0)
            {
                yield return(ImplementInterfaceCodeAction.CreateImplementCodeAction(this, document, options, state));

                if (ShouldImplementDisposePattern(state, explicitly: false))
                {
                    yield return(ImplementInterfaceWithDisposePatternCodeAction.CreateImplementWithDisposePatternCodeAction(this, document, options, state));
                }

                var delegatableMembers = GetDelegatableMembers(state);
                foreach (var member in delegatableMembers)
                {
                    yield return(ImplementInterfaceCodeAction.CreateImplementThroughMemberCodeAction(this, document, options, state, member));
                }

                if (state.ClassOrStructType.IsAbstract)
                {
                    yield return(ImplementInterfaceCodeAction.CreateImplementAbstractlyCodeAction(this, document, options, state));
                }
            }

            if (state.MembersWithoutExplicitImplementation.Length > 0)
            {
                yield return(ImplementInterfaceCodeAction.CreateImplementExplicitlyCodeAction(this, document, options, state));

                if (ShouldImplementDisposePattern(state, explicitly: true))
                {
                    yield return(ImplementInterfaceWithDisposePatternCodeAction.CreateImplementExplicitlyWithDisposePatternCodeAction(this, document, options, state));
                }
            }

            if (AnyImplementedImplicitly(state))
            {
                yield return(ImplementInterfaceCodeAction.CreateImplementRemainingExplicitlyCodeAction(this, document, options, state));
            }
        }
 internal ImplementInterfaceCodeAction(
     AbstractImplementInterfaceService service,
     Document document,
     ImplementTypeOptions options,
     State state,
     bool explicitly,
     bool abstractly,
     bool onlyRemaining,
     ISymbol throughMember)
 {
     Service         = service;
     Document        = document;
     Options         = options;
     State           = state;
     Abstractly      = abstractly;
     _onlyRemaining  = onlyRemaining;
     Explicitly      = explicitly;
     ThroughMember   = throughMember;
     _equivalenceKey = ComputeEquivalenceKey(state, explicitly, abstractly, onlyRemaining, throughMember, GetType().FullName);
 }
        public async Task <Document> ImplementInterfaceAsync(Document document, ImplementTypeOptions options, SyntaxNode node, CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.Refactoring_ImplementInterface, cancellationToken))
            {
                var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                var state = State.Generate(this, document, model, node, cancellationToken);
                if (state == null)
                {
                    return(document);
                }

                // While implementing just one default action, like in the case of pressing enter after interface name in VB,
                // choose to implement with the dispose pattern as that's the Dev12 behavior.
                var action = ShouldImplementDisposePattern(state, explicitly: false)
                    ? ImplementInterfaceWithDisposePatternCodeAction.CreateImplementWithDisposePatternCodeAction(this, document, options, state)
                    : ImplementInterfaceCodeAction.CreateImplementCodeAction(this, document, options, state);

                return(await action.GetUpdatedDocumentAsync(cancellationToken).ConfigureAwait(false));
            }
        }
        private IEnumerable <CodeAction> GetActions(Document document, ImplementTypeOptions options, State state)
        {
            if (state == null)
            {
                yield break;
            }

            if (state.MembersWithoutExplicitOrImplicitImplementationWhichCanBeImplicitlyImplemented.Length > 0)
            {
                var totalMemberCount        = 0;
                var inaccessibleMemberCount = 0;

                foreach (var(_, members) in state.MembersWithoutExplicitOrImplicitImplementationWhichCanBeImplicitlyImplemented)
                {
                    foreach (var member in members)
                    {
                        totalMemberCount++;

                        if (AccessibilityHelper.IsLessAccessibleThan(member, state.ClassOrStructType))
                        {
                            inaccessibleMemberCount++;
                        }
                    }
                }

                // If all members to implement are inaccessible, then "Implement interface" codeaction
                // will be the same as "Implement interface explicitly", so there is no point in having both of them
                if (totalMemberCount != inaccessibleMemberCount)
                {
                    yield return(ImplementInterfaceCodeAction.CreateImplementCodeAction(this, document, options, state));
                }

                if (ShouldImplementDisposePattern(state, explicitly: false))
                {
                    yield return(ImplementInterfaceWithDisposePatternCodeAction.CreateImplementWithDisposePatternCodeAction(this, document, options, state));
                }

                var delegatableMembers = GetDelegatableMembers(state);
                foreach (var member in delegatableMembers)
                {
                    yield return(ImplementInterfaceCodeAction.CreateImplementThroughMemberCodeAction(this, document, options, state, member));
                }

                if (state.ClassOrStructType.IsAbstract)
                {
                    yield return(ImplementInterfaceCodeAction.CreateImplementAbstractlyCodeAction(this, document, options, state));
                }
            }

            if (state.MembersWithoutExplicitImplementation.Length > 0)
            {
                yield return(ImplementInterfaceCodeAction.CreateImplementExplicitlyCodeAction(this, document, options, state));

                if (ShouldImplementDisposePattern(state, explicitly: true))
                {
                    yield return(ImplementInterfaceWithDisposePatternCodeAction.CreateImplementExplicitlyWithDisposePatternCodeAction(this, document, options, state));
                }
            }

            if (AnyImplementedImplicitly(state))
            {
                yield return(ImplementInterfaceCodeAction.CreateImplementRemainingExplicitlyCodeAction(this, document, options, state));
            }
        }
        public ImmutableArray <CodeAction> GetCodeActions(Document document, ImplementTypeOptions options, SemanticModel model, SyntaxNode node, CancellationToken cancellationToken)
        {
            var state = State.Generate(this, document, model, node, cancellationToken);

            return(GetActions(document, options, state).ToImmutableArray());
        }
Exemple #8
0
 public IEntityBase ImplementToNewType(PersistentTypeKind newTypeKind, string newTypeName,
                                       ImplementTypeOptions options)
 {
     throw new NotImplementedException();
 }
Exemple #9
0
 public void ImplementToType(IEntityBase targetType, ImplementTypeOptions options)
 {
     throw new NotImplementedException();
 }
Exemple #10
0
 public void ImplementToType(IEntityBase targetType, ImplementTypeOptions options)
 {
     this.Store.MakeActionWithinTransaction(string.Format("Implementing interface '{0}' to existing type '{1}'",
                                                          this.Name, targetType.Name), () => InternalImplementToType(targetType, options));
 }
Exemple #11
0
        public IEntityBase ImplementToNewType(PersistentTypeKind newTypeKind, string newTypeName, ImplementTypeOptions options)
        {
            if (!newTypeKind.In(PersistentTypeKind.Entity, PersistentTypeKind.Structure))
            {
                throw new ArgumentOutOfRangeException("newTypeKind", "Interface can be implemented only be Entities or Structures!");
            }

            EntityBase newEntity = null;

            this.Store.MakeActionWithinTransaction(string.Format("Implementing new '{0}': {1} from interface '{2}'",
                                                                 newTypeName, newTypeKind, this.Name),
                                                   delegate
            {
                newEntity = newTypeKind == PersistentTypeKind.Entity
                                            ? (EntityBase) new Entity(this.Partition)
                                            : new Structure(this.Partition);

                newEntity.Access        = this.Access;
                newEntity.Documentation = this.Documentation;
                newEntity.Name          = newTypeName;

                this.EntityModel.PersistentTypes.Add(newEntity);

                InternalImplementToType(newEntity, options);
            });

            return(newEntity);
        }
Exemple #12
0
        private void InternalImplementToType(IEntityBase targetType, ImplementTypeOptions options)
        {
            EntityBase entityBase = (EntityBase)targetType;

            List <PropertyBase> addedProperties = new List <PropertyBase>();

            foreach (PropertyBase property in this.Properties)
            {
                if (!entityBase.ContainsProperty(property.PropertyKind, property.Name))
                {
                    PropertyBase copiedProperty =
                        (PropertyBase)property.Copy(new[] { PersistentTypeHasProperties.PersistentTypeDomainRoleId });
                    entityBase.Properties.Add(copiedProperty);
                    addedProperties.Add(copiedProperty);
                }
            }

            foreach (NavigationProperty navigationProperty in this.NavigationProperties)
            {
                if (!entityBase.ContainsProperty(PropertyKind.Navigation, navigationProperty.Name))
                {
                    NavigationProperty copiedNavigationProperty = (NavigationProperty)navigationProperty.Copy(new[]
                    {
                        PersistentTypeHasNavigationProperties.PersistentTypeOfNavigationPropertyDomainRoleId,
                    });
                    entityBase.NavigationProperties.Add(copiedNavigationProperty);
                    copiedNavigationProperty.PersistentTypeHasAssociations.SourcePersistentType = entityBase;
                    addedProperties.Add(copiedNavigationProperty);
                }
            }

            foreach (EntityIndex entityIndex in this.Indexes)
            {
                if (!entityBase.ContainsIndex(entityIndex))
                {
                    EntityIndex copiedIndex =
                        (EntityIndex)entityIndex.Copy(new[] { InterfaceHasIndexes.InterfaceOfIndexDomainRoleId });
                    entityBase.Indexes.Add(copiedIndex);
                }
            }

            if (Util.IsFlagSet(ImplementTypeOptions.CopyInheritedInterfaces, options))
            {
                foreach (Interface inheritedInterface in this.InheritedInterfaces)
                {
                    if (!entityBase.InheritedInterfaces.Contains(inheritedInterface))
                    {
                        entityBase.InheritedInterfaces.Add(inheritedInterface);
                    }
                }
            }

            if (!targetType.InheritedInterfaces.Contains(this))
            {
                entityBase.InheritedInterfaces.Add(this);
            }

            var duplicatedInfo = PersistentTypeValidation.FindDuplicatedPropertieInInheritanceTree(targetType, null);

            foreach (var addedProperty in addedProperties)
            {
                Func <IPropertyBase, bool> foundPropertyFunc =
                    item => item.PropertyKind == addedProperty.PropertyKind &&
                    Util.StringEqual(item.Name, addedProperty.Name, true);

                addedProperty.IsInherited =
                    duplicatedInfo.PropertiesWithDifferentType.Any(foundPropertyFunc) ||
                    duplicatedInfo.PropertiesWithSameType.Any(foundPropertyFunc);
            }
        }