using Microsoft.CodeAnalysis; using System.Linq; namespace Semmle.Extraction { /// /// Defines which entities belong in the trap file /// for the currently extracted entity. This is used to ensure that /// trap files do not contain redundant information. Generally a symbol /// should have an affinity with exactly one trap file, except for constructed /// symbols. /// public interface IExtractionScope { /// /// Whether the given symbol belongs in the trap file. /// /// The symbol to populate. bool InScope(ISymbol symbol); /// /// Whether the given file belongs in the trap file. /// /// The path to populate. bool InFileScope(string path); bool IsGlobalScope { get; } bool FromSource { get; } } /// /// The scope of symbols in an assembly. /// public class AssemblyScope : IExtractionScope { private readonly IAssemblySymbol assembly; private readonly string filepath; public AssemblyScope(IAssemblySymbol symbol, string path, bool isOutput) { assembly = symbol; filepath = path; IsGlobalScope = isOutput; } public bool IsGlobalScope { get; } public bool InFileScope(string path) => path == filepath; public bool InScope(ISymbol symbol) => SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, assembly) || SymbolEqualityComparer.Default.Equals(symbol, assembly); public bool FromSource => false; } /// /// The scope of symbols in a source file. /// public class SourceScope : IExtractionScope { private readonly SyntaxTree sourceTree; public SourceScope(SyntaxTree tree) { sourceTree = tree; } public bool IsGlobalScope => false; public bool InFileScope(string path) => path == sourceTree.FilePath; public bool InScope(ISymbol symbol) => symbol.Locations.Any(loc => loc.SourceTree == sourceTree); public bool FromSource => true; } }