/// <summary> /// Creates compilation syntax unit from the specified external type information and validation. /// </summary> /// <param name="info">The container external type information.</param> /// <param name="validation">The container type validation to use.</param> /// <param name="compilation">The project compilation.</param> /// <param name="generator">The syntax generator.</param> public static SyntaxNode CreateUnit(ICodeGenerateContainerInfo info, ICodeGenerateContainerValidation validation, Compilation compilation = null, SyntaxGenerator generator = null) { if (info == null) { throw new ArgumentNullException(nameof(info)); } if (validation == null) { throw new ArgumentNullException(nameof(validation)); } if (compilation == null) { compilation = CodeAnalysisEditorUtility.ProjectCompilation; } if (generator == null) { generator = CodeAnalysisEditorUtility.Generator; } if (!info.TryGetTargetType(out Type type)) { throw new ArgumentException("The specified container external type info has invalid target type information.", nameof(info)); } CodeGenerateContainer container = CreateContainer(info, validation, compilation); return(CodeGenerateContainerEditorUtility.CreateUnit(container, generator, type.Namespace)); }
/// <summary> /// Creates container external type information from the specified type and validation. /// </summary> /// <param name="type">The target type.</param> /// <param name="validation">The container type validation to use.</param> public static CodeGenerateContainerInfo CreateInfo(Type type, ICodeGenerateContainerValidation validation) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (validation == null) { throw new ArgumentNullException(nameof(validation)); } var info = new CodeGenerateContainerInfo { TypeName = type.AssemblyQualifiedName }; IEnumerable <FieldInfo> fields = validation.GetFields(type); IEnumerable <PropertyInfo> properties = validation.GetProperties(type); foreach (FieldInfo field in fields) { if (validation.Validate(field)) { info.Members.Add(new CodeGenerateContainerInfo.MemberInfo { Active = true, Name = field.Name }); } } foreach (PropertyInfo property in properties) { if (validation.Validate(property)) { info.Members.Add(new CodeGenerateContainerInfo.MemberInfo { Active = true, Name = property.Name }); } } return(info); }
/// <summary> /// Creates container from the specified type using specified validation. /// <para> /// The specified validation will not be used to validate specified type. /// </para> /// </summary> /// <param name="type">The target type.</param> /// <param name="validation">The type validation to use.</param> /// <param name="compilation">The project compilation.</param> public static CodeGenerateContainer Create(Type type, ICodeGenerateContainerValidation validation = null, Compilation compilation = null) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (validation == null) { validation = DefaultValidation; } if (compilation == null) { compilation = CodeAnalysisEditorUtility.ProjectCompilation; } var container = new CodeGenerateContainer(type.Name, type.IsValueType); foreach (FieldInfo field in validation.GetFields(type)) { if (validation.Validate(field)) { if (TryCreateField(compilation, field.Name, field.FieldType, false, out CodeGenerateContainerField containerField)) { container.Fields.Add(containerField); } } } foreach (PropertyInfo property in validation.GetProperties(type)) { if (validation.Validate(property)) { if (TryCreateField(compilation, property.Name, property.PropertyType, true, out CodeGenerateContainerField containerField)) { container.Fields.Add(containerField); } } } return(container); }
public static void GenerateResolver(string assetPath, ICodeGenerateContainerValidation validation = null, Compilation compilation = null, SyntaxGenerator generator = null) { if (string.IsNullOrEmpty(assetPath)) { throw new ArgumentException("Value cannot be null or empty.", nameof(assetPath)); } var info = AssetInfoEditorUtility.LoadInfo <Utf8JsonResolverAssetInfo>(assetPath); string source = GenerateResolver(info, validation, compilation, generator); string path = GetDestinationSourcePath(assetPath, info.ResolverName, info.DestinationSource); File.WriteAllText(path, source); AssetDatabase.ImportAsset(path); if (info.DestinationSource == null) { info.DestinationSource = AssetDatabase.LoadAssetAtPath <TextAsset>(path); AssetInfoEditorUtility.SaveInfo(assetPath, info); } }
/// <summary> /// Creates compilation unit from the specified container type using validation. /// </summary> /// <param name="type">The type of the container.</param> /// <param name="validation">The validation to use.</param> /// <param name="compilation">The project compilation.</param> /// <param name="generator">The syntax generator.</param> public static SyntaxNode CreateUnit(Type type, ICodeGenerateContainerValidation validation = null, Compilation compilation = null, SyntaxGenerator generator = null) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (validation == null) { validation = DefaultValidation; } if (compilation == null) { compilation = CodeAnalysisEditorUtility.ProjectCompilation; } if (generator == null) { generator = CodeAnalysisEditorUtility.Generator; } CodeGenerateContainer container = Create(type, validation, compilation); return(CreateUnit(container, generator, type.Namespace)); }
public static void GenerateResolverAll(ICodeGenerateContainerValidation validation = null, Compilation compilation = null, SyntaxGenerator generator = null) { const string resolverSearchPattern = "*." + RESOLVER_ASSET_EXTENSION_NAME; string[] underAssets = Directory.GetFiles("Assets", resolverSearchPattern, SearchOption.AllDirectories); string[] underPackages = Directory.GetFiles("Packages", resolverSearchPattern, SearchOption.AllDirectories); for (int i = 0; i < underAssets.Length; i++) { string path = underAssets[i]; GenerateResolver(path, validation, compilation, generator); } for (int i = 0; i < underPackages.Length; i++) { string path = underPackages[i]; if (CanGenerateResolver(path)) { GenerateResolver(path, validation, compilation, generator); } } }
public static string GenerateExternalSources(IReadOnlyList <string> externalPaths, ICollection <string> sourcePaths, Type attributeType = null, ICodeGenerateContainerValidation validation = null, Compilation compilation = null, SyntaxGenerator generator = null) { if (externalPaths == null) { throw new ArgumentNullException(nameof(externalPaths)); } if (sourcePaths == null) { throw new ArgumentNullException(nameof(sourcePaths)); } if (validation == null) { validation = CodeGenerateContainerAssetEditorUtility.DefaultValidation; } if (compilation == null) { compilation = CodeAnalysisEditorUtility.ProjectCompilation; } if (generator == null) { generator = CodeAnalysisEditorUtility.Generator; } string externalsTempPath = FileUtil.GetUniqueTempPathInProject(); var types = new HashSet <Type>(); CSharpSyntaxRewriter rewriterAddAttribute = null; if (attributeType != null && compilation.TryConstructTypeSymbol(attributeType, out ITypeSymbol typeSymbol)) { rewriterAddAttribute = GetAttributeRewriter(compilation, generator, typeSymbol); } Directory.CreateDirectory(externalsTempPath); for (int i = 0; i < externalPaths.Count; i++) { string externalPath = externalPaths[i]; var info = AssetInfoEditorUtility.LoadInfo <CodeGenerateContainerInfo>(externalPath); if (info.TryGetTargetType(out Type type)) { if (types.Add(type)) { SyntaxNode unit = CodeGenerateContainerInfoEditorUtility.CreateUnit(info, validation, compilation, generator); if (rewriterAddAttribute != null) { unit = rewriterAddAttribute.Visit(unit); } string sourcePath = $"{externalsTempPath}/{Guid.NewGuid():N}.cs"; string source = unit.NormalizeWhitespace().ToFullString(); File.WriteAllText(sourcePath, source); sourcePaths.Add(sourcePath); } else { Debug.LogWarning($"The specified type already generated: '{type}'."); } } } return(externalsTempPath); }
public static string GenerateResolver(Utf8JsonResolverAssetInfo info, ICodeGenerateContainerValidation validation = null, Compilation compilation = null, SyntaxGenerator generator = null) { if (info == null) { throw new ArgumentNullException(nameof(info)); } if (validation == null) { validation = CodeGenerateContainerAssetEditorUtility.DefaultValidation; } if (compilation == null) { compilation = CodeAnalysisEditorUtility.ProjectCompilation; } if (generator == null) { generator = CodeAnalysisEditorUtility.Generator; } var sourcePaths = new List <string>(); string resolverName = Utf8JsonEditorUtility.FormatResolverName(info.ResolverName); string namespaceRoot = info.NamespaceRoot; string externalsTemp = string.Empty; Type attributeType = null; var generateArguments = new Utf8JsonGenerateArguments { IgnoreReadOnly = info.IgnoreReadOnly, IgnoreEmpty = info.IgnoreEmpty, IsTypeRequireAttribute = info.AttributeRequired, }; if (info.AttributeRequired && info.TryGetAttributeType(out attributeType)) { generateArguments.TypeRequiredAttributeShortName = attributeType.Name; } if (info.Sources.Count > 0) { var externals = new List <string>(); for (int i = 0; i < info.Sources.Count; i++) { TextAsset asset = info.Sources[i]; string path = AssetDatabase.GetAssetPath(asset); if (!string.IsNullOrEmpty(path)) { if (path.EndsWith(".cs", StringComparison.OrdinalIgnoreCase)) { sourcePaths.Add(path); } else if (path.EndsWith(Utf8JsonExternalTypeEditorUtility.EXTERNAL_TYPE_ASSET_EXTENSION, StringComparison.OrdinalIgnoreCase)) { externals.Add(path); } } } if (externals.Count > 0) { externalsTemp = Utf8JsonExternalTypeEditorUtility.GenerateExternalSources(externals, sourcePaths, attributeType, validation, compilation, generator); } } string source = Utf8JsonEditorUtility.GenerateResolver(sourcePaths, resolverName, namespaceRoot, generateArguments); if (!string.IsNullOrEmpty(externalsTemp)) { FileUtil.DeleteFileOrDirectory(externalsTemp); } if (info.ResolverAsset) { source = AppendResolverAsset(source, resolverName, namespaceRoot, compilation, generator); } return(source); }
/// <summary> /// Creates container from the specified external type information and validation. /// </summary> /// <param name="info">The container external type information.</param> /// <param name="validation">The container type validation to use.</param> /// <param name="compilation">The project compilation.</param> public static CodeGenerateContainer CreateContainer(ICodeGenerateContainerInfo info, ICodeGenerateContainerValidation validation, Compilation compilation = null) { if (info == null) { throw new ArgumentNullException(nameof(info)); } if (validation == null) { throw new ArgumentNullException(nameof(validation)); } if (compilation == null) { compilation = CodeAnalysisEditorUtility.ProjectCompilation; } if (!info.TryGetTargetType(out Type type)) { throw new ArgumentException("The specified container external type info has invalid target type information.", nameof(info)); } var container = new CodeGenerateContainer(type.Name, type.IsValueType); IEnumerable <FieldInfo> fields = validation.GetFields(type); IEnumerable <PropertyInfo> properties = validation.GetProperties(type); foreach (FieldInfo field in fields) { if (info.TryGetMember(field.Name, out CodeGenerateContainerInfo.MemberInfo member) && member.Active) { if (CodeGenerateContainerEditorUtility.TryCreateField(compilation, field.Name, field.FieldType, false, out CodeGenerateContainerField containerField)) { container.Fields.Add(containerField); } } } foreach (PropertyInfo property in properties) { if (info.TryGetMember(property.Name, out CodeGenerateContainerInfo.MemberInfo member) && member.Active) { if (CodeGenerateContainerEditorUtility.TryCreateField(compilation, property.Name, property.PropertyType, true, out CodeGenerateContainerField containerField)) { container.Fields.Add(containerField); } } } return(container); }