/// <summary> /// Gets the sequence of processed discovered custom types. /// </summary> /// <param name="diagnostics">The collection of produced <see cref="Diagnostic"/> instances.</param> /// <param name="structDeclarationSymbol">The type symbol for the shader type.</param> /// <param name="types">The sequence of discovered custom types.</param> /// <returns>A sequence of custom type definitions to add to the shader source.</returns> private static ImmutableArray <(string Name, string Definition)> GetDeclaredTypes( ImmutableArray <Diagnostic> .Builder diagnostics, INamedTypeSymbol structDeclarationSymbol, IEnumerable <INamedTypeSymbol> types) { ImmutableArray <(string, string)> .Builder builder = ImmutableArray.CreateBuilder <(string, string)>(); IReadOnlyCollection <INamedTypeSymbol> invalidTypes; // Process the discovered types foreach (var type in HlslKnownTypes.GetCustomTypes(types, out invalidTypes)) { var structType = type.GetFullMetadataName().ToHlslIdentifierName(); var structDeclaration = StructDeclaration(structType); // Declare the fields of the current type foreach (var field in type.GetMembers().OfType <IFieldSymbol>()) { if (field.IsStatic) { continue; } INamedTypeSymbol fieldType = (INamedTypeSymbol)field.Type; // Convert the name to the fully qualified HLSL version if (!HlslKnownTypes.TryGetMappedName(fieldType.GetFullMetadataName(), out string?mappedType)) { mappedType = fieldType.GetFullMetadataName().ToHlslIdentifierName(); } // Get the field name as a valid HLSL identifier if (!HlslKnownKeywords.TryGetMappedName(field.Name, out string?mappedName)) { mappedName = field.Name; } structDeclaration = structDeclaration.AddMembers( FieldDeclaration(VariableDeclaration( IdentifierName(mappedType !)).AddVariables( VariableDeclarator(Identifier(mappedName !))))); } // Insert the trailing ; right after the closing bracket (after normalization) builder.Add(( structType, structDeclaration .NormalizeWhitespace(eol: "\n") .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) .ToFullString())); } // Process the invalid types foreach (INamedTypeSymbol invalidType in invalidTypes) { diagnostics.Add(InvalidDiscoveredType, structDeclarationSymbol, structDeclarationSymbol, invalidType); } return(builder.ToImmutable()); }
public static TypeSyntax TrackType(this SyntaxNode node, SemanticModel semanticModel, ICollection <INamedTypeSymbol> discoveredTypes) { ITypeSymbol typeSymbol = semanticModel.GetTypeInfo(node).Type !; string typeName = typeSymbol.ToDisplayString(ISymbolExtensions.FullyQualifiedWithoutGlobalFormat); discoveredTypes.Add((INamedTypeSymbol)typeSymbol); if (HlslKnownTypes.TryGetMappedName(typeName, out string?mappedName)) { return(ParseTypeName(mappedName !)); } return(ParseTypeName(typeName.Replace(".", "__"))); }
/// <summary> /// Tracks the associated type for a <see cref="SyntaxNode"/> value and returns the HLSL compatible <see cref="TypeSyntax"/>. /// </summary> /// <param name="node">The input <see cref="SyntaxNode"/> to check.</param> /// <param name="semanticModel">The <see cref="SemanticModel"/> instance with info on the input tree.</param> /// <param name="discoveredTypes">The collection of currently discovered types.</param> /// <returns>A <see cref="SyntaxNode"/> instance that represents a type compatible with HLSL.</returns> public static TypeSyntax TrackType(this SyntaxNode node, SemanticModel semanticModel, ICollection <INamedTypeSymbol> discoveredTypes) { ITypeSymbol typeSymbol = semanticModel.GetTypeInfo(node).Type !; string typeName = typeSymbol.GetFullyQualifiedName(); discoveredTypes.Add((INamedTypeSymbol)typeSymbol); if (HlslKnownTypes.TryGetMappedName(typeName, out string?mappedName)) { return(ParseTypeName(mappedName !)); } return(ParseTypeName(typeName.ToHlslIdentifierName())); }
public static TRoot ReplaceAndTrackType <TRoot>(this TRoot node, TypeSyntax targetType, SyntaxNode sourceType, SemanticModel semanticModel, ICollection <INamedTypeSymbol> discoveredTypes) where TRoot : SyntaxNode { // Skip immediately for function pointers if (sourceType is FunctionPointerTypeSyntax) { return(node.ReplaceNode(targetType, ParseTypeName("void*"))); } // Handle the various possible type kinds ITypeSymbol typeSymbol = sourceType switch { RefTypeSyntax refType => semanticModel.GetTypeInfo(refType.Type).Type !, PointerTypeSyntax pointerType => semanticModel.GetTypeInfo(pointerType.ElementType).Type !, _ => semanticModel.GetTypeInfo(sourceType).Type ! }; // Do nothing if the type is just void if (typeSymbol.SpecialType == SpecialType.System_Void) { return(node); } string typeName = typeSymbol.ToDisplayString(ISymbolExtensions.FullyQualifiedWithoutGlobalFormat); discoveredTypes.Add((INamedTypeSymbol)typeSymbol); if (HlslKnownTypes.TryGetMappedName(typeName, out string?mappedName)) { TypeSyntax newType = ParseTypeName(mappedName !); return(node.ReplaceNode(targetType, newType)); } return(node.ReplaceNode(targetType, ParseTypeName(typeName.Replace(".", "__")))); }