/// <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); }
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); }
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); }