using System; using System.Collections.Generic; namespace Semmle.Extraction.CIL { /// /// Something that is extracted from an entity. /// /// /// /// The extraction algorithm proceeds as follows: /// - Construct entity /// - Call Extract() /// - ILabelledEntity check if already extracted /// - Enumerate Contents to produce more extraction products /// - Extract these until there is nothing left to extract /// public interface IExtractionProduct { /// /// Perform further extraction/population of this item as necessary. /// /// /// The extraction context. void Extract(Context cx); } /// /// An entity which has been extracted. /// public interface IExtractedEntity : IEntity, IExtractionProduct { /// /// The contents of the entity. /// IEnumerable Contents { get; } } /// /// An entity that has contents to extract. There is no need to populate /// a key as it's done in the contructor. /// public abstract class UnlabelledEntity : IExtractedEntity { public abstract IEnumerable Contents { get; } public Label Label { get; set; } public Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException(); public virtual IId Id => FreshId.Instance; public virtual void Extract(Context cx2) { cx2.Extract(this); } public readonly Context cx; protected UnlabelledEntity(Context cx) { this.cx = cx; cx.cx.AddFreshLabel(this); } TrapStackBehaviour IEntity.TrapStackBehaviour => TrapStackBehaviour.NoLabel; } /// /// An entity that needs to be populated during extraction. /// This assigns a key and optionally extracts its contents. /// public abstract class LabelledEntity : ILabelledEntity { public abstract IEnumerable Contents { get; } public Label Label { get; set; } public Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException(); public Id ShortId { get; set; } public abstract Id IdSuffix { get; } public IId Id => ShortId + IdSuffix; public void Extract(Context cx2) { cx2.Populate(this); } public readonly Context cx; protected LabelledEntity(Context cx) { this.cx = cx; } public override string ToString() => Id.ToString(); TrapStackBehaviour IEntity.TrapStackBehaviour => TrapStackBehaviour.NoLabel; } /// /// An entity with a defined ID. /// public interface ILabelledEntity : IExtractedEntity { Id ShortId { get; set; } Id IdSuffix { get; } } /// /// A tuple that is an extraction product. /// class Tuple : IExtractionProduct { readonly Extraction.Tuple tuple; public Tuple(string name, params object[] args) { tuple = new Extraction.Tuple(name, args); } public void Extract(Context cx) { cx.cx.Emit(tuple); } public override string ToString() => tuple.ToString(); } }