/// <summary> /// Retrieves the method layout for a UdonSharpBehaviour method. /// This includes the method name, name of return variable, and name of parameter values. /// This is used internally by GetMethodLinkage in the EmitContext. /// This is also used when calling across UdonSharpBehaviours to determine what variables to set for parameters and such. /// </summary> /// <remarks>This method is thread safe and may be called safely from multiple Contexts at a time</remarks> public MethodExportLayout GetUsbMethodLayout(MethodSymbol method, AbstractPhaseContext context) { if (_udonSharpBehaviourType == null) { _udonSharpBehaviourType = GetTypeSymbol(typeof(UdonSharpBehaviour), context); } while (method.OverridenMethod != null && method.OverridenMethod.ContainingType != _udonSharpBehaviourType && !method.OverridenMethod.ContainingType.IsExtern) { method = method.OverridenMethod; } lock (_layoutLock) { if (_layouts.TryGetValue(method, out MethodExportLayout layout)) { return(layout); } BuildLayout(method.ContainingType, context); return(_layouts[method]); } }
public TypeSymbol GetUdonTypeSymbol(ITypeSymbol type, AbstractPhaseContext context) { if (!TypeSymbol.TryGetSystemType(type, out var systemType)) { throw new InvalidOperationException("foundType should not be null"); } systemType = UdonSharpUtils.UserTypeToUdonType(systemType); return(GetTypeSymbol(systemType, context)); }
/// <summary> /// Builds a layout for a given type. /// First traverses all base types and builds their layouts when needed since the base type layouts inform the layout of derived types. /// </summary> private void BuildLayout(TypeSymbol typeSymbol, AbstractPhaseContext context) { Stack <TypeSymbol> typesToBuild = new Stack <TypeSymbol>(); while (typeSymbol.BaseType != null && !_builtLayouts.ContainsKey(typeSymbol)) { typesToBuild.Push(typeSymbol); if (typeSymbol == _udonSharpBehaviourType) { break; } typeSymbol = typeSymbol.BaseType; } while (typesToBuild.Count > 0) { TypeSymbol currentBuildType = typesToBuild.Pop(); Dictionary <string, int> idCounters; if (currentBuildType.BaseType != null && _builtLayouts.TryGetValue(currentBuildType.BaseType, out TypeLayout parentLayout)) { idCounters = new Dictionary <string, int>(parentLayout.SymbolCounters); } else { idCounters = new Dictionary <string, int>(); } Dictionary <MethodSymbol, MethodExportLayout> layouts = new Dictionary <MethodSymbol, MethodExportLayout>(); foreach (Symbol symbol in currentBuildType.GetMembers(context)) { if (symbol is MethodSymbol methodSymbol && (methodSymbol.OverridenMethod == null || methodSymbol.OverridenMethod.ContainingType == _udonSharpBehaviourType || methodSymbol.OverridenMethod.ContainingType.IsExtern)) { layouts.Add(methodSymbol, BuildMethodLayout(methodSymbol, idCounters)); } } _builtLayouts.Add(currentBuildType, new TypeLayout(layouts, idCounters)); } }
public Symbol GetSymbol(ISymbol sourceSymbol, AbstractPhaseContext context) { if (sourceSymbol == null) { throw new NullReferenceException("Source symbol cannot be null"); } if (sourceSymbol is ITypeSymbol typeSymbol) { return(GetTypeSymbol(typeSymbol, context)); } if (sourceSymbol.ContainingType != null) { return(GetTypeSymbol(sourceSymbol.ContainingType, context).GetMember(sourceSymbol, context)); } throw new InvalidOperationException($"Could not get symbol for {sourceSymbol}"); }
public TypeSymbol GetTypeSymbol(Type systemType, AbstractPhaseContext context) { int arrayDepth = 0; while (systemType.IsArray) { arrayDepth++; systemType = systemType.GetElementType(); } ITypeSymbol typeSymbol = RoslynCompilation.GetTypeByMetadataName(systemType.FullName); for (int i = 0; i < arrayDepth; ++i) { typeSymbol = RoslynCompilation.CreateArrayTypeSymbol(typeSymbol, 1); } return(GetTypeSymbol(typeSymbol, context)); }
public TypeSymbol GetTypeSymbol(SpecialType type, AbstractPhaseContext context) { return(GetTypeSymbol(RoslynCompilation.GetSpecialType(type), context)); }
public TypeSymbol GetTypeSymbol(ITypeSymbol type, AbstractPhaseContext context) { TypeSymbol typeSymbol = _typeSymbolLookup.GetOrAdd(type, (key) => TypeSymbolFactory.CreateSymbol(type, context)); return(typeSymbol); }