示例#1
0
        public void Conversions()
        {
            TypedConstant common = new TypedConstant(systemType, TypedConstantKind.Type, namedType);
            TypedConstant lang = (TypedConstant)common;
            TypedConstant common2 = lang;

            Assert.Equal(common.Value, lang.Value);
            Assert.Equal(common.Kind, lang.Kind);
            Assert.Equal<object>(common.Type, lang.Type);

            Assert.Equal(common.Value, common2.Value);
            Assert.Equal(common.Kind, common2.Kind);
            Assert.Equal(common.Type, common2.Type);

            TypedConstant commonArray = new TypedConstant(arrayType, 
                new[] { new TypedConstant(systemType, TypedConstantKind.Type, namedType) }.AsImmutableOrNull());

            TypedConstant langArray = (TypedConstant)commonArray;
            TypedConstant commonArray2 = langArray;

            Assert.Equal(commonArray.Values.Single(), langArray.Values.Single());
            Assert.Equal(commonArray.Kind, langArray.Kind);
            Assert.Equal<object>(commonArray.Type, langArray.Type);

            Assert.Equal(commonArray.Values, commonArray2.Values);
            Assert.Equal(commonArray.Kind, commonArray2.Kind);
            Assert.Equal(commonArray.Type, commonArray2.Type);
        }
        internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder<SynthesizedAttributeData> attributes)
        {
            base.AddSynthesizedAttributes(compilationState, ref attributes);

            var compilation = this.DeclaringCompilation;
            var systemType = compilation.GetWellKnownType(WellKnownType.System_Type);
            var intType = compilation.GetSpecialType(SpecialType.System_Int32);
            var item1 = new TypedConstant(systemType, TypedConstantKind.Type, ((PointerTypeSymbol)this.Type).PointedAtType);
            var item2 = new TypedConstant(intType, TypedConstantKind.Primitive, this.FixedSize);
            AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(
                WellKnownMember.System_Runtime_CompilerServices_FixedBufferAttribute__ctor,
                ImmutableArray.Create<TypedConstant>(item1, item2)));
        }
        // Decode the value of enum constant
        private static string DisplayEnumConstant(TypedConstant constant)
        {
            Debug.Assert(constant.Kind == TypedConstantKind.Enum);

            // Create a ConstantValue of enum underlying type
            SpecialType splType = ((INamedTypeSymbol)constant.Type).EnumUnderlyingType.SpecialType;
            ConstantValue valueConstant = ConstantValue.Create(constant.Value, splType);

            string typeName = constant.Type.ToDisplayString(SymbolDisplayFormat.QualifiedNameOnlyFormat);
            if (valueConstant.IsUnsigned)
            {
                return DisplayUnsignedEnumConstant(constant, splType, valueConstant.UInt64Value, typeName);
            }
            else
            {
                return DisplaySignedEnumConstant(constant, splType, valueConstant.Int64Value, typeName);
            }
        }
示例#4
0
        private Cci.IMetadataExpression CreateMetadataExpression(TypedConstant argument, EmitContext context)
        {
            if (argument.IsNull)
            {
                return CreateMetadataConstant(argument.Type, null, context);
            }

            switch (argument.Kind)
            {
                case TypedConstantKind.Array:
                    return CreateMetadataArray(argument, context);

                case TypedConstantKind.Type:
                    return CreateType(argument, context);

                default:
                    return CreateMetadataConstant(argument.Type, argument.Value, context);
            }
        }
示例#5
0
        private static string GetLiteralString(TypedConstant constant)
        {
            var type = constant.Type;
            var value = constant.Value;

            if (type.TypeKind == TypeKind.Enum)
            {
                var namedType = (INamedTypeSymbol)type;
                var pairs = (from member in namedType.GetMembers().OfType<IFieldSymbol>()
                             where member.IsConst && member.HasConstantValue
                             select Tuple.Create(member.Name, member.ConstantValue)).ToDictionary(tuple => tuple.Item2, tuple => tuple.Item1);

                return $"{VisitorHelper.GetId(namedType)}.{pairs[value]}";
            }

            if (value is ITypeSymbol)
            {
                return VisitorHelper.GetId((ITypeSymbol)value);
            }

            return value.ToString();
        }
示例#6
0
        private static ExpressionSyntax GetLiteralExpression(TypedConstant constant)
        {
            if (constant.Type.TypeKind == TypeKind.Array)
            {
                if (constant.Values == null)
                {
                    return GetLiteralExpression(null, constant.Type);
                }
                var items = (from value in constant.Values
                             select GetLiteralExpression(value)).ToList();
                if (items.TrueForAll(x => x != null))
                {
                    return SyntaxFactory.ArrayCreationExpression(
                        (ArrayTypeSyntax)GetTypeSyntax(constant.Type),
                        SyntaxFactory.InitializerExpression(
                            SyntaxKind.ArrayInitializerExpression,
                            SyntaxFactory.SeparatedList(
                                from value in constant.Values
                                select GetLiteralExpression(value))));
                }
                return SyntaxFactory.ArrayCreationExpression(
                    (ArrayTypeSyntax)GetTypeSyntax(constant.Type));
            }

            var expr = GetLiteralExpression(constant.Value, constant.Type);
            if (expr == null)
            {
                return null;
            }

            switch (constant.Type.SpecialType)
            {
                case SpecialType.System_SByte:
                    return SyntaxFactory.CastExpression(
                        SyntaxFactory.PredefinedType(
                            SyntaxFactory.Token(SyntaxKind.SByteKeyword)),
                        expr);
                case SpecialType.System_Byte:
                    return SyntaxFactory.CastExpression(
                        SyntaxFactory.PredefinedType(
                            SyntaxFactory.Token(SyntaxKind.ByteKeyword)),
                        expr);
                case SpecialType.System_Int16:
                    return SyntaxFactory.CastExpression(
                        SyntaxFactory.PredefinedType(
                            SyntaxFactory.Token(SyntaxKind.ShortKeyword)),
                        expr);
                case SpecialType.System_UInt16:
                    return SyntaxFactory.CastExpression(
                        SyntaxFactory.PredefinedType(
                            SyntaxFactory.Token(SyntaxKind.UShortKeyword)),
                        expr);
                default:
                    return expr;
            }
        }
        internal SynthesizedAttributeData SynthesizeDebuggableAttribute()
        {
            TypeSymbol debuggableAttribute = GetWellKnownType(WellKnownType.System_Diagnostics_DebuggableAttribute);

            Debug.Assert((object)debuggableAttribute != null, "GetWellKnownType unexpectedly returned null");
            if (debuggableAttribute is MissingMetadataTypeSymbol)
            {
                return(null);
            }

            TypeSymbol debuggingModesType = GetWellKnownType(WellKnownType.System_Diagnostics_DebuggableAttribute__DebuggingModes);

            Debug.Assert((object)debuggingModesType != null, "GetWellKnownType unexpectedly returned null");
            if (debuggingModesType is MissingMetadataTypeSymbol)
            {
                return(null);
            }

            var defaulDebuggingMode = (FieldSymbol)GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute_DebuggingModes__Default);

            if ((object)defaulDebuggingMode == null || !defaulDebuggingMode.HasConstantValue)
            {
                return(null);
            }

            var disableOptsDebuggingMode = (FieldSymbol)GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute_DebuggingModes__DisableOptimizations);

            if ((object)disableOptsDebuggingMode == null || !disableOptsDebuggingMode.HasConstantValue)
            {
                return(null);
            }

            var enableENCDebuggingMode = (FieldSymbol)GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute_DebuggingModes__EnableEditAndContinue);

            if ((object)enableENCDebuggingMode == null || !enableENCDebuggingMode.HasConstantValue)
            {
                return(null);
            }

            var ignorePDBDebuggingMode = (FieldSymbol)GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute_DebuggingModes__IgnoreSymbolStoreSequencePoints);

            if ((object)ignorePDBDebuggingMode == null || !ignorePDBDebuggingMode.HasConstantValue)
            {
                return(null);
            }

            Debug.Assert(options.DebugInformationKind.IsValid() && options.DebugInformationKind != DebugInformationKind.None);

            bool emittingFullDebugInfo = options.DebugInformationKind == DebugInformationKind.Full;
            bool optimizationsDisabled = !options.Optimize;

            int constantVal = ignorePDBDebuggingMode.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false).Int32Value;

            if (emittingFullDebugInfo)
            {
                constantVal |= defaulDebuggingMode.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false).Int32Value;
            }

            if (optimizationsDisabled)
            {
                constantVal |= disableOptsDebuggingMode.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false).Int32Value;

                if (emittingFullDebugInfo)
                {
                    constantVal |= enableENCDebuggingMode.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false).Int32Value;
                }
            }

            var typedConstantDebugMode = new TypedConstant(debuggingModesType, TypedConstantKind.Enum, constantVal);

            return(SynthesizeAttribute(
                       WellKnownMember.System_Diagnostics_DebuggableAttribute__ctorDebuggingModes,
                       ImmutableArray.Create(typedConstantDebugMode)));
        }
示例#8
0
        static bool TryBindTypedConstant(TypeSymbol target, LangElement element, PhpCompilation compilation, out TypedConstant result)
        {
            if (element is LongIntLiteral llit)
            {
                return(TryBindTypedConstant(target, llit.Value, out result));
            }
            if (element is DoubleLiteral dlit)
            {
                return(TryBindTypedConstant(target, dlit.Value, out result));
            }
            if (element is StringLiteral slit)
            {
                return(TryBindTypedConstant(target, slit.Value, out result));
            }

            if (element is TypeRef tref)
            {
                var system_type = compilation.GetWellKnownType(WellKnownType.System_Type);
                result = new TypedConstant(system_type, TypedConstantKind.Type, compilation.GetTypeFromTypeRef(tref));
                return(target == system_type);
            }

            if (element is GlobalConstUse gconst)
            {
                var qname = gconst.FullName.Name.QualifiedName;
                if (qname.IsSimpleName)
                {
                    // common constants
                    if (qname == QualifiedName.True)
                    {
                        return(TryBindTypedConstant(target, true, out result));
                    }
                    if (qname == QualifiedName.False)
                    {
                        return(TryBindTypedConstant(target, true, out result));
                    }
                    if (qname == QualifiedName.Null)
                    {
                        return(TryBindTypedConstant(target, (object)null, out result));
                    }

                    // lookup constant
                    var csymbol = compilation.GlobalSemantics.ResolveConstant(qname.Name.Value);
                    if (csymbol is FieldSymbol fld && fld.HasConstantValue)
                    {
                        return(TryBindTypedConstant(target, fld.ConstantValue, out result));
                    }
                }

                // note: namespaced constants are unreachable
            }

            if (element is ClassConstUse cconst)
            {
                // lookup the type container
                var ctype = compilation.GetTypeFromTypeRef(cconst.TargetType);
                if (ctype.IsValidType())
                {
                    // lookup constant/enum field (both are FieldSymbol)
                    var member = ctype.LookupMember <FieldSymbol>(cconst.Name.Value);
                    if (member != null && member.HasConstantValue)
                    {
                        return(TryBindTypedConstant(target, member.ConstantValue, out result));
                    }
                }
            }

            //
            result = default;
            return(false);
        }
 private IMetadataExpression TranslateMetadata(TypedConstant typedConstant) {
   return new CompileTimeConstant() {
     Type = this.Map(typedConstant.Type),
     Value = typedConstant.Value,
   };
 }
示例#10
0
        internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder<SynthesizedAttributeData> attributes)
        {
            base.AddSynthesizedAttributes(compilationState, ref attributes);

            if (this.IsAsync || this.IsIterator)
            {
                var compilation = this.DeclaringCompilation;

                // The async state machine type is not synthesized until the async method body is rewritten. If we are
                // only emitting metadata the method body will not have been rewritten, and the async state machine
                // type will not have been created. In this case, omit the attribute.
                NamedTypeSymbol stateMachineType;
                if (compilationState.TryGetStateMachineType(this, out stateMachineType))
                {
                    WellKnownMember ctor = this.IsAsync ?
                        WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor :
                        WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor;

                    var arg = new TypedConstant(compilation.GetWellKnownType(WellKnownType.System_Type), TypedConstantKind.Type, stateMachineType.GetUnboundGenericTypeOrSelf());

                    AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(ctor, ImmutableArray.Create(arg)));
                }
            }
        }
示例#11
0
        private static string DisplayUnsignedEnumConstant(TypedConstant constant, SpecialType specialType, ulong constantToDecode, string typeName)
        {
            Debug.Assert(constant.Kind == TypedConstantKind.Enum);

            // Specified valueConstant might have an exact matching enum field
            // or it might be a bitwise Or of multiple enum fields.
            // For the later case, we keep track of the current value of
            // bitwise Or of possible enum fields.
            ulong curValue = 0;

            // Initialize the value string to empty
            PooledStringBuilder?pooledBuilder      = null;
            StringBuilder?      valueStringBuilder = null;

            // Iterate through all the constant members in the enum type
            var members = constant.Type !.GetMembers();

            foreach (var member in members)
            {
                var field = member as IFieldSymbol;

                if (field is object && field.HasConstantValue)
                {
                    ConstantValue memberConstant = ConstantValue.Create(field.ConstantValue !, specialType); // use MemberNotNull when available https://github.com/dotnet/roslyn/issues/41964
                    ulong         memberValue    = memberConstant.UInt64Value;

                    // Do we have an exact matching enum field
                    if (memberValue == constantToDecode)
                    {
                        if (pooledBuilder != null)
                        {
                            pooledBuilder.Free();
                        }

                        return(typeName + "." + field.Name);
                    }

                    // specifiedValue might be a bitwise Or of multiple enum fields
                    // Is the current member included in the specified value?
                    if ((memberValue & constantToDecode) == memberValue)
                    {
                        // update the current value
                        curValue = curValue | memberValue;

                        if (valueStringBuilder == null)
                        {
                            pooledBuilder      = PooledStringBuilder.GetInstance();
                            valueStringBuilder = pooledBuilder.Builder;
                        }
                        else
                        {
                            valueStringBuilder.Append(" | ");
                        }

                        valueStringBuilder.Append(typeName);
                        valueStringBuilder.Append(".");
                        valueStringBuilder.Append(field.Name);
                    }
                }
            }

            if (pooledBuilder != null)
            {
                if (curValue == constantToDecode)
                {
                    // return decoded enum constant
                    return(pooledBuilder.ToStringAndFree());
                }

                // Unable to decode the enum constant
                pooledBuilder.Free();
            }

            // Unable to decode the enum constant, just display the integral value
            Debug.Assert(constant.ValueInternal is object);
            var result = constant.ValueInternal.ToString();

            Debug.Assert(result is object);
            return(result);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="AttributeArgumentSemantics"/> class.
 /// </summary>
 /// <param name="semanticObject">The Roslyn semantic object.</param>
 public AttributeArgumentSemantics(TypedConstant semanticObject)
     : base(semanticObject)
 {
 }
        static void VerifyUnion(DiagnosticsReportContext context, Location callerLocation, ITypeSymbol type)
        {
            var unionKeys = type.GetMembers().OfType <IPropertySymbol>().Where(x => x.GetAttributes().FindAttributeShortName(UnionKeyAttributeShortName) != null).ToArray();

            if (unionKeys.Length == 0)
            {
                context.Add(Diagnostic.Create(UnionTypeRequiresUnionKey, callerLocation, type.Locations, type.Name));
                return;
            }
            else if (unionKeys.Length != 1)
            {
                context.Add(Diagnostic.Create(UnionKeyDoesNotAllowMultipleKey, callerLocation, type.Locations, type.Name));
                return;
            }

            var unionKeyProperty = unionKeys[0];

            if (type.TypeKind != TypeKind.Interface && !unionKeyProperty.GetMethod.IsAbstract)
            {
                context.Add(Diagnostic.Create(UnionTypeRequiresUnionKey, callerLocation, type.Locations, type.Name));
                return;
            }

            var ctorArguments  = type.GetAttributes().FindAttributeShortName(UnionAttributeShortName)?.ConstructorArguments;
            var firstArguments = ctorArguments?.FirstOrDefault();

            if (firstArguments == null)
            {
                return;
            }

            TypedConstant fallbackType = default(TypedConstant);

            if (ctorArguments.Value.Length == 2)
            {
                fallbackType = ctorArguments.Value[1];
            }

            if (type.TypeKind != TypeKind.Interface)
            {
                foreach (var item in firstArguments.Value.Values.Concat(new[] { fallbackType }).Where(x => !x.IsNull).Select(x => x.Value).OfType <ITypeSymbol>())
                {
                    var found = item.FindBaseTargetType(type.ToDisplayString());

                    if (found == null)
                    {
                        context.Add(Diagnostic.Create(AllUnionSubTypesMustBeInheritedType, callerLocation, type.Locations, type.Name, item.Name));
                        return;
                    }
                }
            }
            else
            {
                foreach (var item in firstArguments.Value.Values.Concat(new[] { fallbackType }).Where(x => !x.IsNull).Select(x => x.Value).OfType <ITypeSymbol>())
                {
                    var typeString = type.ToDisplayString();
                    if (!(item as INamedTypeSymbol).AllInterfaces.Any(x => x.OriginalDefinition?.ToDisplayString() == typeString))
                    {
                        context.Add(Diagnostic.Create(AllUnionSubTypesMustBeInheritedType, callerLocation, type.Locations, type.Name, item.Name));
                        return;
                    }
                }
            }
        }
 private static object GetItem(TypedConstant arg) => arg.Kind == TypedConstantKind.Array ? arg.Values : arg.Value;
示例#15
0
        private DeclarativeSecurityAction DecodeSecurityAttributeAction(
            Symbol targetSymbol,
            CSharpCompilation compilation,
            AttributeSyntax?nodeOpt,
            out bool hasErrors,
            BindingDiagnosticBag diagnostics
            )
        {
            Debug.Assert((object)targetSymbol != null);
            Debug.Assert(
                targetSymbol.Kind == SymbolKind.Assembly ||
                targetSymbol.Kind == SymbolKind.NamedType ||
                targetSymbol.Kind == SymbolKind.Method
                );
            Debug.Assert(this.IsSecurityAttribute(compilation));

            var ctorArgs = this.CommonConstructorArguments;

            if (!ctorArgs.Any())
            {
                // NOTE:    Security custom attributes must have a valid SecurityAction as its first argument, we have none here.
                // NOTE:    Ideally, we should always generate 'CS7048: First argument to a security attribute must be a valid SecurityAction' for this case.
                // NOTE:    However, native compiler allows applying System.Security.Permissions.HostProtectionAttribute attribute without any argument and uses
                // NOTE:    SecurityAction.LinkDemand as the default SecurityAction in this case. We maintain compatibility with the native compiler for this case.

                // BREAKING CHANGE: Even though the native compiler intends to allow only HostProtectionAttribute to be applied without any arguments,
                //                  it doesn't quite do this correctly

                // The implementation issue leads to the native compiler allowing any user defined security attribute with a parameterless constructor and a named property argument as the first
                // attribute argument to have the above mentioned behavior, even though the comment clearly mentions that this behavior was intended only for the HostProtectionAttribute.
                // We currently allow this case only for the HostProtectionAttribute. In future if need arises, we can exactly match native compiler's behavior.

                if (
                    this.IsTargetAttribute(
                        targetSymbol,
                        AttributeDescription.HostProtectionAttribute
                        )
                    )
                {
                    hasErrors = false;
                    return(DeclarativeSecurityAction.LinkDemand);
                }
            }
            else
            {
                TypedConstant firstArg     = ctorArgs.First();
                var           firstArgType = (TypeSymbol?)firstArg.TypeInternal;
                if (
                    firstArgType is object &&
                    firstArgType.Equals(
                        compilation.GetWellKnownType(
                            WellKnownType.System_Security_Permissions_SecurityAction
                            )
                        )
                    )
                {
                    return(DecodeSecurityAction(
                               firstArg,
                               targetSymbol,
                               nodeOpt,
                               diagnostics,
                               out hasErrors
                               ));
                }
            }

            // CS7048: First argument to a security attribute must be a valid SecurityAction
            diagnostics.Add(
                ErrorCode.ERR_SecurityAttributeMissingAction,
                nodeOpt != null ? nodeOpt.Name.Location : NoLocation.Singleton
                );
            hasErrors = true;
            return(DeclarativeSecurityAction.None);
        }
示例#16
0
        private static void ProcessField(CsharpCodeBuilder source, IFieldSymbol fieldSymbol, CodeWriter codeWriter)
        {
            // get the name and type of the field
            string      fieldName = fieldSymbol.Name;
            ITypeSymbol fieldType = fieldSymbol.Type;

            AttributeData attributeData = fieldSymbol.GetAttributes()
                                          .Single(p => p.AttributeClass.SafeEquals(typeof(AutoNotifyAttribute)));
            // get the AutoNotify attribute from the field, and any associated data

            TypedConstant overridenNameOpt =
                attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == nameof(AutoNotifyAttribute.PropertyName)).Value;

            string propertyName = chooseName(fieldName, overridenNameOpt);

            if (!System.Text.RegularExpressions.Regex.IsMatch(propertyName, "^[_a-zA-Z][_a-zA-Z0-9]*$"))
            {
                codeWriter.Context.ReportDiagnostic(KnifeDiagnostic.AutoNotify.InvalidPropertyName(propertyName));
            }
            if (propertyName == fieldName)
            {
                codeWriter.Context.ReportDiagnostic(KnifeDiagnostic.AutoNotify.PropertyNameEqualFieldName(propertyName));
            }

            source.AppendCodeLines($@"
public {fieldType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} {propertyName} 
{{
    get 
    {{
        return this.{fieldName};
    }}
    set
    {{
        if(this.{fieldName} != value)
        {{
            this.{fieldName} = value;
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof({propertyName})));
        }}
    }}
}}

");

            string chooseName(string field, TypedConstant overridenNameOption)
            {
                if (!overridenNameOption.IsNull)
                {
                    return(overridenNameOption.Value.ToString());
                }

                field = field.TrimStart('_');
                if (field.Length == 0)
                {
                    return(string.Empty);
                }

                if (field.Length == 1)
                {
                    return(field.ToUpperInvariant());
                }

                return(field.Substring(0, 1).ToUpperInvariant() + field.Substring(1));
            }
        }
示例#17
0
        public void Execute(GeneratorExecutionContext context)
        {
#if DEBUG
            //if (!Debugger.IsAttached) Debugger.Launch();
#endif
            if (!(context.Compilation is CSharpCompilation compilation))
            {
                return;
            }
            if (!(context.ParseOptions is CSharpParseOptions parseOptions))
            {
                return;
            }

            // check if required types exists.
            if (!(compilation.GetTypeByMetadataName("System.ReadOnlySpan`1") is { } readOnlySpanSymbol))
            {
                return;
            }
            if (!(compilation.GetTypeByMetadataName("System.Runtime.CompilerServices.Unsafe") is { } unsafeSymbol))
            {
                return;
            }
            if (!(compilation.GetTypeByMetadataName("System.Runtime.InteropServices.MemoryMarshal") is { } memoryMarshalSymbol))
            {
                return;
            }

            SourceText attributeSourceText = constractSourceText(new PrimitiveStaticDataAttributeTemplate().TransformText());
            context.AddSource(PrimitiveStaticDataAttributeTemplate.TypeFullName, attributeSourceText);

            try
            {
                compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(attributeSourceText, options: parseOptions));

                INamedTypeSymbol attrSymbol = compilation.GetTypeByMetadataName(PrimitiveStaticDataAttributeTemplate.TypeFullName) !;

                var candidateMethodSyntaxes = compilation.
                                              SyntaxTrees.
                                              SelectMany(tree => tree.GetRoot().DescendantNodes()).
                                              OfType <MethodDeclarationSyntax>().
                                              Where(method => method.IsExtendedPartial() &&
                                                    method.Modifiers.Any(SyntaxKind.StaticKeyword) &&
                                                    method.AttributeLists.Count > 0 &&
                                                    method.ParentNodes().OfType <TypeDeclarationSyntax>().All(type => type.Modifiers.Any(SyntaxKind.PartialKeyword)));

                foreach (var methodSyntax in candidateMethodSyntaxes)
                {
                    SemanticModel semantic = compilation.GetSemanticModel(methodSyntax.SyntaxTree);

                    if (!(semantic.GetDeclaredSymbol(methodSyntax) is { } methodSymbol) ||
                        methodSymbol.MethodKind != MethodKind.Ordinary ||
                        methodSymbol.PartialImplementationPart is not null ||
                        !equalsSymbol(methodSymbol.ReturnType.OriginalDefinition, readOnlySpanSymbol))
                    {
                        continue;
                    }

                    var returnSpanType = (INamedTypeSymbol)methodSymbol.ReturnType;
                    if (!isPrimitiveType(returnSpanType.TypeArguments[0]))
                    {
                        continue;
                    }

                    foreach (AttributeData attr in methodSymbol.GetReturnTypeAttributes())
                    {
                        if (!equalsSymbol(attr.AttributeClass, attrSymbol) ||
                            attr.ConstructorArguments.Length < 1)
                        {
                            continue;
                        }

                        TypedConstant arg1 = attr.ConstructorArguments[0];

                        bool             argIsSingleByteValues = false;
                        IArrayTypeSymbol arraySymbol;
                        object[]         values = default !;
示例#18
0
        private static ExpressionSyntax GetLiteralExpression(TypedConstant constant)
        {
            if (constant.Type.TypeKind == TypeKind.Array)
            {
                if (constant.Values == null)
                {
                    return GetLiteralExpression(null, constant.Type);
                }
                var items = (from value in constant.Values
                             select GetLiteralExpression(value)).ToList();
                if (items.TrueForAll(x => x != null))
                {
                    return SyntaxFactory.ArrayCreationExpression(
                        SyntaxFactory.Token(SyntaxKind.NewKeyword),
                        default(SyntaxList<AttributeListSyntax>),
                        GetTypeSyntax(
                            ((IArrayTypeSymbol)constant.Type).ElementType
                        ),
                        null,
                        SyntaxFactory.SingletonList(
                            SyntaxFactory.ArrayRankSpecifier()
                        ),
                        SyntaxFactory.CollectionInitializer(
                            SyntaxFactory.SeparatedList(
                                from value in constant.Values
                                select GetLiteralExpression(value)
                            )
                        )
                    );
                }
                return SyntaxFactory.ArrayCreationExpression(
                    SyntaxFactory.Token(SyntaxKind.NewKeyword),
                    default(SyntaxList<AttributeListSyntax>),
                    GetTypeSyntax(
                        ((IArrayTypeSymbol)constant.Type).ElementType
                    ),
                    null,
                    new SyntaxList<ArrayRankSpecifierSyntax>(),
                    SyntaxFactory.CollectionInitializer()
                );
            }

            var expr = GetLiteralExpression(constant.Value, constant.Type);
            if (expr == null)
            {
                return null;
            }

            switch (constant.Type.SpecialType)
            {
                case SpecialType.System_SByte:
                    return SyntaxFactory.CTypeExpression(
                        expr,
                        SyntaxFactory.PredefinedType(
                            SyntaxFactory.Token(SyntaxKind.SByteKeyword)));
                case SpecialType.System_Byte:
                    return SyntaxFactory.CTypeExpression(
                        expr,
                        SyntaxFactory.PredefinedType(
                            SyntaxFactory.Token(SyntaxKind.ByteKeyword)));
                case SpecialType.System_Int16:
                    return SyntaxFactory.CTypeExpression(
                        expr,
                        SyntaxFactory.PredefinedType(
                            SyntaxFactory.Token(SyntaxKind.ShortKeyword)));
                case SpecialType.System_UInt16:
                    return SyntaxFactory.CTypeExpression(
                        expr,
                        SyntaxFactory.PredefinedType(
                            SyntaxFactory.Token(SyntaxKind.UShortKeyword)));
                default:
                    return expr;
            }
        }
示例#19
0
 public OperatorInfo(int precedence, TypedConstant expression)
 {
     Precedence = precedence;
     Expression = expression;
 }
示例#20
0
        internal void ToUIText(InlineCollection block, TypedConstant constant)
        {
            switch (constant.Kind)
            {
            case TypedConstantKind.Primitive:
                if (constant.Value is bool)
                {
                    block.Add(WpfHelper.Render((bool)constant.Value ? "true" : "false", Keyword));
                }
                else if (constant.Value is string)
                {
                    block.Add(WpfHelper.Render(constant.ToCSharpString(), Text));
                }
                else
                {
                    block.Add(WpfHelper.Render(constant.ToCSharpString(), Number));
                }
                break;

            case TypedConstantKind.Enum:
                var en = constant.ToCSharpString();
                if (en.IndexOf('|') != -1)
                {
                    var items = constant.Type.GetMembers().Where(i => {
                        var field = i as IFieldSymbol;
                        return(field != null &&
                               field.HasConstantValue != false &&
                               UnsafeArithmeticHelper.Equals(UnsafeArithmeticHelper.And(constant.Value, field.ConstantValue), field.ConstantValue) &&
                               UnsafeArithmeticHelper.IsZero(field.ConstantValue) == false);
                    });
                    var flags = items.ToArray();
                    for (int i = 0; i < flags.Length; i++)
                    {
                        if (i > 0)
                        {
                            block.Add(" | ");
                        }
                        block.Add(WpfHelper.Render(constant.Type.Name + "." + flags[i].Name, Enum));
                    }
                }
                else
                {
                    block.Add(WpfHelper.Render(constant.Type.Name + en.Substring(en.LastIndexOf('.')), Enum));
                }
                break;

            case TypedConstantKind.Type:
                block.Add(WpfHelper.Render("typeof", Keyword));
                block.Add("(");
                ToUIText(block, constant.Value as ITypeSymbol, null);
                block.Add(")");
                break;

            case TypedConstantKind.Array:
                block.Add("{");
                bool c = false;
                foreach (var item in constant.Values)
                {
                    if (c == false)
                    {
                        c = true;
                    }
                    else
                    {
                        block.Add(", ");
                    }
                    ToUIText(block, item);
                }
                block.Add("}");
                break;

            default:
                block.Add(constant.ToCSharpString());
                break;
            }
        }
示例#21
0
        void Format(InlineCollection block, TypedConstant constant)
        {
            if (constant.IsNull)
            {
                block.Add("null".Render(Keyword));
                return;
            }
            switch (constant.Kind)
            {
            case TypedConstantKind.Primitive:
                if (constant.Value is bool)
                {
                    block.Add(WpfHelper.Render((bool)constant.Value ? "true" : "false", Keyword));
                }
                else if (constant.Value is string)
                {
                    block.Add(constant.ToCSharpString().Render(Text));
                }
                else
                {
                    block.Add(constant.ToCSharpString().Render(Number));
                }
                break;

            case TypedConstantKind.Enum:
                var en = constant.ToCSharpString();
                int d;
                if (en.IndexOf('|') != -1)
                {
                    var items = constant.Type.GetMembers().Where(i => {
                        var field = i as IFieldSymbol;
                        return(field != null &&
                               field.HasConstantValue &&
                               UnsafeArithmeticHelper.Equals(UnsafeArithmeticHelper.And(constant.Value, field.ConstantValue), field.ConstantValue) &&
                               UnsafeArithmeticHelper.IsZero(field.ConstantValue) == false);
                    });
                    var flags = items.ToArray();
                    for (int i = 0; i < flags.Length; i++)
                    {
                        if (i > 0)
                        {
                            block.Add(" | ");
                        }
                        block.Add(constant.Type.Render(null, Enum));
                        block.Add(".");
                        block.Add(flags[i].Render(null, EnumField));
                    }
                }
                else if ((d = en.LastIndexOf('.')) != -1)
                {
                    block.Add(constant.Type.Render(null, Enum));
                    block.Add(".");
                    block.Add(en.Substring(d + 1).Render(EnumField));
                }
                else
                {
                    block.Add(en.Render(Enum));
                }
                break;

            case TypedConstantKind.Type:
                block.Add("typeof".Render(Keyword));
                block.Add("(");
                Format(block, constant.Value as ISymbol, null, false);
                block.Add(")");
                break;

            case TypedConstantKind.Array:
                block.Add("new".Render(Keyword));
                block.Add("[] { ");
                bool c = false;
                foreach (var item in constant.Values)
                {
                    if (c)
                    {
                        block.Add(", ");
                    }
                    else
                    {
                        c = true;
                    }
                    Format(block, item);
                }
                block.Add(" }");
                break;

            default:
                block.Add(constant.ToCSharpString());
                break;
            }
        }
示例#22
0
        private static TypedConstant GetParamArrayArgument(ParameterSymbol parameter, ImmutableArray<TypedConstant> constructorArgsArray, int argumentsCount, int argsConsumedCount, Conversions conversions)
        {
            Debug.Assert(argsConsumedCount <= argumentsCount);

            int paramArrayArgCount = argumentsCount - argsConsumedCount;
            if (paramArrayArgCount == 0)
            {
                return new TypedConstant(parameter.Type, ImmutableArray<TypedConstant>.Empty);
            }

            // If there's exactly one argument and it's an array of an appropriate type, then just return it.
            if (paramArrayArgCount == 1 && constructorArgsArray[argsConsumedCount].Kind == TypedConstantKind.Array)
            {
                TypeSymbol argumentType = (TypeSymbol)constructorArgsArray[argsConsumedCount].Type;

                // Easy out (i.e. don't both classifying conversion).
                if (argumentType == parameter.Type)
                {
                    return constructorArgsArray[argsConsumedCount];
                }

                HashSet<DiagnosticInfo> useSiteDiagnostics = null; // ignoring, since already bound argument and parameter
                Conversion conversion = conversions.ClassifyConversion(argumentType, parameter.Type, ref useSiteDiagnostics, builtinOnly: true);

                // NOTE: Won't always succeed, even though we've performed overload resolution.
                // For example, passing int[] to params object[] actually treats the int[] as an element of the object[].
                if (conversion.IsValid && conversion.Kind == ConversionKind.ImplicitReference)
                {
                    return constructorArgsArray[argsConsumedCount];
                }
            }

            Debug.Assert(!constructorArgsArray.IsDefault);
            Debug.Assert(argsConsumedCount <= constructorArgsArray.Length);

            var values = new TypedConstant[paramArrayArgCount];

            for (int i = 0; i < paramArrayArgCount; i++)
            {
                values[i] = constructorArgsArray[argsConsumedCount++];
            }

            return new TypedConstant(parameter.Type, values.AsImmutableOrNull());
        }
示例#23
0
        private static string DisplayUnsignedEnumConstant(TypedConstant constant, SpecialType specialType, ulong constantToDecode, string typeName)
        {
            // Specified valueConstant might have an exact matching enum field
            // or it might be a bitwise Or of multiple enum fields.
            // For the later case, we keep track of the current value of
            // bitwise Or of possible enum fields.
            ulong curValue = 0;

            // Initialize the value string to empty
            PooledStringBuilder pooledBuilder = null;
            StringBuilder valueStringBuilder = null;

            // Iterate through all the constant members in the enum type
            var members = constant.Type.GetMembers();
            foreach (var member in members)
            {
                var field = member as IFieldSymbol;

                if ((object)field != null && field.HasConstantValue)
                {
                    ConstantValue memberConstant = ConstantValue.Create(field.ConstantValue, specialType);
                    ulong memberValue = memberConstant.UInt64Value;

                    // Do we have an exact matching enum field
                    if (memberValue == constantToDecode)
                    {
                        if (pooledBuilder != null)
                        {
                            pooledBuilder.Free();
                        }

                        return typeName + "." + field.Name;
                    }

                    // specifiedValue might be a bitwise Or of multiple enum fields
                    // Is the current member included in the specified value?
                    if ((memberValue & constantToDecode) == memberValue)
                    {
                        // update the current value
                        curValue = curValue | memberValue;

                        if (valueStringBuilder == null)
                        {
                            pooledBuilder = PooledStringBuilder.GetInstance();
                            valueStringBuilder = pooledBuilder.Builder;
                        }
                        else
                        {
                            valueStringBuilder.Append(" | ");
                        }

                        valueStringBuilder.Append(typeName);
                        valueStringBuilder.Append(".");
                        valueStringBuilder.Append(field.Name);
                    }
                }
            }

            if (pooledBuilder != null)
            {
                if (curValue == constantToDecode)
                {
                    // return decoded enum constant
                    return pooledBuilder.ToStringAndFree();
                }

                // Unable to decode the enum constant
                pooledBuilder.Free();
            }

            // Unable to decode the enum constant, just display the integral value
            return constant.Value.ToString();
        }
示例#24
0
        private DeclarativeSecurityAction DecodeSecurityAction(TypedConstant typedValue, Symbol targetSymbol, AttributeSyntax?nodeOpt, BindingDiagnosticBag diagnostics, out bool hasErrors)
        {
            Debug.Assert((object)targetSymbol != null);
            Debug.Assert(targetSymbol.Kind == SymbolKind.Assembly || targetSymbol.Kind == SymbolKind.NamedType || targetSymbol.Kind == SymbolKind.Method);
            Debug.Assert(typedValue.ValueInternal is object);

            int  securityAction = (int)typedValue.ValueInternal;
            bool isPermissionRequestAction;

            switch (securityAction)
            {
            case (int)DeclarativeSecurityAction.InheritanceDemand:
            case (int)DeclarativeSecurityAction.LinkDemand:
                if (this.IsTargetAttribute(targetSymbol, AttributeDescription.PrincipalPermissionAttribute))
                {
                    // CS7052: SecurityAction value '{0}' is invalid for PrincipalPermission attribute
                    object   displayString;
                    Location syntaxLocation = GetSecurityAttributeActionSyntaxLocation(nodeOpt, typedValue, out displayString);
                    diagnostics.Add(ErrorCode.ERR_PrincipalPermissionInvalidAction, syntaxLocation, displayString);
                    hasErrors = true;
                    return(DeclarativeSecurityAction.None);
                }

                isPermissionRequestAction = false;
                break;

            case 1:
            // Native compiler allows security action value 1 for security attributes on types/methods, even though there is no corresponding field in System.Security.Permissions.SecurityAction enum.
            // We will maintain compatibility.

            case (int)DeclarativeSecurityAction.Assert:
            case (int)DeclarativeSecurityAction.Demand:
            case (int)DeclarativeSecurityAction.PermitOnly:
            case (int)DeclarativeSecurityAction.Deny:
                isPermissionRequestAction = false;
                break;

            case (int)DeclarativeSecurityAction.RequestMinimum:
            case (int)DeclarativeSecurityAction.RequestOptional:
            case (int)DeclarativeSecurityAction.RequestRefuse:
                isPermissionRequestAction = true;
                break;

            default:
            {
                // CS7049: Security attribute '{0}' has an invalid SecurityAction value '{1}'
                object   displayString;
                Location syntaxLocation = GetSecurityAttributeActionSyntaxLocation(nodeOpt, typedValue, out displayString);
                diagnostics.Add(ErrorCode.ERR_SecurityAttributeInvalidAction, syntaxLocation, nodeOpt != null ? nodeOpt.GetErrorDisplayName() : "", displayString);
                hasErrors = true;
                return(DeclarativeSecurityAction.None);
            }
            }

            // Validate security action for symbol kind
            if (isPermissionRequestAction)
            {
                if (targetSymbol.Kind == SymbolKind.NamedType || targetSymbol.Kind == SymbolKind.Method)
                {
                    // Types and methods cannot take permission requests.

                    // CS7051: SecurityAction value '{0}' is invalid for security attributes applied to a type or a method
                    object   displayString;
                    Location syntaxLocation = GetSecurityAttributeActionSyntaxLocation(nodeOpt, typedValue, out displayString);
                    diagnostics.Add(ErrorCode.ERR_SecurityAttributeInvalidActionTypeOrMethod, syntaxLocation, displayString);
                    hasErrors = true;
                    return(DeclarativeSecurityAction.None);
                }
            }
            else
            {
                if (targetSymbol.Kind == SymbolKind.Assembly)
                {
                    // Assemblies cannot take declarative security.

                    // CS7050: SecurityAction value '{0}' is invalid for security attributes applied to an assembly
                    object   displayString;
                    Location syntaxLocation = GetSecurityAttributeActionSyntaxLocation(nodeOpt, typedValue, out displayString);
                    diagnostics.Add(ErrorCode.ERR_SecurityAttributeInvalidActionAssembly, syntaxLocation, displayString);
                    hasErrors = true;
                    return(DeclarativeSecurityAction.None);
                }
            }

            hasErrors = false;
            return((DeclarativeSecurityAction)securityAction);
        }
示例#25
0
        internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder<SynthesizedAttributeData> attributes)
        {
            base.AddSynthesizedAttributes(compilationState, ref attributes);

            if (this.IsAsync || this.IsIterator)
            {
                var compilation = this.DeclaringCompilation;

                // The async state machine type is not synthesized until the async method body is rewritten. If we are
                // only emitting metadata the method body will not have been rewritten, and the async state machine
                // type will not have been created. In this case, omit the attribute.
                NamedTypeSymbol stateMachineType;
                if (compilationState.TryGetStateMachineType(this, out stateMachineType))
                {
                    WellKnownMember ctor = this.IsAsync ?
                        WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor :
                        WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor;

                    var arg = new TypedConstant(compilation.GetWellKnownType(WellKnownType.System_Type), TypedConstantKind.Type, stateMachineType.GetUnboundGenericTypeOrSelf());

                    AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(ctor, ImmutableArray.Create(arg)));
                }

                if (this.IsAsync)
                {
                    // Async kick-off method calls MoveNext, which contains user code. 
                    // This means we need to emit DebuggerStepThroughAttribute in order
                    // to have correct stepping behavior during debugging.
                    AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDebuggerStepThroughAttribute());
                }
            }
        }
 private static string GetArgumentValue(TypedConstant typedConstant)
 {
     switch (typedConstant.Kind)
     {
         case TypedConstantKind.Error:
         case TypedConstantKind.Enum:
         case TypedConstantKind.Primitive:
             return typedConstant.Value.ToString();
         case TypedConstantKind.Type:
         case TypedConstantKind.Array:
             return typedConstant.ToCSharpString();
         default:
             throw new ArgumentOutOfRangeException(nameof(typedConstant));
     }
 }
示例#27
0
        /// <remarks>
        /// These won't be returned by GetAttributes on source methods, but they
        /// will be returned by GetAttributes on metadata symbols.
        /// </remarks>
        internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder<SynthesizedAttributeData> attributes)
        {
            base.AddSynthesizedAttributes(compilationState, ref attributes);

            CSharpCompilation compilation = this.DeclaringCompilation;

            if (this.ContainsExtensionMethods)
            {
                // No need to check if [Extension] attribute was explicitly set since
                // we'll issue CS1112 error in those cases and won't generate IL.
                AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor));
            }

            if (this.Indexers.Any())
            {
                string defaultMemberName = this.Indexers.First().MetadataName; // UNDONE: IndexerNameAttribute
                var defaultMemberNameConstant = new TypedConstant(compilation.GetSpecialType(SpecialType.System_String), TypedConstantKind.Primitive, defaultMemberName);

                AddSynthesizedAttribute(ref attributes, compilation.TrySynthesizeAttribute(
                    WellKnownMember.System_Reflection_DefaultMemberAttribute__ctor,
                    ImmutableArray.Create(defaultMemberNameConstant)));
            }

            NamedTypeSymbol baseType = this.BaseTypeNoUseSiteDiagnostics;
            if ((object)baseType != null && baseType.ContainsDynamic())
            {
                AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(baseType, customModifiersCount: 0));
            }
        }
 public RoslynAttrubuteArgumentMetadata(TypedConstant typeConstant)
 {
     _typeConstant = typeConstant;
 }
示例#29
0
 private static MetadataTypeOf CreateType(TypedConstant argument, EmitContext context)
 {
     Debug.Assert(argument.Value != null);
     var moduleBeingBuilt = (PEModuleBuilder)context.Module;
     var syntaxNodeOpt = (SyntaxNode)context.SyntaxNodeOpt;
     var diagnostics = context.Diagnostics;
     return new MetadataTypeOf(moduleBeingBuilt.Translate((TypeSymbol)argument.Value, syntaxNodeOpt, diagnostics),
                               moduleBeingBuilt.Translate((TypeSymbol)argument.Type, syntaxNodeOpt, diagnostics));
 }
        private static (Type type, int executionOrder) GetCodeGeneratorTypeForAttribute(GeneratorKnownTypes generatorKnownTypes, AttributeData attributeData, Func <AssemblyName, Assembly> assemblyLoader)
        {
            Requires.NotNull(assemblyLoader, nameof(assemblyLoader));

            var attributeType = attributeData.AttributeClass;

            if (attributeType != null)
            {
                foreach (var generatorCandidateAttribute in attributeType.GetAttributes())
                {
                    if (generatorCandidateAttribute.AttributeClass.OriginalDefinition.Equals(generatorKnownTypes.CodeGenerationAttributeAttributeTypeSymbol))
                    {
                        var executionOrder    = 0;
                        var hasOrderInterface = attributeType.AllInterfaces.Any(i => i.OriginalDefinition.Equals(generatorKnownTypes.IOrderCodeGenerationTypeSymbol));
                        if (hasOrderInterface)
                        {
                            var executionOrderArgument = attributeData.NamedArguments.FirstOrDefault(a => a.Key == nameof(IOrderedCodeGeneration.ExecutionOrder));
                            if (!string.IsNullOrEmpty(executionOrderArgument.Key))
                            {
                                executionOrder = (int)executionOrderArgument.Value.Value;
                            }
                        }

                        string        assemblyName = null;
                        string        fullTypeName = null;
                        TypedConstant firstArg     = generatorCandidateAttribute.ConstructorArguments.Single();
                        if (firstArg.Value is string typeName)
                        {
                            // This string is the full name of the type, which MAY be assembly-qualified.
                            int  commaIndex          = typeName.IndexOf(',');
                            bool isAssemblyQualified = commaIndex >= 0;
                            if (isAssemblyQualified)
                            {
                                fullTypeName = typeName.Substring(0, commaIndex);
                                assemblyName = typeName.Substring(commaIndex + 1).Trim();
                            }
                            else
                            {
                                fullTypeName = typeName;
                                assemblyName = generatorCandidateAttribute.AttributeClass.ContainingAssembly.Name;
                            }
                        }
                        else if (firstArg.Value is INamedTypeSymbol typeOfValue)
                        {
                            // This was a typeof(T) expression
                            fullTypeName = GetFullTypeName(typeOfValue);
                            assemblyName = typeOfValue.ContainingAssembly.Name;
                        }

                        if (assemblyName != null)
                        {
                            Logger.Info($"assemblyLoader assemblyName = {assemblyName}, fullTypeName = {fullTypeName}");
                            var assembly = assemblyLoader(new AssemblyName(assemblyName));
                            if (assembly != null)
                            {
                                return(assembly.GetType(fullTypeName), executionOrder);
                            }
                        }

                        Verify.FailOperation("Unable to find code generator: {0} in {1}", fullTypeName, assemblyName);
                    }
                }
            }

            return(null, 0);
        }
示例#31
0
        bool TryResolveCtor(NamedTypeSymbol type, PhpCompilation compilation, out MethodSymbol ctor, out ImmutableArray <TypedConstant> args)
        {
            if (type.IsValidType())
            {
                var candidates = type.InstanceConstructors;
                for (int i = 0; i < candidates.Length; i++)
                {
                    var m = candidates[i];

                    if (m.DeclaredAccessibility != Accessibility.Public)
                    {
                        continue;                                                  // TODO: or current class context
                    }
                    if (m.IsGenericMethod)
                    {
                        Debug.Fail("unexpected"); continue;
                    }                                                              // NS
                    if (m.ParameterCount < _arguments.Length)
                    {
                        continue;                                       // be strict
                    }
                    var match     = true;
                    var ps        = m.Parameters;
                    var boundargs = new TypedConstant[ps.Length];

                    for (var pi = 0; match && pi < ps.Length; pi++)
                    {
                        if (pi >= _arguments.Length)
                        {
                            //if (ps[pi].IsOptional)
                            //{
                            //    boundargs[pi] = ps[pi].ExplicitDefaultConstantValue.AsTypedConstant();
                            //    continue; // ok
                            //}
                            //else
                            {
                                match = false;
                                break;
                            }
                        }

                        if (TryBindTypedConstant(ps[pi].Type, _arguments[pi], compilation, out var arg))
                        {
                            boundargs[pi] = arg;
                        }
                        else
                        {
                            match = false;
                            break;
                        }
                    }

                    if (match)
                    {
                        ctor = m;
                        args = boundargs.AsImmutable();
                        return(true);
                    }
                }
            }

            //
            ctor = new MissingMethodSymbol();
            args = ImmutableArray <TypedConstant> .Empty;
            return(false);
        }
        private static string GetArgumentString(TypedConstant argument)
        {
            if (argument.Type == null ||
                argument.Type.SpecialType != SpecialType.System_String ||
                argument.IsNull)
            {
                return null;
            }

            return ((string)argument.Value).Trim();
        }
示例#33
0
        /// <summary>
        /// Gets the typed constant kind for the given attribute parameter type.
        /// </summary>
        /// <param name="type">Type to validated</param>
        /// <param name="compilation">compilation</param>
        /// <returns>TypedConstantKind for the attribute parameter type.</returns>
        public static TypedConstantKind GetAttributeParameterTypedConstantKind(this TypeSymbol type, CSharpCompilation compilation)
        {
            // Spec (17.1.3)
            // The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:
            //  1) One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
            //     2) The type object.
            //     3) The type System.Type.
            //     4) An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility.
            //     5) Single-dimensional arrays of the above types.
            // A constructor argument or public field which does not have one of these types, cannot be used as a positional
            // or named parameter in an attribute specification.

            TypedConstantKind kind = TypedConstantKind.Error;

            if ((object)type == null)
            {
                return(TypedConstantKind.Error);
            }

            if (type.Kind == SymbolKind.ArrayType)
            {
                var arrayType = (ArrayTypeSymbol)type;
                if (arrayType.Rank != 1)
                {
                    return(TypedConstantKind.Error);
                }

                kind = TypedConstantKind.Array;
                type = arrayType.ElementType;
            }

            // enum or enum[]
            if (type.IsEnumType())
            {
                // SPEC VIOLATION: Dev11 doesn't enforce either the Enum type or its enclosing types (if any) to have public accessibility.
                // We will be consistent with Dev11 behavior.

                if (kind == TypedConstantKind.Error)
                {
                    // set only if kind is not already set (i.e. its not an array of enum)
                    kind = TypedConstantKind.Enum;
                }

                type = type.GetEnumUnderlyingType();
            }

            var typedConstantKind = TypedConstant.GetTypedConstantKind(type, compilation);

            switch (typedConstantKind)
            {
            case TypedConstantKind.Array:
            case TypedConstantKind.Enum:
            case TypedConstantKind.Error:
                return(TypedConstantKind.Error);

            default:
                if (kind == TypedConstantKind.Array || kind == TypedConstantKind.Enum)
                {
                    // Array/Enum type with valid element/underlying type
                    return(kind);
                }

                return(typedConstantKind);
            }
        }
示例#34
0
        private MetadataCreateArray CreateMetadataArray(TypedConstant argument, EmitContext context)
        {
            Debug.Assert(!argument.Values.IsDefault);
            var values = argument.Values;
            var arrayType = Emit.PEModuleBuilder.Translate((ArrayTypeSymbol)argument.Type);

            if (values.Length == 0)
            {
                return new MetadataCreateArray(arrayType,
                                               arrayType.GetElementType(context),
                                               ImmutableArray<Cci.IMetadataExpression>.Empty);
            }

            var metadataExprs = new Cci.IMetadataExpression[values.Length];
            for (int i = 0; i < values.Length; i++)
            {
                metadataExprs[i] = CreateMetadataExpression(values[i], context);
            }

            return new MetadataCreateArray(arrayType,
                                           arrayType.GetElementType(context),
                                           metadataExprs.AsImmutableOrNull());
        }
示例#35
0
        private static Location GetSecurityAttributeActionSyntaxLocation(AttributeSyntax?nodeOpt, TypedConstant typedValue, out object displayString)
        {
            if (nodeOpt == null)
            {
                displayString = "";
                return(NoLocation.Singleton);
            }

            var argList = nodeOpt.ArgumentList;

            if (argList == null || argList.Arguments.IsEmpty())
            {
                // Optional SecurityAction parameter with default value.
                displayString = (FormattableString)$"{typedValue.ValueInternal}";
                return(nodeOpt.Location);
            }

            AttributeArgumentSyntax argSyntax = argList.Arguments[0];

            displayString = argSyntax.ToString();
            return(argSyntax.Location);
        }
示例#36
0
        private static void AppendConstant(StringBuilder result, TypedConstant constant)
        {
            switch (constant.Kind)
            {
                case TypedConstantKind.Array:
                    result.Append("{");
                    int i = 0;

                    foreach (var item in constant.Values)
                    {
                        if (i > 0)
                        {
                            result.Append(", ");
                        }

                        AppendConstant(result, item);
                    }

                    result.Append("}");
                    break;

                case TypedConstantKind.Type:
                    result.Append("typeof(");
                    result.Append(constant.Value);
                    result.Append(")");
                    break;

                case TypedConstantKind.Enum:
                case TypedConstantKind.Primitive:
                    var value = constant.Value;
                    if (value.GetType() == typeof(string))
                    {
                        result.Append("\"");
                        result.Append(value);
                        result.Append("\"");
                    }
                    else if (value.GetType() == typeof(bool))
                    {
                        result.Append(value.ToString().ToLower());
                    }
                    else
                    {
                        result.Append(value);
                    }
                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(constant.Kind);
            }
        }
示例#37
0
            /// <summary>
            /// Gets the set of logging classes containing methods to output.
            /// </summary>
            public IReadOnlyList <LoggerClass> GetLogClasses(IEnumerable <ClassDeclarationSyntax> classes)
            {
                INamedTypeSymbol loggerMessageAttribute = _compilation.GetBestTypeByMetadataName(LoggerMessageAttribute);

                if (loggerMessageAttribute == null)
                {
                    // nothing to do if this type isn't available
                    return(Array.Empty <LoggerClass>());
                }

                INamedTypeSymbol loggerSymbol = _compilation.GetBestTypeByMetadataName("Microsoft.Extensions.Logging.ILogger");

                if (loggerSymbol == null)
                {
                    // nothing to do if this type isn't available
                    return(Array.Empty <LoggerClass>());
                }

                INamedTypeSymbol logLevelSymbol = _compilation.GetBestTypeByMetadataName("Microsoft.Extensions.Logging.LogLevel");

                if (logLevelSymbol == null)
                {
                    // nothing to do if this type isn't available
                    return(Array.Empty <LoggerClass>());
                }

                INamedTypeSymbol exceptionSymbol = _compilation.GetBestTypeByMetadataName("System.Exception");

                if (exceptionSymbol == null)
                {
                    Diag(DiagnosticDescriptors.MissingRequiredType, null, "System.Exception");
                    return(Array.Empty <LoggerClass>());
                }

                INamedTypeSymbol enumerableSymbol = _compilation.GetSpecialType(SpecialType.System_Collections_IEnumerable);
                INamedTypeSymbol stringSymbol     = _compilation.GetSpecialType(SpecialType.System_String);

                var results = new List <LoggerClass>();
                var ids     = new HashSet <int>();

                // we enumerate by syntax tree, to minimize the need to instantiate semantic models (since they're expensive)
                foreach (var group in classes.GroupBy(x => x.SyntaxTree))
                {
                    SemanticModel?sm = null;
                    foreach (ClassDeclarationSyntax classDec in group)
                    {
                        // stop if we're asked to
                        _cancellationToken.ThrowIfCancellationRequested();

                        LoggerClass?lc                   = null;
                        string      nspace               = string.Empty;
                        string?     loggerField          = null;
                        bool        multipleLoggerFields = false;

                        ids.Clear();
                        foreach (MemberDeclarationSyntax member in classDec.Members)
                        {
                            var method = member as MethodDeclarationSyntax;
                            if (method == null)
                            {
                                // we only care about methods
                                continue;
                            }

                            sm ??= _compilation.GetSemanticModel(classDec.SyntaxTree);
                            IMethodSymbol logMethodSymbol = sm.GetDeclaredSymbol(method, _cancellationToken) as IMethodSymbol;
                            Debug.Assert(logMethodSymbol != null, "log method is present.");
                            (int eventId, int?level, string message, string?eventName, bool skipEnabledCheck) = (-1, null, string.Empty, null, false);

                            foreach (AttributeListSyntax mal in method.AttributeLists)
                            {
                                foreach (AttributeSyntax ma in mal.Attributes)
                                {
                                    IMethodSymbol attrCtorSymbol = sm.GetSymbolInfo(ma, _cancellationToken).Symbol as IMethodSymbol;
                                    if (attrCtorSymbol == null || !loggerMessageAttribute.Equals(attrCtorSymbol.ContainingType, SymbolEqualityComparer.Default))
                                    {
                                        // badly formed attribute definition, or not the right attribute
                                        continue;
                                    }

                                    bool hasMisconfiguredInput = false;
                                    ImmutableArray <AttributeData>?boundAttributes = logMethodSymbol?.GetAttributes();

                                    if (boundAttributes == null || boundAttributes !.Value.Length == 0)
                                    {
                                        continue;
                                    }

                                    foreach (AttributeData attributeData in boundAttributes)
                                    {
                                        if (!SymbolEqualityComparer.Default.Equals(attributeData.AttributeClass, loggerMessageAttribute))
                                        {
                                            continue;
                                        }

                                        // supports: [LoggerMessage(0, LogLevel.Warning, "custom message")]
                                        // supports: [LoggerMessage(eventId: 0, level: LogLevel.Warning, message: "custom message")]
                                        if (attributeData.ConstructorArguments.Any())
                                        {
                                            foreach (TypedConstant typedConstant in attributeData.ConstructorArguments)
                                            {
                                                if (typedConstant.Kind == TypedConstantKind.Error)
                                                {
                                                    hasMisconfiguredInput = true;
                                                }
                                            }

                                            ImmutableArray <TypedConstant> items = attributeData.ConstructorArguments;
                                            Debug.Assert(items.Length == 3);

                                            eventId = items[0].IsNull ? -1 : (int)GetItem(items[0]);
                                            level   = items[1].IsNull ? null : (int?)GetItem(items[1]);
                                            message = items[2].IsNull ? "" : (string)GetItem(items[2]);
                                        }

                                        // argument syntax takes parameters. e.g. EventId = 0
                                        // supports: e.g. [LoggerMessage(EventId = 0, Level = LogLevel.Warning, Message = "custom message")]
                                        if (attributeData.NamedArguments.Any())
                                        {
                                            foreach (KeyValuePair <string, TypedConstant> namedArgument in attributeData.NamedArguments)
                                            {
                                                TypedConstant typedConstant = namedArgument.Value;
                                                if (typedConstant.Kind == TypedConstantKind.Error)
                                                {
                                                    hasMisconfiguredInput = true;
                                                }
                                                else
                                                {
                                                    TypedConstant value = namedArgument.Value;
                                                    switch (namedArgument.Key)
                                                    {
                                                    case "EventId":
                                                        eventId = (int)GetItem(value);
                                                        break;

                                                    case "Level":
                                                        level = value.IsNull ? null : (int?)GetItem(value);
                                                        break;

                                                    case "SkipEnabledCheck":
                                                        skipEnabledCheck = (bool)GetItem(value);
                                                        break;

                                                    case "EventName":
                                                        eventName = (string?)GetItem(value);
                                                        break;

                                                    case "Message":
                                                        message = value.IsNull ? "" : (string)GetItem(value);
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    if (hasMisconfiguredInput)
                                    {
                                        // skip further generator execution and let compiler generate the errors
                                        break;
                                    }

                                    IMethodSymbol?methodSymbol = sm.GetDeclaredSymbol(method, _cancellationToken);
                                    if (methodSymbol != null)
                                    {
                                        var lm = new LoggerMethod
                                        {
                                            Name              = methodSymbol.Name,
                                            Level             = level,
                                            Message           = message,
                                            EventId           = eventId,
                                            EventName         = eventName,
                                            IsExtensionMethod = methodSymbol.IsExtensionMethod,
                                            Modifiers         = method.Modifiers.ToString(),
                                            SkipEnabledCheck  = skipEnabledCheck
                                        };

                                        ExtractTemplates(message, lm.TemplateMap, lm.TemplateList);

                                        bool keepMethod = true;   // whether or not we want to keep the method definition or if it's got errors making it so we should discard it instead
                                        if (lm.Name[0] == '_')
                                        {
                                            // can't have logging method names that start with _ since that can lead to conflicting symbol names
                                            // because the generated symbols start with _
                                            Diag(DiagnosticDescriptors.InvalidLoggingMethodName, method.Identifier.GetLocation());
                                            keepMethod = false;
                                        }

                                        if (!methodSymbol.ReturnsVoid)
                                        {
                                            // logging methods must return void
                                            Diag(DiagnosticDescriptors.LoggingMethodMustReturnVoid, method.ReturnType.GetLocation());
                                            keepMethod = false;
                                        }

                                        if (method.Arity > 0)
                                        {
                                            // we don't currently support generic methods
                                            Diag(DiagnosticDescriptors.LoggingMethodIsGeneric, method.Identifier.GetLocation());
                                            keepMethod = false;
                                        }

                                        bool isStatic  = false;
                                        bool isPartial = false;
                                        foreach (SyntaxToken mod in method.Modifiers)
                                        {
                                            if (mod.IsKind(SyntaxKind.PartialKeyword))
                                            {
                                                isPartial = true;
                                            }
                                            else if (mod.IsKind(SyntaxKind.StaticKeyword))
                                            {
                                                isStatic = true;
                                            }
                                        }

                                        if (!isPartial)
                                        {
                                            Diag(DiagnosticDescriptors.LoggingMethodMustBePartial, method.GetLocation());
                                            keepMethod = false;
                                        }

                                        if (method.Body != null)
                                        {
                                            Diag(DiagnosticDescriptors.LoggingMethodHasBody, method.Body.GetLocation());
                                            keepMethod = false;
                                        }

                                        // ensure there are no duplicate ids.
                                        if (ids.Contains(lm.EventId))
                                        {
                                            Diag(DiagnosticDescriptors.ShouldntReuseEventIds, ma.GetLocation(), lm.EventId, classDec.Identifier.Text);
                                        }
                                        else
                                        {
                                            _ = ids.Add(lm.EventId);
                                        }

                                        string msg = lm.Message;
                                        if (msg.StartsWith("INFORMATION:", StringComparison.OrdinalIgnoreCase) ||
                                            msg.StartsWith("INFO:", StringComparison.OrdinalIgnoreCase) ||
                                            msg.StartsWith("WARNING:", StringComparison.OrdinalIgnoreCase) ||
                                            msg.StartsWith("WARN:", StringComparison.OrdinalIgnoreCase) ||
                                            msg.StartsWith("ERROR:", StringComparison.OrdinalIgnoreCase) ||
                                            msg.StartsWith("ERR:", StringComparison.OrdinalIgnoreCase))
                                        {
                                            Diag(DiagnosticDescriptors.RedundantQualifierInMessage, ma.GetLocation(), method.Identifier.ToString());
                                        }

                                        bool foundLogger    = false;
                                        bool foundException = false;
                                        bool foundLogLevel  = level != null;
                                        foreach (IParameterSymbol paramSymbol in methodSymbol.Parameters)
                                        {
                                            string paramName   = paramSymbol.Name;
                                            bool   needsAtSign = false;
                                            if (paramSymbol.DeclaringSyntaxReferences.Length > 0)
                                            {
                                                ParameterSyntax paramSyntax = paramSymbol.DeclaringSyntaxReferences[0].GetSyntax(_cancellationToken) as ParameterSyntax;
                                                if (paramSyntax != null && !string.IsNullOrEmpty(paramSyntax.Identifier.Text))
                                                {
                                                    needsAtSign = paramSyntax.Identifier.Text[0] == '@';
                                                }
                                            }
                                            if (string.IsNullOrWhiteSpace(paramName))
                                            {
                                                // semantic problem, just bail quietly
                                                keepMethod = false;
                                                break;
                                            }

                                            ITypeSymbol paramTypeSymbol = paramSymbol !.Type;
                                            if (paramTypeSymbol is IErrorTypeSymbol)
                                            {
                                                // semantic problem, just bail quietly
                                                keepMethod = false;
                                                break;
                                            }

                                            string?qualifier = null;
                                            if (paramSymbol.RefKind == RefKind.In)
                                            {
                                                qualifier = "in";
                                            }
                                            else if (paramSymbol.RefKind == RefKind.Ref)
                                            {
                                                qualifier = "ref";
                                            }
                                            string typeName = paramTypeSymbol.ToDisplayString(
                                                SymbolDisplayFormat.FullyQualifiedFormat.WithMiscellaneousOptions(
                                                    SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier));

                                            var lp = new LoggerParameter
                                            {
                                                Name         = paramName,
                                                Type         = typeName,
                                                Qualifier    = qualifier,
                                                CodeName     = needsAtSign ? "@" + paramName : paramName,
                                                IsLogger     = !foundLogger && IsBaseOrIdentity(paramTypeSymbol !, loggerSymbol),
                                                IsException  = !foundException && IsBaseOrIdentity(paramTypeSymbol !, exceptionSymbol),
                                                IsLogLevel   = !foundLogLevel && IsBaseOrIdentity(paramTypeSymbol !, logLevelSymbol),
                                                IsEnumerable = IsBaseOrIdentity(paramTypeSymbol !, enumerableSymbol) && !IsBaseOrIdentity(paramTypeSymbol !, stringSymbol),
                                            };

                                            foundLogger    |= lp.IsLogger;
                                            foundException |= lp.IsException;
                                            foundLogLevel  |= lp.IsLogLevel;

                                            bool forceAsTemplateParams = false;
                                            if (lp.IsLogger && lm.TemplateMap.ContainsKey(paramName))
                                            {
                                                Diag(DiagnosticDescriptors.ShouldntMentionLoggerInMessage, paramSymbol.Locations[0], paramName);
                                                forceAsTemplateParams = true;
                                            }
                                            else if (lp.IsException && lm.TemplateMap.ContainsKey(paramName))
                                            {
                                                Diag(DiagnosticDescriptors.ShouldntMentionExceptionInMessage, paramSymbol.Locations[0], paramName);
                                                forceAsTemplateParams = true;
                                            }
                                            else if (lp.IsLogLevel && lm.TemplateMap.ContainsKey(paramName))
                                            {
                                                Diag(DiagnosticDescriptors.ShouldntMentionLogLevelInMessage, paramSymbol.Locations[0], paramName);
                                                forceAsTemplateParams = true;
                                            }
                                            else if (lp.IsLogLevel && level != null && !lm.TemplateMap.ContainsKey(paramName))
                                            {
                                                Diag(DiagnosticDescriptors.ArgumentHasNoCorrespondingTemplate, paramSymbol.Locations[0], paramName);
                                            }
                                            else if (lp.IsTemplateParameter && !lm.TemplateMap.ContainsKey(paramName))
                                            {
                                                Diag(DiagnosticDescriptors.ArgumentHasNoCorrespondingTemplate, paramSymbol.Locations[0], paramName);
                                            }

                                            if (paramName[0] == '_')
                                            {
                                                // can't have logging method parameter names that start with _ since that can lead to conflicting symbol names
                                                // because all generated symbols start with _
                                                Diag(DiagnosticDescriptors.InvalidLoggingMethodParameterName, paramSymbol.Locations[0]);
                                            }

                                            lm.AllParameters.Add(lp);
                                            if (lp.IsTemplateParameter || forceAsTemplateParams)
                                            {
                                                lm.TemplateParameters.Add(lp);
                                            }
                                        }

                                        if (keepMethod)
                                        {
                                            if (isStatic && !foundLogger)
                                            {
                                                Diag(DiagnosticDescriptors.MissingLoggerArgument, method.GetLocation(), lm.Name);
                                                keepMethod = false;
                                            }
                                            else if (!isStatic && foundLogger)
                                            {
                                                Diag(DiagnosticDescriptors.LoggingMethodShouldBeStatic, method.GetLocation());
                                            }
                                            else if (!isStatic && !foundLogger)
                                            {
                                                if (loggerField == null)
                                                {
                                                    (loggerField, multipleLoggerFields) = FindLoggerField(sm, classDec, loggerSymbol);
                                                }

                                                if (multipleLoggerFields)
                                                {
                                                    Diag(DiagnosticDescriptors.MultipleLoggerFields, method.GetLocation(), classDec.Identifier.Text);
                                                    keepMethod = false;
                                                }
                                                else if (loggerField == null)
                                                {
                                                    Diag(DiagnosticDescriptors.MissingLoggerField, method.GetLocation(), classDec.Identifier.Text);
                                                    keepMethod = false;
                                                }
                                                else
                                                {
                                                    lm.LoggerField = loggerField;
                                                }
                                            }

                                            if (level == null && !foundLogLevel)
                                            {
                                                Diag(DiagnosticDescriptors.MissingLogLevel, method.GetLocation());
                                                keepMethod = false;
                                            }

                                            foreach (KeyValuePair <string, string> t in lm.TemplateMap)
                                            {
                                                bool found = false;
                                                foreach (LoggerParameter p in lm.AllParameters)
                                                {
                                                    if (t.Key.Equals(p.Name, StringComparison.OrdinalIgnoreCase))
                                                    {
                                                        found = true;
                                                        break;
                                                    }
                                                }

                                                if (!found)
                                                {
                                                    Diag(DiagnosticDescriptors.TemplateHasNoCorrespondingArgument, ma.GetLocation(), t.Key);
                                                }
                                            }
                                        }

                                        if (lc == null)
                                        {
                                            // determine the namespace the class is declared in, if any
                                            SyntaxNode?potentialNamespaceParent = classDec.Parent;
                                            while (potentialNamespaceParent != null &&
                                                   potentialNamespaceParent is not NamespaceDeclarationSyntax
#if ROSLYN4_0_OR_GREATER
                                                   && potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax
#endif
                                                   )
                                            {
                                                potentialNamespaceParent = potentialNamespaceParent.Parent;
                                            }

#if ROSLYN4_0_OR_GREATER
                                            if (potentialNamespaceParent is BaseNamespaceDeclarationSyntax namespaceParent)
#else
                                            if (potentialNamespaceParent is NamespaceDeclarationSyntax namespaceParent)
#endif
                                            {
                                                nspace = namespaceParent.Name.ToString();
                                                while (true)
                                                {
                                                    namespaceParent = namespaceParent.Parent as NamespaceDeclarationSyntax;
                                                    if (namespaceParent == null)
                                                    {
                                                        break;
                                                    }

                                                    nspace = $"{namespaceParent.Name}.{nspace}";
                                                }
                                            }
                                        }

                                        if (keepMethod)
                                        {
                                            lc ??= new LoggerClass
                                            {
                                                Keyword     = classDec.Keyword.ValueText,
                                                Namespace   = nspace,
                                                Name        = classDec.Identifier.ToString() + classDec.TypeParameterList,
                                                ParentClass = null,
                                            };

                                            LoggerClass currentLoggerClass = lc;
                                            var         parentLoggerClass  = (classDec.Parent as TypeDeclarationSyntax);
示例#38
0
        private Cci.IMetadataNamedArgument CreateMetadataNamedArgument(string name, TypedConstant argument, EmitContext context)
        {
            var symbol = LookupName(name);
            var value = CreateMetadataExpression(argument, context);
            TypeSymbol type;
            var fieldSymbol = symbol as FieldSymbol;
            if ((object)fieldSymbol != null)
            {
                type = fieldSymbol.Type;
            }
            else
            {
                type = ((PropertySymbol)symbol).Type;
            }

            PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module;
            return new MetadataNamedArgument(symbol, moduleBeingBuilt.Translate(type, syntaxNodeOpt: context.SyntaxNodeOpt, diagnostics: context.Diagnostics), value);
        }
示例#39
0
 protected abstract string ToString(TypedConstant typedConstant);
示例#40
0
        private MetadataCreateArray CreateMetadataArray(TypedConstant argument, EmitContext context)
        {
            Debug.Assert(!argument.Values.IsDefault);
            var values = argument.Values;
            var arrayType = (IArrayTypeSymbol)argument.Type; //  Emit.PEModuleBuilder.Translate((ArrayTypeSymbol)argument.Type);

            throw new System.NotImplementedException();
            //if (values.Length == 0)
            //{
            //    return new MetadataCreateArray(arrayType,
            //                                   arrayType.GetElementType(context),
            //                                   ImmutableArray<Cci.IMetadataExpression>.Empty);
            //}

            //var metadataExprs = new Cci.IMetadataExpression[values.Length];
            //for (int i = 0; i < values.Length; i++)
            //{
            //    metadataExprs[i] = CreateMetadataExpression(values[i], context);
            //}

            //return new MetadataCreateArray(arrayType,
            //                               arrayType.GetElementType(context),
            //                               metadataExprs.AsImmutableOrNull());
        }
        /// <remarks>
        /// Since this method is expected to be called on every nested expression of the argument, it doesn't
        /// need to recurse (directly).
        /// </remarks>
        internal static bool CanBeValidAttributeArgument(ExpressionSyntax node, Binder typeBinder)
        {
            Debug.Assert(node != null);
            switch (node.Kind())
            {
            // ObjectCreationExpression for primitive types, such as "new int()", are treated as constants and allowed in attribute arguments.
            case SyntaxKind.ObjectCreationExpression:
            {
                var objectCreation = (ObjectCreationExpressionSyntax)node;
                if (objectCreation.Initializer == null)
                {
                    var unusedDiagnostics = DiagnosticBag.GetInstance();
                    var type = typeBinder.BindType(objectCreation.Type, unusedDiagnostics).Type;
                    unusedDiagnostics.Free();

                    var kind = TypedConstant.GetTypedConstantKind(type, typeBinder.Compilation);
                    switch (kind)
                    {
                    case TypedConstantKind.Primitive:
                    case TypedConstantKind.Enum:
                        switch (type.TypeKind)
                        {
                        case TypeKind.Struct:
                        case TypeKind.Class:
                        case TypeKind.Enum:
                            return(true);

                        default:
                            return(false);
                        }
                    }
                }

                return(false);
            }

            // sizeof(int)
            case SyntaxKind.SizeOfExpression:

            // typeof(int)
            case SyntaxKind.TypeOfExpression:

            // constant expressions

            // SPEC:    Section 7.19: Only the following constructs are permitted in constant expressions:

            //  Literals (including the null literal).
            case SyntaxKind.NumericLiteralExpression:
            case SyntaxKind.StringLiteralExpression:
            case SyntaxKind.CharacterLiteralExpression:
            case SyntaxKind.TrueLiteralExpression:
            case SyntaxKind.FalseLiteralExpression:
            case SyntaxKind.NullLiteralExpression:

            //  References to const members of class and struct types.
            //  References to members of enumeration types.
            case SyntaxKind.IdentifierName:
            case SyntaxKind.GenericName:
            case SyntaxKind.AliasQualifiedName:
            case SyntaxKind.QualifiedName:
            case SyntaxKind.PredefinedType:
            case SyntaxKind.SimpleMemberAccessExpression:

            //  References to const parameters or local variables. Not valid for attribute arguments, so skipped here.

            //  Parenthesized sub-expressions, which are themselves constant expressions.
            case SyntaxKind.ParenthesizedExpression:

            //  Cast expressions, provided the target type is one of the types listed above.
            case SyntaxKind.CastExpression:

            //  checked and unchecked expressions
            case SyntaxKind.UncheckedExpression:
            case SyntaxKind.CheckedExpression:

            //  Default value expressions
            case SyntaxKind.DefaultExpression:

            //  The predefined +, –, !, and ~ unary operators.
            case SyntaxKind.UnaryPlusExpression:
            case SyntaxKind.UnaryMinusExpression:
            case SyntaxKind.LogicalNotExpression:
            case SyntaxKind.BitwiseNotExpression:

            //  The predefined +, –, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators, provided each operand is of a type listed above.
            case SyntaxKind.AddExpression:
            case SyntaxKind.MultiplyExpression:
            case SyntaxKind.SubtractExpression:
            case SyntaxKind.DivideExpression:
            case SyntaxKind.ModuloExpression:
            case SyntaxKind.LeftShiftExpression:
            case SyntaxKind.RightShiftExpression:
            case SyntaxKind.BitwiseAndExpression:
            case SyntaxKind.BitwiseOrExpression:
            case SyntaxKind.ExclusiveOrExpression:
            case SyntaxKind.LogicalAndExpression:
            case SyntaxKind.LogicalOrExpression:
            case SyntaxKind.EqualsExpression:
            case SyntaxKind.NotEqualsExpression:
            case SyntaxKind.GreaterThanExpression:
            case SyntaxKind.LessThanExpression:
            case SyntaxKind.GreaterThanOrEqualExpression:
            case SyntaxKind.LessThanOrEqualExpression:
            case SyntaxKind.InvocationExpression:     //  To support nameof(); anything else will be a compile-time error
            case SyntaxKind.ConditionalExpression:    //  The ?: conditional operator.
                return(true);

            default:
                return(false);
            }
        }
 private static void CheckLanguage(TypedConstant argument, ref bool supportsCSharp, ref bool supportsVB)
 {
     if (argument.Kind == TypedConstantKind.Primitive &&
         argument.Type != null &&
         argument.Type.SpecialType == SpecialType.System_String)
     {
         string supportedLanguage = (string)argument.Value;
         if (supportedLanguage == LanguageNames.CSharp)
         {
             supportsCSharp = true;
         }
         else if (supportedLanguage == LanguageNames.VisualBasic)
         {
             supportsVB = true;
         }
     }
 }
        internal SynthesizedAttributeData SynthesizeDebuggableAttribute()
        {
            TypeSymbol debuggableAttribute = GetWellKnownType(WellKnownType.System_Diagnostics_DebuggableAttribute);

            Debug.Assert((object)debuggableAttribute != null, "GetWellKnownType unexpectedly returned null");
            if (debuggableAttribute is MissingMetadataTypeSymbol)
            {
                return(null);
            }

            TypeSymbol debuggingModesType = GetWellKnownType(WellKnownType.System_Diagnostics_DebuggableAttribute__DebuggingModes);

            Debug.Assert((object)debuggingModesType != null, "GetWellKnownType unexpectedly returned null");
            if (debuggingModesType is MissingMetadataTypeSymbol)
            {
                return(null);
            }

            // IgnoreSymbolStoreDebuggingMode flag is checked by the CLR, it is not referred to by the debugger.
            // It tells the JIT that it doesn't need to load the PDB at the time it generates jitted code.
            // The PDB would still be used by a debugger, or even by the runtime for putting source line information
            // on exception stack traces. We always set this flag to avoid overhead of JIT loading the PDB.
            // The theoretical scenario for not setting it would be a language compiler that wants their sequence points
            // at specific places, but those places don't match what CLR's heuristics calculate when scanning the IL.
            var ignoreSymbolStoreDebuggingMode = (FieldSymbol)GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute_DebuggingModes__IgnoreSymbolStoreSequencePoints);

            if ((object)ignoreSymbolStoreDebuggingMode == null || !ignoreSymbolStoreDebuggingMode.HasConstantValue)
            {
                return(null);
            }

            int constantVal = ignoreSymbolStoreDebuggingMode.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false).Int32Value;

            // Since .NET 2.0 the combinations of None, Default and DisableOptimizations have the following effect:
            //
            // None                                         JIT optimizations enabled
            // Default                                      JIT optimizations enabled
            // DisableOptimizations                         JIT optimizations enabled
            // Default | DisableOptimizations               JIT optimizations disabled
            if (_options.OptimizationLevel == OptimizationLevel.Debug)
            {
                var defaultDebuggingMode = (FieldSymbol)GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute_DebuggingModes__Default);
                if ((object)defaultDebuggingMode == null || !defaultDebuggingMode.HasConstantValue)
                {
                    return(null);
                }

                var disableOptimizationsDebuggingMode = (FieldSymbol)GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute_DebuggingModes__DisableOptimizations);
                if ((object)disableOptimizationsDebuggingMode == null || !disableOptimizationsDebuggingMode.HasConstantValue)
                {
                    return(null);
                }

                constantVal |= defaultDebuggingMode.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false).Int32Value;
                constantVal |= disableOptimizationsDebuggingMode.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false).Int32Value;
            }

            if (_options.EnableEditAndContinue)
            {
                var enableEncDebuggingMode = (FieldSymbol)GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute_DebuggingModes__EnableEditAndContinue);
                if ((object)enableEncDebuggingMode == null || !enableEncDebuggingMode.HasConstantValue)
                {
                    return(null);
                }

                constantVal |= enableEncDebuggingMode.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false).Int32Value;
            }

            var typedConstantDebugMode = new TypedConstant(debuggingModesType, TypedConstantKind.Enum, constantVal);

            return(TrySynthesizeAttribute(
                       WellKnownMember.System_Diagnostics_DebuggableAttribute__ctorDebuggingModes,
                       ImmutableArray.Create(typedConstantDebugMode)));
        }
示例#44
0
        /// <summary>
        /// Gets the rewritten attribute constructor arguments, i.e. the arguments
        /// are in the order of parameters, which may differ from the source
        /// if named constructor arguments are used.
        /// 
        /// For example:
        ///     void Foo(int x, int y, int z, int w = 3);
        /// 
        ///     Foo(0, z: 2, y: 1);
        ///     
        ///     Arguments returned: 0, 1, 2, 3
        /// </summary>
        /// <returns>Rewritten attribute constructor arguments</returns>
        /// <remarks>
        /// CONSIDER: Can we share some code will call rewriting in the local rewriter?
        /// </remarks>
        private ImmutableArray<TypedConstant> GetRewrittenAttributeConstructorArguments(
            out ImmutableArray<int> constructorArgumentsSourceIndices,
            MethodSymbol attributeConstructor,
            ImmutableArray<TypedConstant> constructorArgsArray,
            ImmutableArray<string> constructorArgumentNamesOpt,
            AttributeSyntax syntax,
            DiagnosticBag diagnostics,
            ref bool hasErrors)
        {
            Debug.Assert((object)attributeConstructor != null);
            Debug.Assert(!constructorArgsArray.IsDefault);
            Debug.Assert(!hasErrors);

            int argumentsCount = constructorArgsArray.Length;

            // argsConsumedCount keeps track of the number of constructor arguments
            // consumed from this.ConstructorArguments array
            int argsConsumedCount = 0;

            bool hasNamedCtorArguments = !constructorArgumentNamesOpt.IsDefault;
            Debug.Assert(!hasNamedCtorArguments ||
                constructorArgumentNamesOpt.Length == argumentsCount);

            // index of the first named constructor argument
            int firstNamedArgIndex = -1;

            ImmutableArray<ParameterSymbol> parameters = attributeConstructor.Parameters;
            int parameterCount = parameters.Length;

            var reorderedArguments = new TypedConstant[parameterCount];
            int[] sourceIndices = null;

            for (int i = 0; i < parameterCount; i++)
            {
                Debug.Assert(argsConsumedCount <= argumentsCount);

                ParameterSymbol parameter = parameters[i];
                TypedConstant reorderedArgument;

                if (parameter.IsParams && parameter.Type.IsSZArray() && i + 1 == parameterCount)
                {
                    reorderedArgument = GetParamArrayArgument(parameter, constructorArgsArray, argumentsCount, argsConsumedCount, this.Conversions);
                    sourceIndices = sourceIndices ?? CreateSourceIndicesArray(i, parameterCount);
                }
                else if (argsConsumedCount < argumentsCount)
                {
                    if (!hasNamedCtorArguments ||
                        constructorArgumentNamesOpt[argsConsumedCount] == null)
                    {
                        // positional constructor argument
                        reorderedArgument = constructorArgsArray[argsConsumedCount];
                        if (sourceIndices != null)
                        {
                            sourceIndices[i] = argsConsumedCount;
                        }
                        argsConsumedCount++;
                    }
                    else
                    {
                        // named constructor argument

                        // Store the index of the first named constructor argument
                        if (firstNamedArgIndex == -1)
                        {
                            firstNamedArgIndex = argsConsumedCount;
                        }

                        // Current parameter must either have a matching named argument or a default value
                        // For the former case, argsConsumedCount must be incremented to note that we have
                        // consumed a named argument. For the latter case, argsConsumedCount stays same.
                        int matchingArgumentIndex;
                        reorderedArgument = GetMatchingNamedOrOptionalConstructorArgument(out matchingArgumentIndex, constructorArgsArray,
                            constructorArgumentNamesOpt, parameter, firstNamedArgIndex, argumentsCount, ref argsConsumedCount, syntax, diagnostics);

                        sourceIndices = sourceIndices ?? CreateSourceIndicesArray(i, parameterCount);
                        sourceIndices[i] = matchingArgumentIndex;
                    }
                }
                else
                {
                    reorderedArgument = GetDefaultValueArgument(parameter, syntax, diagnostics);
                    sourceIndices = sourceIndices ?? CreateSourceIndicesArray(i, parameterCount);
                }

                if (!hasErrors)
                {
                    if (reorderedArgument.Kind == TypedConstantKind.Error)
                    {
                        hasErrors = true;
                    }
                    else if (reorderedArgument.Kind == TypedConstantKind.Array && parameter.Type.TypeKind == TypeKind.Array && (TypeSymbol)reorderedArgument.Type != parameter.Type)
                    {
                        // NOTE: As in dev11, we don't allow array covariance conversions (presumably, we don't have a way to
                        // represent the conversion in metadata).
                        diagnostics.Add(ErrorCode.ERR_BadAttributeArgument, syntax.Location);
                        hasErrors = true;
                    }
                }

                reorderedArguments[i] = reorderedArgument;
            }

            constructorArgumentsSourceIndices = sourceIndices != null ? sourceIndices.AsImmutableOrNull() : default(ImmutableArray<int>);
            return reorderedArguments.AsImmutableOrNull();
        }
        private static string DisplayUnsignedEnumConstant(TypedConstant constant, SpecialType specialType, ulong constantToDecode, string typeName)
        {
            // Specified valueConstant might have an exact matching enum field
            // or it might be a bitwise Or of multiple enum fields.
            // For the later case, we keep track of the current value of
            // bitwise Or of possible enum fields.
            ulong curValue = 0;

            // Initialize the value string to empty
            PooledStringBuilder pooledBuilder      = null;
            StringBuilder       valueStringBuilder = null;

            // Iterate through all the constant members in the enum type
            var members = constant.Type.GetMembers();

            foreach (var member in members)
            {
                var field = member as IFieldSymbol;

                if ((object)field != null && field.HasConstantValue)
                {
                    ConstantValue memberConstant = ConstantValue.Create(field.ConstantValue, specialType);
                    ulong         memberValue    = memberConstant.UInt64Value;

                    // Do we have an exact matching enum field
                    if (memberValue == constantToDecode)
                    {
                        if (pooledBuilder != null)
                        {
                            pooledBuilder.Free();
                        }

                        return(typeName + "." + field.Name);
                    }

                    // specifiedValue might be a bitwise Or of multiple enum fields
                    // Is the current member included in the specified value?
                    if ((memberValue & constantToDecode) == memberValue)
                    {
                        // update the current value
                        curValue = curValue | memberValue;

                        if (valueStringBuilder == null)
                        {
                            pooledBuilder      = PooledStringBuilder.GetInstance();
                            valueStringBuilder = pooledBuilder.Builder;
                        }
                        else
                        {
                            valueStringBuilder.Append(" | ");
                        }

                        valueStringBuilder.Append(typeName);
                        valueStringBuilder.Append(".");
                        valueStringBuilder.Append(field.Name);
                    }
                }
            }

            if (pooledBuilder != null)
            {
                if (curValue == constantToDecode)
                {
                    // return decoded enum constant
                    return(pooledBuilder.ToStringAndFree());
                }

                // Unable to decode the enum constant
                pooledBuilder.Free();
            }

            // Unable to decode the enum constant, just display the integral value
            return(constant.Value.ToString());
        }
 protected override string ToString(TypedConstant typedConstant)
 => typedConstant.ToCSharpString();
示例#47
0
        void CollectUnion(INamedTypeSymbol type)
        {
            var unionKeys = type.GetMembers().OfType <IPropertySymbol>().Where(x => x.GetAttributes().FindAttributeShortName(UnionKeyAttributeShortName) != null).ToArray();

            if (unionKeys.Length == 0)
            {
                throw new Exception($"Union class requires abstract [UnionKey]property. Type: {type.Name}. Location:{type.Locations[0]}");
            }
            else if (unionKeys.Length != 1)
            {
                throw new Exception($"[UnionKey]property does not allow multiple key. Type: {type.Name}. Location:{type.Locations[0]}");
            }

            var unionKeyProperty = unionKeys[0];

            if (type.TypeKind != TypeKind.Interface)
            {
                if (!unionKeyProperty.GetMethod.IsAbstract)
                {
                    throw new Exception($"Union class requires abstract [UnionKey]property. Type: {type.Name}. Location:{type.Locations[0]}");
                }
            }

            var ctorArguments  = type.GetAttributes().FindAttributeShortName(UnionAttributeShortName)?.ConstructorArguments;
            var firstArguments = ctorArguments?.FirstOrDefault();

            if (firstArguments == null)
            {
                return;
            }
            TypedConstant fallbackType = default(TypedConstant);

            if (ctorArguments.Value.Length == 2)
            {
                fallbackType = ctorArguments.Value[1];
            }

            var subTypList = new List <string>();

            if (type.TypeKind != TypeKind.Interface)
            {
                foreach (var item in firstArguments.Value.Values.Concat(new[] { fallbackType }).Where(x => !x.IsNull).Select(x => x.Value).OfType <ITypeSymbol>())
                {
                    var found = item.FindBaseTargetType(type.ToDisplayString());

                    if (found == null)
                    {
                        throw new Exception($"All Union subTypes must be inherited type. Type: {type.Name}, SubType: {item.Name}. Location:{type.Locations[0]}");
                    }
                    subTypList.Add(item.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
                }
            }
            else
            {
                foreach (var item in firstArguments.Value.Values.Concat(new[] { fallbackType }).Where(x => !x.IsNull).Select(x => x.Value).OfType <ITypeSymbol>())
                {
                    var typeString = type.ToDisplayString();
                    if (!(item as INamedTypeSymbol).AllInterfaces.Any(x => x.OriginalDefinition?.ToDisplayString() == typeString))
                    {
                        throw new Exception($"All Union subTypes must be inherited type. Type: {type.Name}, SubType: {item.Name}. Location:{type.Locations[0]}");
                    }

                    subTypList.Add(item.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
                }
            }

            unionTypeContainer.Add(new UnionType
            {
                Name                 = type.Name,
                FullName             = type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
                Namespace            = type.ContainingNamespace.IsGlobalNamespace ? null : type.ContainingNamespace.ToDisplayString(),
                UnionKeyTypeName     = unionKeyProperty.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
                UnionKeyPropertyName = unionKeyProperty.Name,
                SubTypeNames         = subTypList.ToArray(),
                FallbackTypeName     = fallbackType.IsNull ? null : (fallbackType.Value as INamedTypeSymbol).ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
            });
        }