public static void ExtractModifiers(Context cx, IEntity key, ISymbol symbol) { bool interfaceDefinition = symbol.ContainingType != null && symbol.ContainingType.Kind == SymbolKind.NamedType && symbol.ContainingType.TypeKind == TypeKind.Interface; Modifier.HasAccessibility(cx, key, symbol.DeclaredAccessibility); if (symbol.Kind == SymbolKind.ErrorType) { cx.Emit(Tuples.has_modifiers(key, Modifier.Create(cx, Accessibility.Public))); } if (symbol.IsAbstract && (symbol.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)symbol).TypeKind != TypeKind.Interface) && !interfaceDefinition) { Modifier.HasModifier(cx, key, "abstract"); } if (symbol.IsSealed) { HasModifier(cx, key, "sealed"); } bool fromSource = symbol.DeclaringSyntaxReferences.Length > 0; if (symbol.IsStatic && !(symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsConst && !fromSource)) { HasModifier(cx, key, "static"); } if (symbol.IsVirtual) { HasModifier(cx, key, "virtual"); } // For some reason, method in interfaces are "virtual", not "abstract" if (symbol.IsAbstract && interfaceDefinition) { HasModifier(cx, key, "virtual"); } if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly) { HasModifier(cx, key, "readonly"); } if (symbol.IsOverride) { HasModifier(cx, key, "override"); } if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).IsAsync) { HasModifier(cx, key, "async"); } if (symbol.IsExtern) { HasModifier(cx, key, "extern"); } foreach (var modifier in symbol.GetSourceLevelModifiers()) { HasModifier(cx, key, modifier); } if (symbol.Kind == SymbolKind.NamedType) { INamedTypeSymbol nt = symbol as INamedTypeSymbol; if (nt is null) { throw new InternalError(symbol, "Symbol kind is inconsistent with its type"); } if (nt.TypeKind == TypeKind.Struct) { if (nt.IsReadOnly) { HasModifier(cx, key, "readonly"); } if (nt.IsRefLikeType) { HasModifier(cx, key, "ref"); } } } }
public static void ExtractModifiers(Context cx, IEntity key, ISymbol symbol) { bool interfaceDefinition = symbol.ContainingType != null && symbol.ContainingType.Kind == SymbolKind.NamedType && symbol.ContainingType.TypeKind == TypeKind.Interface; Modifier.HasAccessibility(cx, key, symbol.DeclaredAccessibility); if (symbol.Kind == SymbolKind.ErrorType) { cx.Emit(Tuples.has_modifiers(key, Modifier.Create(cx, Accessibility.Public))); } if (symbol.IsAbstract && (symbol.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)symbol).TypeKind != TypeKind.Interface) && !interfaceDefinition) { Modifier.HasModifier(cx, key, "abstract"); } if (symbol.IsSealed) { HasModifier(cx, key, "sealed"); } bool fromSource = symbol.DeclaringSyntaxReferences.Length > 0; if (symbol.IsStatic && !(symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsConst && !fromSource)) { HasModifier(cx, key, "static"); } if (symbol.IsVirtual) { HasModifier(cx, key, "virtual"); } // For some reason, method in interfaces are "virtual", not "abstract" if (symbol.IsAbstract && interfaceDefinition) { HasModifier(cx, key, "virtual"); } if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly) { HasModifier(cx, key, "readonly"); } if (symbol.IsOverride) { HasModifier(cx, key, "override"); } if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).IsAsync) { HasModifier(cx, key, "async"); } if (symbol.IsExtern) { HasModifier(cx, key, "extern"); } foreach (var modifier in symbol.GetSourceLevelModifiers()) { HasModifier(cx, key, modifier); } if (symbol.Kind == SymbolKind.NamedType) { INamedTypeSymbol nt = symbol as INamedTypeSymbol; if (nt.TypeKind == TypeKind.Struct) { // Sadly, these properties are internal so cannot be accessed directly. // This seems to be a deficiency in the model. var readonlyProperty = nt.GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance); var isByRefProperty = nt.GetType().GetProperty("IsByRefLikeType", BindingFlags.NonPublic | BindingFlags.Instance); bool isReadOnly = (bool)readonlyProperty.GetValue(nt); bool isByRefLikeType = (bool)isByRefProperty.GetValue(nt); if (isReadOnly) { HasModifier(cx, key, "readonly"); } if (isByRefLikeType) { HasModifier(cx, key, "ref"); } } } }