mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
136 lines
4.6 KiB
C#
136 lines
4.6 KiB
C#
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 => PathAsDatabaseId(Path);
|
|
|
|
public override bool NeedsPopulation => Context.DefinesFile(Path) || Path == Context.Extractor.OutputPath;
|
|
|
|
public override void Populate()
|
|
{
|
|
if (Path == null)
|
|
{
|
|
Context.TrapWriter.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.TrapWriter.files(this, PathAsDatabaseString(Path), name, extension);
|
|
|
|
Context.TrapWriter.containerparent(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.TrapWriter.numlines(this, lineCounts);
|
|
Context.TrapWriter.Archive(fi.FullName, text.Encoding);
|
|
}
|
|
}
|
|
|
|
Context.TrapWriter.file_extraction_mode(this, Context.Extractor.Standalone ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
public override void WriteId(System.IO.TextWriter trapFile)
|
|
{
|
|
if (Path is null)
|
|
trapFile.Write("GENERATED;sourcefile");
|
|
else
|
|
{
|
|
trapFile.Write(DatabasePath);
|
|
trapFile.Write(";sourcefile");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a path string into a string to use as an ID
|
|
/// in the QL database.
|
|
/// </summary>
|
|
/// <param name="path">An absolute path.</param>
|
|
/// <returns>The database ID.</returns>
|
|
public static string PathAsDatabaseId(string path)
|
|
{
|
|
if (path.Length >= 2 && path[1] == ':' && Char.IsLower(path[0]))
|
|
path = Char.ToUpper(path[0]) + "_" + path.Substring(2);
|
|
return path.Replace('\\', '/').Replace(":", "_");
|
|
}
|
|
|
|
public static string PathAsDatabaseString(string path) => path.Replace('\\', '/');
|
|
|
|
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.TrapWriter.files(this, "", "", "");
|
|
}
|
|
|
|
public override void WriteId(TextWriter trapFile)
|
|
{
|
|
trapFile.Write("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;
|
|
}
|
|
}
|