From 0224ff19d0ca3c2b76dd771ebaa0caeec9085042 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Tue, 23 Jan 2024 16:25:23 +0100 Subject: [PATCH] Update for error/warning messages --- Signed-off-by: Peter Kriens Signed-off-by: Peter Kriens --- .../src/aQute/service/reporter/Report.java | 11 + .../src/aQute/service/reporter/packageinfo | 2 +- .../test/aQute/bnd/main/TestBndMainBase.java | 58 +++- .../test/test/MacroTest.java | 36 +-- .../src/aQute/bnd/osgi/MessageReporter.java | 272 +++++++++++++++++ .../src/aQute/bnd/osgi/Processor.java | 281 +++++------------- 6 files changed, 403 insertions(+), 257 deletions(-) create mode 100644 biz.aQute.bndlib/src/aQute/bnd/osgi/MessageReporter.java diff --git a/aQute.libg/src/aQute/service/reporter/Report.java b/aQute.libg/src/aQute/service/reporter/Report.java index db5cd772f2..fb85297c53 100644 --- a/aQute.libg/src/aQute/service/reporter/Report.java +++ b/aQute.libg/src/aQute/service/reporter/Report.java @@ -35,6 +35,17 @@ public Location dup() { l.length = length; return l; } + + public void to(Location l) { + l.message = message; + l.line = line; + l.file = file; + l.context = context; + l.reference = reference; + l.methodName = methodName; + l.details = details; + l.length = length; + } } /** diff --git a/aQute.libg/src/aQute/service/reporter/packageinfo b/aQute.libg/src/aQute/service/reporter/packageinfo index 897578ff5b..71cb8980c7 100644 --- a/aQute.libg/src/aQute/service/reporter/packageinfo +++ b/aQute.libg/src/aQute/service/reporter/packageinfo @@ -1 +1 @@ -version 1.2.0 +version 1.3.0 diff --git a/biz.aQute.bnd/test/aQute/bnd/main/TestBndMainBase.java b/biz.aQute.bnd/test/aQute/bnd/main/TestBndMainBase.java index a12a71cb8a..006a6f19d1 100644 --- a/biz.aQute.bnd/test/aQute/bnd/main/TestBndMainBase.java +++ b/biz.aQute.bnd/test/aQute/bnd/main/TestBndMainBase.java @@ -1,5 +1,7 @@ package aQute.bnd.main; +import static aQute.libg.re.Catalog.caseInsenstive; +import static aQute.libg.re.Catalog.lit; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -8,6 +10,8 @@ import java.io.PrintStream; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; @@ -20,11 +24,11 @@ import aQute.bnd.main.testrules.WatchedTemporaryFolder; import aQute.bnd.osgi.About; import aQute.bnd.osgi.Jar; +import aQute.lib.strings.Strings; +import aQute.libg.re.RE; public class TestBndMainBase { - private static final String WARNING_LINE = "(?m)^WARNING: .*$"; - @Rule public WatchedFolder folder = new WatchedTemporaryFolder(); @@ -130,26 +134,52 @@ protected void expectErrorContainsPattern(String regex) { .containsPattern(regex); } + final static RE WARNINGS_P = caseInsenstive(lit("Warnings")); + final static RE ERRORS_P = caseInsenstive(lit("Errors")); + final static RE SEPARATOR_P = caseInsenstive(lit("-------")); + protected void expectNoError(boolean ignoreWarnings, String... expects) { String errors = capturedStdIO.getSystemErrContent(); + List lines = Strings.split("\\R", errors); + boolean skip = false; + line: for (Iterator it = lines.iterator(); it.hasNext();) { + String line = it.next(); + if (Strings.nonNullOrEmpty(Strings.trim(line))) { + it.remove(); + continue; + } - if (ignoreWarnings) { - errors = errors.replaceAll(WARNING_LINE, "") - .trim(); - } - if (expects != null) { - for (String expect : expects) { - assertThat(capturedStdIO.getSystemErrContent()).as("missing error") - .contains(expect); - errors = errors.replaceAll(expect, "") - .trim(); + if (SEPARATOR_P.lookingAt(line) + .isPresent()) { + it.remove(); + continue; + } + if (WARNINGS_P.lookingAt(line) + .isPresent()) { + skip = ignoreWarnings; + it.remove(); + continue; + } else if (ERRORS_P.lookingAt(line) + .isPresent()) { + skip = false; + it.remove(); + continue; + } + if (expects != null) { + for (String expect : expects) { + if (skip) + continue line; + skip = line.contains(expect); + } } + if (skip) + it.remove(); } - assertEquals("non-empty error output", "", errors); + assertThat(lines).isEmpty(); } protected void expectNoError() { - expectNoError(false); + expectNoError(true); } protected void expectJarEntry(Jar jar, String path) { diff --git a/biz.aQute.bndlib.tests/test/test/MacroTest.java b/biz.aQute.bndlib.tests/test/test/MacroTest.java index 4e9ba08a59..d51e767d8f 100644 --- a/biz.aQute.bndlib.tests/test/test/MacroTest.java +++ b/biz.aQute.bndlib.tests/test/test/MacroTest.java @@ -1276,7 +1276,7 @@ public void testRandom() { @Test public void testSuper() { try (Processor top = new Processor(); - Processor middle = new Processor(top); + Processor middle = new Processor(top); Processor bottom = new Processor(middle)) { top.setProperty("a", "top.a"); @@ -1770,35 +1770,13 @@ public void testWarning() { p.setProperty("real", "true"); Macro m = new Macro(p); - m.process(" ${warning;xw;1;2;3 ${three}}"); - m.process(" ${error;xe;1;2;3 ${three}}"); + m.process(" ${warning;xw;w1;w2;w3 w${three}}"); + m.process(" ${error;xe;e1;e2;e3 e${three}}"); m.process(" ${if;1;$}"); - assertTrue(p.getWarnings() - .get(0) - .endsWith("xw"), "xw"); - assertTrue(p.getWarnings() - .get(1) - .endsWith("1"), "1"); - assertTrue(p.getWarnings() - .get(2) - .endsWith("2"), "2"); - assertTrue(p.getWarnings() - .get(3) - .endsWith("3 333"), "3 333"); - - assertTrue(p.getErrors() - .get(0) - .endsWith("xe"), "xw"); - assertTrue(p.getErrors() - .get(1) - .endsWith("1"), "1"); - assertTrue(p.getErrors() - .get(2) - .endsWith("2"), "2"); - assertTrue(p.getErrors() - .get(3) - .endsWith("3 333"), "3 333"); + assertThat(p.getWarnings()).containsExactly("xw", "w1", "w2", "w3 w333", + "No translation found for macro: a"); + assertThat(p.getErrors()).containsExactly("xe", "e1", "e2", "e3 e333"); } catch (IOException e) { fail(e); } @@ -1919,7 +1897,7 @@ public void testJoin() { assertEquals("aa\nbb\ncc\ndd\nee\nff", m.process("${unescape;${sjoin;\\n;aa,bb,cc;dd,ee,ff}}")); } catch (IOException e) { fail(e); - } + } } @Test diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/MessageReporter.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/MessageReporter.java new file mode 100644 index 0000000000..b4c5ae794c --- /dev/null +++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/MessageReporter.java @@ -0,0 +1,272 @@ +package aQute.bnd.osgi; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import aQute.bnd.exceptions.Exceptions; +import aQute.bnd.header.Attrs; +import aQute.bnd.header.Parameters; +import aQute.service.reporter.Report.Location; +import aQute.service.reporter.Reporter; +import aQute.service.reporter.Reporter.SetLocation; + +/** + * This is the error and warning messages collected. It implements a concurrent + * message handling system. + */ +public class MessageReporter { + + final Processor processor; + final AtomicInteger counter = new AtomicInteger(1000); + volatile ConcurrentHashMap messages = new ConcurrentHashMap<>(); + + class Message extends Location implements SetLocation, Comparable { + @Override + public String toString() { + return "Message [error=" + error + ", sequence=" + sequence + ", message=" + message + "]"; + } + + final boolean error; + final int sequence; + final String message; + + Message(int sequence, String message, boolean error) { + this.sequence = sequence; + this.message = message; + this.error = error; + } + + Message(int sequence, Message m, String actualPrefix) { + this.sequence = sequence; + this.message = actualPrefix.concat(m.message); + this.error = m.error; + m.to(this); + } + + @Override + public SetLocation file(String file) { + this.file = file; + return this; + } + + @Override + public SetLocation header(String header) { + this.header = header; + return this; + } + + @Override + public SetLocation context(String context) { + this.context = context; + return this; + } + + @Override + public SetLocation method(String methodName) { + this.methodName = methodName; + return this; + } + + @Override + public SetLocation line(int n) { + this.line = n; + return this; + } + + @Override + public SetLocation reference(String reference) { + this.reference = reference; + return this; + } + + @Override + public SetLocation details(Object details) { + this.details = details; + return null; + } + + @Override + public Location location() { + return this; + } + + @Override + public SetLocation length(int length) { + this.length = length; + return this; + } + + @Override + public int compareTo(Message o) { + return Integer.compare(sequence, o.sequence); + } + + void fixup(Instructions fixupInstrs, List errors, List warnings) { + + boolean error = this.error; + + Instruction matcher = fixupInstrs.finder(message); + String type = error ? Constants.FIXUPMESSAGES_IS_ERROR : Constants.FIXUPMESSAGES_IS_WARNING; + String message = this.message; + + if (matcher != null && !matcher.isNegated()) { + + Attrs attrs = fixupInstrs.get(matcher); + String restrict = attrs.get(Constants.FIXUPMESSAGES_RESTRICT_DIRECTIVE); + String replace = attrs.get(Constants.FIXUPMESSAGES_REPLACE_DIRECTIVE); + String is = attrs.get(Constants.FIXUPMESSAGES_IS_DIRECTIVE); + + if (restrict == null || restrict.equals(type)) { + + if (is != null && !is.equals(type)) { + error = !error; + } + + if (replace != null) { + try (Processor replacer = new Processor(processor())) { + replacer.setProperty("@", message); + processor().getLogger() + .debug("replacing {} with {}", message, replace); + message = replacer.getReplacer() + .process(replace); + } catch (Exception e) { + throw Exceptions.duck(e); + } + } + + if (attrs.isEmpty() || Constants.FIXUPMESSAGES_IS_IGNORE.equals(is)) { + message = null; + } + } + } + if (message != null) { + if (error) + errors.add(message); + else + warnings.add(message); + } + } + + + } + + class Cache { + final List errors = new ArrayList<>(); + final List warnings = new ArrayList<>(); + + Cache() { + boolean failOk = processor().isFailOk(); + Instructions fixupInstrs = new Instructions(); + Parameters fixup = processor().getMergedParameters(Constants.FIXUPMESSAGES); + fixup.forEach((k, v) -> fixupInstrs.put(Instruction.legacy(k), v)); + + messages.values() + .stream() + .sorted() + .forEach(m -> { + m.fixup(fixupInstrs, failOk ? warnings : errors, warnings); + }); + } + } + + MessageReporter(Processor processor) { + this.processor = processor; + } + + List getWarnings() { + return fixup().warnings; + } + + List getErrors() { + return fixup().errors; + } + + Cache fixup() { + return new Cache(); + } + + Location getLocation(String msg) { + return messages.get(msg); + } + + public SetLocation error(String format, Object... args) { + try { + for (int i = 0; i < args.length; i++) { + if (args[i] instanceof Throwable t) { + args[i] = Exceptions.causes(t); + } + } + String s = Processor.formatArrays(format, args); + Message m = new Message(counter.getAndIncrement(), s, true); + messages.putIfAbsent(s, m); + return m; + } finally { + processor().signal(); + } + } + + SetLocation warning(String format, Object... args) { + String s = Processor.formatArrays(format, args); + Message m = new Message(counter.getAndIncrement(), s, false); + messages.putIfAbsent(s, m); + return m; + } + + void getInfo(Reporter from, String prefix) { + String actualPrefix = prefix == null ? prefix = processor().getBase() + " :" : prefix; + + MessageReporter other; + if (from instanceof Processor processor) { + other = processor.reporter; + } else if (from instanceof MessageReporter mr) { + other = mr; + } else { + // backward compatible reporters + addAll(true, prefix, from); + addAll(false, prefix, from); + from.getErrors() + .clear(); + from.getWarnings() + .clear(); + return; + } + + ConcurrentHashMap older = other.clear(); + older.values() + .stream() + .sorted() + .map(m -> new Message(counter.getAndIncrement(), m, actualPrefix)) + .forEach(m -> { + messages.putIfAbsent(m.message, m); + }); + } + + /* + * for backward compatible reporters + */ + void addAll(boolean error, String prefix, Reporter reporter) { + for (String message : new ArrayList<>(error ? reporter.getErrors() : reporter.getWarnings())) { + String newMessage = prefix.isEmpty() ? message : prefix.concat(message); + Message m = new Message(counter.getAndIncrement(), newMessage, error); + Location location = reporter.getLocation(message); + if (location != null) + location.to(m); + } + } + + ConcurrentHashMap clear() { + ConcurrentHashMap previous = messages; + messages = new ConcurrentHashMap<>(); + return previous; + } + + Processor processor() { + return this.processor.current(); + } + + Message remove(String message) { + return messages.remove(message); + } +} diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java index 6177465093..e1cb7ec05b 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java +++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java @@ -12,7 +12,6 @@ import java.io.OutputStream; import java.io.PrintStream; import java.lang.reflect.Array; -import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URI; @@ -110,8 +109,6 @@ public class Processor extends Domain implements Reporter, Registry, Constants, public final static String LIST_SPLITTER = "\\s*,\\s*"; final ThreadLocal bracket = new ThreadLocal<>(); - final List errors = new ArrayList<>(); - final List warnings = new ArrayList<>(); private final Set basicPlugins = Collections .newSetFromMap(new ConcurrentHashMap<>()); private final Set toBeClosed = Collections @@ -120,9 +117,7 @@ public class Processor extends Domain implements Reporter, Registry, Constants, private volatile CloseableMemoize pluginLoader = newPluginLoader(); private volatile Memoize pluginsContainer = newPluginsContainer(); - boolean pedantic; - boolean trace; - boolean exceptions; + final MessageReporter reporter = new MessageReporter(this); boolean fileMustExist = true; private File base = new File("").getAbsoluteFile(); @@ -139,7 +134,9 @@ public class Processor extends Domain implements Reporter, Registry, Constants, Collection filter; Boolean strict; - boolean fixupMessages; + boolean trace; + boolean pedantic; + boolean exceptions; public static class FileLine { public static final FileLine DUMMY = new FileLine(null, 0, 0); @@ -210,92 +207,33 @@ public Processor getTop() { } public void getInfo(Reporter processor, String prefix) { - if (prefix == null) - prefix = getBase() + " :"; - if (isFailOk()) - addAll(warnings, processor.getErrors(), prefix, processor); - else - addAll(errors, processor.getErrors(), prefix, processor); - addAll(warnings, processor.getWarnings(), prefix, processor); - - processor.getErrors() - .clear(); - processor.getWarnings() - .clear(); - + reporter.getInfo(processor, prefix); } public void getInfo(Reporter processor) { getInfo(processor, ""); } - private void addAll(List to, List from, String prefix, Reporter reporter) { - try { - for (String message : from) { - String newMessage = prefix.isEmpty() ? message : prefix + message; - to.add(newMessage); - - Location location = reporter.getLocation(message); - if (location != null) { - SetLocation newer = location(newMessage); - for (Field f : newer.getClass() - .getFields()) { - if (!"message".equals(f.getName())) { - f.set(newer, f.get(location)); - } - } - } - } - } catch (Exception e) { - throw Exceptions.duck(e); - } - } - /** * A processor can mark itself current for a thread. */ - private Processor current() { + Processor current() { Processor p = current.get(); if (p == null) return this; return p; } + @SuppressWarnings("resource") @Override public SetLocation warning(String string, Object... args) { - fixupMessages = false; - Processor p = current(); - String s = formatArrays(string, args); - if (!p.warnings.contains(s)) - p.warnings.add(s); - p.signal(); - return p.location(s); + return current().reporter.warning(string, args); } + @SuppressWarnings("resource") @Override public SetLocation error(String string, Object... args) { - fixupMessages = false; - Processor p = current(); - try { - - // - // Make Throwables into a string that shows their causes - // - - for (int i = 0; i < args.length; i++) { - if (args[i] instanceof Throwable t) { - args[i] = Exceptions.causes(t); - } - } - if (p.isFailOk()) - return p.warning(string, args); - String s = formatArrays(string, args); - if (!p.errors.contains(s)) - p.errors.add(s); - return p.location(s); - } finally { - p.signal(); - } + return current().reporter.error(string, args); } /** @@ -335,15 +273,13 @@ public SetLocation exception(Throwable t, String format, Object... args) { if (p.exceptions) { printExceptionSummary(t, System.err); } - // unroll InvocationTargetException + t = Exceptions.unrollCause(t, InvocationTargetException.class); + String s = formatArrays("Exception: %s", Exceptions.toString(t)); - if (p.isFailOk()) { - p.warnings.add(s); - } else { - p.errors.add(s); - } - return error(format, args); + reporter.error(s); + + return reporter.error(format, args); } public int printExceptionSummary(Throwable e, PrintStream out) { @@ -374,14 +310,12 @@ public void signal() {} @Override public List getWarnings() { - fixupMessages(); - return warnings; + return reporter.getWarnings(); } @Override public List getErrors() { - fixupMessages(); - return errors; + return reporter.getErrors(); } /** @@ -407,16 +341,6 @@ public void removeClose(AutoCloseable closeable) { toBeClosed.remove(closeable); } - @Override - public boolean isPedantic() { - Processor p = current(); - return p.pedantic; - } - - public void setPedantic(boolean pedantic) { - this.pedantic = pedantic; - } - public void use(Processor reporter) { setPedantic(reporter.isPedantic()); setTrace(reporter.isTrace()); @@ -566,10 +490,7 @@ public void setBase(File base) { } public void clear() { - errors.clear(); - warnings.clear(); - locations.clear(); - fixupMessages = false; + reporter.clear(); } public Logger getLogger() { @@ -581,7 +502,6 @@ public Logger getLogger() { */ @Override public void trace(String msg, Object... parms) { - Processor p = current(); if (p.trace) { String s = formatArrays(msg, parms); @@ -703,7 +623,6 @@ public Properties getProperties() { fixup = false; begin(); } - fixupMessages = false; return getProperties0(); } @@ -1408,14 +1327,6 @@ public static String merge(String... strings) { return join(result); } - public boolean isExceptions() { - return exceptions; - } - - public void setExceptions(boolean exceptions) { - this.exceptions = exceptions; - } - /** * Make the file short if it is inside our base directory, otherwise long. * @@ -1447,10 +1358,6 @@ public static boolean isDuplicate(String key) { return key.indexOf(DUPLICATE_MARKER, key.length() - 1) >= 0; } - public void setTrace(boolean x) { - trace = x; - } - public static class CL extends ActivelyClosingClassLoader { static { ClassLoader.registerAsParallelCapable(); @@ -1500,91 +1407,31 @@ public boolean isOk() { return isFailOk() || getErrors().isEmpty(); } - /** - * Move errors and warnings to their proper place by scanning the fixup - * messages property. - */ - private void fixupMessages() { - if (fixupMessages) - return; - fixupMessages = true; - Parameters fixup = getMergedParameters(Constants.FIXUPMESSAGES); - if (fixup.isEmpty()) - return; - - Instructions instrs = new Instructions(); - fixup.forEach((k, v) -> instrs.put(Instruction.legacy(k), v)); - - doFixup(instrs, errors, warnings, FIXUPMESSAGES_IS_ERROR); - doFixup(instrs, warnings, errors, FIXUPMESSAGES_IS_WARNING); - } - - private void doFixup(Instructions instrs, List messages, List other, String type) { - for (int i = 0; i < messages.size(); i++) { - String message = messages.get(i); - Instruction matcher = instrs.finder(message); - if (matcher == null || matcher.isNegated()) - continue; - - Attrs attrs = instrs.get(matcher); - - // - // Default the pattern applies to the errors and warnings - // but we can restrict it: e.g. restrict:=error - // - - String restrict = attrs.get(FIXUPMESSAGES_RESTRICT_DIRECTIVE); - if (restrict != null && !restrict.equals(type)) - continue; - - // - // We can optionally replace the message with another text. E.g. - // replace:"hello world". This can use macro expansion, the ${@} - // macro is set to the old message. - // - String replace = attrs.get(FIXUPMESSAGES_REPLACE_DIRECTIVE); - if (replace != null) { - logger.debug("replacing {} with {}", message, replace); - setProperty("@", message); - message = getReplacer().process(replace); - messages.set(i, message); - unsetProperty("@"); - } - - // - // - String is = attrs.get(FIXUPMESSAGES_IS_DIRECTIVE); - - if (attrs.isEmpty() || FIXUPMESSAGES_IS_IGNORE.equals(is)) { - messages.remove(i--); - } else { - if (is != null && !type.equals(is)) { - messages.remove(i--); - other.add(message); - } - } - } - } - public boolean check(String... pattern) throws IOException { Set missed = Create.set(); + List errors = getErrors(); + List warnings = getWarnings(); if (pattern != null) { for (String p : pattern) { boolean match = false; Pattern pat = Pattern.compile(p); for (Iterator i = errors.iterator(); i.hasNext();) { - if (pat.matcher(i.next()) + String next = i.next(); + if (pat.matcher(next) .find()) { i.remove(); match = true; + reporter.remove(next); } } for (Iterator i = warnings.iterator(); i.hasNext();) { - if (pat.matcher(i.next()) + String next = i.next(); + if (pat.matcher(next) .find()) { i.remove(); match = true; + reporter.remove(next); } } if (!match) @@ -1592,7 +1439,7 @@ public boolean check(String... pattern) throws IOException { } } - if (missed.isEmpty() && isPerfect()) + if (missed.isEmpty() && errors.isEmpty() && warnings.isEmpty()) return true; if (!missed.isEmpty()) @@ -1603,6 +1450,9 @@ public boolean check(String... pattern) throws IOException { } protected void report(Appendable out) throws IOException { + List errors = getErrors(); + List warnings = getWarnings(); + if (errors.size() > 0) { out.append(String.format("-----------------%nErrors%n")); for (int i = 0; i < errors.size(); i++) { @@ -1760,11 +1610,6 @@ public synchronized Class getClass(String type, File jar) throws Exception { return cl.loadClass(type); } - public boolean isTrace() { - Processor p = current(); - return p.trace; - } - private static final Pattern DURATION_P = Pattern .compile("\\s*(\\d+)\\s*(NANOSECONDS|MICROSECONDS|MILLISECONDS|SECONDS|MINUTES|HOURS|DAYS)?"); @@ -1984,11 +1829,6 @@ public String replaceExtension(String s, String extension, String newExtension) return s + newExtension; } - /** - * Create a location object and add it to the locations - */ - List locations = new ArrayList<>(); - static class SetLocationImpl extends Location implements SetLocation { public SetLocationImpl(String s) { this.message = s; @@ -2064,20 +1904,9 @@ public SetLocation setLocation(String header, String clause, SetLocation setLoca return setLocation; } - private SetLocation location(String s) { - SetLocationImpl loc = new SetLocationImpl(s); - locations.add(loc); - return loc; - } - @Override public Location getLocation(String msg) { - assert msg != null : "Must provide message"; - for (Location l : locations) - if ((l.message != null) && msg.equals(l.message)) - return l; - - return null; + return reporter.getLocation(msg); } /** @@ -2232,8 +2061,7 @@ public static int getLine(String s, int index) { * not set, we assume the latest version. */ - Version upto = null; - + Version upto = null; public boolean since(Version introduced) { if (upto == null) { String uptov = getProperty(UPTO); @@ -2389,15 +2217,6 @@ public String _thisfile(String[] args) { return IO.absolutePath(propertiesFile); } - /** - * Copy the settings of another processor - */ - public void getSettings(Processor p) { - this.trace = p.isTrace(); - this.pedantic = p.isPedantic(); - this.exceptions = p.isExceptions(); - } - static final String _frangeHelp = "${frange;[;true|false]}"; /** @@ -2755,4 +2574,40 @@ private void runit(RunnableWithException r) { exception(e, "failed to run a runnable at the end of a bracket: %s", e.getMessage()); } } + + /** + * Copy the settings of another processor + */ + public void getSettings(Processor p) { + this.trace = p.isTrace(); + this.pedantic = p.isPedantic(); + this.exceptions = p.isExceptions(); + } + + public boolean isExceptions() { + return this.exceptions; + } + + public void setExceptions(boolean exceptions) { + this.exceptions = exceptions; + } + + public void setTrace(boolean x) { + trace = x; + } + + public boolean isTrace() { + Processor p = current(); + return p.trace; + } + + @Override + public boolean isPedantic() { + return this.pedantic; + } + + public void setPedantic(boolean pedantic) { + this.pedantic = pedantic; + } + }