C#: Fix up test output

C#: Fix a qltest whereby a tuple type having multiple underlying types was causing an issue with the IR sanity checks.
C#: Revert more changes.
C#: Fix tests and remove dead code.
This commit is contained in:
Calum Grant
2019-11-06 18:22:26 +00:00
parent a261cbaeef
commit fe83bac0fb
21 changed files with 774 additions and 921 deletions

View File

@@ -204,7 +204,7 @@ namespace Semmle.Extraction.CSharp.Entities
if (type.ContainsTypeParameters(cx, method))
type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0));
else
trapFile.WriteSubId(Type.Create(cx, type).TypeRef);
trapFile.WriteSubId(Type.Create(cx, type));
}
protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method)

View File

@@ -86,8 +86,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.Write(";parameter");
}
// If we don't have the type of the parameter, do not populate it.
public override bool NeedsPopulation => symbol.Type.TypeKind != TypeKind.Error;
public override bool NeedsPopulation => true;
string Name
{

View File

@@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities
return;
}
trapFile.typeref_type((TypeRef)TypeRef, this);
trapFile.typeref_type((NamedTypeRef)TypeRef, this);
if (symbol.IsGenericType)
{
@@ -151,39 +151,34 @@ namespace Semmle.Extraction.CSharp.Entities
public NamedType Create(Context cx, INamedTypeSymbol init) => new NamedType(cx, init);
}
public override Type TypeRef => Entities.TypeRef.Create(Context, this, symbol);
public override Type TypeRef => NamedTypeRef.Create(Context, symbol);
}
class TypeRef : Type<ITypeSymbol>
class NamedTypeRef : Type<INamedTypeSymbol>
{
readonly Type referencedType;
public TypeRef(Context cx, Type type, ITypeSymbol symbol) : base(cx, symbol)
public NamedTypeRef(Context cx, INamedTypeSymbol symbol) : base(cx, symbol)
{
referencedType = type;
referencedType = Type.Create(cx, symbol);
}
public static TypeRef Create(Context cx, Type referencedType, ITypeSymbol type) =>
NamedTypeRefFactory.Instance.CreateEntity2(cx, (referencedType, type));
public static NamedTypeRef Create(Context cx, INamedTypeSymbol type) =>
NamedTypeRefFactory.Instance.CreateEntity2(cx, type);
class NamedTypeRefFactory : ICachedEntityFactory<(Type, ITypeSymbol), TypeRef>
class NamedTypeRefFactory : ICachedEntityFactory<INamedTypeSymbol, NamedTypeRef>
{
public static readonly NamedTypeRefFactory Instance = new NamedTypeRefFactory();
public TypeRef Create(Context cx, (Type, ITypeSymbol) init) => new TypeRef(cx, init.Item1, init.Item2);
public NamedTypeRef Create(Context cx, INamedTypeSymbol init) => new NamedTypeRef(cx, init);
}
public override bool NeedsPopulation => true;
public override void WriteId(TextWriter trapFile)
{
void ExpandType(Context cx0, TextWriter tb0, ITypeSymbol sub)
{
sub.BuildTypeId(cx0, tb0, ExpandType);
}
symbol.BuildTypeId(Context, trapFile, ExpandType);
trapFile.Write(";typeref");
trapFile.WriteSubId(referencedType);
trapFile.Write(";typeRef");
}
public override void Populate(TextWriter trapFile)

View File

@@ -42,7 +42,7 @@ namespace Semmle.Extraction.CSharp.Entities
PopulateGenerics();
var underlyingType = NamedType.Create(Context, symbol.TupleUnderlyingType);
trapFile.tuple_underlying_type(this, underlyingType.TypeRef);
trapFile.tuple_underlying_type(this, underlyingType);
int index = 0;
foreach (var element in TupleElements)

View File

@@ -95,7 +95,6 @@ namespace Semmle.Extraction.CSharp.Entities
var baseTypes = new List<Type>();
if (symbol.BaseType != null)
{
// !! Do not extend "object" if the base type is missing :-(
Type baseKey = Create(Context, symbol.BaseType);
trapFile.extend(this, baseKey.TypeRef);
if (symbol.TypeKind != TypeKind.Struct)
@@ -269,7 +268,6 @@ namespace Semmle.Extraction.CSharp.Entities
public static Type Create(Context cx, ITypeSymbol type)
{
type = type.DisambiguateType();
const bool errorTypeIsNull = false;
return type == null || (errorTypeIsNull && type.TypeKind == TypeKind.Error) ?
NullType.Create(cx).Type : (Type)cx.CreateEntity(type);

View File

@@ -120,8 +120,7 @@ namespace Semmle.Extraction.CSharp
var syntaxTrees = new List<SyntaxTree>();
var syntaxTreeTasks = ReadSyntaxTrees(
compilerArguments.SourceFiles.
Select(src => canonicalPathCache.GetCanonicalPath(src.Path)).
Where(f => !f.EndsWith(".dll")),
Select(src => canonicalPathCache.GetCanonicalPath(src.Path)),
analyser,
compilerArguments.ParseOptions,
compilerArguments.Encoding,

View File

@@ -4,8 +4,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace Semmle.Extraction.CSharp
{
@@ -135,34 +133,15 @@ namespace Semmle.Extraction.CSharp
/// <param name="subTermAction">The action to apply to syntactic sub terms of this type.</param>
public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction)
{
switch(type.SpecialType)
if (type.SpecialType != SpecialType.None)
{
case SpecialType.System_Object:
case SpecialType.System_Void:
case SpecialType.System_Boolean:
case SpecialType.System_Char:
case SpecialType.System_SByte:
case SpecialType.System_Byte:
case SpecialType.System_Int16:
case SpecialType.System_UInt16:
case SpecialType.System_Int32:
case SpecialType.System_UInt32:
case SpecialType.System_Int64:
case SpecialType.System_UInt64:
case SpecialType.System_Decimal:
case SpecialType.System_Single:
case SpecialType.System_Double:
case SpecialType.System_String:
case SpecialType.System_IntPtr:
case SpecialType.System_UIntPtr:
/*
* Use the keyword ("int" etc) for the built-in types.
* This makes the IDs shorter and means that all built-in types map to
* the same entities (even when using multiple versions of mscorlib).
*/
trapFile.Write(type.ToDisplayString());
return;
/*
* Use the keyword ("int" etc) for the built-in types.
* This makes the IDs shorter and means that all built-in types map to
* the same entities (even when using multiple versions of mscorlib).
*/
trapFile.Write(type.ToDisplayString());
return;
}
using (cx.StackGuard)
@@ -186,7 +165,7 @@ namespace Semmle.Extraction.CSharp
case TypeKind.Pointer:
var ptr = (IPointerTypeSymbol)type;
subTermAction(cx, trapFile, ptr.PointedAtType);
trapFile.Write("*");
trapFile.Write('*');
return;
case TypeKind.TypeParameter:
var tp = (ITypeParameterSymbol)type;
@@ -214,28 +193,8 @@ namespace Semmle.Extraction.CSharp
trapFile.Write(']');
}
private static void BuildAssembly(IAssemblySymbol asm, TextWriter trapFile, bool extraPrecise = false)
static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction)
{
var assembly = asm.Identity;
trapFile.Write(assembly.Name);
trapFile.Write('_');
trapFile.Write(assembly.Version.Major);
trapFile.Write('.');
trapFile.Write(assembly.Version.Minor);
trapFile.Write('.');
trapFile.Write(assembly.Version.Build);
if (extraPrecise)
{
trapFile.Write('.');
trapFile.Write(assembly.Version.Revision);
}
trapFile.Write("::");
}
public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction)
{
bool prefixAssembly = !(named.ContainingAssembly is null);
if (named.IsTupleType)
{
trapFile.Write('(');
@@ -258,8 +217,6 @@ namespace Semmle.Extraction.CSharp
}
else if (named.ContainingNamespace != null)
{
if (prefixAssembly)
BuildAssembly(named.ContainingAssembly, trapFile);
named.ContainingNamespace.BuildNamespace(cx, trapFile);
}
@@ -290,6 +247,26 @@ namespace Semmle.Extraction.CSharp
static void BuildNamespace(this INamespaceSymbol ns, Context cx, TextWriter trapFile)
{
// Only include the assembly information in each type ID
// for normal extractions. This is because standalone extractions
// lack assembly information or may be ambiguous.
bool prependAssemblyToTypeId = !cx.Extractor.Standalone && ns.ContainingAssembly != null;
if (prependAssemblyToTypeId)
{
// Note that we exclude the revision number as this has
// been observed to be unstable.
var assembly = ns.ContainingAssembly.Identity;
trapFile.Write(assembly.Name);
trapFile.Write('_');
trapFile.Write(assembly.Version.Major);
trapFile.Write('.');
trapFile.Write(assembly.Version.Minor);
trapFile.Write('.');
trapFile.Write(assembly.Version.Build);
trapFile.Write("::");
}
trapFile.WriteSubId(Namespace.Create(cx, ns));
trapFile.Write('.');
}
@@ -379,7 +356,7 @@ namespace Semmle.Extraction.CSharp
}
trapFile.Write(namedType.Name);
if (namedType.IsGenericType && namedType.TypeArguments.Any())
if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any())
{
trapFile.Write('<');
trapFile.BuildList(",", namedType.TypeArguments, (p, tb0) =>
@@ -478,30 +455,6 @@ namespace Semmle.Extraction.CSharp
public static SymbolInfo GetSymbolInfo(this Context cx, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode node) =>
cx.GetModel(node).GetSymbolInfo(node);
/// <summary>
/// Gets the symbol for a particular syntax node.
/// Throws an exception if the symbol is not found.
/// </summary>
///
/// <remarks>
/// This gives a nicer message than a "null pointer exception",
/// and should be used where we require a symbol to be resolved.
/// </remarks>
///
/// <param name="cx">The extraction context.</param>
/// <param name="node">The syntax node.</param>
/// <returns>The resolved symbol.</returns>
public static ISymbol GetSymbol(this Context cx, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode node)
{
var info = GetSymbolInfo(cx, node);
if (info.Symbol == null)
{
throw new InternalError(node, "Could not resolve symbol");
}
return info.Symbol;
}
/// <summary>
/// Determines the type of a node, or default
/// if the type could not be determined.
@@ -515,84 +468,11 @@ namespace Semmle.Extraction.CSharp
return new AnnotatedTypeSymbol(info.Type.DisambiguateType(), info.Nullability.Annotation);
}
/// <summary>
/// Gets the annotated type of an IPropertySymbol.
/// This has not yet been exposed on the public API.
/// </summary>
public static AnnotatedTypeSymbol GetAnnotatedType(this IPropertySymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation);
/// <summary>
/// Gets the annotated type of an IFieldSymbol.
/// This has not yet been exposed on the public API.
/// </summary>
public static AnnotatedTypeSymbol GetAnnotatedType(this IFieldSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation);
private static bool IsSpecialized(this IMethodSymbol method) =>
method.IsGenericMethod &&
!ReferenceEquals(method, method.OriginalDefinition) &&
method.TypeParameters.Zip(method.TypeArguments, (a, b) => !ReferenceEquals(a, b)).Any(b => b);
/// <summary>
/// Gets the annotated return type of an IMethodSymbol.
/// This has not yet been exposed on the public API.
/// </summary>
public static AnnotatedTypeSymbol GetAnnotatedReturnType(this IMethodSymbol symbol) => new AnnotatedTypeSymbol(symbol.ReturnType, symbol.ReturnNullableAnnotation);
/// <summary>
/// Gets the type annotation for a NullableAnnotation.
/// </summary>
public static Kinds.TypeAnnotation GetTypeAnnotation(this NullableAnnotation na)
{
switch(na)
{
case NullableAnnotation.Annotated:
return Kinds.TypeAnnotation.Annotated;
case NullableAnnotation.NotAnnotated:
return Kinds.TypeAnnotation.NotAnnotated;
default:
return Kinds.TypeAnnotation.None;
}
}
/// <summary>
/// Gets the annotated element type of an IArrayTypeSymbol.
/// This has not yet been exposed on the public API.
/// </summary>
public static AnnotatedTypeSymbol GetAnnotatedElementType(this IArrayTypeSymbol symbol) =>
new AnnotatedTypeSymbol(symbol.ElementType, symbol.ElementNullableAnnotation);
/// <summary>
/// Gets the annotated type arguments of an INamedTypeSymbol.
/// This has not yet been exposed on the public API.
/// </summary>
public static IEnumerable<AnnotatedTypeSymbol> GetAnnotatedTypeArguments(this INamedTypeSymbol symbol) =>
symbol.TypeArguments.Zip(symbol.TypeArgumentsNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a));
/// <summary>
/// Gets the annotated type arguments of an IMethodSymbol.
/// This has not yet been exposed on the public API.
/// </summary>
public static IEnumerable<AnnotatedTypeSymbol> GetAnnotatedTypeArguments(this IMethodSymbol symbol) =>
symbol.TypeArguments.Zip(symbol.TypeArgumentsNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a));
/// <summary>
/// Gets the annotated type constraints of an ITypeParameterSymbol.
/// This has not yet been exposed on the public API.
/// </summary>
public static IEnumerable<AnnotatedTypeSymbol> GetAnnotatedTypeConstraints(this ITypeParameterSymbol symbol) =>
symbol.ConstraintTypes.Zip(symbol.ConstraintNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a));
/// <summary>
/// Creates an AnnotatedTypeSymbol from an ITypeSymbol.
/// Note: not currently used but might be useful.
/// </summary>
public static AnnotatedTypeSymbol WithAnnotation(this ITypeSymbol symbol, NullableAnnotation annotation) =>
new AnnotatedTypeSymbol(symbol, annotation);
/// <summary>
/// Holds if this type looks like an "anonymous" type. Names of anonymous types
/// sometimes collide so they need to be handled separately.
/// </summary>
public static bool IsAnonymous(this INamedTypeSymbol type) =>
type.IsAnonymousType || type.Name.StartsWith("<>");
}
}

View File

@@ -388,7 +388,7 @@ namespace Semmle.Extraction.CSharp
internal static void nullability_member(this TextWriter trapFile, NullabilityEntity nullability, int index, NullabilityEntity child)
{
trapFile.WriteTuple(nameof(nullability_member), nullability, index, child);
trapFile.WriteTuple("nullability_member", nullability, index, child);
}
internal static void numlines(this TextWriter trapFile, IEntity label, LineCounts lineCounts)
@@ -481,7 +481,7 @@ namespace Semmle.Extraction.CSharp
trapFile.WriteTuple("tuple_element", type, index, field);
}
internal static void tuple_underlying_type(this TextWriter trapFile, TupleType type, Type underlying)
internal static void tuple_underlying_type(this TextWriter trapFile, TupleType type, NamedType underlying)
{
trapFile.WriteTuple("tuple_underlying_type", type, underlying);
}
@@ -526,12 +526,12 @@ namespace Semmle.Extraction.CSharp
trapFile.WriteTuple("type_parameters", param, child, typeOrMethod, (int)param.Variance);
}
internal static void typeref_type(this TextWriter trapFile, TypeRef typeref, Type type)
internal static void typeref_type(this TextWriter trapFile, NamedTypeRef typeref, Type type)
{
trapFile.WriteTuple("typeref_type", typeref, type);
}
internal static void typerefs(this TextWriter trapFile, TypeRef type, string name)
internal static void typerefs(this TextWriter trapFile, NamedTypeRef type, string name)
{
trapFile.WriteTuple("typerefs", type, name);
}

View File

@@ -87,22 +87,6 @@ namespace Semmle.Extraction
/// <param name="scope">The extraction scope (what to include in this trap file).</param>
/// <returns></returns>
Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope);
/// <summary>
/// Adjusts the algorithm used to generate identifiers in trap files.
/// </summary>
TrapIdenfierMode TrapIdentifiers { get; }
}
/// <summary>
/// Configures how to generate identifiers in trap files.
/// </summary>
public enum TrapIdenfierMode
{
Imprecise, // Names are not qualified by assembly version
Flexible, // Some names are qualified by assembly versions - typerefs are not however.
Precise, // All names are qualified by their partial assembly version (excludes build number)
ExtraPrecise // All names are qualified by their full assembly version.
}
/// <summary>
@@ -128,7 +112,6 @@ namespace Semmle.Extraction
public Extractor(bool standalone, string outputPath, ILogger logger)
{
Standalone = standalone;
if (Standalone) TrapIdentifiers = TrapIdenfierMode.Imprecise;
OutputPath = outputPath;
Logger = logger;
}
@@ -214,7 +197,5 @@ namespace Semmle.Extraction
public ILogger Logger { get; private set; }
public static string Version => $"{ThisAssembly.Git.BaseTag} ({ThisAssembly.Git.Sha})";
public TrapIdenfierMode TrapIdentifiers { get; } = TrapIdenfierMode.Imprecise;
}
}