示例#1
0
        /// <summary>
        /// Obtient le nom de l'espace de nom d'une classe.
        /// </summary>
        /// <param name="classNode">Node de la classe.</param>
        /// <returns>Nom complet de l'espace de nom.</returns>
        public static string GetNameSpaceFullName(this ClassDeclarationSyntax classNode)
        {
            var nsNode = classNode.FirstAncestorOrSelf <NamespaceDeclarationSyntax>();

            if (nsNode == null)
            {
                return(null);
            }

            return(nsNode.Name.ToString());
        }
示例#2
0
        public override void VisitClassDeclaration(ClassDeclarationSyntax node)
        {
            var namespaceDeclaration = node.FirstAncestorOrSelf <NamespaceDeclarationSyntax>();
            var namespaceExplanation = namespaceDeclaration == null
                ? " without a namespace"
                : $" within the {namespaceDeclaration.Name} namespace";

            Console.WriteLine($"Found class with name {node.Identifier.Text}{namespaceExplanation}");

            base.VisitClassDeclaration(node);
        }
示例#3
0
            public override void VisitClassDeclaration(ClassDeclarationSyntax node)
            {
                if (node.Modifiers.Any(SyntaxKind.PublicKeyword))
                {
                    var @namespace = node.FirstAncestorOrSelf <NamespaceDeclarationSyntax>();
                    if (@namespace is null)
                    {
                        return;
                    }

                    this.namespaces.Add(@namespace.Name);
                }
            }
示例#4
0
        private static async Task <CompilationUnitSyntax> GeneratePartialDeclaration(Document document, ClassDeclarationSyntax classDecl, bool isCharp6, CancellationToken cancellationToken)
        {
            var strDecl = (StructDeclarationSyntax)classDecl.ChildNodes().First(x => x is StructDeclarationSyntax);

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken);

            var ti = semanticModel.GetTypeInfo(strDecl);

            var opt = new CodeGenerationOptions(isCharp6);

            var def            = new RecordDefinition(strDecl, opt);
            var generatedNodes = GetGeneratedNodes(def).ToArray();

            var newClassDecl = classDecl.GetPartialTypeDelaration()
                               .AddMembers(generatedNodes)
                               .WithAdditionalAnnotations(Formatter.Annotation);

            var ns = classDecl.FirstAncestorOrSelf <NamespaceDeclarationSyntax>()?.Name.WithoutTrivia().GetText().ToString();

            MemberDeclarationSyntax topDecl;

            if (ns != null)
            {
                topDecl = NamespaceDeclaration(IdentifierName(ns))
                          .AddMembers(newClassDecl)
                          .WithAdditionalAnnotations(Formatter.Annotation);
            }
            else
            {
                topDecl = newClassDecl;
            }

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false) as CompilationUnitSyntax;

            return(CompilationUnit().AddUsings(WithComponentModel(root.Usings))
                   .AddMembers(topDecl)
                   .WithTrailingTrivia(CarriageReturnLineFeed)
                   .WithAdditionalAnnotations(Formatter.Annotation));
        }
        private async Task <Solution> MoveToNewFile(Document document, ClassDeclarationSyntax classDeclaration, CancellationToken cancellationToken)
        {
            var className = classDeclaration.Identifier.Text;

            var syntaxRoot = await document.GetSyntaxRootAsync();

            var newNamespace = classDeclaration
                               .FirstAncestorOrSelf <NamespaceDeclarationSyntax>()
                               .WithMembers(SyntaxFactory.List(new[] { (MemberDeclarationSyntax)classDeclaration }));
            var compilationUnit = SyntaxFactory.CompilationUnit()
                                  .WithMembers(SyntaxFactory.List(new[] { (MemberDeclarationSyntax)newNamespace }))
                                  .WithUsings(SyntaxFactory.List(syntaxRoot.DescendantNodes().OfType <UsingDirectiveSyntax>()))
                                  .WithAdditionalAnnotations(Formatter.Annotation);

            var newDocument = document.Project.AddDocument(className + ".cs", string.Empty, folders: document.Folders).WithSyntaxRoot(compilationUnit);

            newDocument = newDocument.Project
                          .GetDocument(document.Id)
                          .WithSyntaxRoot(syntaxRoot.RemoveNode(classDeclaration, SyntaxRemoveOptions.KeepNoTrivia));

            return(newDocument.Project.Solution);
        }
        private string RenderFactoryImplementation(ClassDeclarationSyntax concreteClassDeclarationSyntax,
                                                   INamedTypeSymbol concreteClassTypeSymbol,
                                                   INamedTypeSymbol factoryInterfaceTypeSymbol,
                                                   string factoryName)
        {
            var fileName             = "{0}.Generated.cs".FormatWith(factoryName);
            var factoryInterfaceName = factoryInterfaceTypeSymbol.Name;

            var project = this.solution.Projects.Single(proj => proj.GetDocument(concreteClassDeclarationSyntax.SyntaxTree) != null);
            var typeDeclarationDocument = project.GetDocument(concreteClassDeclarationSyntax.SyntaxTree);
            var factoryGeneratorEngine  = new FactoryGeneratorEngine(project, this.templatePath);

            var usingsToFilterOut      = new[] { concreteClassTypeSymbol.ContainingNamespace.ToString() };
            var outerUsingDeclarations = FilterOutUsings(concreteClassDeclarationSyntax.FirstAncestorOrSelf <CompilationUnitSyntax>().Usings, usingsToFilterOut);
            var innerUsingDeclarations = FilterOutUsings(concreteClassDeclarationSyntax.FirstAncestorOrSelf <NamespaceDeclarationSyntax>().Usings, usingsToFilterOut);

            var factoryInterfaceMethods = GetSuitableFactoryInterfaceMethods(concreteClassTypeSymbol, factoryInterfaceTypeSymbol);

            var allContractMethodParameters = factoryInterfaceMethods.SelectMany(contractTypeMethod => contractTypeMethod.Parameters).ToArray();

            if (!factoryInterfaceMethods.Any())
            {
                throw new InvalidOperationException("The interface {0} has no suitable method returning any interface implemented by {1}. Please check if their is any.".FormatWith(factoryInterfaceTypeSymbol, concreteClassTypeSymbol));
            }

            var allConstructorParameters = factoryInterfaceMethods.Select(factoryMethod => SelectConstructorFromFactoryMethod(factoryMethod, concreteClassTypeSymbol))
                                           .SelectMany(selectedConstructor => selectedConstructor.Parameters).ToArray();
            var constructorParametersUsingSelfType   = allConstructorParameters.Where(p => p.Type.Name == factoryInterfaceTypeSymbol.Name).ToArray();
            var constructorParametersWithoutSelfType = allConstructorParameters.Except(constructorParametersUsingSelfType)
                                                       .ToArray();
            var injectedParameters = (from parameter in (IEnumerable <IParameterSymbol>)constructorParametersWithoutSelfType
                                      where !allContractMethodParameters.Any(contractMethodParameter => CompareParameters(contractMethodParameter, parameter))
                                      select parameter).Distinct(new ParameterEqualityComparer()).ToArray();

            var concreteClassName = GetXmlDocSafeTypeName(concreteClassTypeSymbol.ToString());
            var @namespace        = GetDeclarationNamespaceFullName(concreteClassDeclarationSyntax);

            var generateCodeArguments = new[] { new Value("\"DeveloperInTheFlow.FactoryGenerator\"", false), new Value(string.Format("\"{0}\"", this.version), true) };

            // Class attributes
            var classAttributes = concreteClassDeclarationSyntax.AttributeLists
                                  .SelectMany(al => al.Attributes).Where(attributeSyntax =>
            {
                var attributeName = attributeSyntax.Name.ToString();
                return(this.attributeImportList.Any(attributeName.Contains));
            })
                                  .Select(a =>
            {
                var lastIndex = a.ArgumentList.Arguments.Count - 1;

                var arguments = a.ArgumentList.Arguments.Select((arg,
                                                                 i) => new Value(arg.ToString(), i == lastIndex));
                return(Attribute.Create(a.Name.ToString(), arguments));
            })
                                  .Concat(new[]
            {
                Attribute.Create("global::System.CodeDom.Compiler.GeneratedCode", generateCodeArguments),
                Attribute.Create("global::System.Diagnostics.DebuggerNonUserCodeAttribute")
            }).ToArray();

            // Generic types of the factory
            var classGenericTypes = this.genericTypeBuilderService.Build(factoryInterfaceTypeSymbol.TypeParameters);

            // Constructor of the factory
            var constructor = this.constructorBuilderService.Build(concreteClassDeclarationSyntax, injectedParameters);

            // Fields of the factory
            var fields = this.fieldsBuilderService.Build(injectedParameters).ToArray();

            // Methods of the factory
            var methods = this.methodsBuilderService.Build(concreteClassTypeSymbol, fields, injectedParameters, factoryInterfaceMethods, factoryInterfaceName);

            // Interface of the factory
            var inherit = factoryInterfaceTypeSymbol.ToString();

            // The factory
            var factoryClass = new Class(classAttributes, concreteClassName, constructor, methods, fields, classGenericTypes, inherit, factoryName);

            // The file containing the factory
            var factoryFile = FactoryFile.Create(@namespace,
                                                 factoryClass,
                                                 innerUsingDeclarations.ToFullString(),
                                                 outerUsingDeclarations.ToFullString());

            object model = factoryFile;
            var    transformationScript = string.Format(@"{0}\{1}.tcs", Path.GetDirectoryName(this.templatePath), factoryFile.FactoryFor);

            // Execute the script associated to the template in order to adapt the model for the template whether it exists.
            if (File.Exists(transformationScript))
            {
                var json = JObject.FromObject(factoryFile);
                model = Transform(json, transformationScript);
            }

            // The result of the generator
            var factoryResult = factoryGeneratorEngine.Generate(fileName, typeDeclarationDocument.Folders, model, factoryFile.FactoryFor);

            var existingDocument = project.Documents.SingleOrDefault(doc => doc.Name.Equals(fileName, StringComparison.OrdinalIgnoreCase) && doc.Folders.SequenceEqual(typeDeclarationDocument.Folders));

            if (existingDocument != null)
            {
                UpdateDocument(existingDocument, factoryResult.Code);

                return(existingDocument.FilePath);
            }

            this.solution = factoryResult.Document.Project.Solution;

            var projectFolder = Path.GetDirectoryName(project.FilePath);

            if (projectFolder == null)
            {
                throw new InvalidOperationException("Cannot determines the folder path of the project.");
            }

            var generatedFileFolderPath = Path.Combine(projectFolder, string.Join(@"\", typeDeclarationDocument.Folders));
            var generatedFilePath       = Path.Combine(generatedFileFolderPath, factoryResult.Document.Name);

            return(generatedFilePath);
        }