From cfd1d4df53db7ec734bce22c2a81a0322906641e Mon Sep 17 00:00:00 2001 From: MeltyPlayer Date: Tue, 1 Aug 2023 20:33:39 -0500 Subject: [PATCH] Optimized some parsing logic. --- .../src/binary/BinarySchemaStructureParser.cs | 11 +- Schema/src/binary/SymbolTypeUtil.cs | 106 +++++++++++++++--- .../src/binary/attributes/BMemberAttribute.cs | 14 +-- 3 files changed, 102 insertions(+), 29 deletions(-) diff --git a/Schema/src/binary/BinarySchemaStructureParser.cs b/Schema/src/binary/BinarySchemaStructureParser.cs index ad15a91..88754e0 100644 --- a/Schema/src/binary/BinarySchemaStructureParser.cs +++ b/Schema/src/binary/BinarySchemaStructureParser.cs @@ -153,7 +153,7 @@ public IBinarySchemaStructure ParseStructure( } var localPositions = - structureSymbol.HasAttribute(diagnostics); + structureSymbol.HasAttribute(); var structureEndianness = new EndiannessParser().GetEndianness(diagnostics, structureSymbol); @@ -173,7 +173,7 @@ public IBinarySchemaStructure ParseStructure( var methodSymbol = memberSymbol as IMethodSymbol; var isMethod = methodSymbol != null; var hasRunAtReadTimeAttribute = - memberSymbol.HasAttribute(diagnostics); + memberSymbol.HasAttribute(); if (hasRunAtReadTimeAttribute) { if (isMethod) { if (methodSymbol.Parameters.Length == 1 && methodSymbol @@ -198,7 +198,7 @@ public IBinarySchemaStructure ParseStructure( } bool isIgnored = - memberSymbol.HasAttribute(diagnostics) || + memberSymbol.HasAttribute() || (memberSymbol.Name == nameof(IChildOf.Parent) && parentTypeSymbol != null); @@ -516,9 +516,8 @@ memberType is BinarySchemaStructureParser.PrimitiveMemberType .GetAttribute( diagnostics, memberSymbol); - var isNullTerminatedString = - memberSymbol.HasAttribute( - diagnostics); + var isNullTerminatedString = memberSymbol + .HasAttribute(); var hasStringLengthAttribute = stringLengthSourceAttribute != null || isNullTerminatedString; diff --git a/Schema/src/binary/SymbolTypeUtil.cs b/Schema/src/binary/SymbolTypeUtil.cs index de7508e..70a8c31 100644 --- a/Schema/src/binary/SymbolTypeUtil.cs +++ b/Schema/src/binary/SymbolTypeUtil.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; using Microsoft.CodeAnalysis; @@ -15,10 +17,12 @@ namespace schema.binary { internal static class SymbolTypeUtil { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ISymbol GetSymbolFromType(SemanticModel semanticModel, Type type) => SymbolTypeUtil.GetSymbolFromIdentifier(semanticModel, type.FullName); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ISymbol GetSymbolFromIdentifier( SemanticModel semanticModel, string identifier) { @@ -26,6 +30,7 @@ public static ISymbol GetSymbolFromIdentifier( return symbol.First(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool CanBeStoredAs(this ITypeSymbol symbol) => symbol.CanBeStoredAs(typeof(TType)); @@ -44,6 +49,7 @@ public static bool CanBeStoredAs(this ITypeSymbol symbol, Type type) { } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool ImplementsGeneric(this ITypeSymbol symbol, Type type) => symbol.ImplementsGeneric(type, out _); @@ -62,19 +68,76 @@ public static bool ImplementsGeneric(this ITypeSymbol symbol, } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsBinaryDeserializable(this ITypeSymbol symbol) => symbol.Implements(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsBinarySerializable(this ITypeSymbol symbol) => symbol.Implements(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool Implements(this ITypeSymbol symbol) => symbol.Implements(typeof(TType)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool Implements(this ITypeSymbol symbol, Type type) => symbol.AllInterfaces.Any(i => i.IsExactlyType(type)); + // Namespace + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool IsInSameNamespaceAs(this ISymbol symbol, ISymbol other) + => symbol.ContainingNamespace.Equals(other.ContainingNamespace); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool IsInSameNamespaceAs(this ISymbol symbol, Type other) + => symbol.IsInNamespace(other.Namespace); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool IsInNamespace( + this ISymbol symbol, + string fullNamespacePath) { + var fullNamespacePathLength = fullNamespacePath.Length; + + var currentNamespace = symbol.ContainingNamespace; + var currentNamespaceName = currentNamespace.Name; + var currentNamespaceNameLength = currentNamespaceName.Length; + + if (fullNamespacePathLength == 0 && currentNamespaceNameLength == 0) { + return true; + } + + var fullNamespaceI = fullNamespacePathLength - 1; + var currentNamespaceI = currentNamespaceNameLength - 1; + + for (; fullNamespaceI >= 0; --fullNamespaceI, --currentNamespaceI) { + if (currentNamespaceI == -1) { + if (fullNamespacePath[fullNamespaceI] != '.') { + return false; + } + + --fullNamespaceI; + currentNamespace = currentNamespace.ContainingNamespace; + currentNamespaceName = currentNamespace.Name; + currentNamespaceNameLength = currentNamespaceName.Length; + if (currentNamespaceNameLength == 0) { + return false; + } + + currentNamespaceI = currentNamespaceNameLength - 1; + } + + if (fullNamespacePath[fullNamespaceI] != + currentNamespaceName[currentNamespaceI]) { + return false; + } + } + + return fullNamespaceI == -1 && currentNamespaceI == -1 && + currentNamespace.ContainingNamespace.Name.Length == 0; + } + public static string[]? GetContainingNamespaces(this ISymbol symbol) { var namespaceSymbol = symbol.ContainingNamespace; if (namespaceSymbol == null) { @@ -93,6 +156,7 @@ public static bool Implements(this ITypeSymbol symbol, Type type) return namespaces.ToArray(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string? MergeContainingNamespaces(ISymbol symbol) => MergeNamespaceParts(GetContainingNamespaces(symbol)); @@ -138,38 +202,43 @@ public static bool MatchesGeneric(this INamedTypeSymbol symbol, return sameName && sameNamespace && sameTypeArguments; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsExactlyType(this ISymbol symbol, Type expectedType) => symbol.Name == expectedType.Name && - SymbolTypeUtil.MergeContainingNamespaces(symbol) == - expectedType.Namespace; + symbol.IsInSameNamespaceAs(expectedType); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static ImmutableArray GetAttributeData( + this ISymbol symbol) + => symbol.GetAttributes(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool HasAttribute(this ISymbol symbol, Type expectedType) - => symbol.GetAttributes() + => symbol.GetAttributeData() .Any(attributeData => attributeData.AttributeClass!.IsExactlyType( expectedType)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static IEnumerable GetAttributeData(this ISymbol symbol) { var attributeType = typeof(TAttribute); - return symbol.GetAttributes() - .Where(attributeData => { - var attributeSymbol = attributeData.AttributeClass; - - return attributeSymbol.Name == attributeType.Name && - SymbolTypeUtil.MergeContainingNamespaces( - attributeSymbol) == - attributeType.Namespace; - }); + return symbol + .GetAttributeData() + .Where(attributeData + => attributeData.AttributeClass?.IsExactlyType( + attributeType) ?? false); } - internal static bool HasAttribute( - this ISymbol symbol, - IList diagnostics) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool HasAttribute(this ISymbol symbol) where TAttribute : Attribute - => symbol.GetAttribute(diagnostics) != null; + => symbol.GetAttributeData().Any(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static TAttribute? GetAttribute( this ISymbol symbol, IList diagnostics) @@ -178,6 +247,7 @@ internal static bool HasAttribute( .SingleOrDefault(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static TAttribute? GetAttribute( IList diagnostics, ISymbol symbol) @@ -185,6 +255,7 @@ internal static bool HasAttribute( => symbol.GetAttributes(diagnostics) .SingleOrDefault(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static IEnumerable GetAttributes( this ISymbol symbol, IList diagnostics) @@ -275,6 +346,7 @@ public static string GetQualifiersAndNameFor( return sb.ToString(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string GetSymbolQualifiers(this INamedTypeSymbol typeSymbol) => (typeSymbol.IsStatic ? "static " : "") + SymbolTypeUtil.AccessibilityToModifier( @@ -284,6 +356,7 @@ public static string GetSymbolQualifiers(this INamedTypeSymbol typeSymbol) "partial " + (typeSymbol.TypeKind == TypeKind.Class ? "class" : "struct"); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string AccessibilityToModifier( Accessibility accessibility) => accessibility switch { @@ -371,6 +444,7 @@ or SpecialType.System_Boolean $"{mergedNamespaceText}{mergedContainersText}{referencedSymbol.Name}"; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void GetMemberInStructure( this ITypeSymbol structureSymbol, string memberName, diff --git a/Schema/src/binary/attributes/BMemberAttribute.cs b/Schema/src/binary/attributes/BMemberAttribute.cs index 7e5d44f..5efa640 100644 --- a/Schema/src/binary/attributes/BMemberAttribute.cs +++ b/Schema/src/binary/attributes/BMemberAttribute.cs @@ -177,13 +177,13 @@ protected IMemberReference GetReadTimeOnlySourceRelativeToStructure( private bool IsMemberWritePrivateOrIgnored_(ISymbol symbol) => symbol switch { - IPropertySymbol propertySymbol - => (propertySymbol.SetMethod - ?.DeclaredAccessibility ?? - Accessibility.Private) == Accessibility.Private, - IFieldSymbol fieldSymbol - => fieldSymbol.DeclaredAccessibility == Accessibility.Private, - } || symbol.HasAttribute(this.diagnostics_); + IPropertySymbol propertySymbol + => (propertySymbol.SetMethod + ?.DeclaredAccessibility ?? + Accessibility.Private) == Accessibility.Private, + IFieldSymbol fieldSymbol + => fieldSymbol.DeclaredAccessibility == Accessibility.Private, + } || symbol.HasAttribute(); }