this class contains also its syntax node which was used to create it. It can be used to extend the syntax later with delegation methods
Inheritance: Class, IConstructorList
Example #1
0
 public void IncludeMixinInChild(MixinReference mixin, ClassWithSourceCode child)
 {
     var childMembers = child.MembersFromThisAndBase;
     var mixinMembers = mixin.Class.MembersFromThisAndBase;
     foreach(var mixinMember in mixinMembers)
     {
         var membersWithSameSignatureInChild = childMembers
             .Where(x => _memberCompare.IsSameAs(x, mixinMember))
             .ToList();
         // 1. case: method does not exist in child => implement it
         if (!membersWithSameSignatureInChild.Any())
             _membersToImplement.Add(mixinMember.Clone());
         else // 2. case: method does exist in child, but is abstract and not overridden => override it
         {
             // member is declared as abstract in a base class of child
             // but not in child itself
             var abstractMembers = membersWithSameSignatureInChild
                 .Where(x => 
                     x.IsAbstract && 
                     x.Class != child && 
                     !child.HasOverride(x));
             _membersToImplement.AddRange(abstractMembers.Select(x => x.Clone(true)));
         }
     }
 }
        protected override ClassDeclarationSyntax InternalExecute(
            ClassWithSourceCode childClass, 
            SemanticModel semantic, 
            Settings settings = null)
        {
            // create a field declaration and add it to the child class
            // check the following cases:
            // 1. if mixin type is a concrete type that has a parameterless constructor
            //    if injection setting is not set => init field with new instance of type
            // 2. if mixin is interface or does not have a parameterless constructor
            //    do nothing
            var positionOfClassInSourceFile = childClass.SourceCode.GetLocation().SourceSpan.Start;
            var typeSyntax = ParseTypeName(
                _mixin.Class.TypeSymbol.ReduceQualifiedTypeName(semantic,positionOfClassInSourceFile));
            var newFieldDeclaration =
                FieldDeclaration(
                    VariableDeclaration(typeSyntax)
                    .WithVariables(
                        SingletonSeparatedList(
                            VariableDeclarator(_mixin.Name))))
                .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword)));

            var newClassDeclaration = childClass.SourceCode.AddMembers(newFieldDeclaration);

            return newClassDeclaration;
        }
        private async Task<Solution> CreateMixin(
            IMixinCommand mixinCommand, 
            Document document,
            ClassWithSourceCode childClass,
            CancellationToken cancellationToken)
        {
            // get service provider and read settings from storage
            var serviceProvider = Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider;
            var settings = new Settings(serviceProvider);

            var model = await document.GetSemanticModelAsync(cancellationToken);
           
            if (mixinCommand.CanExecute(childClass,settings))
            {
                // execute the command => we get a new class declaration
                var newClassDeclaration = mixinCommand.Execute(childClass.SourceCode, model,settings);
                // replace the old class declaration in the syntax tree
                var root = await model.SyntaxTree.GetRootAsync(cancellationToken);
                var newRoot = root.ReplaceNode(childClass.SourceCode, newClassDeclaration);
                // create a new document from the new syntax tree
                var newDocument = document.WithSyntaxRoot(newRoot);
                return newDocument.Project.Solution;
            }

            return null;
        }
 public override bool CanExecute(ClassWithSourceCode childClass, Settings settings = null)
 {
     // this feature is only available if the mixin class is an interface
     if (Mixin == null || !Mixin.Class.IsInterface)
         return false;
     return base.CanExecute(childClass, settings);
 }
 public override bool CanExecute(ClassWithSourceCode childClass, Settings settings = null)
 {
     if (settings == null || !settings.InjectMixins)
         return false;
     return !(childClass.AllConstructorsHaveParameter(_mixin.Name.ConvertFieldNameToParameterName()) &&
           childClass.HasConstructor);
 }
        public void Setup()
        {
            _child = Substitute.For<ClassWithSourceCode>();
            _mixin = Substitute.For<MixinReference>();
            _mixin.Name.Returns(x => "_mixin");

            _command = new InjectMixinsIntoChildCommand(_mixin);
        }
 public override bool CanExecute(
     ClassWithSourceCode childClass, 
     Settings settings = null)
 {
     // ensure that the child class does not already have a 
     // reference to the mixin with the given name
     var mixinField = childClass.SourceCode.FindMixinReference(_mixin.Name);
     return mixinField == null;
 }
 protected override ClassDeclarationSyntax InternalExecute(
     ClassWithSourceCode childClass, 
     SemanticModel semantic, 
     Settings settings = null)
 {
     var constructorSyntaxWriter = new ConstructorInjectionSyntaxWriter(_mixin, semantic);
     var classDeclaration = (ClassDeclarationSyntax)constructorSyntaxWriter.Visit(childClass.SourceCode);
     return classDeclaration;
 }
Example #9
0
 public virtual bool CanExecute(ClassWithSourceCode childClass, Settings settings = null)
 {
     if (Mixin == null)
         return false;
     var canExecute = false;
     // check that at least one command is executable
     foreach (var command in _commands)
         canExecute = canExecute || command.CanExecute(childClass, settings);
     return canExecute;
 }
        protected override ClassDeclarationSyntax InternalExecute(
            ClassWithSourceCode childClass, 
            SemanticModel semantic, 
            Settings settings = null)
        {
            var classDeclaration = childClass.SourceCode;
            var positionInSource = classDeclaration.GetLocation().SourceSpan.Start;

            var interfaceWriter = new AddInterfacesToChildSyntaxWriter(_mixin, semantic, positionInSource);
            classDeclaration = (ClassDeclarationSyntax)interfaceWriter.Visit(classDeclaration);
            return classDeclaration;
        }
Example #11
0
        protected override ClassDeclarationSyntax InternalExecute(
            ClassWithSourceCode childClass, 
            SemanticModel semantic, 
            Settings settings = null)
        {
            var syntaxWriter = new IncludeMixinSyntaxWriter(
                _mixer.MembersToImplement,
                _mixin,
                semantic,
                settings);
            var classDeclaration = (ClassDeclarationSyntax)syntaxWriter.Visit(childClass.SourceCode);

            return classDeclaration;
        }
Example #12
0
        public override bool CanExecute(ClassWithSourceCode childClass, Settings settings = null)
        {
            if (_mixin == null || childClass == null)
                return false;
            // do the mixin operation the first time
            if (_mixer == null)
            {
                _mixer = new Mixer();
                _mixer.IncludeMixinInChild(_mixin, childClass);
            }

            // command can be executed if we either have to forward members or extend a constructor
            return _mixer.MembersToImplement.Any();
        }
Example #13
0
        public ClassWithSourceCode Create(ClassDeclarationSyntax classDeclaration)
        {
            var @class = new ClassWithSourceCode(classDeclaration)
            {
                Name = classDeclaration.Identifier.ToString()
            };

            // create readers for reading syntax members
            var syntaxReaders = new SyntaxWalkerWithSemantic[]
            {
                new PropertySyntaxReader(@class, _semantic),
                new MethodSyntaxReader(@class, _semantic),
                new EventSyntaxReader(@class, _semantic),
                new BaseClassSyntaxReader(@class, _semantic),
                new InterfaceSyntaxReader(@class.Interfaces, _semantic),
                new ConstructorSyntaxReader(@class, _semantic)
            };

            foreach (var syntaxReader in syntaxReaders)
                syntaxReader.Visit(classDeclaration);

            return @class;
        }
Example #14
0
 /// <summary>
 /// executes the command on the given child class.
 /// Logic of command execution must be implemented in derived classes.
 /// </summary>
 /// <param name="semantic">semantic model of the child's and mixin's source code</param>
 /// <param name="settings">optional settings object</param>
 /// <returns></returns>
 protected abstract ClassDeclarationSyntax InternalExecute(
     ClassWithSourceCode childClass,
     SemanticModel semantic, 
     Settings settings = null);
Example #15
0
 /// <summary>
 /// called to check if the command can be executed.
 /// </summary>
 /// <param name="settings">optional settings</param>
 /// <returns>true if the command can be executed, otherwise false</returns>
 public abstract bool CanExecute(
     ClassWithSourceCode childClass, 
     Settings settings = null);
 public override bool CanExecute(ClassWithSourceCode childClass, Settings settings = null)
 {
     return settings != null && settings.AddInterfacesToChild;
 }