public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol) { bool interfaceDefinition = symbol.ContainingType != null && symbol.ContainingType.Kind == SymbolKind.NamedType && symbol.ContainingType.TypeKind == TypeKind.Interface; HasAccessibility(cx, trapFile, key, symbol.DeclaredAccessibility); if (symbol.Kind == SymbolKind.ErrorType) { trapFile.has_modifiers(key, Modifier.Create(cx, Accessibility.Public)); } if (symbol.IsAbstract && (symbol.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)symbol).TypeKind != TypeKind.Interface) && !interfaceDefinition) { HasModifier(cx, trapFile, key, "abstract"); } if (symbol.IsSealed) { HasModifier(cx, trapFile, key, "sealed"); } bool fromSource = symbol.DeclaringSyntaxReferences.Length > 0; if (symbol.IsStatic && !(symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsConst && !fromSource)) { HasModifier(cx, trapFile, key, "static"); } if (symbol.IsVirtual) { HasModifier(cx, trapFile, key, "virtual"); } // For some reason, method in interfaces are "virtual", not "abstract" if (symbol.IsAbstract && interfaceDefinition) { HasModifier(cx, trapFile, key, "virtual"); } if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly) { HasModifier(cx, trapFile, key, "readonly"); } if (symbol.IsOverride) { HasModifier(cx, trapFile, key, "override"); } if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).IsAsync) { HasModifier(cx, trapFile, key, "async"); } if (symbol.IsExtern) { HasModifier(cx, trapFile, key, "extern"); } foreach (var modifier in symbol.GetSourceLevelModifiers()) { HasModifier(cx, trapFile, 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, trapFile, key, "readonly"); } if (nt.IsRefLikeType) { HasModifier(cx, trapFile, key, "ref"); } } } }
protected void PopulateType(TextWriter trapFile, bool constructUnderlyingTupleType = false) { PopulateMetadataHandle(trapFile); PopulateAttributes(); trapFile.Write("types("); trapFile.WriteColumn(this); trapFile.Write(','); trapFile.WriteColumn((int)GetClassType(Context, symbol, constructUnderlyingTupleType)); trapFile.Write(",\""); symbol.BuildDisplayName(Context, trapFile, constructUnderlyingTupleType); trapFile.WriteLine("\")"); // Visit base types var baseTypes = new List <Type>(); if (symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base) { var baseKey = Create(Context, @base); trapFile.extend(this, baseKey.TypeRef); if (symbol.TypeKind != TypeKind.Struct) { baseTypes.Add(baseKey); } } if (!(base.symbol is IArrayTypeSymbol)) { foreach (var t in base.symbol.Interfaces.Select(i => Create(Context, i))) { trapFile.implement(this, t.TypeRef); baseTypes.Add(t); } } var containingType = ContainingType; if (containingType != null && symbol.Kind != SymbolKind.TypeParameter) { var originalDefinition = symbol.TypeKind == TypeKind.Error ? this : Create(Context, symbol.OriginalDefinition); trapFile.nested_types(this, containingType, originalDefinition); } else if (symbol.ContainingNamespace != null) { trapFile.parent_namespace(this, Namespace.Create(Context, symbol.ContainingNamespace)); } if (symbol is IArrayTypeSymbol array) { // They are in the namespace of the original object var elementType = array.ElementType; var ns = elementType.TypeKind == TypeKind.TypeParameter ? Context.Compilation.GlobalNamespace : elementType.ContainingNamespace; if (ns != null) { trapFile.parent_namespace(this, Namespace.Create(Context, ns)); } } if (symbol is IPointerTypeSymbol pointer) { var elementType = pointer.PointedAtType; var ns = elementType.TypeKind == TypeKind.TypeParameter ? Context.Compilation.GlobalNamespace : elementType.ContainingNamespace; if (ns != null) { trapFile.parent_namespace(this, Namespace.Create(Context, ns)); } } if (symbol.BaseType != null && symbol.BaseType.SpecialType == SpecialType.System_MulticastDelegate) { // This is a delegate. // The method "Invoke" has the return type. var invokeMethod = ((INamedTypeSymbol)symbol).DelegateInvokeMethod; ExtractParametersForDelegateLikeType(trapFile, invokeMethod, t => trapFile.delegate_return_type(this, t)); } if (symbol is IFunctionPointerTypeSymbol functionPointer) { ExtractParametersForDelegateLikeType(trapFile, functionPointer.Signature, t => trapFile.function_pointer_return_type(this, t)); } Modifier.ExtractModifiers(Context, trapFile, this, symbol); if (IsSourceDeclaration && symbol.FromSource()) { var declSyntaxReferences = symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).ToArray(); var baseLists = declSyntaxReferences.OfType <ClassDeclarationSyntax>().Select(c => c.BaseList); baseLists = baseLists.Concat(declSyntaxReferences.OfType <InterfaceDeclarationSyntax>().Select(c => c.BaseList)); baseLists = baseLists.Concat(declSyntaxReferences.OfType <StructDeclarationSyntax>().Select(c => c.BaseList)); baseLists .Where(bl => bl != null) .SelectMany(bl => bl.Types) .Zip( baseTypes.Where(bt => bt.symbol.SpecialType != SpecialType.System_Object), (s, t) => TypeMention.Create(Context, s.Type, this, t)) .Enumerate(); } }
public override void Populate(TextWriter trapFile) { PopulateMetadataHandle(trapFile); PopulateAttributes(); ContainingType.PopulateGenerics(); PopulateNullability(trapFile, symbol.GetAnnotatedType()); Field unboundFieldKey = Field.Create(Context, symbol.OriginalDefinition); trapFile.fields(this, (symbol.IsConst ? 2 : 1), symbol.Name, ContainingType, Type.Type.TypeRef, unboundFieldKey); PopulateModifiers(trapFile); if (symbol.IsVolatile) { Modifier.HasModifier(Context, trapFile, this, "volatile"); } if (symbol.IsConst) { Modifier.HasModifier(Context, trapFile, this, "const"); if (symbol.HasConstantValue) { trapFile.constant_value(this, Expression.ValueAsString(symbol.ConstantValue)); } } foreach (var l in Locations) { trapFile.field_location(this, l); } if (!IsSourceDeclaration || !symbol.FromSource()) { return; } Context.BindComments(this, Location.symbol); int child = 0; foreach (var initializer in symbol.DeclaringSyntaxReferences. Select(n => n.GetSyntax()). OfType <VariableDeclaratorSyntax>(). Where(n => n.Initializer != null)) { Context.PopulateLater(() => { var loc = Context.Create(initializer.GetLocation()); var simpleAssignExpr = new Expression(new ExpressionInfo(Context, Type, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null)); Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Initializer.Value, simpleAssignExpr, 0)); var access = new Expression(new ExpressionInfo(Context, Type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 1, false, null)); trapFile.expr_access(access, this); if (!symbol.IsStatic) { This.CreateImplicit(Context, Entities.Type.Create(Context, symbol.ContainingType), Location, access, -1); } }); } foreach (var initializer in symbol.DeclaringSyntaxReferences. Select(n => n.GetSyntax()). OfType <EnumMemberDeclarationSyntax>(). Where(n => n.EqualsValue != null)) { // Mark fields that have explicit initializers. var expr = new Expression(new ExpressionInfo(Context, Type, Context.Create(initializer.EqualsValue.Value.FixedLocation()), Kinds.ExprKind.FIELD_ACCESS, this, child++, false, null)); trapFile.expr_access(expr, this); } if (IsSourceDeclaration) { foreach (var syntax in symbol.DeclaringSyntaxReferences. Select(d => d.GetSyntax()).OfType <VariableDeclaratorSyntax>(). Select(d => d.Parent).OfType <VariableDeclarationSyntax>()) { TypeMention.Create(Context, syntax.Type, this, Type); } } }
public static void HasModifier(Context cx, TextWriter trapFile, IEntity target, string modifier) { trapFile.has_modifiers(target, Modifier.Create(cx, modifier)); }
public override void Populate(TextWriter trapFile) { PopulateMetadataHandle(trapFile); PopulateAttributes(); ContainingType.PopulateGenerics(); PopulateNullability(trapFile, symbol.GetAnnotatedType()); var unboundFieldKey = Field.Create(Context, symbol.OriginalDefinition); trapFile.fields(this, (symbol.IsConst ? 2 : 1), symbol.Name, ContainingType, Type.Type.TypeRef, unboundFieldKey); PopulateModifiers(trapFile); if (symbol.IsVolatile) { Modifier.HasModifier(Context, trapFile, this, "volatile"); } if (symbol.IsConst) { Modifier.HasModifier(Context, trapFile, this, "const"); if (symbol.HasConstantValue) { trapFile.constant_value(this, Expression.ValueAsString(symbol.ConstantValue)); } } foreach (var l in Locations) { trapFile.field_location(this, l); } if (!IsSourceDeclaration || !symbol.FromSource()) { return; } Context.BindComments(this, Location.symbol); var child = 0; foreach (var initializer in symbol.DeclaringSyntaxReferences .Select(n => n.GetSyntax()) .OfType <VariableDeclaratorSyntax>() .Where(n => n.Initializer != null)) { Context.PopulateLater(() => { var loc = Context.Create(initializer.GetLocation()); var fieldAccess = AddInitializerAssignment(trapFile, initializer.Initializer.Value, loc, null, ref child); if (!symbol.IsStatic) { This.CreateImplicit(Context, Entities.Type.Create(Context, symbol.ContainingType), Location, fieldAccess, -1); } }); } foreach (var initializer in symbol.DeclaringSyntaxReferences .Select(n => n.GetSyntax()) .OfType <EnumMemberDeclarationSyntax>() .Where(n => n.EqualsValue != null)) { // Mark fields that have explicit initializers. var constValue = symbol.HasConstantValue ? Expression.ValueAsString(symbol.ConstantValue) : null; var loc = Context.Create(initializer.GetLocation()); AddInitializerAssignment(trapFile, initializer.EqualsValue.Value, loc, constValue, ref child); } if (IsSourceDeclaration) { foreach (var syntax in symbol.DeclaringSyntaxReferences .Select(d => d.GetSyntax()) .OfType <VariableDeclaratorSyntax>() .Select(d => d.Parent) .OfType <VariableDeclarationSyntax>()) { TypeMention.Create(Context, syntax.Type, this, Type); } } }
public override void Populate() { ExtractMetadataHandle(); ExtractAttributes(); ContainingType.ExtractGenerics(); Field unboundFieldKey = Field.Create(Context, symbol.OriginalDefinition); Context.Emit(Tuples.fields(this, (symbol.IsConst ? 2 : 1), symbol.Name, ContainingType, Type.TypeRef, unboundFieldKey)); ExtractModifiers(); if (symbol.IsVolatile) { Modifier.HasModifier(Context, this, "volatile"); } if (symbol.IsConst) { Modifier.HasModifier(Context, this, "const"); if (symbol.HasConstantValue) { Context.Emit(Tuples.constant_value(this, Expression.ValueAsString(symbol.ConstantValue))); } } foreach (var l in Locations) { Context.Emit(Tuples.field_location(this, l)); } if (!IsSourceDeclaration || !symbol.FromSource()) { return; } Context.BindComments(this, Location.symbol); int child = 0; foreach (var initializer in symbol.DeclaringSyntaxReferences. Select(n => n.GetSyntax()). OfType <VariableDeclaratorSyntax>(). Where(n => n.Initializer != null)) { Context.PopulateLater(() => { Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Initializer.Value, this, child++)); }); } foreach (var initializer in symbol.DeclaringSyntaxReferences. Select(n => n.GetSyntax()). OfType <EnumMemberDeclarationSyntax>(). Where(n => n.EqualsValue != null)) { // Mark fields that have explicit initializers. var expr = new Expression(new ExpressionInfo(Context, Type, Context.Create(initializer.EqualsValue.Value.FixedLocation()), Kinds.ExprKind.FIELD_ACCESS, this, child++, false, null)); Context.Emit(Tuples.expr_access(expr, this)); } if (IsSourceDeclaration) { foreach (var syntax in symbol.DeclaringSyntaxReferences. Select(d => d.GetSyntax()).OfType <VariableDeclaratorSyntax>(). Select(d => d.Parent).OfType <VariableDeclarationSyntax>()) { TypeMention.Create(Context, syntax.Type, this, Type); } } }
protected void PopulateType(TextWriter trapFile) { PopulateMetadataHandle(trapFile); PopulateAttributes(); trapFile.Write("types("); trapFile.WriteColumn(this); trapFile.Write(','); trapFile.WriteColumn((int)GetClassType(Context, symbol)); trapFile.Write(",\""); symbol.BuildDisplayName(Context, trapFile); trapFile.WriteLine("\")"); // Visit base types var baseTypes = new List <Type>(); if (symbol.BaseType != null) { Type baseKey = Create(Context, symbol.BaseType); trapFile.extend(this, baseKey.TypeRef); if (symbol.TypeKind != TypeKind.Struct) { baseTypes.Add(baseKey); } } if (symbol.TypeKind == TypeKind.Interface) { trapFile.extend(this, Create(Context, Context.Compilation.ObjectType)); } if (!(base.symbol is IArrayTypeSymbol)) { foreach (var t in base.symbol.Interfaces.Select(i => Create(Context, i))) { trapFile.implement(this, t.TypeRef); baseTypes.Add(t); } } var containingType = ContainingType; if (containingType != null && symbol.Kind != SymbolKind.TypeParameter) { Type originalDefinition = symbol.TypeKind == TypeKind.Error ? this : Create(Context, symbol.OriginalDefinition); trapFile.nested_types(this, containingType, originalDefinition); } else if (symbol.ContainingNamespace != null) { trapFile.parent_namespace(this, Namespace.Create(Context, symbol.ContainingNamespace)); } if (symbol is IArrayTypeSymbol) { // They are in the namespace of the original object ITypeSymbol elementType = ((IArrayTypeSymbol)symbol).ElementType; INamespaceSymbol ns = elementType.TypeKind == TypeKind.TypeParameter ? Context.Compilation.GlobalNamespace : elementType.ContainingNamespace; if (ns != null) { trapFile.parent_namespace(this, Namespace.Create(Context, ns)); } } if (symbol is IPointerTypeSymbol) { ITypeSymbol elementType = ((IPointerTypeSymbol)symbol).PointedAtType; INamespaceSymbol ns = elementType.TypeKind == TypeKind.TypeParameter ? Context.Compilation.GlobalNamespace : elementType.ContainingNamespace; if (ns != null) { trapFile.parent_namespace(this, Namespace.Create(Context, ns)); } } if (symbol.BaseType != null && symbol.BaseType.SpecialType == SpecialType.System_MulticastDelegate) { // This is a delegate. // The method "Invoke" has the return type. var invokeMethod = ((INamedTypeSymbol)symbol).DelegateInvokeMethod; // Copy the parameters from the "Invoke" method to the delegate type for (var i = 0; i < invokeMethod.Parameters.Length; ++i) { var param = invokeMethod.Parameters[i]; var originalParam = invokeMethod.OriginalDefinition.Parameters[i]; var originalParamEntity = SymbolEqualityComparer.Default.Equals(param, originalParam) ? null : DelegateTypeParameter.Create(Context, originalParam, Create(Context, ((INamedTypeSymbol)symbol).OriginalDefinition)); DelegateTypeParameter.Create(Context, param, this, originalParamEntity); } var returnKey = Create(Context, invokeMethod.ReturnType); trapFile.delegate_return_type(this, returnKey.TypeRef); if (invokeMethod.ReturnsByRef) { trapFile.type_annotation(this, Kinds.TypeAnnotation.Ref); } if (invokeMethod.ReturnsByRefReadonly) { trapFile.type_annotation(this, Kinds.TypeAnnotation.ReadonlyRef); } } Modifier.ExtractModifiers(Context, trapFile, this, symbol); if (IsSourceDeclaration && symbol.FromSource()) { var declSyntaxReferences = symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).ToArray(); var baseLists = declSyntaxReferences.OfType <ClassDeclarationSyntax>().Select(c => c.BaseList); baseLists = baseLists.Concat(declSyntaxReferences.OfType <InterfaceDeclarationSyntax>().Select(c => c.BaseList)); baseLists = baseLists.Concat(declSyntaxReferences.OfType <StructDeclarationSyntax>().Select(c => c.BaseList)); baseLists. Where(bl => bl != null). SelectMany(bl => bl.Types). Zip(baseTypes.Where(bt => bt.symbol.SpecialType != SpecialType.System_Object), (s, t) => TypeMention.Create(Context, s.Type, this, t)). Enumerate(); } }
public static void HasModifier(Context cx, IEntity target, string modifier) { cx.Emit(Tuples.has_modifiers(target, Modifier.Create(cx, modifier))); }
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) { // 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); bool isReadOnly = (bool)readonlyProperty.GetValue(nt); bool isByRefLikeType = nt.IsRefLikeType; if (isReadOnly) { HasModifier(cx, key, "readonly"); } if (isByRefLikeType) { HasModifier(cx, key, "ref"); } } } }