private static async Task Generate(Solution solution, string spaRoot, string projectName) { var definitionPath = "../../model"; var outputPath = $"{spaRoot}/app/services"; var frontEnd = solution.Projects.First(projet => projet.AssemblyName == $"{projectName}.FrontEnd"); var controllers = frontEnd.Documents.Where(document => document.Name.Contains("Controller") && document.Folders.Contains("Controllers") && !document.Folders.Contains("Transverse") && document.Folders.Count == 2 && !document.Name.Contains("ReferenceList")); foreach (var controller in controllers) { var syntaxTree = await controller.GetSyntaxTreeAsync(); var controllerClass = syntaxTree.GetRoot().DescendantNodes().OfType <ClassDeclarationSyntax>().First(); var controllerName = $"{controllerClass.Identifier.ToString().Replace("Controller", string.Empty).ToDashCase()}.ts"; Console.Out.WriteLine($"Generating {controllerName}"); var methods = controllerClass.ChildNodes().OfType <MethodDeclarationSyntax>(); var model = await controller.GetSemanticModelAsync(); var serviceList = methods .Where(method => method.Modifiers.Any(mod => mod.IsKind(SyntaxKind.PublicKeyword))) .Select(method => GetService(method, model)); var fileName = $"{outputPath}/{controller.Folders.Last().ToDashCase()}/{controllerName}"; var fileInfo = new FileInfo(fileName); var directoryInfo = fileInfo.Directory; if (!directoryInfo.Exists) { Directory.CreateDirectory(directoryInfo.FullName); } var template = new ServiceSpa { ProjectName = projectName, DefinitionPath = definitionPath, Services = serviceList }; var output = template.TransformText(); File.WriteAllText(fileName, output, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); } }
/// <summary> /// Point d'entrée. /// </summary> /// <param name="args"> /// Premier argument : chemin de la solution. /// Deuxième argument : racine de la SPA. /// Troisième argument : namespace du projet (exemple : "Kinetix"). /// </param> public static async Task Main(string[] args) { _solutionPath = args[0]; _serviceRoot = args[1]; _projectName = args[2]; _kinetix = args[3]; var instance = MSBuildLocator.QueryVisualStudioInstances().First(); Console.WriteLine($"Using MSBuild at '{instance.MSBuildPath}' to load projects."); MSBuildLocator.RegisterInstance(instance); var msWorkspace = MSBuildWorkspace.Create(); msWorkspace.WorkspaceFailed += MsWorkspace_WorkspaceFailed; Solution solution = await msWorkspace.OpenSolutionAsync(_solutionPath); // If path is not to services add "standard" path var outputPath = _serviceRoot.EndsWith("services") ? _serviceRoot : $"{_serviceRoot}/app/services"; var frontEnds = solution.Projects.Where(projet => projet.AssemblyName.StartsWith(_projectName) && projet.AssemblyName.EndsWith("FrontEnd")); var controllers = frontEnds.SelectMany(f => f.Documents).Where(document => document.Name.Contains("Controller") && !document.Folders.Contains("Transverse")); foreach (var controller in controllers) { var syntaxTree = await controller.GetSyntaxTreeAsync(); var controllerClass = GetClassDeclaration(syntaxTree); var model = await solution.GetDocument(syntaxTree).GetSemanticModelAsync(); var modelClass = model.GetDeclaredSymbol(controllerClass); // Skip if we extend a MVC controller if (_kinetix == "framework" && modelClass.BaseType.Name == "Controller") { continue; } IReadOnlyList <string> folders = controller.Folders; var firstFolder = frontEnds.Count() > 1 ? $"/{controller.Project.Name.Split('.')[1].ToDashCase()}" : string.Empty; var secondFolder = folders.Count > 1 ? $"/{string.Join("/", folders.Skip(1).Select(f => f.ToDashCase()))}" : string.Empty; var folderCount = (frontEnds.Count() > 1 ? 1 : 0) + folders.Count - 1; var controllerName = $"{firstFolder}{secondFolder}/{controllerClass.Identifier.ToString().Replace("Controller", string.Empty).ToDashCase()}.ts".Substring(1); Console.WriteLine($"Generating {controllerName}"); var methods = GetMethodDeclarations(controllerClass, model); // If controller is not a direct Controller extender, ie it extends a base class string aspControllerClass = _kinetix == "Core" ? "Controller" : "ApiController"; if (modelClass.BaseType.Name != aspControllerClass) { var baseClassSyntaxTree = modelClass.BaseType.DeclaringSyntaxReferences.First().SyntaxTree; methods = methods.Concat(GetMethodDeclarations( GetClassDeclaration(baseClassSyntaxTree), await solution.GetDocument(baseClassSyntaxTree).GetSemanticModelAsync())); } var serviceList = methods .Where(m => m.method.Modifiers.Any(mod => mod.IsKind(SyntaxKind.PublicKeyword))) .Select(GetService) .Where(s => s != null) .ToList(); var fileName = $"{outputPath}/{controllerName}"; var fileInfo = new FileInfo(fileName); var directoryInfo = fileInfo.Directory; if (!directoryInfo.Exists) { Directory.CreateDirectory(directoryInfo.FullName); } var template = new ServiceSpa { ProjectName = _projectName, FolderCount = folderCount, Services = serviceList }; var output = template.TransformText(); File.WriteAllText(fileName, output, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); } }
/// <summary> /// Point d'entrée. /// </summary> /// <param name="args"> /// Premier argument : chemin de la solution. /// Deuxième argument : racine de la SPA. /// Troisième argument : namespace du projet (exemple : "Kinetix"). /// </param> public static async Task Main(string[] args) { _solutionPath = args[0]; _serviceRoot = args[1]; _projectName = args[2]; _kinetix = args[3]; Solution solution = null; #if NET471 var msWorkspace = MSBuildWorkspace.Create(); msWorkspace.WorkspaceFailed += MsWorkspace_WorkspaceFailed; solution = await msWorkspace.OpenSolutionAsync(_solutionPath); #endif #if NETCOREAPP2_1 var adhocWorkspace = new AnalyzerManager(_solutionPath).GetWorkspace(); adhocWorkspace.WorkspaceFailed += AdhocWorkspace_WorkspaceFailed; solution = adhocWorkspace.CurrentSolution; // Weirdly, I have a lot of duplicate project references after loading a solution, so this is a quick hack to fix that. foreach (var project in solution.Projects) { solution = solution.WithProjectReferences(project.Id, project.ProjectReferences.Distinct()); } #endif // If path is not to services add "standard" path var outputPath = _serviceRoot.EndsWith("services") ? _serviceRoot : $"{_serviceRoot}/app/services"; var frontEnds = solution.Projects.Where(projet => projet.AssemblyName.StartsWith(_projectName) && projet.AssemblyName.EndsWith("FrontEnd")); var controllers = frontEnds.SelectMany(f => f.Documents).Where(document => document.Name.Contains("Controller") && !document.Folders.Contains("Transverse")); foreach (var controller in controllers) { var syntaxTree = await controller.GetSyntaxTreeAsync(); var controllerClass = GetClassDeclaration(syntaxTree); var model = await solution.GetDocument(syntaxTree).GetSemanticModelAsync(); var modelClass = model.GetDeclaredSymbol(controllerClass); // Skip if we extend a MVC controller if (_kinetix == "framework" && modelClass.BaseType.Name == "Controller") { continue; } IReadOnlyList <string> folders = null; #if NET471 folders = controller.Folders; #endif #if NETCOREAPP2_1 var parts = Path.GetRelativePath(controller.Project.FilePath, controller.FilePath).Split(@"\"); folders = parts.Skip(1).Take(parts.Length - 2).ToList(); #endif var firstFolder = frontEnds.Count() > 1 ? $"/{controller.Project.Name.Split('.')[1].ToDashCase()}" : string.Empty; var secondFolder = folders.Count > 1 ? $"/{string.Join("/", folders.Skip(1).Select(f => f.ToDashCase()))}" : string.Empty; var folderCount = (frontEnds.Count() > 1 ? 1 : 0) + folders.Count - 1; var controllerName = $"{firstFolder}{secondFolder}/{controllerClass.Identifier.ToString().Replace("Controller", string.Empty).ToDashCase()}.ts".Substring(1); Console.WriteLine($"Generating {controllerName}"); var methods = GetMethodDeclarations(controllerClass, model); // If controller is not a direct Controller extender, ie it extends a base class string aspControllerClass = _kinetix == "Core" ? "Controller" : "ApiController"; if (modelClass.BaseType.Name != aspControllerClass) { var baseClassSyntaxTree = modelClass.BaseType.DeclaringSyntaxReferences.First().SyntaxTree; methods = methods.Concat(GetMethodDeclarations( GetClassDeclaration(baseClassSyntaxTree), await solution.GetDocument(baseClassSyntaxTree).GetSemanticModelAsync())); } var serviceList = methods .Where(m => m.method.Modifiers.Any(mod => mod.IsKind(SyntaxKind.PublicKeyword))) .Select(GetService) .Where(s => s != null) .ToList(); var fileName = $"{outputPath}/{controllerName}"; var fileInfo = new FileInfo(fileName); var directoryInfo = fileInfo.Directory; if (!directoryInfo.Exists) { Directory.CreateDirectory(directoryInfo.FullName); } var template = new ServiceSpa { ProjectName = _projectName, FolderCount = folderCount, Services = serviceList }; var output = template.TransformText(); File.WriteAllText(fileName, output, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); } }