Esempio n. 1
0
        /// <summary>
        /// Returns the constraint clause for the given type parameter.
        /// The `early` parameter indicates whether the clauses can be from the first phase of constraint
        /// checking where the constraint types may still contain invalid or duplicate types.
        /// </summary>
        internal TypeParameterConstraintClause GetTypeParameterConstraintClause(bool early, int ordinal)
        {
            var clauses = _lazyTypeParameterConstraints;

            if (clauses.IsDefault)
            {
                // Early step.
                var diagnostics = DiagnosticBag.GetInstance();
                if (ImmutableInterlocked.InterlockedInitialize(ref _lazyTypeParameterConstraints, MakeTypeParameterConstraintsEarly(diagnostics)))
                {
                    this.AddDeclarationDiagnostics(diagnostics);
                }
                diagnostics.Free();
                clauses = _lazyTypeParameterConstraints;
            }

            if (!early && clauses.IsEarly())
            {
                // Late step.
                var diagnostics = DiagnosticBag.GetInstance();
                var constraints = ConstraintsHelper.MakeTypeParameterConstraintsLate(TypeParameters, clauses, diagnostics);
                Debug.Assert(!constraints.IsEarly());
                if (ImmutableInterlocked.InterlockedCompareExchange(ref _lazyTypeParameterConstraints, constraints, clauses) == clauses)
                {
                    this.AddDeclarationDiagnostics(diagnostics);
                }
                diagnostics.Free();
                clauses = _lazyTypeParameterConstraints;
            }

            return((clauses.Length > 0) ? clauses[ordinal] : TypeParameterConstraintClause.Empty);
        }
Esempio n. 2
0
        public static bool ChangeAttributeValue(this Entity entity, string attributeName, string propertyName, object newValue, Func <float, float, float> calculator)
        {
            // 값을 변경하고 그에 맞는 ChangeEvent를 전달한다.
            var attributeType = AttributeHelper.GetType(attributeName);

            if (attributeType == null)
            {
                return(false);
            }

            propertyName = propertyName.ToCamelCase();
            var propertyType = attributeType.GetProperty(propertyName);

            if (propertyType == null)
            {
                return(false);
            }

            if (!entity.Has(attributeType))
            {
                return(false);
            }

            var attribute     = entity.Get(attributeType);
            var previousValue = propertyType.GetValue(attribute);

            // 연산이 필요할 경우 연산한 결과를 newValue에 넣어준다.
            if (calculator != null)
            {
                newValue = calculator(newValue.As <float>(), previousValue.As <float>());
            }

            // contraints를 적용한 다음, 다시 PropertyType에 맞게 바꿔서 넣어준다.
            var nextValue = ConstraintsHelper.ApplyConstraints(attribute, propertyName, newValue);

            if (Equals(previousValue, nextValue))
            {
                return(false);
            }

            entity.InvokeTrigger(TriggerType.BeforeChange, propertyType);
            attribute.SetValue(propertyName, nextValue);
            entity.InvokeTrigger(TriggerType.AfterChange, propertyType);
            return(true);
        }
Esempio n. 3
0
        public override ImmutableArray <TypeParameterConstraintClause> GetTypeParameterConstraintClauses(bool early)
        {
            var clauses = _lazyTypeParameterConstraints;

            if (clauses.IsDefault)
            {
                // Early step.
                var diagnostics = DiagnosticBag.GetInstance();
                var constraints = this.MakeTypeParameterConstraintsEarly(
                    _binder,
                    TypeParameters,
                    _syntax.ConstraintClauses,
                    _syntax.Identifier.GetLocation(),
                    diagnostics);
                lock (_declarationDiagnostics)
                {
                    if (_lazyTypeParameterConstraints.IsDefault)
                    {
                        _declarationDiagnostics.AddRange(diagnostics);
                        _lazyTypeParameterConstraints = constraints;
                    }
                }
                diagnostics.Free();
                clauses = _lazyTypeParameterConstraints;
            }

            if (!early && clauses.IsEarly())
            {
                // Late step.
                var diagnostics = DiagnosticBag.GetInstance();
                var constraints = ConstraintsHelper.MakeTypeParameterConstraintsLate(TypeParameters, clauses, diagnostics);
                Debug.Assert(!constraints.IsEarly());
                lock (_declarationDiagnostics)
                {
                    if (_lazyTypeParameterConstraints.IsEarly())
                    {
                        _declarationDiagnostics.AddRange(diagnostics);
                        _lazyTypeParameterConstraints = constraints;
                    }
                }
                diagnostics.Free();
            }

            return(_lazyTypeParameterConstraints);
        }
        protected override DiagnosticInfo ResolveInfo()
        {
            var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance();

            var warningsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance();

            ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;

            // CheckTypeConstraints should only add nullability warnings to warningsBuilder.
            ConstraintsHelper.CheckTypeConstraints(
                _type,
                _conversions,
                _compilation,
                diagnosticsBuilder,
                warningsBuilder,
                ref useSiteDiagnosticsBuilder);
            // If there are multiple constraint check warnings, we'll report the first one only.
            var diagnostic = (warningsBuilder.Count == 0) ? null : warningsBuilder[0].DiagnosticInfo;

            useSiteDiagnosticsBuilder?.Free();
            warningsBuilder.Free();
            diagnosticsBuilder.Free();
            return(diagnostic);
        }
        private ImmutableArray <TypeWithAnnotations> GetDeclaredConstraintTypes(ConsList <PETypeParameterSymbol> inProgress)
        {
            Debug.Assert(!inProgress.ContainsReference(this));
            Debug.Assert(!inProgress.Any() || ReferenceEquals(inProgress.Head.ContainingSymbol, this.ContainingSymbol));

            if (_lazyDeclaredConstraintTypes.IsDefault)
            {
                ImmutableArray <TypeWithAnnotations> declaredConstraintTypes;

                var      moduleSymbol = ((PEModuleSymbol)this.ContainingModule);
                PEModule peModule     = moduleSymbol.Module;
                GenericParameterConstraintHandleCollection constraints = GetConstraintHandleCollection(peModule);

                bool hasUnmanagedModreqPattern = false;

                if (constraints.Count > 0)
                {
                    var symbolsBuilder = ArrayBuilder <TypeWithAnnotations> .GetInstance();

                    MetadataDecoder tokenDecoder = GetDecoder(moduleSymbol);

                    TypeWithAnnotations bestObjectConstraint = default;

                    var metadataReader = peModule.MetadataReader;
                    foreach (var constraintHandle in constraints)
                    {
                        TypeWithAnnotations type = GetConstraintTypeOrDefault(moduleSymbol, metadataReader, tokenDecoder, constraintHandle, ref hasUnmanagedModreqPattern);

                        if (!type.HasType)
                        {
                            // Dropped 'System.ValueType' constraint type when the 'valuetype' constraint was also specified.
                            continue;
                        }

                        // Drop 'System.Object' constraint type.
                        if (ConstraintsHelper.IsObjectConstraint(type, ref bestObjectConstraint))
                        {
                            continue;
                        }

                        symbolsBuilder.Add(type);
                    }

                    if (bestObjectConstraint.HasType)
                    {
                        // See if we need to put Object! or Object~ back in order to preserve nullability information for the type parameter.
                        if (ConstraintsHelper.IsObjectConstraintSignificant(CalculateIsNotNullableFromNonTypeConstraints(), bestObjectConstraint))
                        {
                            Debug.Assert(!HasNotNullConstraint && !HasValueTypeConstraint);
                            if (symbolsBuilder.Count == 0)
                            {
                                if (bestObjectConstraint.NullableAnnotation.IsOblivious() && !HasReferenceTypeConstraint)
                                {
                                    bestObjectConstraint = default;
                                }
                            }
                            else
                            {
                                inProgress = inProgress.Prepend(this);
                                foreach (TypeWithAnnotations constraintType in symbolsBuilder)
                                {
                                    if (!ConstraintsHelper.IsObjectConstraintSignificant(IsNotNullableFromConstraintType(constraintType, inProgress, out _), bestObjectConstraint))
                                    {
                                        bestObjectConstraint = default;
                                        break;
                                    }
                                }
                            }

                            if (bestObjectConstraint.HasType)
                            {
                                symbolsBuilder.Insert(0, bestObjectConstraint);
                            }
                        }
                    }

                    declaredConstraintTypes = symbolsBuilder.ToImmutableAndFree();
                }
                else
                {
                    declaredConstraintTypes = ImmutableArray <TypeWithAnnotations> .Empty;
                }

                // - presence of unmanaged pattern has to be matched with `valuetype`
                // - IsUnmanagedAttribute is allowed iff there is an unmanaged pattern
                if (hasUnmanagedModreqPattern && (_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0 ||
                    hasUnmanagedModreqPattern != peModule.HasIsUnmanagedAttribute(_handle))
                {
                    // we do not recognize these combinations as "unmanaged"
                    hasUnmanagedModreqPattern = false;
                    _lazyCachedConstraintsUseSiteInfo.InterlockedCompareExchange(primaryDependency: null, new UseSiteInfo <AssemblySymbol>(new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this)));
                }

                _lazyHasIsUnmanagedConstraint = hasUnmanagedModreqPattern.ToThreeState();
                ImmutableInterlocked.InterlockedInitialize(ref _lazyDeclaredConstraintTypes, declaredConstraintTypes);
            }

            return(_lazyDeclaredConstraintTypes);
        }