private static Dictionary<ITypeSymbol, string> GetFormattableMembers(SemanticModel model) { return new Dictionary<ITypeSymbol, string>() { [model.GetClrType(typeof(string))] = nameof(string.Format), [model.GetClrType(typeof(StringBuilder))] = nameof(StringBuilder.AppendFormat), }; }
public static ITypeSymbol UnwrapFromNullableType(this ITypeSymbol type, SemanticModel semanticModel) { var namedType = type as INamedTypeSymbol; if (namedType == null) return null; if (type.UnwrapGenericIfNeeded().Equals(semanticModel.GetClrType(typeof (Nullable<>)))) { return namedType.TypeArguments[0]; } return null; }
private HashSet<INamedTypeSymbol> GetWellKnownFactories(SemanticModel model) { return new HashSet<INamedTypeSymbol>() { model.GetClrType(typeof(Enumerable)), model.GetClrType(typeof(Queryable)), model.GetClrType(typeof(Convert)), }; }
private HashSet<INamedTypeSymbol> GetWellKnownImmutableSystemTypes(SemanticModel model) { return new HashSet<INamedTypeSymbol>() { model.GetClrType(typeof(object)), model.GetClrType(typeof(Delegate)), model.GetClrType(typeof(string)), model.GetClrType(typeof(Enum)), model.GetClrType(typeof(Type)), model.GetClrType(typeof(IEquatable<>)), model.GetClrType(typeof(IComparable<>)), model.GetClrType(typeof(IFormattable)), model.GetClrType(typeof(IEnumerable<>)), model.GetClrType(typeof(IQueryable<>)), model.GetClrType(typeof(ICustomFormatter)), }; }
private bool IsTaskOfT(AwaitExpressionSyntax awaitExpression, SemanticModel semanticModel) { var type = semanticModel.GetTypeInfo(awaitExpression.Expression); return type.Type?.UnwrapGenericIfNeeded()?.Equals( semanticModel.GetClrType(typeof(Task<>))) == true; }
private bool IsArrayOfObjects(ITypeSymbol expressionType, SemanticModel semanticModel) { var arrayType = expressionType as IArrayTypeSymbol; return arrayType?.Rank == 1 && arrayType?.ElementType.Equals(semanticModel.GetClrType(typeof (object))) == true; }
private bool DefaultSectionThrows(SwitchStatementSyntax switchStatement, SemanticModel semanticModel) { var defaultCase = switchStatement.Sections.FirstOrDefault(s => s.Labels.OfType<DefaultSwitchLabelSyntax>().Any()); if (defaultCase == null) { return false; } bool throwsInvalidOperation = defaultCase.Statements // Filtering throw .OfType<ThrowStatementSyntax>() .Select(s => s.Expression) // Filtering throw new Exception .OfType<ObjectCreationExpressionSyntax>() // Filtering unknown symbols .Select(s => semanticModel.GetSymbolInfo(s.Type).Symbol) .Where(s => s != null) // True, if throw new InvalidOperationException() .Any(s => s.Equals(semanticModel.GetClrType(typeof(InvalidOperationException)))); if (throwsInvalidOperation) { return true; } bool hasContractAssertOrAssumeWithFalse = defaultCase.Statements // Getting only expressions .OfType<ExpressionStatementSyntax>() // that calls functions .Select(s => s.Expression as InvocationExpressionSyntax) .Where(s => s != null) // with first argument equals to false .Where(s => s.ArgumentList.Arguments.FirstOrDefault()?.Expression?.Kind() == SyntaxKind.FalseLiteralExpression) // with known symbols .Select(s => semanticModel.GetSymbolInfo(s).Symbol as IMethodSymbol) .Where(s => s != null) // Contract.Assert/Assume or Debug.Assert .Any(m => (m.ContainingType.Equals(semanticModel.GetClrType(typeof(Contract))) && (m.Name == "Assert" || m.Name == "Assume")) || (m.ContainingType.Name == "Debug" && m.Name == "Assert")); if (hasContractAssertOrAssumeWithFalse) { return true; } return false; }
private static void GetSize(SemanticModel semanticModel, ITypeSymbol type, ref int capacity, ref int largestFieldSize, ref int actualSize) { int currentItemSize; int newLargestFieldSize = largestFieldSize; if (TryGetPrimitiveSize(type, out currentItemSize, ref newLargestFieldSize)) { if (currentItemSize > largestFieldSize) { // we're trying to add large item. For instance, in case: byte b; int i; // In this case we need to adjust current size and capacity to larger bucket largestFieldSize = newLargestFieldSize; int padding = (largestFieldSize - capacity % largestFieldSize)%largestFieldSize; var oldCapacity = capacity; capacity += padding; // Removing very first case, when capacity was zero. In that case, no need to change size. if (oldCapacity != 0) { actualSize = capacity; } } if (actualSize + currentItemSize > capacity) { // Need to take max value from it. // Consider case, when the field is of a large struct type. In this case, bucket size would be IntPtr.Size // but actual size would be much larger! // And in this case, large struct size would be computed by this method and would be adjusted by IntPtr.Size. capacity += Math.Max(currentItemSize, largestFieldSize); } actualSize += currentItemSize; } else { bool empty = true; foreach (var field in type.GetMembers().OfType<IFieldSymbol>().Where(f => !f.IsStatic)) { GetSize(semanticModel, field.Type, ref capacity, ref largestFieldSize, ref actualSize); empty = false; } if (empty) { // Empty struct is similar to byte struct. The size is 1. GetSize(semanticModel, semanticModel.GetClrType(typeof(byte)), ref capacity, ref largestFieldSize, ref actualSize); } // When composite type layed out, need to adjust actual size to current capacity, // because CLR will not put new fields into padding left from the composite type. // Consider following example: // struct NestedWithLongAndByteAndInt2 { struct N { byte b; long l; byte b2; } N n; int i; } // In this case, for N field capacity is 24, but actual size is 17. // But in this case, int i would not be stored in the same bucket, but new bucket would be created. actualSize = capacity; } }
private bool IsCollection(ITypeSymbol symbol, SemanticModel semanticModel) { return symbol.AllInterfaces.Any(i => i.Equals(semanticModel.GetClrType(typeof(IEnumerable)))); }