private void ValidateServiceClass( string serviceClassName, List <TypeParameter> typeParameters, List <InjectedService> injectedServices, string serviceClassFilePath, string serviceNamespace, string outServiceClassFilePath) { var usingDirectives = new HashSet <string>(); var fieldDeclarations = new List <FieldDeclaration>(); var ctorParameters = new FormalParameterList(); var fixedParams = ctorParameters.FixedParameters; var ctorBody = new ConstructorBody(); var statements = ctorBody.Statements; var appendBody = new ClassInterfaceBody() { FieldDeclarations = fieldDeclarations, ConstructorDeclaration = new ConstructorDeclaration() { FormalParameterList = ctorParameters, Body = ctorBody } }; if (injectedServices != null && injectedServices.Count > 0) { foreach (var injectedService in injectedServices) { var injectedServiceIdentifier = injectedService.ServiceIdentifier ?? Regex.Replace( Regex.Replace( injectedService.Type, @"^I?([A-Z])", "$1"), @"^[A-Z]", m => m.ToString().ToLower()); if (!Regex.Match(serviceNamespace, "^" + Regex.Escape(injectedService.Namespace)).Success) { usingDirectives.Add(injectedService.Namespace); } fieldDeclarations.Add( new FieldDeclaration() { Modifiers = new List <string>() { Keywords.Private, Keywords.Readonly }, Type = injectedService.Type, VariableDeclarator = new VariableDeclarator() { Identifier = "_" + injectedServiceIdentifier } }); fixedParams.Add( new FixedParameter() { Type = injectedService.Type, Identifier = injectedServiceIdentifier }); statements.Add( new Statement() { SimpleAssignment = new SimpleAssignment() { LeftHandSide = "_" + injectedServiceIdentifier, RightHandSide = injectedServiceIdentifier } }); } } var serviceClassFile = new ServiceFile() { UsingDirectives = usingDirectives.ToList(), ServiceNamespace = serviceNamespace, ServiceDeclaration = new ClassInterfaceDeclaration() { IsInterface = false, Modifiers = new List <string>() { Keywords.Public }, Identifier = serviceClassName, TypeParameters = typeParameters.Copy(), Body = new ClassInterfaceBody() { FieldDeclarations = fieldDeclarations, ConstructorDeclaration = new ConstructorDeclaration() { Modifiers = new List <string>() { Keywords.Public }, Identifier = serviceClassName, FormalParameterList = ctorParameters, Body = ctorBody } } } }; if (!File.Exists(serviceClassFilePath)) { // Create <service> class file // Create serviceClass StringTemplate with empty class body _logger.LogDebug("Creating new service class and writing it to file."); UpdateWrittenTo(serviceClassFilePath, outServiceClassFilePath); _ioUtilService.WriteStringToFile( _serviceCommandStgService.RenderServiceFile( usingDirectives: usingDirectives.ToList(), serviceNamespace: serviceNamespace, service: serviceClassFile.ServiceDeclaration), outServiceClassFilePath); } else { var serviceClassParser = new CSharpParserWrapper(GetPathFromWrittenTo(serviceClassFilePath)); var serviceClassRewrite = _serviceCommandService.InjectDataIntoServiceClass( serviceClassFile, serviceClassParser, serviceClassName, _userSettings.Value.TabString); if (serviceClassRewrite != null) { _logger.LogDebug("Overwriting service class file."); UpdateWrittenTo(serviceClassFilePath, outServiceClassFilePath); _ioUtilService.WriteStringToFile( serviceClassRewrite, outServiceClassFilePath); } else { _logger.LogDebug("Service class file was already up to date."); } } }
private void ConsolidateServiceClassAndInterface( SourceOfTruth sourceOfTruth, string serviceClassName, string serviceInterfaceName, List <TypeParameter> typeParameters, List <InjectedService> injectedServices, string serviceClassFilePath, string serviceInterfaceFilePath, string serviceNamespace, string outServiceClassFilePath, string outServiceInterfaceFilePath) { var usingDirectives = new HashSet <string>(); var fieldDeclarations = new List <FieldDeclaration>(); var ctorParameters = new FormalParameterList(); var fixedParams = ctorParameters.FixedParameters; var ctorBody = new ConstructorBody(); var statements = ctorBody.Statements; var appendBody = new ClassInterfaceBody() { FieldDeclarations = fieldDeclarations, ConstructorDeclaration = new ConstructorDeclaration() { FormalParameterList = ctorParameters, Body = ctorBody } }; if (injectedServices != null && injectedServices.Count > 0) { foreach (var injectedService in injectedServices) { var injectedServiceIdentifier = injectedService.ServiceIdentifier ?? Regex.Replace( Regex.Replace( injectedService.Type, @"^I?([A-Z])", "$1"), @"^[A-Z]", m => m.ToString().ToLower()); if (!Regex.Match(serviceNamespace, "^" + Regex.Escape(injectedService.Namespace)).Success) { usingDirectives.Add(injectedService.Namespace); } fieldDeclarations.Add( new FieldDeclaration() { Modifiers = new List <string>() { Keywords.Private, Keywords.Readonly }, Type = injectedService.Type, VariableDeclarator = new VariableDeclarator() { Identifier = "_" + injectedServiceIdentifier } }); fixedParams.Add( new FixedParameter() { Type = injectedService.Type, Identifier = injectedServiceIdentifier }); statements.Add( new Statement() { SimpleAssignment = new SimpleAssignment() { LeftHandSide = "_" + injectedServiceIdentifier, RightHandSide = injectedServiceIdentifier } }); } } CSharpParserWrapper serviceClassParser = null; CSharpParserWrapper serviceInterfaceParser = null; ServiceFile classScraperResults = null; ServiceFile interfaceScraperResults = null; //Check if <service> class file exists: if (File.Exists(serviceClassFilePath)) { _logger.LogDebug("Service class file found. Pulling data from service class."); // Else: // Parse <service> class file // Extract list of existing public method signatures serviceClassParser = new CSharpParserWrapper(GetPathFromWrittenTo(serviceClassFilePath)); classScraperResults = _serviceCommandService.ScrapeServiceClass( serviceClassParser, serviceClassName, serviceNamespace, typeParameters); } else { _logger.LogDebug($"No service class file found at {serviceClassFilePath}."); } //Check if <service> interface file exists: if (File.Exists(serviceInterfaceFilePath)) { _logger.LogDebug("Service interface file found. Pulling data from service interface."); // Else: // Parse <service> interface file // Extract list of existing method signatures serviceInterfaceParser = new CSharpParserWrapper(GetPathFromWrittenTo(serviceInterfaceFilePath)); interfaceScraperResults = _serviceCommandService.ScrapeServiceInterface( serviceInterfaceParser, serviceInterfaceName, serviceNamespace, typeParameters); } else { _logger.LogDebug($"No service interface file found at {serviceInterfaceFilePath}."); } if (classScraperResults is null && interfaceScraperResults is null) { _logger.LogDebug("Creating new service class and interface and writing them to file."); // Create <service> class file // Create serviceClass StringTemplate with empty class body var classDeclaration = new ClassInterfaceDeclaration() { IsInterface = false, Modifiers = new List <string>() { Keywords.Public }, Identifier = serviceClassName, TypeParameters = typeParameters.Copy(), Base = new ClassInterfaceBase() { InterfaceTypeList = new List <string>() { serviceInterfaceName + _cSharpCommonStgService.RenderTypeParamList(typeParameters.Copy()) } }, Body = new ClassInterfaceBody() { FieldDeclarations = fieldDeclarations, ConstructorDeclaration = new ConstructorDeclaration() { Modifiers = new List <string>() { Keywords.Public }, Identifier = serviceClassName, FormalParameterList = ctorParameters, Body = ctorBody } } }; UpdateWrittenTo(serviceClassFilePath, outServiceClassFilePath); _ioUtilService.WriteStringToFile( _serviceCommandStgService.RenderServiceFile( usingDirectives: usingDirectives.ToList(), serviceNamespace: serviceNamespace, service: classDeclaration), outServiceClassFilePath); // Create <service> interface file // Create serviceInterface StringTemplate with empty interface body var interfaceDeclaration = new ClassInterfaceDeclaration() { IsInterface = true, Modifiers = new List <string>() { Keywords.Public }, Identifier = serviceInterfaceName, TypeParameters = typeParameters.Copy() }; UpdateWrittenTo(serviceInterfaceFilePath, outServiceInterfaceFilePath); _ioUtilService.WriteStringToFile( _serviceCommandStgService.RenderServiceFile( serviceNamespace: serviceNamespace, service: interfaceDeclaration), outServiceInterfaceFilePath); }
public Task Execute(BreadcrumbCommand breadcrumbCommand) { var areaRootNamespace = _projectEnvironment.Value.RootNamespace + (breadcrumbCommand.Area is null || breadcrumbCommand.Area.TrimEnd(@"/\ ".ToCharArray()) == string.Empty ? string.Empty : $".Areas.{breadcrumbCommand.Area.TrimEnd(@"/\ ".ToCharArray())}"); var controllerRootNamespace = areaRootNamespace + ".Controllers"; var breadcrumbRootNamespace = areaRootNamespace + "." + (breadcrumbCommand?.BreadcrumbServiceDirectory?.TrimEnd(@"/\ ".ToCharArray()) ?? "Services.Breadcrumbs" ).Replace("/", ".").Replace(@"\", "."); var defaultAreaBreadcrumbServiceRootName = _projectEnvironment.Value.RootNamespace + (breadcrumbCommand.Area is null || breadcrumbCommand.Area.TrimEnd(@"/\ ".ToCharArray()) == string.Empty ? string.Empty : breadcrumbCommand.Area.TrimEnd(@"/\ ".ToCharArray())) + "Breadcrumb"; var defaultAreaBreadcrumbServiceName = defaultAreaBreadcrumbServiceRootName + "Service"; var commandRootDirectory = Path.Combine( _projectEnvironment.Value.RootDirectory, (breadcrumbCommand.Area is null || breadcrumbCommand.Area.TrimEnd(@"/\ ".ToCharArray()) == string.Empty ? string.Empty : Path.Combine("Areas", breadcrumbCommand.Area))); var targetDirectory = Path.Combine( commandRootDirectory, breadcrumbCommand.TargetDirectory ?? "Controllers"); var breadcrumbOutputDirectory = Path.Combine( commandRootDirectory, breadcrumbCommand?.BreadcrumbServiceDirectory ?? "Services/Breadcrumbs"); Directory.CreateDirectory(breadcrumbOutputDirectory); if (!Directory.Exists(targetDirectory)) { _logger.LogError($"TargetDirectory does not exist at {targetDirectory}"); // throw return(Task.CompletedTask); } var filenames = new List <string>(); if (breadcrumbCommand.TargetFile != null) { var targetFile = Path.Combine(targetDirectory, breadcrumbCommand.TargetFile); if (!File.Exists(targetFile)) { _logger.LogError($"TargetFile does not exist at {targetFile}"); // throw return(Task.CompletedTask); } filenames.Add(targetFile); _logger.LogDebug("Service interface file was already up to date."); } else { filenames = GetCSharpFilesInDirectory(targetDirectory, breadcrumbCommand.IsRecursive ?? false); } var controllerDict = new ControllerDictionary(); foreach (var filename in filenames) { var controllerParser = new CSharpParserWrapper(GetPathFromWrittenTo(filename)); var tree = controllerParser.GetParseTree(); var visitor = _breadcrumbControllerScraperFactory.Create( controllerParser.Tokens); visitor.Visit(tree); var scraperResults = visitor.Results; foreach (var nameKey in scraperResults.NamespaceDict.Keys) { if (controllerDict.NamespaceDict.ContainsKey(nameKey)) { foreach (var classKey in scraperResults.NamespaceDict[nameKey].ClassDict.Keys) { controllerDict.NamespaceDict[nameKey].ClassDict[classKey] = scraperResults.NamespaceDict[nameKey].ClassDict[classKey]; } } else { controllerDict.NamespaceDict[nameKey] = scraperResults.NamespaceDict[nameKey]; } } } //public class InjectedService //{ // public string Type { get; set; } // public string ServiceIdentifier { get; set; } // public string Namespace { get; set; } //} var usingDirectives = new HashSet <string>() { "SmartBreadcrumbs.Nodes" }; var fieldDeclarations = new List <FieldDeclaration>(); var ctorParameters = new FormalParameterList(); var fixedParams = ctorParameters.FixedParameters; var ctorBody = new ConstructorBody(); var statements = ctorBody.Statements; foreach (var injectedService in breadcrumbCommand.InjectedServices) { var injectedServiceIdentifier = injectedService.ServiceIdentifier ?? Regex.Replace( Regex.Replace( injectedService.Type, @"^I?([A-Z])", "$1"), @"^[A-Z]", m => m.ToString().ToLower()); if (!Regex.Match(breadcrumbRootNamespace, "^" + Regex.Escape(injectedService.Namespace)).Success) { usingDirectives.Add(injectedService.Namespace); } fieldDeclarations.Add( new FieldDeclaration() { Modifiers = new List <string>() { Keywords.Private, Keywords.Readonly }, Type = injectedService.Type, VariableDeclarator = new VariableDeclarator() { Identifier = "_" + injectedServiceIdentifier } }); fixedParams.Add( new FixedParameter() { Type = injectedService.Type, Identifier = injectedServiceIdentifier }); statements.Add( new Statement() { SimpleAssignment = new SimpleAssignment() { LeftHandSide = "_" + injectedServiceIdentifier, RightHandSide = injectedServiceIdentifier } }); } var startupRegInfoList = new List <StartupRegistrationInfo>(); foreach (var controllerNamespace in controllerDict.NamespaceDict.Values) { var namespaceSuffix = Regex.Replace( controllerNamespace.Namespace, "^" + Regex.Escape(controllerRootNamespace + "."), string.Empty); var serviceNamePrefix = namespaceSuffix.Replace(".", ""); var serviceClassName = serviceNamePrefix == string.Empty ? defaultAreaBreadcrumbServiceRootName : serviceNamePrefix + "BreadcrumbService"; var serviceInterfaceName = $"I{serviceClassName}"; var serviceClassFilename = Path.Combine(breadcrumbOutputDirectory, $"{serviceClassName}.cs"); var serviceInterfaceFilename = Path.Combine(breadcrumbOutputDirectory, $"{serviceInterfaceName}.cs"); var outServiceClassFilename = Path.Combine(breadcrumbOutputDirectory, $"X{serviceClassName}.cs"); var outServiceInterfaceFilename = Path.Combine(breadcrumbOutputDirectory, $"X{serviceInterfaceName}.cs"); startupRegInfoList.Add(new StartupRegistrationInfo() { ServiceNamespace = breadcrumbRootNamespace, ServiceClassType = serviceClassName, ServiceBaseType = serviceInterfaceName, HasTypeParameters = false, ServiceLifespan = ServiceLifetime.Scoped }); var classDeclaration = new BreadcrumbServiceDeclaration() { IsInterface = false, Modifiers = new List <string>() { Keywords.Public }, Identifier = serviceClassName, Base = new ClassInterfaceBase() { InterfaceTypeList = new List <string>() { serviceInterfaceName } }, Body = new BreadcrumbServiceBody() { FieldDeclarations = fieldDeclarations, ConstructorDeclaration = new ConstructorDeclaration() { Modifiers = new List <string>() { Keywords.Public }, Identifier = serviceClassName, FormalParameterList = ctorParameters, Body = ctorBody } } }; var interfaceDeclaration = new BreadcrumbServiceDeclaration() { IsInterface = true, Identifier = serviceInterfaceName }; foreach (var controllerClass in controllerNamespace.ClassDict.Values) { var controllerNamePattern = breadcrumbCommand.ControllerNamePattern?.Replace( "$ControllerType$", controllerClass.Controller) ?? $"\"{Regex.Replace(controllerClass.Controller, "Controller$", string.Empty)}\""; foreach (var controllerAction in controllerClass.ActionDict.Values) { var methodDeclaration = new BreadcrumbMethodDeclaration() { ControllerRoot = controllerClass.ControllerRoot, Action = controllerAction.Action, HasId = controllerAction.HasId, Controller = controllerClass.Controller, ControllerNamePattern = controllerNamePattern }; classDeclaration.Body.MethodDeclarations.Add(methodDeclaration); interfaceDeclaration.Body.MethodDeclarations.Add(methodDeclaration); } } if (!File.Exists(serviceClassFilename)) { var cos = _breadcrumbCommandStgService.RenderBreadcrumbServiceFile( usingDirectives.ToList(), breadcrumbRootNamespace, classDeclaration); _ioUtilService.WriteStringToFile( cos, outServiceClassFilename); UpdateWrittenTo(serviceClassFilename, outServiceClassFilename); var ios = _breadcrumbCommandStgService.RenderBreadcrumbServiceFile( usingDirectives.ToList(), breadcrumbRootNamespace, interfaceDeclaration); _ioUtilService.WriteStringToFile( ios, outServiceInterfaceFilename); UpdateWrittenTo(serviceInterfaceFilename, outServiceInterfaceFilename); } else { var breadcrumbClassParser = new CSharpParserWrapper( GetPathFromWrittenTo( Path.Combine(breadcrumbOutputDirectory, serviceClassFilename))); var tree = breadcrumbClassParser.GetParseTree(); var visitor = _breadcrumbClassInjectorFactory.Create( breadcrumbClassParser.Tokens, usingDirectives.ToList(), breadcrumbRootNamespace, classDeclaration, _userSettings.Value.TabString); visitor.Visit(tree); if (visitor.IsModified) { _ioUtilService.WriteStringToFile( visitor.Rewriter.GetText(), outServiceClassFilename); UpdateWrittenTo(serviceClassFilename, outServiceClassFilename); } var serviceClassParser = new CSharpParserWrapper(GetPathFromWrittenTo(serviceClassFilename)); var classScraperResults = _serviceCommandService.ScrapeServiceClass( serviceClassParser, serviceClassName, breadcrumbRootNamespace, null); _ioUtilService.WriteStringToFile( _serviceCommandService.GetInterfaceServiceFileFromClass( classScraperResults, serviceInterfaceName, breadcrumbRootNamespace), outServiceInterfaceFilename); UpdateWrittenTo(serviceInterfaceFilename, outServiceInterfaceFilename); } } RegisterServicesInStartup(startupRegInfoList); InjectBreadcrumbsIntoControllers(controllerFilepaths: filenames, controllerDictionary: controllerDict, breadcrumbServiceNamespace: breadcrumbRootNamespace, controllerRootNamespace: controllerRootNamespace, defaultAreaBreadcrumbServiceRootName: defaultAreaBreadcrumbServiceRootName, tabString: _userSettings.Value.TabString); return(Task.CompletedTask); }