Example #1
0
        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);
                    }
                }
            }
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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);
                    }
                }
            }
        }