Adapting ProblemReport.build to use a sublogger for child messages (e.g. the subtypes tried for an instantiable type). Review by: spoon git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5269 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/rebind/rpc/ProblemReport.java b/user/src/com/google/gwt/user/rebind/rpc/ProblemReport.java index 56b000b..848fc8d 100644 --- a/user/src/com/google/gwt/user/rebind/rpc/ProblemReport.java +++ b/user/src/com/google/gwt/user/rebind/rpc/ProblemReport.java
@@ -44,9 +44,43 @@ */ public enum Priority { FATAL, DEFAULT, AUXILIARY} - private Map<JClassType, List<String>> allProblems; - private Map<JClassType, List<String>> auxiliaries; - private Map<JClassType, List<String>> fatalProblems; + /** + * An individual report, which may require multiple entries (expressed as + * logs under a branchpoint), but relates to an individual issue. + */ + public class Problem { + private String message; + private List<String> childMessages; + + private Problem(String message, String[] children) { + this.message = message; + // most problems don't have sub-messages, so init at zero size + childMessages = new ArrayList<String>(children.length); + for (int i = 0; i < children.length; i++) { + childMessages.add(children[i]); + } + } + + public void addChild(String message) { + childMessages.add(message); + } + + public String getPrimaryMessage() { + return message; + } + + public Iterable<String> getSubMessages() { + return childMessages; + } + + public boolean hasSubMessages() { + return !childMessages.isEmpty(); + } + } + + private Map<JClassType, List<Problem>> allProblems; + private Map<JClassType, List<Problem>> auxiliaries; + private Map<JClassType, List<Problem>> fatalProblems; private JClassType contextType; /** @@ -61,9 +95,9 @@ o2.getParameterizedQualifiedSourceName()); } }; - allProblems = new TreeMap<JClassType, List<String>>(comparator); - auxiliaries = new TreeMap<JClassType, List<String>>(comparator); - fatalProblems = new TreeMap<JClassType, List<String>>(comparator); + allProblems = new TreeMap<JClassType, List<Problem>>(comparator); + auxiliaries = new TreeMap<JClassType, List<Problem>>(comparator); + fatalProblems = new TreeMap<JClassType, List<Problem>>(comparator); contextType = null; } @@ -77,7 +111,7 @@ * @param extraLines additional continuation lines for the message, usually * for additional explanations. */ - public void add(JClassType type, String message, Priority priority, + public Problem add(JClassType type, String message, Priority priority, String... extraLines) { String contextString = ""; if (contextType != null) { @@ -85,62 +119,34 @@ contextType.getParameterizedQualifiedSourceName() + ")"; } message = message + contextString; - for (String line : extraLines) { - message = message + "\n " + line; - } + Problem entry = new Problem(message, extraLines); if (priority == Priority.AUXILIARY) { - addToMap(type, message, auxiliaries); - return; + addToMap(type, entry, auxiliaries); + return entry; } // both FATAL and DEFAULT problems go in allProblems... - addToMap(type, message, allProblems); + addToMap(type, entry, allProblems); // only FATAL problems go in fatalProblems... if (priority == Priority.FATAL) { - addToMap(type, message, fatalProblems); + addToMap(type, entry, fatalProblems); } + return entry; } - /** - * Returns list of auxiliary "problems" logged against a given type. - * - * @param type type to fetch problems for - * @return {@code null} if no auxiliaries were logged. Otherwise, a list - * of strings describing messages, including the context in which the - * problem was found. - */ - public List<String> getAuxiliaryMessagesForType(JClassType type) { - List<String> list = auxiliaries.get(type); + public String getWorstMessageForType(JClassType type) { + List<Problem> list = fatalProblems.get(type); if (list == null) { - list = new ArrayList<String>(0); + list = allProblems.get(type); + if (list == null) { + list = auxiliaries.get(type); + } } - return list; - } - - /** - * Returns list of problems logged against a given type. - * - * @param type type to fetch problems for - * @return {@code null} if no problems were logged. Otherwise, a list - * of strings describing problems, including the context in which the - * problem was found. - */ - public List<String> getProblemsForType(JClassType type) { - List<String> list = allProblems.get(type); if (list == null) { - list = new ArrayList<String>(0); + return null; } - return list; - } - - /** - * Returns the number of types against which problems were reported. - * - * @return number of problematic types - */ - public int getProblemTypeCount() { - return allProblems.size(); + return list.get(0).getPrimaryMessage() + (list.size() > 1 ? ", etc." : ""); } /** @@ -189,20 +195,53 @@ } /** + * Test accessor returning list of auxiliary "problems" logged against a + * given type. + * + * @param type type to fetch problems for + * @return {@code null} if no auxiliaries were logged. Otherwise, a list + * of strings describing messages, including the context in which the + * problem was found. + */ + List<Problem> getAuxiliaryMessagesForType(JClassType type) { + List<Problem> list = auxiliaries.get(type); + if (list == null) { + list = new ArrayList<Problem>(0); + } + return list; + } + + /** + * Test accessor returning list of problems logged against a given type. + * + * @param type type to fetch problems for + * @return {@code null} if no problems were logged. Otherwise, a list + * of strings describing problems, including the context in which the + * problem was found. + */ + List<Problem> getProblemsForType(JClassType type) { + List<Problem> list = allProblems.get(type); + if (list == null) { + list = new ArrayList<Problem>(0); + } + return list; + } + + /** * Adds an entry to one of the problem maps. * * @param type the type to add * @param message the message to add for {@code type} * @param map the map to add to */ - private void addToMap(JClassType type, String message, - Map<JClassType, List<String>> map) { - List<String> entry = map.get(type); - if (entry == null) { - entry = new ArrayList<String>(); - map.put(type, entry); + private void addToMap(JClassType type, Problem problem, + Map<JClassType, List<Problem>> map) { + List<Problem> list = map.get(type); + if (list == null) { + list = new ArrayList<Problem>(); + map.put(type, list); } - entry.add(message); + list.add(problem); } /** @@ -213,10 +252,17 @@ * @param problems the problems to log */ private void doReport(TreeLogger logger, Type level, - Map<JClassType, List<String>> problems) { + Map<JClassType, List<Problem>> problems) { for (JClassType type : problems.keySet()) { - for (String message : problems.get(type)) { - logger.log(level, message); + for (Problem problem : problems.get(type)) { + if (problem.hasSubMessages()) { + TreeLogger sublogger = logger.branch(level, problem.getPrimaryMessage()); + for (String sub : problem.getSubMessages()) { + sublogger.log(level, sub); + } + } else { + logger.log(level, problem.getPrimaryMessage()); + } } } }
diff --git a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java index 616367a..58db2d6 100644 --- a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java +++ b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java
@@ -1324,26 +1324,15 @@ if (possiblyInstantiableTypes.size() == 0) { String possibilities[] = new String[candidates.size()]; for (int i = 0; i < possibilities.length; i++) { - JClassType subtype = candidates.get(i); - List<String> auxiliaries = problems.getAuxiliaryMessagesForType(subtype); - List<String> errors = problems.getProblemsForType(subtype); - if (errors.isEmpty()) { - if (auxiliaries.isEmpty()) { - possibilities[i] = " subtype " + - subtype.getParameterizedQualifiedSourceName() + - " is not instantiable"; - } else { - // message with have the form "FQCN some-problem-description" - possibilities[i] = " subtype " + auxiliaries.get(0); - if (auxiliaries.size() > 1) { - possibilities[i] = possibilities[i] + ", etc."; - } - } + JClassType subtype = candidates.get(i); + String worstMessage = problems.getWorstMessageForType(subtype); + if (worstMessage == null) { + possibilities[i] = " subtype " + + subtype.getParameterizedQualifiedSourceName() + + " is not instantiable"; } else { - possibilities[i] = " subtype " + errors.get(0); - if (errors.size() > 1 || !auxiliaries.isEmpty()) { - possibilities[i] = possibilities[i] + ", etc."; - } + // message with have the form "FQCN some-problem-description" + possibilities[i] = " subtype " + worstMessage; } } problems.add(baseType, baseType.getParameterizedQualifiedSourceName()