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();
}
}