mirror of
https://github.com/github/codeql.git
synced 2026-05-05 05:35:13 +02:00
C#: Migrate extractor to this repository.
This commit is contained in:
77
csharp/extractor/Semmle.Extraction/Entities/Assembly.cs
Normal file
77
csharp/extractor/Semmle.Extraction/Entities/Assembly.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Semmle.Extraction.Entities
|
||||
{
|
||||
public class Assembly : Location
|
||||
{
|
||||
readonly string assemblyPath;
|
||||
readonly IAssemblySymbol assembly;
|
||||
|
||||
Assembly(Context cx, Microsoft.CodeAnalysis.Location init)
|
||||
: base(cx, init)
|
||||
{
|
||||
if (init == null)
|
||||
{
|
||||
// This is the output assembly
|
||||
assemblyPath = cx.Extractor.OutputPath;
|
||||
assembly = cx.Compilation.Assembly;
|
||||
}
|
||||
else
|
||||
{
|
||||
assembly = symbol.MetadataModule.ContainingAssembly;
|
||||
var identity = assembly.Identity;
|
||||
var idString = identity.Name + " " + identity.Version;
|
||||
assemblyPath = cx.Extractor.GetAssemblyFile(idString);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Populate()
|
||||
{
|
||||
if (assemblyPath != null)
|
||||
{
|
||||
Context.Emit(Tuples.assemblies(this, File.Create(Context, assemblyPath), assembly.ToString(),
|
||||
assembly.Identity.Name, assembly.Identity.Version.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public override int GetHashCode() =>
|
||||
symbol == null ? 91187354 : symbol.GetHashCode();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as Assembly;
|
||||
if (other == null || other.GetType() != typeof(Assembly))
|
||||
return false;
|
||||
|
||||
return Equals(symbol, other.symbol);
|
||||
}
|
||||
|
||||
public new static Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) => AssemblyConstructorFactory.Instance.CreateEntity(cx, loc);
|
||||
|
||||
class AssemblyConstructorFactory : ICachedEntityFactory<Microsoft.CodeAnalysis.Location, Assembly>
|
||||
{
|
||||
public static readonly AssemblyConstructorFactory Instance = new AssemblyConstructorFactory();
|
||||
|
||||
public Assembly Create(Context cx, Microsoft.CodeAnalysis.Location init) => new Assembly(cx, init);
|
||||
}
|
||||
|
||||
public static Location CreateOutputAssembly(Context cx)
|
||||
{
|
||||
if (cx.Extractor.OutputPath == null)
|
||||
throw new InternalError("Attempting to create the output assembly in standalone extraction mode");
|
||||
return AssemblyConstructorFactory.Instance.CreateEntity(cx, null);
|
||||
}
|
||||
|
||||
public override IId Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return assemblyPath == null
|
||||
? new Key(assembly, ";assembly")
|
||||
: new Key(assembly, "#file:///", assemblyPath.Replace("\\", "/"), ";assembly");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
csharp/extractor/Semmle.Extraction/Entities/File.cs
Normal file
124
csharp/extractor/Semmle.Extraction/Entities/File.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using Semmle.Util;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Semmle.Extraction.Entities
|
||||
{
|
||||
public class File : CachedEntity<string>
|
||||
{
|
||||
File(Context cx, string path)
|
||||
: base(cx, path)
|
||||
{
|
||||
Path = path;
|
||||
}
|
||||
|
||||
public string Path
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string DatabasePath => FileAsDatabaseString(Path);
|
||||
|
||||
public override bool NeedsPopulation => Context.DefinesFile(Path) || Path == Context.Extractor.OutputPath;
|
||||
|
||||
public override void Populate()
|
||||
{
|
||||
if (Path == null)
|
||||
{
|
||||
Context.Emit(Tuples.files(this, "", "", ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
var fi = new FileInfo(Path);
|
||||
|
||||
string extension = fi.Extension ?? "";
|
||||
string name = fi.Name;
|
||||
name = name.Substring(0, name.Length - extension.Length);
|
||||
int fromSource = extension.ToLowerInvariant().Equals(".cs") ? 1 : 2;
|
||||
|
||||
// remove the dot from the extension
|
||||
if (extension.Length > 0)
|
||||
extension = extension.Substring(1);
|
||||
Context.Emit(Tuples.files(this, DatabasePath, name, extension));
|
||||
|
||||
Context.Emit(Tuples.containerparent(Entities.Folder.Create(Context, fi.Directory), this));
|
||||
if (fromSource == 1)
|
||||
{
|
||||
foreach (var text in Context.Compilation.SyntaxTrees.
|
||||
Where(t => t.FilePath == Path).
|
||||
Select(tree => tree.GetText()))
|
||||
{
|
||||
var rawText = text.ToString();
|
||||
var lineCounts = LineCounter.ComputeLineCounts(rawText);
|
||||
if (rawText.Length > 0 && rawText[rawText.Length - 1] != '\n') lineCounts.Total++;
|
||||
|
||||
Context.Emit(Tuples.numlines(this, lineCounts));
|
||||
Context.TrapWriter.Archive(fi.FullName, text.Encoding);
|
||||
}
|
||||
}
|
||||
|
||||
Context.Emit(Tuples.file_extraction_mode(this, Context.Extractor.Standalone ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
public override IId Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path == null ?
|
||||
new Key("GENERATED;sourcefile") :
|
||||
new Key(DatabasePath, ";sourcefile");
|
||||
}
|
||||
}
|
||||
|
||||
internal static string FileAsDatabaseString(string fileName)
|
||||
{
|
||||
fileName = fileName.Replace('\\', '/');
|
||||
if (fileName.Length > 1 && fileName[1] == ':')
|
||||
fileName = Char.ToUpper(fileName[0]) + fileName.Substring(1);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public static File Create(Context cx, string path) => FileFactory.Instance.CreateEntity(cx, path);
|
||||
|
||||
public static File CreateGenerated(Context cx) => GeneratedFile.Create(cx);
|
||||
|
||||
class GeneratedFile : File
|
||||
{
|
||||
GeneratedFile(Context cx)
|
||||
: base(cx, "") { }
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public override void Populate()
|
||||
{
|
||||
Context.Emit(Tuples.files(this, "", "", ""));
|
||||
}
|
||||
|
||||
public override IId Id => new Key("GENERATED;sourcefile");
|
||||
|
||||
public static GeneratedFile Create(Context cx) =>
|
||||
GeneratedFileFactory.Instance.CreateEntity(cx, null);
|
||||
|
||||
class GeneratedFileFactory : ICachedEntityFactory<string, GeneratedFile>
|
||||
{
|
||||
public static readonly GeneratedFileFactory Instance = new GeneratedFileFactory();
|
||||
|
||||
public GeneratedFile Create(Context cx, string init) => new GeneratedFile(cx);
|
||||
}
|
||||
}
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => null;
|
||||
|
||||
class FileFactory : ICachedEntityFactory<string, File>
|
||||
{
|
||||
public static readonly FileFactory Instance = new FileFactory();
|
||||
|
||||
public File Create(Context cx, string init) => new File(cx, init);
|
||||
}
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
|
||||
}
|
||||
}
|
||||
55
csharp/extractor/Semmle.Extraction/Entities/Folder.cs
Normal file
55
csharp/extractor/Semmle.Extraction/Entities/Folder.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.Entities
|
||||
{
|
||||
class Folder : CachedEntity<DirectoryInfo>
|
||||
{
|
||||
Folder(Context cx, DirectoryInfo init)
|
||||
: base(cx, init)
|
||||
{
|
||||
Path = init.FullName;
|
||||
}
|
||||
|
||||
public string Path
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string DatabasePath => File.FileAsDatabaseString(Path);
|
||||
|
||||
public override void Populate()
|
||||
{
|
||||
// Ensure that the name of the root directory is consistent
|
||||
// with the XmlTrapWriter.
|
||||
// Linux/Windows: java.io.File.getName() returns ""
|
||||
// On Linux: System.IO.DirectoryInfo.Name returns "/"
|
||||
// On Windows: System.IO.DirectoryInfo.Name returns "L:\"
|
||||
string shortName = symbol.Parent == null ? "" : symbol.Name;
|
||||
|
||||
Context.Emit(Tuples.folders(this, DatabasePath, shortName));
|
||||
if (symbol.Parent != null)
|
||||
{
|
||||
Context.Emit(Tuples.containerparent(Create(Context, symbol.Parent), this));
|
||||
}
|
||||
}
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public override IId Id => new Key(DatabasePath, ";folder");
|
||||
|
||||
public static Folder Create(Context cx, DirectoryInfo folder) =>
|
||||
FolderFactory.Instance.CreateEntity(cx, folder);
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => null;
|
||||
|
||||
class FolderFactory : ICachedEntityFactory<DirectoryInfo, Folder>
|
||||
{
|
||||
public static readonly FolderFactory Instance = new FolderFactory();
|
||||
|
||||
public Folder Create(Context cx, DirectoryInfo init) => new Folder(cx, init);
|
||||
}
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace Semmle.Extraction.Entities
|
||||
{
|
||||
public class GeneratedLocation : SourceLocation
|
||||
{
|
||||
readonly File GeneratedFile;
|
||||
|
||||
GeneratedLocation(Context cx)
|
||||
: base(cx, null)
|
||||
{
|
||||
GeneratedFile = File.CreateGenerated(cx);
|
||||
}
|
||||
|
||||
public override void Populate()
|
||||
{
|
||||
Context.Emit(Tuples.locations_default(this, GeneratedFile, 0, 0, 0, 0));
|
||||
}
|
||||
|
||||
public override IId Id => new Key("loc,", GeneratedFile, ",0,0,0,0");
|
||||
|
||||
public override int GetHashCode() => 98732567;
|
||||
|
||||
public override bool Equals(object obj) => obj != null && obj.GetType() == typeof(GeneratedLocation);
|
||||
|
||||
public static GeneratedLocation Create(Context cx) => GeneratedLocationFactory.Instance.CreateEntity(cx, null);
|
||||
|
||||
class GeneratedLocationFactory : ICachedEntityFactory<string, GeneratedLocation>
|
||||
{
|
||||
public static GeneratedLocationFactory Instance = new GeneratedLocationFactory();
|
||||
|
||||
public GeneratedLocation Create(Context cx, string init) => new GeneratedLocation(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
csharp/extractor/Semmle.Extraction/Entities/Location.cs
Normal file
30
csharp/extractor/Semmle.Extraction/Entities/Location.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
namespace Semmle.Extraction.Entities
|
||||
{
|
||||
public abstract class Location : CachedEntity<Microsoft.CodeAnalysis.Location>
|
||||
{
|
||||
public Location(Context cx, Microsoft.CodeAnalysis.Location init)
|
||||
: base(cx, init) { }
|
||||
|
||||
internal static Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) =>
|
||||
loc == null ? GeneratedLocation.Create(cx)
|
||||
: loc.IsInSource ? SourceLocation.Create(cx, loc)
|
||||
: Assembly.Create(cx, loc);
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => symbol;
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
|
||||
}
|
||||
|
||||
public static class LocationExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a Location entity.
|
||||
/// </summary>
|
||||
/// <param name="cx">The extraction context.</param>
|
||||
/// <param name="location">The CodeAnalysis location.</param>
|
||||
/// <returns>The Location entity.</returns>
|
||||
public static Location Create(this Context cx, Microsoft.CodeAnalysis.Location location) =>
|
||||
Location.Create(cx, location);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Semmle.Extraction.Entities
|
||||
{
|
||||
public class SourceLocation : Location
|
||||
{
|
||||
protected SourceLocation(Context cx, Microsoft.CodeAnalysis.Location init)
|
||||
: base(cx, init) { }
|
||||
|
||||
public new static Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) => SourceLocationFactory.Instance.CreateEntity(cx, loc);
|
||||
|
||||
public override void Populate()
|
||||
{
|
||||
Position = symbol.GetLineSpan();
|
||||
FileEntity = File.Create(Context, Position.Path);
|
||||
Context.Emit(Tuples.locations_default(this, FileEntity, Position.Span.Start.Line + 1, Position.Span.Start.Character + 1,
|
||||
Position.Span.End.Line + 1, Position.Span.End.Character));
|
||||
}
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public FileLinePositionSpan Position
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public File FileEntity
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public override IId Id
|
||||
{
|
||||
get
|
||||
{
|
||||
FileLinePositionSpan l = symbol.GetLineSpan();
|
||||
FileEntity = Entities.File.Create(Context, l.Path);
|
||||
return new Key("loc,", FileEntity, ",", l.Span.Start.Line + 1, ",",
|
||||
l.Span.Start.Character + 1, ",", l.Span.End.Line + 1, ",", l.Span.End.Character);
|
||||
}
|
||||
}
|
||||
|
||||
class SourceLocationFactory : ICachedEntityFactory<Microsoft.CodeAnalysis.Location, SourceLocation>
|
||||
{
|
||||
public static readonly SourceLocationFactory Instance = new SourceLocationFactory();
|
||||
|
||||
public SourceLocation Create(Context cx, Microsoft.CodeAnalysis.Location init) => new SourceLocation(cx, init);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user