protected override CommandResult ExecuteDetailed(GetTargetsCommandArgs args, ChangeObservable observable) { IEnumerable <Exception> exceptions = Enumerable.Empty <Exception>(); TargetsCommandResult commandResult; if (args.All) { commandResult = new TargetsCommandResult(sdkRepository.GetAllTargets() .Select(t => new TargetResult(t.Name, t.Version, t.LongVersion, t.ShortVersion)) .OrderBy(t => t.Name).ThenByDescending(t => t.Version)); } else { ExecutionContext.WriteWarning("This command is deprecated. Use 'get project-information' instead.", false); ProjectEntity project = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root); TargetsResult targetsResult = targetParser.Targets(project, false); Target[] availableTargets = sdkRepository.GetAllTargets().ToArray(); commandResult = new TargetsCommandResult(targetsResult.ValidTargets .Select(t => new TargetResult(t.Name, t.Version, t.LongVersion, t.ShortVersion, availableTargets.Any(at => t.Name == at.Name && at.LongVersion == t.LongVersion))) .OrderBy(t => t.Name).ThenByDescending(t => t.Version)); exceptions = targetsResult.Errors; } return(new CommandResult(0, commandResult, exceptions)); }
protected override CommandResult ExecuteDetailed(GetSdksCommandArgs args, ChangeObservable observable) { IEnumerable <SdkPath> sdkPaths = Enumerable.Empty <SdkPath>(); IEnumerable <Exception> exceptions = Enumerable.Empty <Exception>(); if (args.All) { sdkPaths = sdkRepository.GetAllTargets() .GroupBy(target => sdkRepository.GetSdk(target).Root.FullName) .Select(group => new SdkPath(group.Key, group.Select(target => new TargetResult(target.Name, target.Version, target.LongVersion, target.ShortVersion)))); } else { ProjectEntity project = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root); TargetsResult targetsResult = targetParser.Targets(project); sdkPaths = targetsResult.ValidTargets .GroupBy(target => sdkRepository.GetSdk(target).Root.FullName) .Select(group => new SdkPath(group.Key, group.Select(target => new TargetResult(target.Name, target.Version, target.LongVersion, target.ShortVersion)))); exceptions = targetsResult.Errors; } return(new CommandResult(0, new SdksCommandResult(sdkPaths))); }
protected override int Execute(SetTargetsCommandArgs args, ChangeObservable observable) { ProjectEntity project = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root); FileEntity fileEntity = FileEntity.Decorate(project); if (!project.Settings.IsPersistent) { throw new TargetNotSettableForProjectException(); } if (args.Add) { Target result = targetParser.AddTarget(project, args.Name, args.Version); userInterface.WriteInformation($"Successfully added target {result.Name} {result.LongVersion} to project {fileEntity.Directory.FullName}."); } else if (args.Remove) { Target result = targetParser.RemoveTarget(project, args.Name, args.Version); userInterface.WriteInformation($"Successfully removed target {result.Name} {result.LongVersion} from project {fileEntity.Directory.FullName}."); } else { throw new SetTargetsOptionMissingException(); } return(0); }
protected override int Execute(UpdateTargetsCommandArgs args, ChangeObservable observable) { ProjectEntity project = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root); targetParser.UpdateTargets(project, args.Downgrade); return(0); }
public void Execute(Entity dataModel, ChangeObservable observable) { ProjectEntity project = ProjectEntity.Decorate(dataModel.Root); IEnumerable <Entity> targets = project.Targets.ToArray(); if (!targets.Any()) { throw new FormattableException("Please use --target to specify for which targets the library shall be generated."); } foreach (Entity target in targets) { VirtualDirectory deployRoot = DeployEntity.Decorate(target).DeployDirectory; VirtualDirectory deployDirectory = deployRoot.Directory("lib", project.Name); BuildEntity buildEntity = BuildEntity.Decorate(target); if (!buildEntity.HasBuildSystem) { TargetEntity targetEntity = TargetEntity.Decorate(target); executionContext.WriteWarning(new CMakeBuildSystemNotFoundException(targetEntity.FullName, buildEntity.BuildType).Message); return; } foreach (string externalLibrary in buildEntity.BuildSystem.ExternalLibraries) { VirtualFile newFile = fileSystem.GetFile(externalLibrary).CopyTo(deployDirectory); executionContext.Observable.OnNext(new Change(() => newFile.Delete(), $"Copied {externalLibrary} to {newFile.FullName}.")); } } }
protected override CommandResult ExecuteDetailed(GetIncludePathsCommandArgs args, ChangeObservable observable) { ExecutionContext.WriteWarning("This command is deprecated. Use 'get project-information' instead.", false); ProjectEntity project = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root); TargetsResult targetsResult = targetParser.Targets(project); IEnumerable <string> paths = targetsResult.ValidTargets .Select(sdkRepository.GetSdk) .Where(sdk => sdk != null) .Distinct() .SelectMany(sdk => sdk.IncludePaths); return(new CommandResult(0, new IncludePathsCommandResult(paths.Select(p => new Path(p))), targetsResult.Errors)); }
private metaDataTemplate FindFieldTemplate(string name, Entity owner) { IEnumerable <metaDataTemplate> possibleTemplates = templateRepository.FieldTemplates.Where(t => t.name.Equals(name, StringComparison.OrdinalIgnoreCase) && FirmwareVersionIsSupported(t.supportedFirmwareVersions)); metaDataTemplate fieldTemplate = NewestTemplate(possibleTemplates); return(fieldTemplate); bool FirmwareVersionIsSupported(string supportedFirmwareVersion) { if (supportedFirmwareVersion == null) { return(true); } ProjectEntity project = ProjectEntity.Decorate(owner.IsRoot() ? owner : owner.Root); Version minTarget = project.Targets.Min(t => TargetEntity.Decorate(t).Version); if (minTarget == null) { return(true); } NuGetVersion targetVersion = new NuGetVersion(minTarget); if (VersionRange.TryParse(supportedFirmwareVersion, out VersionRange supportedVersion)) { return(supportedVersion.Satisfies(targetVersion)); } return(true); } metaDataTemplate NewestTemplate(IEnumerable <metaDataTemplate> templates) { IEnumerable <metaDataTemplate> templatesWithVersion = templates.Where(t => t.supportedFirmwareVersions != null); if (!templatesWithVersion.Any()) { return(templates.FirstOrDefault()); } return(templatesWithVersion.Where(template => template.supportedFirmwareVersions.Equals( templatesWithVersion.Max(t => t.supportedFirmwareVersions), StringComparison.OrdinalIgnoreCase)) .FirstOrDefault()); } }
public int BuildLibraryForProject(Entity project, ChangeObservable observable, string metaFilesDirectory, string libraryLocation, string outputDirectory, Guid libraryGuid, IEnumerable <string> targets, IEnumerable <string> externalLibraries, string buildType) { userInterface.WriteInformation("Starting library generation..."); ProjectEntity projectEntity = ProjectEntity.Decorate(project); IEnumerable <(Target, string)> targetsSet; if (!targets.Any()) { TargetsResult ts = targetParser.Targets(projectEntity, false); if (!ts.ValidTargets.Any()) { throw new FormattableException ("Please use --target to specify for which targets the library shall be generated."); } else { HashSet <(Target, string)> targetsHashSet = new HashSet <(Target, string)>(); foreach (Target target in ts.ValidTargets) { targetsHashSet.Add((target, null)); } targetsSet = targetsHashSet; } } else { targetsSet = targetParser.GetSpecificTargets(targets, false); } Dictionary <Target, IEnumerable <VirtualFile> > externalLibs = ExternalLibrariesParser.ParseExternalLibraries(externalLibraries, targetParser, fileSystem, targetsSet.Select(t => t.Item1)); int result = libraryBuilderExecuter.Execute(projectEntity, metaFilesDirectory, libraryLocation, outputDirectory, observable, userInterface, libraryGuid, targetsSet, externalLibs, buildType); if (result == 0) { userInterface.WriteInformation("Successfully generated library!"); } return(result); }
public void Execute(Entity dataModel, ChangeObservable observable) { ProjectEntity project = ProjectEntity.Decorate(dataModel.Root); if (!project.Settings.IsPersistent) { try { ICodeModel codeModel = dataModel.Root.Value <ICodeModel>(); if (codeModel != null) { VirtualEntry acfFile = codeModel.SourceDirectories .SelectMany(directory => directory.Entries) .Where(entry => entry.Name.EndsWith(Constants.AcfConfigExtension, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (acfFile != null) { using (Stream xmlStream = (acfFile as VirtualFile).OpenRead()) using (XmlReader reader = XmlReader.Create(xmlStream)) { while (reader.Read()) { if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "Component") { string componenttype = reader.GetAttribute("type"); if (componenttype.Contains("::")) { throw new OldAcfConfigException(); } } } } } } } catch (XmlException) { executionContext.WriteWarning("From version 2021.6 on the component type attribute inside the .acf.config file" + " must use the namespace separator '.' instead of '::'!"); } } }
protected override CommandResult ExecuteDetailed(GetCompilerSpecificationsCommandArgs args, ChangeObservable observable) { ProjectEntity project = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root); TargetsResult targetsResult = targetParser.Targets(project); IEnumerable <CompilerInformation> compilers = targetsResult.ValidTargets .Select(sdkRepository.GetSdk) .Where(sdk => sdk != null) .Distinct() .Select(sdk => sdk.CompilerInformation); return(new CommandResult(0, new CompilerSpecificationCommandResult( compilers.Select(c => new CompilerSpecificationResult(c.CompilerPath, "cpp", c.Sysroot, c.Flags, c.IncludePaths.Select(p => new Path(p)), c.Makros.Select(m => new CompilerMacroResult(m.Name, m.Value))))), targetsResult.Errors)); }
protected override CommandResult ExecuteDetailed(GetSdksCommandArgs args, ChangeObservable observable) { string[] sdks; IEnumerable <Exception> exceptions = Enumerable.Empty <Exception>(); if (args.All) { sdks = sdkRepository.Sdks.Select(s => s.Root.FullName).ToArray(); } else { ProjectEntity project = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root); TargetsResult targetsResult = targetParser.Targets(project); sdks = targetsResult.ValidTargets.Select(sdkRepository.GetSdk).Distinct() .Select(s => s.Root.FullName).ToArray(); exceptions = targetsResult.Errors; } return(new CommandResult(0, new SdksCommandResult(sdks.Select(s => new Path(s))), exceptions)); }
public void DeployFiles(Entity dataModel) { IEnumerable <Entity> deployableEntities = dataModel.Root.Hierarchy(); ProjectEntity project = ProjectEntity.Decorate(dataModel.Root); // get targets to deploy for IEnumerable <Target> targets = null; CommandEntity command = CommandEntity.Decorate(dataModel); if (command.IsCommandArgumentSpecified(Constants.TargetArgumentName)) { IEnumerable <string> rawTargets = command.GetMultiValueArgument(Constants.TargetArgumentName); if (rawTargets.Any()) { targets = targetParser.GetSpecificTargets(rawTargets, false).Select(t => t.Item1); } else { targets = targetParser.Targets(project, false).ValidTargets; } } else { targets = targetParser.Targets(project, false).ValidTargets; } if (!targets.Any()) { throw new NoTargetSpecifiedException(); } foreach (Entity deployableEntity in deployableEntities) { DeployFilesFromTemplate(deployableEntity); } if (command.IsCommandArgumentSpecified(Constants.FilesArgumentName)) { IEnumerable <string> files = command.GetMultiValueArgument(Constants.FilesArgumentName); foreach (string file in files) { DeployFileFromArgument(file); } } void DeployFileFromArgument(string file) { Match match = FilesDecoder.Match(file); if (!match.Success) { throw new FormattableException($"The input {file} could not be parsed. Expected pattern is <fileLocation>|<destination>[|<target>]"); } string from = match.Groups["from"].Value; string to = match.Groups["destination"].Value; string rawTarget = match.Groups["target"].Value; VirtualDirectory baseDirectory = null; string relativePath = null; bool recreateStructure = false; string[] path = fileSystem.GetPath(from); int firstWildCard = path.TakeWhile(p => !p.Contains('*') && !p.Contains('?')).Count(); if (firstWildCard != path.Length) { baseDirectory = fileSystem.GetDirectory(Path.Combine(path.Take(firstWildCard).ToArray()), project.Path, false); relativePath = Path.Combine(path.Skip(firstWildCard).ToArray()); recreateStructure = true; } if (recreateStructure) { IEnumerable <VirtualFile> deployFiles = baseDirectory.Files(relativePath, true).ToArray(); if (!deployFiles.Any()) { throw new DeployFileNotFoundException(@from); } foreach (VirtualFile deployFile in deployFiles) { string structure = Path.GetDirectoryName(deployFile.GetRelativePath(baseDirectory)); string fileDestination = string.IsNullOrEmpty(structure) ? to : Path.Combine(to, structure); DeployFile(deployFile.FullName, fileDestination); } } else if (fileSystem.FileExists(from, project.Path)) { DeployFile(from, to); } else { throw new DeployFileNotFoundException(@from); } void DeployFile(string sourceFile, string destinationDirectory) { if (!string.IsNullOrEmpty(rawTarget)) { DeployFileForRawTarget(rawTarget, sourceFile, destinationDirectory); } else { foreach (Target target in targets) { DeployFileForTarget(target, sourceFile, destinationDirectory); } } } void DeployFileForRawTarget(string target, string sourceFile, string destinationDirectory) { Target parsedTarget = targetParser.ParseTarget(target, null, targets); DeployFileForTarget(parsedTarget, sourceFile, destinationDirectory); } void DeployFileForTarget(Target target, string sourceFile, string destinationDirectory) { VirtualFile fileToCopy = fileSystem.GetFile(sourceFile, project.Path); VirtualFile copiedFile = fileSystem.GetDirectory(destinationDirectory, GetOutputDirectory(target).FullName).File(fileToCopy.Name); using (Stream source = fileToCopy.OpenRead(true)) using (Stream destination = copiedFile.OpenWrite()) { destination.SetLength(0); source.CopyTo(destination); executionContext.WriteVerbose($"Deployed file {fileToCopy.FullName} to {copiedFile.FullName}."); } } } void DeployFilesFromTemplate(Entity deployableEntity) { TemplateDescription template = deployableEntity.Template(); if (template == null) { return; } foreach (templateFile file in template.File) { if (!file.deployPathSpecified) { continue; } VirtualFile deployableFile = GetFile(file, dataModel.Root.Path, false, out string path); DeployFile(file, deployableFile, path); } foreach (templateGeneratedFile generatedFile in template.GeneratedFile ?? Enumerable.Empty <templateGeneratedFile>()) { if (!generatedFile.deployPathSpecified) { continue; } VirtualFile deployableFile = GetFile(generatedFile, dataModel.Root.Path, true, out string path); DeployFile(generatedFile, deployableFile, path); } VirtualFile GetDestination(templateFile file, Target target, string name) { string basePath = GetOutputDirectory(target).FullName; string path = resolver.Resolve(file.deployPath ?? string.Empty, deployableEntity); VirtualFile destination = fileSystem.GetFile(Path.Combine(path, name), basePath); return(destination); } void DeployFile(templateFile file, VirtualFile deployableFile, string filePath) { if (deployableFile == null) { executionContext.WriteVerbose($"Could not find file {filePath} in {dataModel.Root.Path}, the file will not be deployed."); return; } foreach (Target target in targets) { VirtualFile destination = GetDestination(file, target, deployableFile.Name); using (Stream source = deployableFile.OpenRead(true)) using (Stream dest = destination.OpenWrite()) { dest.SetLength(0); source.CopyTo(dest); } executionContext.WriteVerbose($"Deployed file {deployableFile.FullName} to {destination.FullName}."); } } VirtualFile GetFile(templateFile file, string basePath, bool isGeneratedFile, out string realFilePath) { string path = resolver.Resolve(file.path ?? string.Empty, deployableEntity); string name = resolver.Resolve(file.name, deployableEntity); if (isGeneratedFile && file is templateGeneratedFile generatedFile) { realFilePath = Path.Combine(path, name); if (!Path.IsPathRooted(realFilePath)) { realFilePath = Path.Combine(Constants.IntermediateFolderName, generatedFile.generator?.ToLowerInvariant() ?? string.Empty, realFilePath); } } else { realFilePath = Path.Combine(path, name); } VirtualFile destination = fileSystem.FileExists(realFilePath, basePath) ? fileSystem.GetFile(realFilePath, basePath) : null; return(destination); } } VirtualDirectory GetOutputDirectory(Target target) { string buildTypeFolder = command.IsCommandArgumentSpecified(Constants.BuildTypeArgumentName) ? FormatBuildType(command.GetSingleValueArgument(Constants.BuildTypeArgumentName)) : Constants.ReleaseFolderName; string basePath = project.Path; if (!command.IsCommandArgumentSpecified(Constants.OutputArgumentName)) { return(fileSystem.GetDirectory(Path.Combine(basePath, Constants.LibraryFolderName, target.GetFullName().Replace(',', '_'), buildTypeFolder))); } basePath = fileSystem.GetDirectory(command.GetSingleValueArgument(Constants.OutputArgumentName), basePath).FullName; basePath = Path.Combine(basePath, target.GetFullName().Replace(',', '_'), buildTypeFolder); return(fileSystem.GetDirectory(basePath)); string FormatBuildType(string buildType) { if (string.IsNullOrEmpty(buildType)) { return(Constants.ReleaseFolderName); } return(buildType.Substring(0, 1).ToUpperInvariant() + buildType.Substring(1).ToLowerInvariant()); } } }
//TODO Patch libmeta here public int Execute(Entity dataModel) { ProjectEntity project = ProjectEntity.Decorate(dataModel.Root); CodeEntity projectCodeEntity = CodeEntity.Decorate(project); string projectName = projectCodeEntity.Namespace; IEnumerable <Entity> targets = project.Targets.ToArray(); if (!targets.Any()) { throw new FormattableException("Please use --target to specify for which targets the library shall be generated."); } Dictionary <Entity, VirtualFile> projectLibraries = targets.ToDictionary(t => t, FindLibrary); List <string> externalLibraries = new List <string>(); List <VirtualFile> deletableFiles = new List <VirtualFile>(); foreach (Entity target in targets) { CopyExternalLibrariesToOutputDirectory(target, projectLibraries, out IEnumerable <string> libraries, out IEnumerable <VirtualFile> toBeDeleted); externalLibraries.AddRange(libraries); deletableFiles.AddRange(toBeDeleted); } CheckMetaFiles(targets.First()); string commandOptionsFile = GenerateCommandOptions(project, projectLibraries, projectName); int result = ExecuteLibraryBuilderWithCommandOptions(commandOptionsFile, project); foreach (VirtualFile deletable in deletableFiles) { deletable.Delete(); } return(result); VirtualFile FindLibrary(Entity target) { VirtualDirectory deployDirectory = DeployEntity.Decorate(target).DeployDirectory; string libFile = deployDirectory.Files("*.so", true) .OrderByDescending(f => f.Name.Equals($"lib{projectName}.so", StringComparison.OrdinalIgnoreCase)) .ThenByDescending(f => f.LastWriteTime) .FirstOrDefault() ?.FullName; if (string.IsNullOrEmpty(libFile)) { throw new LibraryNotFoundException(deployDirectory.FullName); } VirtualFile file = fileSystem.GetFile(libFile); return(file); } void CheckMetaFiles(Entity target) { TemplateEntity projectTemplateEntity = TemplateEntity.Decorate(project); VirtualDirectory deployDirectory = DeployEntity.Decorate(target).DeployDirectory; if (!fileSystem.FileExists(Path.Combine(deployDirectory.FullName, $"{projectName}.libmeta"))) { throw new MetaLibraryNotFoundException(deployDirectory.FullName); } PatchLibmeta(fileSystem.GetFile(Path.Combine(deployDirectory.FullName, $"{projectName}.libmeta"))); IEnumerable <VirtualFile> metaFiles = deployDirectory.Files(searchRecursive: true); IEnumerable <Entity> componentsWithoutMetaFile = projectTemplateEntity.EntityHierarchy .Where(e => e.Type.Equals("component", StringComparison.OrdinalIgnoreCase)) .Where(c => !metaFiles.Any(f => f.Name.Equals($"{c.Name}.{Constants.CompmetaExtension}", StringComparison.Ordinal))) .ToArray(); if (componentsWithoutMetaFile.Any()) { throw new MetaFileNotFoundException(deployDirectory.FullName, $"{componentsWithoutMetaFile.First().Name}.{Constants.CompmetaExtension}"); } IEnumerable <Entity> programsWithoutMetaFile = projectTemplateEntity.EntityHierarchy .Where(e => e.Type.Equals("program", StringComparison.OrdinalIgnoreCase)) .Where(p => !metaFiles.Any(f => f.Name.Equals($"{p.Name}.{Constants.ProgmetaExtension}", StringComparison.Ordinal))) .ToArray(); if (programsWithoutMetaFile.Any()) { throw new MetaFileNotFoundException(deployDirectory.FullName, $"{programsWithoutMetaFile.First().Name}.{Constants.ProgmetaExtension}"); } } void PatchLibmeta(VirtualFile libmetaFile) { if (!externalLibraries.Any()) { return; } XmlSerializer serializer = new XmlSerializer(typeof(MetaConfigurationDocument)); MetaConfigurationDocument document; try { using (Stream fileStream = libmetaFile.OpenRead()) using (XmlReader reader = XmlReader.Create(fileStream)) { document = (MetaConfigurationDocument)serializer.Deserialize(reader); } } catch (XmlException e) { executionContext.WriteWarning($"Cannot parse libmeta file. Cannot patch dependencies. {e.Message}"); return; } document.schemaVersion = "4.0"; LibraryDefinition definition = (LibraryDefinition)document.Item; IEnumerable <string> dependencies = externalLibraries.Select(Path.GetFileName) .Concat(definition.Dependencies?.Select(d => d.path) ?? Enumerable.Empty <string>()); definition.Dependencies = dependencies.Select(d => new DependencyDefinition { path = d }).ToArray(); using (Stream fileStream = libmetaFile.OpenWrite()) using (XmlWriter writer = XmlWriter.Create(fileStream, new XmlWriterSettings { Indent = true })) { serializer.Serialize(writer, document); } } }
public override Entity Resolve(Entity owner, string key, bool fallback = false) { TemplateEntity ownerTemplateEntity = TemplateEntity.Decorate(owner); if (key == EntityKeys.FieldArpDataTypeKey && owner.Type == EntityKeys.FormatKey) { return(ResolveArpDataType()); } if (key == EntityKeys.TypeMetaDataFormatKey && owner.Type == EntityKeys.FormatKey) { return(ResolveTypeMetaDataFormat()); } if (key == EntityKeys.ExpandHiddenTypesFormatKey) { return(ExpandHiddenTypes()); } if (key == EntityKeys.FilterHiddenTypesFormatKey) { return(FilterHiddenTypes()); } if (key == EntityKeys.IsFieldKey) { return(owner.Create(key, CodeEntity.Decorate(owner).AsField != null)); } if (key == EntityKeys.IsTypeKey) { return(owner.Create(key, CodeEntity.Decorate(owner).AsType != null)); } if (key == EntityKeys.BigDataProjectKey) { return(GetBigDataProjectEntity()); } if (key == EntityKeys.NormalProjectKey) { return(GetNormalProjectEntity()); } ISymbol symbol = owner.Value <ISymbol>(); if (symbol != null) { Entity result = owner.PropertyValueEntity(key, symbol); if (result != null) { return(result); } throw new ContentProviderException(key, owner); } if (key == EntityKeys.BaseDirectoryKey && HasBaseDirectory(owner, out string baseDirectory)) { return(owner.Create(key, baseDirectory)); } IType type = owner.Value <IType>(); if (type != null) { return(ResolveType()); } IField field = owner.Value <IField>(); if (field != null) { return(ResolveField()); } IDataType dataType = owner.Value <IDataType>(); if (dataType != null) { return(ResolveDataType()); } ICodeModel codeModel = owner.Value <ICodeModel>(); if (codeModel != null) { return(ResolveCodeModel()); } throw new ContentProviderException(key, owner); IEnumerable <CodeEntity> GetPortEnums() { return(GetAllPorts().Concat(GetPortStructures().SelectMany(p => p.Fields)) .Select(f => f.ResolvedType) .Where(t => t.AsEnum != null) .Distinct()); } IEnumerable <CodeEntity> GetAllPorts() { bool IsPort(CodeEntity fieldEntity) { return(fieldEntity.AsField != null && fieldEntity.AsField.HasAttributeWithoutValue(EntityKeys.PortAttributeKey)); } return(TemplateEntity.Decorate(owner).EntityHierarchy .Select(CodeEntity.Decorate) .SelectMany(c => c.Fields) .Where(IsPort)); } IEnumerable <CodeEntity> GetPortStructures() { HashSet <CodeEntity> structures = new HashSet <CodeEntity>(GetAllPorts() .Select(f => f.ResolvedType) .Where(t => t.AsType != null && t.AsEnum == null), new FullNameCodeEntityComparer()); HashSet <CodeEntity> visited = new HashSet <CodeEntity>(new FullNameCodeEntityComparer()); while (structures.Except(visited).Any()) { foreach (CodeEntity structure in structures.Except(visited).ToArray()) { foreach (CodeEntity structureField in structure.Fields) { CodeEntity structureDataType = structureField.ResolvedType; if (structureDataType.AsType != null && structureDataType.AsEnum == null) { structures.Add(structureDataType); } } visited.Add(structure); } } return(structures); } Entity FilterHiddenTypes() { IEnumerable <IType> types = owner.Select(CodeEntity.Decorate) .Where(c => !c.IsHidden()) .Select(c => c.AsType) .ToArray(); string name = owner.FirstOrDefault()?.Name ?? string.Empty; return(owner.Create(key, types.Select(t => owner.Create(name, t.FullName, t)))); } Entity ExpandHiddenTypes() { IEnumerable <CodeEntity> dataSourceFields = owner.Select(CodeEntity.Decorate); dataSourceFields = ExpandHiddenStructureFields(dataSourceFields); string name = owner.FirstOrDefault()?.Name ?? string.Empty; return(owner.Create(key, dataSourceFields.Select(e => e.AsField) .Select(f => owner.Create(name, f.Name, f)))); IEnumerable <CodeEntity> ExpandHiddenStructureFields(IEnumerable <CodeEntity> fields) { foreach (CodeEntity hiddenField in fields) { CodeEntity hiddenType = hiddenField.ResolvedType; if (hiddenType == null || !hiddenType.IsHidden()) { yield return(hiddenField); continue; } foreach (CodeEntity hiddenTypeField in ExpandHiddenStructureFields(hiddenType.Fields)) { yield return(hiddenTypeField); } } } } T ChooseMetaDataTemplate <T>(IEnumerable <(T template, string name, string context)> templates) { return(templates.OrderByDescending(t => ContextComplexity(t.context ?? string.Empty)) .FirstOrDefault(Matches) .template); bool Matches((T template, string name, string context) template) { if (!key.Equals(template.name, StringComparison.OrdinalIgnoreCase)) { return(false); } if (string.IsNullOrEmpty(template.context)) { return(true); } string[] contextPath = template.context.Split(new [] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries) .Reverse().ToArray(); Entity current = owner; foreach (string part in contextPath) { current = current?.Owner; if (current?[$"is{part}"].Value <bool>() != true) { return(false); } } return(true); } int ContextComplexity(string context) { return(context.Count(c => c == '/' || c == '\\')); } } Entity ResolveType() { switch (key) { case EntityKeys.PathKey: { return(owner.Create(key, type.GetFile(owner).Parent.FullName)); } case EntityKeys.FieldsKey: { return(owner.Create(key, type.Fields.Select(f => owner.Create(key.Singular(), f.Name, f)))); } case EntityKeys.FileKey: { VirtualFile file = owner.Root.Value <ICodeModel>() .Types[type]; return(owner.Create(key, file.Name, file)); } case EntityKeys.BaseTypeKey: { IDataType baseType = type.BaseTypes.FirstOrDefault(); return(owner.Create(key, baseType)); } default: { if (TryResolveTypeTemplate(out Entity result)) { return(result); } if (TryResolveProperty(out result)) { return(result); } if (TryResolveFields(out result)) { return(result); } if (TryResolveRelationship(out result)) { return(result); } throw new ContentProviderException(key, owner); } } bool TryResolveTypeTemplate(out Entity result) { Templates.Type.metaDataTemplate typeMetaDataTemplate = ChooseMetaDataTemplate(templateRepository.TypeTemplates .Select(t => (t, t.name, t.context))); if (typeMetaDataTemplate != null) { result = GetTypeTemplateEntity(typeMetaDataTemplate); return(true); } result = null; return(false); Entity GetTypeTemplateEntity(Templates.Type.metaDataTemplate metaDataTemplate) { if (!metaDataTemplate.hasvalue) { bool hasAttribute = type.HasAttributeWithoutValue(metaDataTemplate.name); return(owner.Create(key, new Func <string>(hasAttribute.ToString), hasAttribute)); } (string[] values, CodePosition position) = GetTypeTemplateValue(); IEnumerable <string> formattedValues = VerifyValues().ToArray(); return(metaDataTemplate.multiplicity == Templates.Type.multiplicity.OneOrMore ? owner.Create(key, formattedValues.Select(v => owner.Create(key.Singular(), v))) : owner.Create(key, formattedValues.First())); IEnumerable <string> VerifyValues() { return(values.Select(VerifyValue)); string VerifyValue(string arg) { (bool success, string message, string newValue) = metaDataTemplate.ValueRestriction.Verify(arg); if (!success) { owner.AddCodeException(new FieldAttributeRestrictionException(metaDataTemplate.name, arg, message, position, type.GetFile(owner))); } return(newValue); } } (string[], CodePosition) GetTypeTemplateValue() { IAttribute attribute = type.Attributes.LastOrDefault(a => a.Name.Equals(metaDataTemplate.name, StringComparison.OrdinalIgnoreCase)); string value = attribute?.Values.FirstOrDefault() ?? resolver.Resolve(metaDataTemplate.defaultvalue, owner); return(metaDataTemplate.multiplicity == Templates.Type.multiplicity.OneOrMore ? value.Split(new[] { metaDataTemplate.split }, StringSplitOptions.RemoveEmptyEntries) : new[] { value }, attribute?.Position ?? new CodePosition(0, 0)); } } } bool TryResolveProperty(out Entity result) { result = owner.PropertyValueEntity(key, type); return(result != null); } bool TryResolveFields(out Entity result) { metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates .FirstOrDefault(t => t.name.Plural().Equals(key, StringComparison .OrdinalIgnoreCase)); if (metaDataTemplate != null) { IEnumerable <IField> fields = type.Fields .Where(f => f.Attributes .Any(a => a.Name .Equals(metaDataTemplate.name, StringComparison.OrdinalIgnoreCase))); result = owner.Create(key, fields.Select(f => owner.Create(metaDataTemplate.name, f.Name, f))); return(true); } result = null; return(false); } bool TryResolveRelationship(out Entity result) { templateRelationship[] relationships = owner.Template().Relationship; templateRelationship relationship = relationships?.FirstOrDefault(r => r.name.Equals(key, StringComparison.OrdinalIgnoreCase)) ?? relationships?.FirstOrDefault(r => r.name.Equals(key.Singular(), StringComparison.OrdinalIgnoreCase)); TemplateDescription relationshipDescription = relationship != null?templateRepository.Template(relationship.type) : null; if (relationshipDescription != null) { IEnumerable <string> names = type.Attributes .Where(a => a.Name.Equals(relationship.name, StringComparison.OrdinalIgnoreCase)) .SelectMany(a => a.Values); result = relationship.GetRelationship(relationshipDescription, owner, names.ToArray()); return(true); } result = null; return(false); } } Entity ResolveField() { switch (key) { case EntityKeys.FieldNameKey: { return(owner.Create(key, field.Name)); } case EntityKeys.DataTypeKey: { IDataType fieldDataType = GetRealFieldDataType(); return(owner.Create(key, fieldDataType.Name, fieldDataType)); } case EntityKeys.ResolvedTypeKey: { ICodeModel model = owner.Root.Value <ICodeModel>(); IDataType fieldDataType = field.DataType; IType realType = fieldDataType.PotentialFullNames .Select(model.Type) .FirstOrDefault(t => t != null); return(owner.Create(key, realType?.Name, realType)); } case EntityKeys.MultiplicityKey: { return(owner.Create(key, field.Multiplicity.Select(m => owner.Create(key, new Func <string>(m.ToString), m)))); } default: { metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates .FirstOrDefault(t => t.name.Equals(key, StringComparison.OrdinalIgnoreCase)); if (metaDataTemplate != null) { return(GetFieldTemplateEntity(metaDataTemplate)); } throw new ContentProviderException(key, owner); } } IDataType GetRealFieldDataType() { ICodeModel rootCodeModel = owner.Root.Value <ICodeModel>(); IEnum @enum = field.DataType.PotentialFullNames.Select(n => rootCodeModel.GetEnum(n)).FirstOrDefault(e => e != null); if (@enum != null) { (IDataType enumBaseType, _) = GetEnumBaseType(@enum); return(enumBaseType); } return(field.DataType); } Entity GetFieldTemplateEntity(metaDataTemplate metaDataTemplate) { if (!metaDataTemplate.hasvalue) { bool hasAttribute = field.HasAttributeWithoutValue(metaDataTemplate.name); return(owner.Create(key, new Func <string>(hasAttribute.ToString), hasAttribute)); } (string[] values, CodePosition position) = GetFieldTemplateValue(); IEnumerable <string> formattedValues = VerifyValues().ToArray(); return(metaDataTemplate.multiplicity == multiplicity.OneOrMore ? owner.Create(key, formattedValues.Select(v => owner.Create(key.Singular(), v))) : owner.Create(key, formattedValues.First())); IEnumerable <string> VerifyValues() { return(values.Select(VerifyValue)); string VerifyValue(string arg) { (bool success, string message, string newValue) = metaDataTemplate.ValueRestriction.Verify(arg); if (!success) { owner.AddCodeException(new FieldAttributeRestrictionException(metaDataTemplate.name, arg, message, position, field.GetFile(owner))); } return(newValue); } } (string[], CodePosition) GetFieldTemplateValue() { IAttribute attribute = field.Attributes.LastOrDefault(a => a.Name.Equals(metaDataTemplate.name, StringComparison.OrdinalIgnoreCase)); string value = string.IsNullOrEmpty(attribute?.Values.FirstOrDefault()) ? resolver.Resolve(metaDataTemplate.defaultvalue, owner) : attribute.Values.First(); return(metaDataTemplate.multiplicity == multiplicity.OneOrMore ? value.Split(new[] { metaDataTemplate.split }, StringSplitOptions.RemoveEmptyEntries) : new[] { value }, attribute?.Position ?? new CodePosition(0, 0)); } } } Entity ResolveCodeModel() { switch (key) { case EntityKeys.PortStructsKey: { return(owner.Create(key, GetPortStructures().Select(c => c.Base))); } case EntityKeys.PortEnumsKey: { return(owner.Create(key, GetPortEnums().Select(c => c.Base))); } case EntityKeys.NamespaceKey: { bool prior206Target = CheckProjectTargets(); IEnumerable <string> relevantTypes = TemplateEntity.Decorate(owner).EntityHierarchy .Select(CodeEntity.Decorate) .Where(c => !c.IsRoot()) .Select(c => c.FullName); string ns = prior206Target ? codeModel.RootNamespaceForOldTarget( relevantTypes.ToArray(), GetPortStructures().Concat(GetPortEnums()) .Select(c => c.FullName) .ToArray()) : codeModel.RootNamespace(relevantTypes.ToArray()); if (string.IsNullOrEmpty(ns)) { ns = owner.Name; } return(owner.Create(key, ns)); } default: throw new ContentProviderException(key, owner); } bool CheckProjectTargets() { IEnumerable <TargetEntity> targets = ProjectEntity.Decorate(owner).Targets.Select(t => TargetEntity.Decorate(t)); return(targets.Any(t => t.Version < new Version(20, 6))); } } Entity ResolveDataType() { switch (key) { case EntityKeys.NameKey: return(owner.Create(key, dataType.Name)); case EntityKeys.FullNameKey: string fullName = GetDataTypeFullName(); return(owner.Create(key, fullName)); default: throw new ContentProviderException(key, owner); } string GetDataTypeFullName() { ICodeModel rootCodeModel = owner.Root.Value <ICodeModel>(); return(dataType.PotentialFullNames.FirstOrDefault(fn => rootCodeModel.Type(fn) != null) ?? dataType.Name); } } Entity ResolveTypeMetaDataFormat() { IEntityBase dataSource = ownerTemplateEntity.FormatOrigin; IDataType dataSourceDataType = dataSource.HasValue <IDataType>() ? dataSource.Value <IDataType>() : dataSource.Value <IField>().DataType; ICodeModel rootCodeModel = dataSource.Root.Value <ICodeModel>(); string dataTypeName = string.Empty; if (dataSourceDataType != null) { dataTypeName = dataSourceDataType.PotentialFullNames .Select(n => rootCodeModel.Type(n)) .FirstOrDefault(t => t != null) ?.Name ?? datatypeConversion.Convert(dataSourceDataType); } return(owner.Create(key, dataTypeName)); } Entity ResolveArpDataType() { IEntityBase dataSource = ownerTemplateEntity.FormatOrigin; IField dataSourceField = dataSource.Value <IField>(); if (dataSourceField == null) { throw new FormatTargetMismatchException("arpDataType", "field|port", dataSource.Type); } ICodeModel rootCodeModel = dataSource.Root.Value <ICodeModel>(); bool isStruct = dataSourceField.DataType.PotentialFullNames.Any(n => rootCodeModel.GetClass(n) != null || rootCodeModel.GetStructure(n) != null); IEnum @enum = dataSourceField.DataType.PotentialFullNames.Select(n => rootCodeModel.GetEnum(n)).FirstOrDefault(e => e != null); bool isArray = dataSourceField.Multiplicity.Any(); string arpName = "DataType::" + GetArpDataType(dataSourceField.DataType.Name); return(owner.Create(key, arpName)); string GetArpDataType(string dataTypeName) { string postfix = isArray ? " | DataType::Array" : string.Empty; if (isStruct) { return("Struct" + postfix); } if (@enum != null) { (IDataType enumBaseType, string formattedBaseType) = GetEnumBaseType(@enum); return($"Enum | DataType::{formattedBaseType}" + postfix); } (bool success, string value) = FormatDataType(dataTypeName); if (!success) { throw new UnknownDataTypeException(value); } return(value + postfix); } } (bool success, string value) FormatDataType(string unformattedValue) { if (unformattedValue.Contains('<')) { unformattedValue = unformattedValue.Substring(0, unformattedValue.IndexOf('<')); } string result = owner.Create("temporaryCtnFormatContainer", unformattedValue).Format()["knownDataTypes"].Value <string>(); Match unkownMatch = UnkownDataTypeRegex.Match(result); if (unkownMatch.Success) { return(false, unkownMatch.Groups["dataType"].Value); } return(true, result); } (IDataType, string) GetEnumBaseType(IEnum @enum) { IDataType enumDataType = @enum.BaseTypes.FirstOrDefault(); string enumBaseType = enumDataType?.Name; if (string.IsNullOrEmpty(enumBaseType)) { throw new MissingEnumDataTypeException(@enum); } (bool formatted, string formattedBaseType) = FormatDataType(enumBaseType); if (!formatted) { throw new UnkownEnumDataTypeException(formattedBaseType, @enum); } return(enumDataType, formattedBaseType); } Entity GetBigDataProjectEntity() { if (HasMoreThan1000Fields()) { return(owner.Create(key, "true", true)); } return(owner.Create(key, "false", false)); } Entity GetNormalProjectEntity() { if (HasMoreThan1000Fields()) { return(owner.Create(key, "false", false)); } return(owner.Create(key, "true", true)); } bool HasMoreThan1000Fields() { ICodeModel model = owner.Value <ICodeModel>(); if (model == null || GetAllPorts().Concat(GetPortStructures().SelectMany(s => s.Fields)).Count() <= 1000) { return(false); } return(true); } }