diff --git a/distribution/ReleaseNotes.txt b/distribution/ReleaseNotes.txt index 1c2eb0846..d577c8b98 100644 --- a/distribution/ReleaseNotes.txt +++ b/distribution/ReleaseNotes.txt @@ -1,8 +1,8 @@ Release Notes planned as v0.13 -- In case of oscillations almost all effected components are shown. -- If an error occurs, the name of the affected file is shown. +- In case of oscillations almost all affected components are shown. +- If an error occurs, the name of the affected circuit file is shown. v0.12.1, released on 05. Jun 2016 - added a fuse to simulate a PROM or PAL. diff --git a/src/main/java/de/neemann/digital/core/ExceptionWithOrigin.java b/src/main/java/de/neemann/digital/core/ExceptionWithOrigin.java index c69296fbb..48ca34316 100644 --- a/src/main/java/de/neemann/digital/core/ExceptionWithOrigin.java +++ b/src/main/java/de/neemann/digital/core/ExceptionWithOrigin.java @@ -1,13 +1,15 @@ package de.neemann.digital.core; import java.io.File; +import java.util.HashSet; +import java.util.Set; /** - * A exception which has a file as an origin + * A exception which has a set of files as an origin. * Created by hneemann on 16.06.17. */ public class ExceptionWithOrigin extends Exception { - private File origin; + private Set origin; /** * Creates a new exception @@ -40,17 +42,46 @@ public class ExceptionWithOrigin extends Exception { /** * @return the origin of the error */ - public File getOrigin() { + public Set getOrigin() { return origin; } + /** + * @return the origin of the error as a string + */ + public String getOriginStr() { + Set orig = getOrigin(); + if (orig == null || orig.isEmpty()) + return null; + + StringBuilder sb = new StringBuilder(); + for (File o : orig) { + if (sb.length() > 0) sb.append(", "); + sb.append(o.getName()); + } + return sb.toString(); + } + /** * Sets the origin of an error * - * @param origin the file which causes the exception + * @param origin the file which had caused the exception */ public void setOrigin(File origin) { + if (getOrigin() == null) { + this.origin = new HashSet<>(); + this.origin.add(origin); + } + } + + /** + * Sets the origin of an error + * + * @param origin a set of file which had caused the exception + */ + public void setOrigin(Set origin) { if (getOrigin() == null) this.origin = origin; } + } diff --git a/src/main/java/de/neemann/digital/core/NodeException.java b/src/main/java/de/neemann/digital/core/NodeException.java index 67c49471f..b491c3d47 100644 --- a/src/main/java/de/neemann/digital/core/NodeException.java +++ b/src/main/java/de/neemann/digital/core/NodeException.java @@ -3,11 +3,11 @@ package de.neemann.digital.core; import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.element.ImmutableList; import de.neemann.digital.core.element.PinDescription; +import de.neemann.digital.lang.Lang; import java.io.File; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collection; +import java.util.*; /** * This exception is thrown if there was a problem creating or running the model. @@ -121,41 +121,72 @@ public class NodeException extends ExceptionWithOrigin { } private final static class ItemConcatenation { - private final StringBuilder sb; - private boolean open; + private final String message; + private final HashMap items; private ItemConcatenation(String message) { - this.sb = new StringBuilder(message); - open = false; + this.message = message; + items = new HashMap<>(); } private void addItem(String item) { - if (open) - sb.append(", "); - else { - sb.append(" ("); - open = true; - } - sb.append(item); + Item it = items.computeIfAbsent(item, Item::new); + it.incUsage(); } @Override public String toString() { - if (open) - sb.append(")"); - return sb.toString(); + if (items.isEmpty()) + return message; + + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (Item e : items.values()) { + if (first) + first = false; + else + sb.append(", "); + sb.append(e); + } + + return message + "\n" + Lang.get("msg_affectedComponentsAre_N", sb.toString()); + } + } + + private final static class Item { + private final String item; + private int usage; + + private Item(String item) { + this.item = item; + } + + private void incUsage() { + usage++; + } + + @Override + public String toString() { + if (usage == 1) + return item; + else + return usage + "*" + item; } } @Override - public File getOrigin() { - File o = super.getOrigin(); + public Set getOrigin() { + Set o = super.getOrigin(); if (o != null) return o; + HashSet originSet = null; for (Node n : nodes) - if (n.getOrigin() != null) - return n.getOrigin(); - return null; + if (n.getOrigin() != null) { + if (originSet == null) originSet = new HashSet<>(); + originSet.add(n.getOrigin()); + } + return originSet; } + } diff --git a/src/main/java/de/neemann/gui/ErrorMessage.java b/src/main/java/de/neemann/gui/ErrorMessage.java index 108aa8251..9b05d1765 100644 --- a/src/main/java/de/neemann/gui/ErrorMessage.java +++ b/src/main/java/de/neemann/gui/ErrorMessage.java @@ -5,7 +5,6 @@ import de.neemann.digital.lang.Lang; import javax.swing.*; import java.awt.*; -import java.io.File; /** * Used to show error messages. @@ -47,12 +46,11 @@ public class ErrorMessage implements Runnable { message.append('\n'); addExceptionMessage(e); - if (e instanceof ExceptionWithOrigin) { - File o = ((ExceptionWithOrigin) e).getOrigin(); - if (o!=null) { - if (message.length() > 0) - message.append('\n'); - message.append(Lang.get("msg_errInFile_N", o.getName())); + if (e instanceof ExceptionWithOrigin) { + String orig = ((ExceptionWithOrigin) e).getOriginStr(); + if (orig != null) { + if (message.length() > 0) message.append('\n'); + message.append(Lang.get("msg_errInFile_N", orig)); } } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index d4c283aef..652194712 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -121,7 +121,7 @@ Es kann dann ein Programm bis zum nächsten BRK-Befehl ausgeführt werden.Setzt den Zähler auf 0 zurück wenn dieser Eingang auf 1 gesetzt wird. Overflow Ausgang. Hat der Zähler das Maximum erreicht, wird dieser Ausgang für eine Taktdauer 1. Gibt den gezählten Wert aus. - D-FlipFLop + D-FlipFlop D Ein Baustein zum Speichern eines Bits. Der an Eingang D anliegende Wert wird abgespeichert wenn Eingang C auf 1 wechselt. Das zu speichernde Bit. @@ -185,7 +185,7 @@ Es können sowohl komplette Takte als auch einzelne Gatter-Veränderungen angeze asynchrones setzen asynchrones löschen - D-FlipFLop, asynchron + D-FlipFlop, asynchron D-AS Ein Baustein zum Speichern eines Bits. Der an Eingang D anliegende Wert wird abgespeichert wenn Eingang C auf 1 wechselt. Das zu speichernde Bit. @@ -914,7 +914,8 @@ Die Icons stammen aus dem Tango Desktop Project. Zu invertierende Eingänge keine Die Namen der Pins konnten nicht ermittelt werden. - Aufgetreten in Datei {0}! + Aufgetreten in Datei {0}. + Betroffen sind: {0}. Ok diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 7c211b1b5..d09fe47c3 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -901,7 +901,8 @@ The icons are taken from the Tango Desktop Project. Inputs to invert none Could not determine the names of the pins. - Occurred in file {0}! + Occurred in file {0}. + Affected are: {0}. Ok