public void Initialize(Entity root) { ProjectEntity project = ProjectEntity.Decorate(root); TemplateEntity template = TemplateEntity.Decorate(root); Target[] availableTargets = sdkRepository.GetAllTargets().ToArray(); ICodeModel codeModel = root.Value <ICodeModel>(); SetProjectName(); SetProjectNamespace(); SetProjectType(); SetProjectTargets(); SetProjectEntities(); SetProjectIncludes(); void SetProjectName() { ProjectName = null; if (fileSystem.FileExists(System.IO.Path.Combine(root.Path, Constants.ProjectFileName))) { ProjectName = root.Name; } } void SetProjectNamespace() { ProjectNamespace = CodeEntity.Decorate(project).Namespace; } void SetProjectType() { ProjectType = project.Type; } void SetProjectTargets() { TargetsResult targetsResult = targetParser.Targets(project, false); ProjectTargets = targetsResult.ValidTargets .Select(t => new ProjectTarget(t, availableTargets.Any(at => t.Name == at.Name && at.LongVersion == t.LongVersion))); Exceptions = targetsResult.Errors; } void SetProjectEntities() { IEnumerable <CodeEntity> entities = template.EntityHierarchy.Select(e => { CodeEntity codeEntity = CodeEntity.Decorate(e); return(codeEntity); } ); ProjectCodeEntities = entities.Select(e => { TemplateEntity te = TemplateEntity.Decorate(e); return(e, te.RelatedEntites.Where(en => !en.Type.Contains("project"))); }) .Where(e => !e.Item1.Type.Contains("project")).ToDictionary(p => p.Item1, p => p.Item2); } void SetProjectIncludes() { IncludePaths = new List <IncludePath>(); IEnumerable <SdkInformation> relevantSdks = ProjectTargets.Select(t => availableTargets.FirstOrDefault(at => t.Target.Name == at.Name && at.LongVersion == t.Target.LongVersion)) .Where(t => t != null) .Select(sdkRepository.GetSdk) .Where(sdk => sdk != null) .Distinct(); var targetsWithIncludePaths = relevantSdks.Select(sdk => (sdk.Targets, sdk.IncludePaths.Concat(sdk.CompilerInformation.IncludePaths).Distinct())); foreach (var item in targetsWithIncludePaths) { foreach (Target target in item.Targets) { foreach (string includePath in item.Item2) { IncludePath existingIncludePath = IncludePaths.Where(i => i.PathValue.Equals(includePath, StringComparison.InvariantCulture)).FirstOrDefault(); if (existingIncludePath == null) { existingIncludePath = new IncludePath(includePath, true, new List <Target>()); IncludePaths.Add(existingIncludePath); } existingIncludePath.Targets = existingIncludePath.Targets.Concat(new[] { target }); } } } foreach (IncludePath codeModelIncludeDirectory in codeModel.IncludeDirectories) { IncludePath existingIncludePath = IncludePaths.Where(p => p.PathValue.Equals(codeModelIncludeDirectory.PathValue, StringComparison.InvariantCulture)).FirstOrDefault(); if (existingIncludePath == null) { IncludePaths.Add(codeModelIncludeDirectory); } else { foreach (Target target in codeModelIncludeDirectory.Targets) { if (!existingIncludePath.Targets.Contains(target)) { existingIncludePath.Targets = existingIncludePath.Targets.Concat(new[] { target }); } } } } } }
public void Initialize(Entity root) { ProjectEntity project = ProjectEntity.Decorate(root); TemplateEntity template = TemplateEntity.Decorate(root); Target[] availableTargets = sdkRepository.GetAllTargets().ToArray(); ICodeModel codeModel = root.Value <ICodeModel>(); SetProjectName(); SetProjectNamespace(); SetProjectType(); SetProjectTargets(); SetProjectEntities(); SetProjectIncludes(); void SetProjectName() { ProjectName = null; if (fileSystem.FileExists(System.IO.Path.Combine(root.Path, Constants.ProjectFileName))) { ProjectName = root.Name; } } void SetProjectNamespace() { ProjectNamespace = CodeEntity.Decorate(project).Namespace; } void SetProjectType() { ProjectType = project.Type; } void SetProjectTargets() { TargetsResult targetsResult = targetParser.Targets(project, false); ProjectTargets = targetsResult.ValidTargets .Select(t => new ProjectTarget(t, availableTargets.Any(at => t.Name == at.Name && at.LongVersion == t.LongVersion))); Exceptions = targetsResult.Errors; } void SetProjectEntities() { IEnumerable <CodeEntity> entities = template.EntityHierarchy.Select(e => { CodeEntity codeEntity = CodeEntity.Decorate(e); return(codeEntity); } ); ProjectCodeEntities = entities.Select(e => { TemplateEntity te = TemplateEntity.Decorate(e); return(e, te.RelatedEntites.Where(en => !en.Type.Contains("project"))); }) .Where(e => !e.Item1.Type.Contains("project")).ToDictionary(p => p.Item1, p => p.Item2); } void SetProjectIncludes() { IEnumerable <SdkInformation> relevantSdks = ProjectTargets.Select(t => availableTargets.FirstOrDefault(at => t.Target.Name == at.Name && at.LongVersion == t.Target.LongVersion)) .Where(t => t != null) .Select(sdkRepository.GetSdk) .Where(sdk => sdk != null) .Distinct(); IncludePaths = relevantSdks.SelectMany(sdk => sdk.IncludePaths) .Concat(relevantSdks.SelectMany(sdk => sdk.CompilerInformation.IncludePaths)) .Distinct() .ToDictionary(x => x, x => true); foreach (KeyValuePair <string, VirtualDirectory> codeModelIncludeDirectory in codeModel.IncludeDirectories) { if (!IncludePaths.ContainsKey(codeModelIncludeDirectory.Key)) { IncludePaths.Add(codeModelIncludeDirectory.Key, codeModelIncludeDirectory.Value != null); } } } }
public override Entity Resolve(Entity owner, string key, bool fallback = false) { switch (key) { case EntityKeys.TargetFullNameKey: return(owner.Create(key, owner.Value <Target>().GetFullName())); case EntityKeys.TargetShortFullNameKey: return(owner.Create(key, owner.Value <Target>().GetShortFullName())); case EntityKeys.TargetEngineerVersionKey: return(owner.Create(key, EngineerVersion(owner.Value <Target>()))); case EntityKeys.TargetVersionKey: Version version = new Version(); string versionString = owner.Value <Target>().Version; if (Version.TryParse(versionString, out Version parsedVersion)) { version = parsedVersion; } return(owner.Create(key, version)); case EntityKeys.NameKey: return(owner.Create(key, owner.Value <Target>().Name)); default: return(GetTargets(key == EntityKeys.ValidatedTargetsKey)); } Entity GetTargets(bool validate) { CommandEntity commandEntity = CommandEntity.Decorate(owner.Origin); if (commandEntity.IsCommandArgumentSpecified(Constants.TargetArgumentName)) { IEnumerable <string> targets = commandEntity.GetMultiValueArgument(Constants.TargetArgumentName); //TODO parseLocation true here is legacy as soon as old generate library command is gone, reset to false IEnumerable <Target> targetsSet = GetSpecificTargets(targets, validate, true).Select(t => t.Item1); return(owner.Create(key, targetsSet.Select(t => owner.Create(key.Singular(), t.Name, t)))); } ProjectEntity project = ProjectEntity.Decorate(owner); TargetsResult result = Targets(project, validate); return(owner.Create(key, result.ValidTargets.Select(t => owner.Create(key.Singular(), t.Name, t)))); } string EngineerVersion(Target target) { string possibleVersion = target.LongVersion.Trim().Split(' ')[0]; if (Version.TryParse(possibleVersion, out Version version)) { int parts = possibleVersion.Split('.').Length; if (parts == 2) { return($"{version.ToString(2)}.0"); } if (parts > 2) { return(version.ToString(3)); } } return(target.ShortVersion); } }
public override Entity Resolve(Entity owner, string key, bool fallback = false) { if (key == EntityKeys.EscapeProjectNameFormatKey && owner.Type == EntityKeys.FormatKey) { return(EscapeProjectName()); } Entity rootEntity = CreateRootEntity(); rootEntity.SetMetaData(true, EntityKeys.IsRoot); return(rootEntity); Entity EscapeProjectName() { string value = owner.Owner?.Value <string>(); if (string.IsNullOrEmpty(value)) { return(owner.Create(key, string.Empty)); } value = Regex.Replace(value, @"[^a-zA-Z0-9_\.]", "_"); //Replace not allowed values with _ int length, newLength; do //Remove double _ and . { length = value.Length; value = value.Replace("__", "_"); value = value.Replace("..", "."); newLength = value.Length; } while (length != newLength); value = value.TrimEnd('.'); //Remove trailing dot string prefix = string.Empty; int lastPoint = value.LastIndexOf('.'); if (lastPoint >= 0) { prefix = value.Substring(0, lastPoint); value = value.Substring(lastPoint + 1); } if (value[0] == '_' && value.Length > 1) { value = "_" + new string(char.ToUpperInvariant(value[1]), 1) + value.Substring(2); } else { value = new string(char.ToUpperInvariant(value[0]), 1) + value.Substring(1); } if (!Regex.IsMatch(value, @"^_?[A-Z]")) {//Start with uppercase letter value = "Library"; } if (!string.IsNullOrEmpty(prefix)) { value = prefix + "." + value; } return(owner.Create(key, value)); } Entity CreateRootEntity() { if (HasRootInHierarchy(out Entity hierarchyRoot)) { return(hierarchyRoot); } if (owner.IsCommand()) { string rootFilePath = owner.GetPathCommandArgument(); VirtualDirectory baseDirectory = fileSystem.FileExists(rootFilePath) ? fileSystem.GetFile(rootFilePath).Parent : fileSystem.DirectoryExists(rootFilePath) ? fileSystem.GetDirectory(rootFilePath) : throw new FormattableException($"The path {rootFilePath} does not exist."); if (owner.HasTemplate()) { return(CreateRootBasedOnTemplate(baseDirectory)); } return(CreateRootBasedOnAllRootTemplates(baseDirectory)); } if (owner.IsTemplateOnly()) { TemplateDescription template = owner.Template(); TemplateDescription rootTemplate = FindRootTemplate(template); if (rootTemplate == null) { throw new RootTemplateNotFoundException(template.name); } return(owner.Create(rootTemplate.name)); } return(CreateFallback()); ICodeModel ParseCodeModel(VirtualDirectory virtualDirectory, Entity root) { try { ICodeModel model = parser.Parse(GetSourceDirectories(virtualDirectory), GetIncludeDirectories(virtualDirectory), out IEnumerable <CodeSpecificException> loggableExceptions); bool firstException = true; foreach (CodeSpecificException loggableException in loggableExceptions) { if (firstException) { executionContext.WriteInformation( "The following code errors were found inside the parsed include files. " + "Containing types cannot be used as port types.", false); firstException = false; } loggableException.CompleteCodeExceptions(virtualDirectory); executionContext.WriteError(loggableException.ToString(), false); } return(model); } catch (Exception exception) { exception.CompleteCodeExceptions(virtualDirectory); throw; } IDictionary <string, VirtualDirectory> GetIncludeDirectories(VirtualDirectory baseDirectory) { IEnumerable <string> includes = HasIncludeDirectoriesCommandArgument(owner) ? GetIncludeDirectoriesCommandArgument(owner) : Enumerable.Empty <string>(); Target[] projectTargets = GetProjectTargets(); if (projectTargets.Any()) { if (!includes.Any() && HasNoIncludeDetectionCommandArgument(owner) && !GetNoIncludeDetectionCommandArgument(owner)) { try { includes = informationService.RetrieveBuildSystemProperties(root, projectTargets[0], executionContext.Observable).IncludePaths; } catch (Exception e) { if (e is FormattableException || e is AggregateException) { executionContext.WriteWarning($"Automatic include detection via cmake could not be executed. See log for details."); executionContext.WriteError(e.ToString(), false); } else { throw; } } } } else { executionContext.WriteWarning($"The project in {baseDirectory.FullName} does not contain a valid target. " + $"Without a valid target port structures from within the SDK can not be generated " + $"and automatic include detection will not work as well."); } includes = includes.Concat(new[] { Path.Combine(Constants.IntermediateFolderName, Constants.GeneratedCodeFolderName) }); includes = includes.Concat(GetTargetIncludes()); IDictionary <string, VirtualDirectory> includeDirectories = includes.Distinct().ToDictionary(x => x, GetIncludeDirectory); return(includeDirectories); IEnumerable <string> GetTargetIncludes() { SdkInformation[] projectSdks = projectTargets.Select(sdkRepository.GetSdk) .Distinct() .ToArray(); return(projectSdks.SelectMany(s => s.IncludePaths.Concat(s.CompilerInformation.IncludePaths))); } VirtualDirectory GetIncludeDirectory(string path) { if (fileSystem.DirectoryExists(path, baseDirectory.FullName)) { return(fileSystem.GetDirectory(path, baseDirectory.FullName)); } executionContext.WriteWarning($"The include path {path} was not found and will not be used.", false); return(null); } Target[] GetProjectTargets() { ProjectEntity project = ProjectEntity.Decorate(root); TargetsResult targetsResult = targetParser.Targets(project, false); Target[] availableTargets = sdkRepository.GetAllTargets().ToArray(); Target[] targets = targetsResult.ValidTargets .Select(tr => availableTargets.FirstOrDefault( t => t.Name == tr.Name && t.LongVersion == tr.LongVersion)) .Where(t => t != null) .ToArray(); return(targets); } } ICollection <VirtualDirectory> GetSourceDirectories(VirtualDirectory baseDirectory) { IEnumerable <string> sources = HasSourceDirectoriesCommandArgument(owner) ? GetSourceDirectoriesCommandArgument(owner) : Enumerable.Empty <string>(); ICollection <VirtualDirectory> sourceDirectories = sources.Select(s => fileSystem.DirectoryExists(s, baseDirectory.FullName) ? fileSystem.GetDirectory(s, baseDirectory.FullName) : throw new FormattableException( $"The path {s} does not exist.")) .ToArray(); if (!sourceDirectories.Any()) { sourceDirectories = baseDirectory.Directories.Any(d => d.Name == Constants.SourceFolderName) ? new[] { baseDirectory.Directory(Constants.SourceFolderName) } : new[] { baseDirectory }; } return(sourceDirectories); } IEnumerable <string> GetSourceDirectoriesCommandArgument(Entity entity) { return(entity.Value <CommandDefinition>() ?.Argument <MultipleValueArgument>(EntityKeys.SourceDirectoryKey) ?.Values ?? entity.Value <CommandArgs>() ?.PropertyValue <IEnumerable <string> >(EntityKeys.SourceDirectoryKey) ?? Enumerable.Empty <string>()); } bool HasSourceDirectoriesCommandArgument(Entity entity) { return(entity.Value <CommandDefinition>() ?.Argument <MultipleValueArgument>(EntityKeys.SourceDirectoryKey) != null || entity.Value <CommandArgs>() ?.HasPropertyValue(EntityKeys.SourceDirectoryKey, typeof(IEnumerable <string>)) == true); } IEnumerable <string> GetIncludeDirectoriesCommandArgument(Entity entity) { return(entity.Value <CommandDefinition>() ?.Argument <MultipleValueArgument>(EntityKeys.IncludeDirectoryKey) ?.Values ?? entity.Value <CommandArgs>() ?.PropertyValue <IEnumerable <string> >(EntityKeys.IncludeDirectoryKey) ?? Enumerable.Empty <string>()); } bool HasIncludeDirectoriesCommandArgument(Entity entity) { return(entity.Value <CommandDefinition>() ?.Argument <MultipleValueArgument>(EntityKeys.IncludeDirectoryKey) != null || entity.Value <CommandArgs>() ?.HasPropertyValue(EntityKeys.IncludeDirectoryKey, typeof(IEnumerable <string>)) == true); } bool GetNoIncludeDetectionCommandArgument(Entity entity) { return(entity.Value <CommandDefinition>() ?.Argument <BoolArgument>(Constants.NoIncludePathDetection) ?.Value ?? entity.Value <CommandArgs>() ?.PropertyValue <bool>(Constants.NoIncludePathDetection.ToPropertyName()) ?? false); } bool HasNoIncludeDetectionCommandArgument(Entity entity) { return(entity.Value <CommandDefinition>() ?.Argument <BoolArgument>(Constants.NoIncludePathDetection) != null || entity.Value <CommandArgs>() ?.HasPropertyValue(Constants.NoIncludePathDetection.ToPropertyName(), typeof(bool)) == true); } } ICodeModel CreateCodeModel(Entity root) { VirtualDirectory rootDirectory = fileSystem.GetDirectory(root.Path); return(ParseCodeModel(rootDirectory, root)); } Entity CreateFallback(VirtualDirectory baseDirectory = null) { Entity fallbackEntity = null; try { if (owner.HasPathCommandArgument()) { VirtualDirectory rootDirectory = fileSystem.GetDirectory(owner.GetPathCommandArgument(), createNew: false); if (rootDirectory != null && fileSystem.DirectoryExists(rootDirectory.FullName)) { IEnumerable <VirtualFile> possibleComponents = rootDirectory.Files(searchString: "*.hpp", searchRecursive: true); bool result = possibleComponents.Where(c => { using (Stream fileStream = c.OpenRead()) using (StreamReader streamReader = new StreamReader(fileStream)) { string content = streamReader.ReadToEnd(); if (content.Contains("MetaComponentBase")) { fallbackEntity = owner.Create("acfproject"); } } return(false); }).Any(); } } } catch (Exception exception) { executionContext.WriteVerbose($"Error while creating fallback root entity.{Environment.NewLine}{exception}"); } if (fallbackEntity == null) { fallbackEntity = owner.Create("project"); } fallbackEntity.AddValue(() => CreateCodeModel(fallbackEntity)); if (baseDirectory != null) { fallbackEntity.AddValue(baseDirectory); } return(fallbackEntity); } bool HasRootInHierarchy(out Entity foundRoot) { foundRoot = owner.EntityHierarchy().FirstOrDefault(HasRootTemplate); return(foundRoot != null); bool HasRootTemplate(Entity possibleRoot) { return(possibleRoot.HasTemplate() && possibleRoot.Template().isRoot); } } TemplateDescription FindRootTemplate(TemplateDescription template) { Stack <TemplateDescription> unvisited = new Stack <TemplateDescription>(new[] { template }); List <TemplateDescription> visited = new List <TemplateDescription>(); while (unvisited.Any()) { TemplateDescription current = unvisited.Pop(); if (current.isRoot) { return(current); } visited.Add(current); foreach (templateRelationship relationship in current.Relationship) { TemplateDescription description = templateRepository.Template(relationship.type); if (description != null && !visited.Contains(description)) { unvisited.Push(description); } } } return(null); } Entity CreateRootBasedOnAllRootTemplates(VirtualDirectory baseDirectory) { return(IdentifyRoot(templateRepository.Templates.Where(t => t.isRoot), baseDirectory)); } Entity IdentifyRoot(IEnumerable <TemplateDescription> templateDescriptions, VirtualDirectory baseDirectory) { Entity root = null; foreach (TemplateDescription possibleTemplate in templateDescriptions.OrderByDescending(Depth)) { root = identifierRepository.FindAllEntities(possibleTemplate.name, owner, possibleTemplate.identifier) .FirstOrDefault(); if (root != null) { break; } } if (root != null) { root.AddValue(() => CreateCodeModel(root)); } else { root = CreateFallback(baseDirectory); } return(root); int Depth(TemplateDescription templateDescription) { int depth = 0; while (!string.IsNullOrEmpty(templateDescription?.basedOn)) { templateDescription = templateRepository.Template(templateDescription.basedOn); depth++; } return(depth); } } Entity CreateRootBasedOnTemplate(VirtualDirectory baseDirectory) { TemplateDescription template = owner.Template(); IEnumerable <TemplateDescription> possibleTemplates = FindAllRootTemplates(); return(IdentifyRoot(possibleTemplates, baseDirectory)); IEnumerable <TemplateDescription> FindAllRootTemplates() { TemplateDescription rootTemplate = FindRootTemplate(template); if (rootTemplate == null) { throw new RootTemplateNotFoundException(template.name); } List <TemplateDescription> result = new List <TemplateDescription>(); Stack <TemplateDescription> unvisited = new Stack <TemplateDescription>(); unvisited.Push(rootTemplate); while (unvisited.Any()) { TemplateDescription current = unvisited.Pop(); result.Add(current); foreach (TemplateDescription description in templateRepository.Templates .Where(t => t.basedOn ?.Equals(current.name, StringComparison .OrdinalIgnoreCase) == true)) { unvisited.Push(description); } } return(result); } } } }