protected override IExpression GetExpression(CSharpElementFactory factory, IExpression contractExpression) { var expression = isDictionary ? factory.CreateExpression( string.Format("$0.{0}(pair => pair.{1} != null)", nameof(Enumerable.All), nameof(KeyValuePair <int, int> .Value)), contractExpression) : factory.CreateExpression(string.Format("$0.{0}(item => item != null)", nameof(Enumerable.All)), contractExpression); var invokedExpression = (IReferenceExpression)((IInvocationExpression)expression).InvokedExpression; Debug.Assert(invokedExpression != null); var allMethodReference = invokedExpression.Reference; var enumerableType = TypeElementUtil.GetTypeElementByClrName(PredefinedType.ENUMERABLE_CLASS, Provider.PsiModule); Debug.Assert(enumerableType != null); var allMethod = enumerableType.Methods.First(method => method.AssertNotNull().ShortName == nameof(Enumerable.All)); Debug.Assert(allMethod != null); allMethodReference.BindTo(allMethod); return(expression); }
static IEnumerable <ITypeElement> GetAllowedExceptions(Location location, [NotNull] IPsiModule psiModule) { switch (location) { case Location.PropertyGetter: yield return(TypeElementUtil.GetTypeElementByClrName(PredefinedType.INVALIDOPERATIONEXCEPTION_FQN, psiModule).AssertNotNull()); yield return(TypeElementUtil.GetTypeElementByClrName(ClrTypeNames.NotSupportedException, psiModule).AssertNotNull()); break; case Location.IndexerGetter: yield return(TypeElementUtil.GetTypeElementByClrName(PredefinedType.ARGUMENTEXCEPTION_FQN, psiModule).AssertNotNull()); yield return(TypeElementUtil.GetTypeElementByClrName(ClrTypeNames.KeyNotFoundException, psiModule).AssertNotNull()); goto case Location.PropertyGetter; case Location.EventAccessor: yield return(TypeElementUtil.GetTypeElementByClrName(PredefinedType.INVALIDOPERATIONEXCEPTION_FQN, psiModule).AssertNotNull()); yield return(TypeElementUtil.GetTypeElementByClrName(ClrTypeNames.NotSupportedException, psiModule).AssertNotNull()); yield return(TypeElementUtil.GetTypeElementByClrName(PredefinedType.ARGUMENTEXCEPTION_FQN, psiModule).AssertNotNull()); break; case Location.GetHashCodeMethodWithParameter: yield return(TypeElementUtil.GetTypeElementByClrName(PredefinedType.ARGUMENTEXCEPTION_FQN, psiModule).AssertNotNull()); break; } }
static bool IsAvailableForType([NotNull] IType type, [NotNull] ITreeNode context) { if (type.IsGenericEnumerableOrDescendant() || type.IsGenericArray(context)) { var elementType = CollectionTypeUtil.ElementTypeByCollectionType(type, context, false); if (elementType != null && elementType.Classify == TypeClassification.REFERENCE_TYPE) { return(true); } } var resultType = type.GetTasklikeUnderlyingType(context); if (resultType != null && resultType.Classify == TypeClassification.REFERENCE_TYPE) { return(true); } if (type.IsLazy()) { var typeElement = TypeElementUtil.GetTypeElementByClrName(PredefinedType.LAZY_FQN, context.GetPsiModule()); var valueType = type.GetGenericUnderlyingType(typeElement); if (valueType != null && valueType.Classify == TypeClassification.REFERENCE_TYPE) { return(true); } } return(false); }
protected override IExpression GetExpression(CSharpElementFactory factory, IExpression contractExpression) { Debug.Assert(nameof(IntPtr.Zero) == nameof(UIntPtr.Zero)); return(factory.CreateExpression( string.Format("$0 != $1.{0}", nameof(IntPtr.Zero)), contractExpression, TypeElementUtil.GetTypeElementByClrName(IsSigned ? PredefinedType.INTPTR_FQN : PredefinedType.UINTPTR_FQN, Provider.PsiModule))); }
protected override IExpression GetExpression(CSharpElementFactory factory, IExpression contractExpression) { Debug.Assert(NumericTypeInfo != null); return(NumericTypeInfo.EpsilonLiteral != null ? factory.CreateExpression( string.Format("$1.{0}($0 - 0{1}) < {2}", nameof(Math.Abs), NumericTypeInfo.LiteralSuffix, NumericTypeInfo.EpsilonLiteral), contractExpression, TypeElementUtil.GetTypeElementByClrName(ClrTypeNames.Math, Provider.PsiModule)) : factory.CreateExpression(string.Format("$0 == 0{0}", NumericTypeInfo.LiteralSuffix), contractExpression)); }
protected override IAttribute CreateAttribute(ITypeElement resolvedAttributeType, CSharpElementFactory factory, IPsiModule psiModule) { if (this.MatchingFlagName == null) { return(base.CreateAttribute(resolvedAttributeType, factory, psiModule)); } var enumType = TypeElementUtil.GetTypeElementByClrName(AutoFixtureConstants.MatchingEnumType, psiModule) as IEnum; var enumValue = enumType?.EnumMembers.FirstOrDefault(f => f.ShortName == this.MatchingFlagName)?.ConstantValue; if (enumValue == null) { return(null); } return(factory.CreateAttribute(resolvedAttributeType, new[] { new AttributeValue(enumValue) }, EmptyArray <Pair <string, AttributeValue> > .Instance)); }
static string TryGetHighlightingMessage([NotNull] ICSharpExpression monitor) { Debug.Assert(CSharpLanguage.Instance != null); var monitorType = monitor.GetExpressionType().ToIType(); if (monitorType.IsString()) { return("Do not lock on strings."); } if (monitorType is IArrayType arrayType && arrayType.ElementType.IsValueType()) { return("Do not lock on arrays of value types."); } var monitorTypeElement = monitorType.GetTypeElement(); if (monitorTypeElement != null) { var psiModule = monitor.GetPsiModule(); foreach (var type in GetClassTypes()) { var objectType = (IClass)TypeElementUtil.GetTypeElementByClrName(type, psiModule).AssertNotNull(); if (monitorTypeElement.IsDescendantOf(objectType)) { var typeName = objectType.WithIdSubstitution().AssertNotNull().GetPresentableName(CSharpLanguage.Instance); if (objectType.IsAbstract) { return($"Do not lock on objects derived from the '{typeName}' class."); } if (objectType.IsSealed) { return($"Do not lock on '{typeName}' objects."); } return($"Do not lock on '{typeName}' objects or objects derived from the '{typeName}' class."); } } } return(null); }
public override bool IsAvailable(IUserDataHolder cache) { var parameter = this.Provider.GetSelectedElement <IRegularParameterDeclaration>()?.DeclaredElement; if (parameter == null || !parameter.IsValid()) { return(false); } //Check whether AF is present this.ResolvedAttributeType = TypeElementUtil.GetTypeElementByClrName(this.AttributeType, this.Provider.PsiModule); if (this.ResolvedAttributeType == null) { return(false); } return(this.IsAvailableWithAttributeInstances(parameter.GetAttributeInstances(this.AttributeType, false))); }
static void AddContractForEnsures( [NotNull] ICSharpContextActionDataProvider provider, [NotNull] Func <IExpression, IExpression> getContractExpression, [NotNull] IParameter parameter, [NotNull] IBlock body, out ICSharpStatement firstNonContractStatement) { var factory = CSharpElementFactory.GetInstance(body); var contractType = TypeElementUtil.GetTypeElementByClrName(PredefinedType.CONTRACT_FQN, provider.PsiModule); var parameterExpression = factory.CreateExpression("$0", parameter); var expression = factory.CreateExpression( string.Format("$0.{0}(out $1)", nameof(Contract.ValueAtReturn)), contractType, parameterExpression); AddContract(ContractKind.Ensures, body, provider.PsiModule, () => getContractExpression(expression), out firstNonContractStatement); }
static ICSharpStatement CreateContractStatement( ContractKind contractKind, [NotNull] IPsiModule psiModule, [NotNull] IExpression contractExpression) { var factory = CSharpElementFactory.GetInstance(contractExpression); var contractType = TypeElementUtil.GetTypeElementByClrName(PredefinedType.CONTRACT_FQN, psiModule); switch (contractKind) { case ContractKind.Requires: return(factory.CreateStatement(string.Format("$0.{0}($1);", nameof(Contract.Requires)), contractType, contractExpression)); case ContractKind.Ensures: return(factory.CreateStatement(string.Format("$0.{0}($1);", nameof(Contract.Ensures)), contractType, contractExpression)); case ContractKind.Invariant: return(factory.CreateStatement(string.Format("$0.{0}($1);", nameof(Contract.Invariant)), contractType, contractExpression)); default: throw new ArgumentOutOfRangeException(nameof(contractKind)); } }
protected override Action <ITextControl> ExecutePsiTransaction(ISolution solution, IProgressIndicator progress) { var parameterDeclaration = this.Provider.GetSelectedElement <IRegularParameterDeclaration>(); if (parameterDeclaration == null) { return(null); } var existingAttributes = parameterDeclaration.AttributesEnumerable .Where(attr => attr.GetAttributeInstance().GetClrName().Equals(this.AttributeType)) .ToArray(); foreach (var existingAttribute in existingAttributes) { parameterDeclaration.RemoveAttribute(existingAttribute); } var psiModule = this.Provider.PsiModule; //Try resolve again. It could happen that IsAvailable method was not invoked (e.g. for Frozen(Matching..)). this.ResolvedAttributeType = this.ResolvedAttributeType ?? TypeElementUtil.GetTypeElementByClrName(this.AttributeType, this.Provider.PsiModule); if (this.ResolvedAttributeType == null) { return(null); } var attribute = this.CreateAttribute(this.ResolvedAttributeType, CSharpElementFactory.GetInstance(parameterDeclaration), psiModule); if (attribute != null) { parameterDeclaration.AddAttributeBefore(attribute, null); } return(null); }
private static ITypeElement getAttributeType(IPsiModule psiModule, IModuleReferenceResolveContext resolveContext, string attributeName) { return(TypeElementUtil.GetTypeElementByClrName(new ClrTypeName(attributeName), psiModule, resolveContext)); }
protected override IExpression GetExpression(CSharpElementFactory factory, IExpression contractExpression) => factory.CreateExpression( string.Format("$0 == $1.{0}", nameof(System.TimeSpan.Zero)), contractExpression, TypeElementUtil.GetTypeElementByClrName(PredefinedType.TIMESPAN_FQN, Provider.PsiModule));
internal static ITypeElement GetArrayType([NotNull] IPsiModule psiModule) => TypeElementUtil.GetTypeElementByClrName(PredefinedType.ARRAY_FQN, psiModule).AssertNotNull();
static Location?TryGetLocation([NotNull] ICSharpTreeNode element, [NotNull] ElementProblemAnalyzerData data) { switch (element.GetContainingFunctionLikeDeclarationOrClosure()) { case IAccessorDeclaration accessorDeclaration: switch (accessorDeclaration.Kind) { case AccessorKind.GETTER: switch (accessorDeclaration.Parent) { case IPropertyDeclaration _: return(Location.PropertyGetter); case IIndexerDeclaration _: return(Location.IndexerGetter); } break; case AccessorKind.ADDER: case AccessorKind.REMOVER: return(Location.EventAccessor); } break; case IPropertyDeclaration _: return(Location.PropertyGetter); case IIndexerDeclaration _: return(Location.IndexerGetter); case IMethodDeclaration methodDeclaration when methodDeclaration.DeclaredElement != null: var psiModule = element.GetPsiModule(); var objectClass = TypeElementUtil.GetTypeElementByClrName(PredefinedType.OBJECT_FQN, psiModule).AssertNotNull(); if (methodDeclaration.DeclaredElement.OverridesOrImplements(GetMethod(objectClass, nameof(object.Equals)))) { return(Location.EqualsMethod); } if (methodDeclaration.DeclaredElement.OverridesOrImplements(GetMethod(objectClass, nameof(GetHashCode)))) { return(Location.GetHashCodeMethod); } if (methodDeclaration.DeclaredElement.OverridesOrImplements(GetMethod(objectClass, nameof(ToString)))) { return(Location.ToStringMethod); } if (methodDeclaration.DeclaredElement.OverridesOrImplements( GetMethod( TypeElementUtil.GetTypeElementByClrName(PredefinedType.GENERIC_IEQUATABLE_FQN, psiModule).AssertNotNull(), nameof(IEquatable <int> .Equals)))) { return(Location.EqualsMethod); } var equalityComparerGenericInterface = TypeElementUtil.GetTypeElementByClrName(ClrTypeNames.IEqualityComparerGeneric, psiModule) .AssertNotNull(); if (methodDeclaration.DeclaredElement.OverridesOrImplements( GetMethod(equalityComparerGenericInterface, nameof(IEqualityComparer <int> .Equals)))) { return(Location.EqualsMethodWithParameters); } if (methodDeclaration.DeclaredElement.OverridesOrImplements( GetMethod(equalityComparerGenericInterface, nameof(IEqualityComparer <int> .GetHashCode)))) { return(Location.GetHashCodeMethodWithParameter); } var equalityComparerInterface = TypeElementUtil.GetTypeElementByClrName(ClrTypeNames.IEqualityComparer, psiModule).AssertNotNull(); if (methodDeclaration.DeclaredElement.OverridesOrImplements( GetMethod(equalityComparerInterface, nameof(IEqualityComparer.Equals)))) { return(Location.EqualsMethodWithParameters); } if (methodDeclaration.DeclaredElement.OverridesOrImplements( GetMethod(equalityComparerInterface, nameof(IEqualityComparer.GetHashCode)))) { return(Location.GetHashCodeMethodWithParameter); } if (methodDeclaration.DeclaredElement.OverridesOrImplements( GetMethod( TypeElementUtil.GetTypeElementByClrName(PredefinedType.IDISPOSABLE_FQN, psiModule).AssertNotNull(), nameof(IDisposable.Dispose)))) { return(Location.DisposeMethod); } if (methodDeclaration.DeclaredElement.ShortName == disposeMethodName && methodDeclaration.DeclaredElement.Parameters.Count == 1) { var parameter = methodDeclaration.DeclaredElement.Parameters[0]; if (parameter != null && parameter.Type.IsBool()) { var controlFlowGraph = (ICSharpControlFlowGraph)ControlFlowBuilder.GetGraph(methodDeclaration); var controlFlowEdge = controlFlowGraph?.ReachableExits.FirstOrDefault( e => e?.Type == ControlFlowEdgeType.THROW && e.Source.SourceElement == element); if (controlFlowEdge != null) { var inspector = CSharpControlFlowGraphInspector.Inspect(controlFlowGraph, data.GetValueAnalysisMode()); var controlFlowContext = inspector.GetContext(controlFlowEdge); var variableInfo = inspector.FindVariableInfo(parameter); if (variableInfo != null) { var variableValue = controlFlowContext?.GetVariableDefiniteState(variableInfo); if (variableValue == null || variableValue == CSharpControlFlowVariableValue.FALSE) { return(Location.DisposeMethodWithParameterFalseCodePath); } } } } } break; case IConstructorDeclaration constructorDeclaration when constructorDeclaration.IsStatic: return(Location.StaticConstructor); case IDestructorDeclaration _: return(Location.Finalizer); case ISignOperatorDeclaration signOperator: var tokenType = signOperator.OperatorSign?.GetTokenType(); if (tokenType == CSharpTokenType.EQEQ || tokenType == CSharpTokenType.NE) { return(Location.EqualityOperator); } break; case IConversionOperatorDeclaration conversionOperatorDeclaration when conversionOperatorDeclaration.Modifier?.GetTokenType() == CSharpTokenType.IMPLICIT_KEYWORD: return(Location.ImplicitCastOperator); } return(null); }
protected override IExpression GetExpression(CSharpElementFactory factory, IExpression contractExpression) => factory.CreateExpression( string.Format("$0 != $1.{0}", nameof(Guid.Empty)), contractExpression, TypeElementUtil.GetTypeElementByClrName(PredefinedType.GUID_FQN, Provider.PsiModule));
public override void AddContracts( ICSharpContextActionDataProvider provider, Func <IExpression, IExpression> getContractExpression, out ICollection <ICSharpStatement> firstNonContractStatements) { var factory = CSharpElementFactory.GetInstance(declaration); var propertyDeclaration = declaration as IPropertyDeclaration; if (propertyDeclaration != null && propertyDeclaration.IsAuto) { var classLikeDeclaration = (IClassLikeDeclaration)declaration.GetContainingTypeDeclaration(); Debug.Assert(classLikeDeclaration != null); var contractInvariantMethodDeclaration = classLikeDeclaration.EnsureContractInvariantMethod(provider.PsiModule); if (contractInvariantMethodDeclaration.Body != null) { var expression = factory.CreateExpression("$0", declaration.DeclaredElement); AddContract( ContractKind.Invariant, contractInvariantMethodDeclaration.Body, provider.PsiModule, () => getContractExpression(expression), out var firstNonContractStatement); firstNonContractStatements = firstNonContractStatement != null ? new[] { firstNonContractStatement } : null; } else { firstNonContractStatements = null; } return; } IEnumerable <IAccessorDeclaration> accessorDeclarations; if (declaration.IsAbstract) { IAccessorOwnerDeclaration overriddenAccessorOwnerDeclaration = null; var containingTypeDeclaration = declaration.GetContainingTypeDeclaration(); Debug.Assert(containingTypeDeclaration != null); var contractClassDeclaration = containingTypeDeclaration.EnsureContractClass(provider.PsiModule); if (propertyDeclaration != null) { overriddenAccessorOwnerDeclaration = propertyDeclaration.EnsureOverriddenPropertyInContractClass(contractClassDeclaration); } if (declaration is IIndexerDeclaration indexerDeclaration) { overriddenAccessorOwnerDeclaration = indexerDeclaration.EnsureOverriddenIndexerInContractClass(contractClassDeclaration); } Debug.Assert(overriddenAccessorOwnerDeclaration != null); accessorDeclarations = overriddenAccessorOwnerDeclaration.AccessorDeclarations; } else { accessorDeclarations = declaration.AccessorDeclarations; } firstNonContractStatements = new List <ICSharpStatement>(2); foreach (var accessorDeclaration in accessorDeclarations) { Debug.Assert(accessorDeclaration != null); if (accessorDeclaration.Body != null) { switch (accessorDeclaration.Kind) { case AccessorKind.GETTER: { var contractType = TypeElementUtil.GetTypeElementByClrName(PredefinedType.CONTRACT_FQN, provider.PsiModule); var resultExpression = factory.CreateExpression( string.Format("$0.{0}<$1>()", nameof(Contract.Result)), contractType, Type); AddContract( ContractKind.Ensures, accessorDeclaration.Body, provider.PsiModule, () => getContractExpression(resultExpression), out var firstNonContractStatement); if (firstNonContractStatement != null) { firstNonContractStatements.Add(firstNonContractStatement); } break; } case AccessorKind.SETTER: { var valueExpression = factory.CreateExpression("value"); AddContract( ContractKind.Requires, accessorDeclaration.Body, provider.PsiModule, () => getContractExpression(valueExpression), out var firstNonContractStatement); if (firstNonContractStatement != null) { firstNonContractStatements.Add(firstNonContractStatement); } break; } } } } if (firstNonContractStatements.Count == 0) { firstNonContractStatements = null; } }
static void AnalyzeNotAllowedItemNotNull( [NotNull] IHighlightingConsumer consumer, [NotNull] IAttributesOwnerDeclaration attributesOwnerDeclaration) { var itemNotNullAttribute = attributesOwnerDeclaration.AttributesEnumerable.FirstOrDefault( attribute => attribute.AssertNotNull().GetAttributeInstance().GetAttributeType().GetClrName().ShortName == ContainerElementNullnessProvider.ItemNotNullAttributeShortName); if (itemNotNullAttribute != null) { if (attributesOwnerDeclaration.OverridesInheritedMember()) { consumer.AddHighlighting( new NotAllowedAnnotationHighlighting( attributesOwnerDeclaration, itemNotNullAttribute, "Annotation is not allowed because the declared element overrides or implements the inherited member.")); return; } var type = TryGetTypeForIfCanBeAnnotatedWithItemNotNull(attributesOwnerDeclaration); if (type != null) { if (type.IsGenericEnumerableOrDescendant() || type.IsGenericArray(attributesOwnerDeclaration)) { var elementType = CollectionTypeUtil.ElementTypeByCollectionType(type, attributesOwnerDeclaration); if (elementType != null) { if (elementType.Classify != TypeClassification.REFERENCE_TYPE) { consumer.AddHighlighting( new NotAllowedAnnotationHighlighting( attributesOwnerDeclaration, itemNotNullAttribute, "Annotation is not allowed because the declared element type is not a reference type.")); } } return; } var resultType = type.GetTasklikeUnderlyingType(attributesOwnerDeclaration); if (resultType != null) { if (resultType.Classify != TypeClassification.REFERENCE_TYPE) { consumer.AddHighlighting( new NotAllowedAnnotationHighlighting( attributesOwnerDeclaration, itemNotNullAttribute, "Annotation is not allowed because the declared task result type is not a reference type.")); } return; } if (type.IsLazy()) { var typeElement = TypeElementUtil.GetTypeElementByClrName(PredefinedType.LAZY_FQN, attributesOwnerDeclaration.GetPsiModule()); var valueType = type.GetGenericUnderlyingType(typeElement); if (valueType != null) { if (valueType.Classify != TypeClassification.REFERENCE_TYPE) { consumer.AddHighlighting( new NotAllowedAnnotationHighlighting( attributesOwnerDeclaration, itemNotNullAttribute, "Annotation is not allowed because the declared lazy value type is not a reference type.")); } } return; } consumer.AddHighlighting( new NotAllowedAnnotationHighlighting( attributesOwnerDeclaration, itemNotNullAttribute, string.Format( "Annotation is not allowed because the declared element must be an {0}<T> (or its descendant), " + "or a generic task-like type, or a {1}<T>.", nameof(IEnumerable <int>), nameof(Lazy <int>)))); } } }