/// <summary> /// Populates an entity, handling the tag stack appropriately /// </summary> /// <param name="optionalSymbol">Symbol for reporting errors.</param> /// <param name="entity">The entity to populate.</param> /// <exception cref="InternalError">Thrown on invalid trap stack behaviour.</exception> private void Populate(ISymbol?optionalSymbol, CachedEntity entity) { if (writingLabel) { // Don't write tuples etc if we're currently defining a label PopulateLater(() => Populate(optionalSymbol, entity)); return; } bool duplicationGuard; bool deferred; switch (entity.TrapStackBehaviour) { case TrapStackBehaviour.NeedsLabel: if (!tagStack.Any()) { ExtractionError("TagStack unexpectedly empty", optionalSymbol, entity); } duplicationGuard = false; deferred = false; break; case TrapStackBehaviour.NoLabel: duplicationGuard = false; deferred = tagStack.Any(); break; case TrapStackBehaviour.OptionalLabel: duplicationGuard = false; deferred = false; break; case TrapStackBehaviour.PushesLabel: duplicationGuard = true; deferred = tagStack.Any(); break; default: throw new InternalError("Unexpected TrapStackBehaviour"); } var a = duplicationGuard && IsEntityDuplicationGuarded(entity, out var loc) ? (Action)(() => WithDuplicationGuard(new Key(entity, loc), () => entity.Populate(TrapWriter.Writer))) : (Action)(() => this.Try(null, optionalSymbol, () => entity.Populate(TrapWriter.Writer))); if (deferred) { populateQueue.Enqueue(a); } else { a(); } }
private void CheckEntityHasUniqueLabel(string id, CachedEntity entity) { if (idLabelCache.ContainsKey(id)) { this.Extractor.Message(new Message("Label collision for " + id, entity.Label.ToString(), CreateLocation(entity.ReportingLocation), "", Severity.Warning)); } else { idLabelCache[id] = entity; } }