/// <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()); }
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); }
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); } }
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); }