public static EditorScriptCompilationOptions GetAdditionalEditorScriptCompilationOptions( AssembliesType assembliesType) { var options = GetAdditionalEditorScriptCompilationOptions(); if (EditorUserBuildSettings.development && (assembliesType == AssembliesType.Player || assembliesType == AssembliesType.PlayerWithoutTestAssemblies)) { options |= EditorScriptCompilationOptions.BuildingDevelopmentBuild; } switch (assembliesType) { case AssembliesType.Editor: options |= EditorScriptCompilationOptions.BuildingIncludingTestAssemblies; options |= EditorScriptCompilationOptions.BuildingForEditor; break; case AssembliesType.Player: options |= EditorScriptCompilationOptions.BuildingIncludingTestAssemblies; options &= ~EditorScriptCompilationOptions.BuildingForEditor; break; case AssembliesType.PlayerWithoutTestAssemblies: options &= ~EditorScriptCompilationOptions.BuildingIncludingTestAssemblies; options &= ~EditorScriptCompilationOptions.BuildingForEditor; break; default: throw new ArgumentOutOfRangeException(nameof(assembliesType)); } return(options); }
/// <summary> /// Collects all assemblies - transitively that are valid for the specified type `Player` or `Editor` /// </summary> /// <param name="assemblyTypes">The assembly type</param> /// <returns>The list of assemblies valid for this platform</returns> private static List <System.Reflection.Assembly> GetAssemblyList(AssembliesType assemblyTypes) { // TODO: Not sure there is a better way to match assemblies returned by CompilationPipeline.GetAssemblies // with runtime assemblies contained in the AppDomain.CurrentDomain.GetAssemblies() // Filter the assemblies var assemblyList = CompilationPipeline.GetAssemblies(assemblyTypes); var assemblyNames = new HashSet <string>(); foreach (var assembly in assemblyList) { CollectAssemblyNames(assembly, assemblyNames); } var allAssemblies = new HashSet <System.Reflection.Assembly>(); foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (!assemblyNames.Contains(assembly.GetName().Name)) { continue; } CollectAssembly(assembly, allAssemblies); } return(allAssemblies.ToList()); }
private void OnGUI() { using (var toolBarScope = new EditorGUILayout.HorizontalScope(EditorStyles.toolbar)) { using (var changeCheckScope = new EditorGUI.ChangeCheckScope()) { type = (AssembliesType)EditorGUILayout.EnumPopup(type, EditorStyles.toolbarPopup); if (changeCheckScope.changed) { EditorPrefs.SetInt(EDITOR_PREFS_TYPE, (int)type); UpdateAssembliesList(); } } GUILayout.FlexibleSpace(); } using (var scrollScope = new EditorGUILayout.ScrollViewScope(scrollPositionViewAssemblies)) { scrollPositionViewAssemblies = scrollScope.scrollPosition; using (var verticalScope = new EditorGUILayout.VerticalScope()) { foreach (var property in assemblyPropertyList) { property.Render(); } } } }
private static Type GetType(AssembliesType assembliesType, string typeFullName) { var assemblies = CompilationPipeline.GetAssemblies(assembliesType); return(assemblies.Select(assembly => GenericAssembly.LoadFile(assembly.outputPath)) .Select(genericAssembly => genericAssembly.GetType(typeFullName)) .FirstOrDefault(type => type != null)); }
public static Assembly[] GetAssemblies(AssembliesType assembliesType) { var options = EditorCompilationInterface.GetAdditionalEditorScriptCompilationOptions(); switch (assembliesType) { case AssembliesType.Editor: return(GetEditorAssemblies(EditorCompilationInterface.Instance, options, null)); case AssembliesType.Player: return(GetPlayerAssemblies(EditorCompilationInterface.Instance, options, null)); default: throw new ArgumentOutOfRangeException("assembliesType"); } }
internal static Assembly[] GetAssemblies(EditorCompilation editorCompilation, AssembliesType assembliesType) { var options = EditorCompilationInterface.GetAdditionalEditorScriptCompilationOptions(); switch (assembliesType) { case AssembliesType.Editor: return(GetEditorAssemblies(editorCompilation, options | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies, null)); case AssembliesType.Player: return(GetPlayerAssemblies(editorCompilation, options | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies, null)); case AssembliesType.PlayerWithoutTestAssemblies: return(GetPlayerAssemblies(editorCompilation, options, null)); default: throw new ArgumentOutOfRangeException("assembliesType"); } }
public static Assembly[] GetAssemblies(AssembliesType assembliesType) { return(GetAssemblies(EditorCompilationInterface.Instance, assembliesType)); }
private void OnEnable() { type = (AssembliesType)EditorPrefs.GetInt(EDITOR_PREFS_TYPE); UpdateAssembliesList(); }
public static List <BurstCompileTarget> FindExecuteMethods(AssembliesType assemblyTypes) { var methodsToCompile = new List <BurstCompileTarget>(); var methodsToCompileSet = new HashSet <MethodInfo>(); var valueTypes = new List <TypeToVisit>(); var interfaceToProducer = new Dictionary <Type, Type>(); var assemblyList = GetAssemblyList(assemblyTypes); //Debug.Log("Filtered Assembly List: " + string.Join(", ", assemblyList.Select(assembly => assembly.GetName().Name))); // Find all ways to execute job types (via producer attributes) var typesVisited = new HashSet <string>(); var typesToVisit = new HashSet <string>(); foreach (var assembly in assemblyList) { var types = new List <Type>(); try { types.AddRange(assembly.GetTypes()); // Collect all generic type instances (excluding indirect instances) CollectGenericTypeInstances(assembly, types); } catch (Exception ex) { Debug.LogWarning("Unexpected exception while collecting types in assembly `" + assembly.FullName + "` Exception: " + ex); } for (var i = 0; i < types.Count; i++) { var t = types[i]; if (typesToVisit.Add(t.FullName)) { // Because the list of types returned by CollectGenericTypeInstances does not detect nested generic classes that are not // used explicitly, we need to create them if a declaring type is actually used // so for example if we have: // class MyClass<T> { class MyNestedClass { } } // class MyDerived : MyClass<int> { } // The CollectGenericTypeInstances will return typically the type MyClass<int>, but will not list MyClass<int>.MyNestedClass // So the following code is correcting this in order to fully query the full graph of generic instance types, including indirect types var nestedTypes = t.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (var nestedType in nestedTypes) { if (t.IsGenericType && !t.IsGenericTypeDefinition) { var parentGenericTypeArguments = t.GetGenericArguments(); // Only create nested types that are closed generic types (full generic instance types) // It happens if for example the parent class is `class MClass<T> { class MyNestedGeneric<T1> {} }` // In that case, MyNestedGeneric<T1> is closed in the context of MClass<int>, so we don't process them if (nestedType.GetGenericArguments().Length == parentGenericTypeArguments.Length) { var instanceNestedType = nestedType.MakeGenericType(parentGenericTypeArguments); types.Add(instanceNestedType); } } else { types.Add(nestedType); } } } } foreach (var t in types) { // If the type has been already visited, don't try to visit it if (!typesVisited.Add(t.FullName) || (t.IsGenericTypeDefinition && !t.IsInterface)) { continue; } try { // collect methods with types having a [BurstCompile] attribute bool visitStaticMethods = HasBurstCompileAttribute(t); bool isValueType = false; if (t.IsInterface) { object[] attrs = t.GetCustomAttributes(typeof(JobProducerTypeAttribute), false); if (attrs.Length == 0) { continue; } JobProducerTypeAttribute attr = (JobProducerTypeAttribute)attrs[0]; interfaceToProducer.Add(t, attr.ProducerType); //Debug.Log($"{t} has producer {attr.ProducerType}"); } else if (t.IsValueType) { // NOTE: Make sure that we don't use a value type generic definition (e.g `class Outer<T> { struct Inner { } }`) // We are only working on plain type or generic type instance! if (!t.IsGenericTypeDefinition) { isValueType = true; } } if (isValueType || visitStaticMethods) { valueTypes.Add(new TypeToVisit(t, visitStaticMethods)); } } catch (Exception ex) { Debug.LogWarning("Unexpected exception while inspecting type `" + t + "` IsConstructedGenericType: " + t.IsConstructedGenericType + " IsGenericTypeDef: " + t.IsGenericTypeDefinition + " IsGenericParam: " + t.IsGenericParameter + " Exception: " + ex); } } } //Debug.Log($"Mapped {interfaceToProducer.Count} producers; {valueTypes.Count} value types"); // Revisit all types to find things that are compilable using the above producers. foreach (var typePair in valueTypes) { var type = typePair.Type; // collect static [BurstCompile] methods if (typePair.CollectStaticMethods) { try { var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (var method in methods) { if (HasBurstCompileAttribute(method)) { var target = new BurstCompileTarget(method, type, null, true); methodsToCompile.Add(target); } } } catch (Exception ex) { Debug.LogException(ex); } } // If the type is not a value type, we don't need to proceed with struct Jobs if (!type.IsValueType) { continue; } // Otherwise try to find if we have an interface producer setup on the class foreach (var interfaceType in type.GetInterfaces()) { var genericLessInterface = interfaceType; if (interfaceType.IsGenericType) { genericLessInterface = interfaceType.GetGenericTypeDefinition(); } Type foundProducer; if (interfaceToProducer.TryGetValue(genericLessInterface, out foundProducer)) { var genericParams = new List <Type> { type }; if (interfaceType.IsGenericType) { genericParams.AddRange(interfaceType.GenericTypeArguments); } try { var executeType = foundProducer.MakeGenericType(genericParams.ToArray()); var executeMethod = executeType.GetMethod("Execute"); if (executeMethod == null) { throw new InvalidOperationException($"Burst reflection error. The type `{executeType}` does not contain an `Execute` method"); } // We will not try to record more than once a method in the methods to compile // This can happen if a job interface is inheriting from another job interface which are using in the end the same // job producer type if (methodsToCompileSet.Add(executeMethod)) { var target = new BurstCompileTarget(executeMethod, type, interfaceType, false); methodsToCompile.Add(target); } } catch (Exception ex) { Debug.LogException(ex); } } } } return(methodsToCompile); }
private static UnityEditor.Compilation.Assembly FindUnityAssembly(string name, AssembliesType type) { UnityEditor.Compilation.Assembly foundAssembly = null; UnityEditor.Compilation.Assembly[] assemblies = CompilationPipeline.GetAssemblies(type); foreach (UnityEditor.Compilation.Assembly asm in assemblies) { if (asm.name == name) { foundAssembly = asm; break; } } return(foundAssembly); }
internal static ScriptAssembly[] GetScriptAssemblies(IEditorCompilation editorCompilation, AssembliesType assembliesType, string[] extraScriptingDefines = null) { var options = EditorCompilationInterface.GetAdditionalEditorScriptCompilationOptions(assembliesType); return(GetScriptAssemblies(editorCompilation, options, extraScriptingDefines)); }
internal static Assembly[] GetAssemblies(EditorCompilation editorCompilation, AssembliesType assembliesType, string[] extraScriptingDefines = null) { return(ToAssemblies(GetScriptAssemblies(editorCompilation, assembliesType, extraScriptingDefines))); }