More cleanup of Errors -- including sources as a factory method rather than push/pop methods (that require try/finally clauses)
I'll want to get this for InjectionPoints sooner or later also.
Also merging AddMessageCommand and AddThrowableErrorCommand, with a command that ads an spi.Message.
git-svn-id: https://google-guice.googlecode.com/svn/trunk@532 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/BindCommandProcessor.java b/src/com/google/inject/BindCommandProcessor.java
index e44d18a..765a225 100644
--- a/src/com/google/inject/BindCommandProcessor.java
+++ b/src/com/google/inject/BindCommandProcessor.java
@@ -201,19 +201,19 @@
Class<? extends Annotation> annotationType = key.getAnnotationType();
if (!Annotations.isRetainedAtRuntime(annotationType)) {
- errors.at(StackTraceElements.forType(annotationType)).missingRuntimeRetention(source);
+ errors.withSource(StackTraceElements.forType(annotationType)).missingRuntimeRetention(source);
}
if (!Key.isBindingAnnotation(annotationType)) {
- errors.at(StackTraceElements.forType(annotationType)).missingBindingAnnotation(source);
+ errors.withSource(StackTraceElements.forType(annotationType)).missingBindingAnnotation(source);
}
}
Class<? super T> rawType = key.getRawType();
if (!Classes.isConcrete(rawType)) {
- Class<? extends Annotation> scopeAnnotation = Scopes.getScopeAnnotation(errors, rawType);
+ Class<? extends Annotation> scopeAnnotation = Scopes.findScopeAnnotation(errors, rawType);
if (scopeAnnotation != null) {
- errors.at(StackTraceElements.forType(rawType))
+ errors.withSource(StackTraceElements.forType(rawType))
.scopeAnnotationOnAbstractType(scopeAnnotation, rawType, source);
}
}
diff --git a/src/com/google/inject/BoundProviderFactory.java b/src/com/google/inject/BoundProviderFactory.java
index e699fc1..22c7fc1 100644
--- a/src/com/google/inject/BoundProviderFactory.java
+++ b/src/com/google/inject/BoundProviderFactory.java
@@ -38,13 +38,10 @@
}
public void notify(final InjectorImpl injector, final Errors errors) {
- errors.pushSource(source);
try {
- providerFactory = injector.getInternalFactory(providerKey, errors);
+ providerFactory = injector.getInternalFactory(providerKey, errors.withSource(source));
} catch (ErrorsException e) {
errors.merge(e.getErrors());
- } finally {
- errors.popSource(source);
}
}
diff --git a/src/com/google/inject/CommandProcessor.java b/src/com/google/inject/CommandProcessor.java
index ec10502..918cb57 100644
--- a/src/com/google/inject/CommandProcessor.java
+++ b/src/com/google/inject/CommandProcessor.java
@@ -16,8 +16,7 @@
package com.google.inject;
-import com.google.inject.commands.AddMessageErrorCommand;
-import com.google.inject.commands.AddThrowableErrorCommand;
+import com.google.inject.commands.AddMessageCommand;
import com.google.inject.commands.BindCommand;
import com.google.inject.commands.BindConstantCommand;
import com.google.inject.commands.BindInterceptorCommand;
@@ -41,29 +40,29 @@
*/
abstract class CommandProcessor implements Command.Visitor<Boolean> {
- protected final Errors errors;
+ protected Errors errors;
protected CommandProcessor(Errors errors) {
this.errors = errors;
}
public void processCommands(List<Command> commands) {
- for (Iterator<Command> i = commands.iterator(); i.hasNext(); ) {
- Command command = i.next();
- errors.pushSource(command.getSource());
- Boolean allDone = command.acceptVisitor(this);
- if (allDone) {
- i.remove();
+ Errors errorsAnyCommand = this.errors;
+ try {
+ for (Iterator<Command> i = commands.iterator(); i.hasNext(); ) {
+ Command command = i.next();
+ this.errors = errorsAnyCommand.withSource(command.getSource());
+ Boolean allDone = command.acceptVisitor(this);
+ if (allDone) {
+ i.remove();
+ }
}
- errors.popSource(command.getSource());
+ } finally {
+ this.errors = errorsAnyCommand;
}
}
- public Boolean visitAddMessageError(AddMessageErrorCommand command) {
- return false;
- }
-
- public Boolean visitAddError(AddThrowableErrorCommand command) {
+ public Boolean visitAddMessage(AddMessageCommand command) {
return false;
}
diff --git a/src/com/google/inject/ConstructorInjector.java b/src/com/google/inject/ConstructorInjector.java
index 66cdada..4cff625 100644
--- a/src/com/google/inject/ConstructorInjector.java
+++ b/src/com/google/inject/ConstructorInjector.java
@@ -52,15 +52,11 @@
throws ErrorsException {
Constructor constructor = constructionProxy.getConstructor();
Object source = StackTraceElements.forMember(constructor);
- errors.pushSource(source);
- try {
- return constructionProxy.getParameters().isEmpty()
- ? null // default constructor.
- : injector.getParametersInjectors(constructor,
- constructionProxy.getParameters(), errors);
- } finally {
- errors.popSource(source);
- }
+ errors = errors.withSource(source);
+ return constructionProxy.getParameters().isEmpty()
+ ? null // default constructor.
+ : injector.getParametersInjectors(constructor,
+ constructionProxy.getParameters(), errors);
}
/**
diff --git a/src/com/google/inject/ErrorsCommandProcessor.java b/src/com/google/inject/ErrorsCommandProcessor.java
index 6b0fdbb..d755391 100644
--- a/src/com/google/inject/ErrorsCommandProcessor.java
+++ b/src/com/google/inject/ErrorsCommandProcessor.java
@@ -16,9 +16,11 @@
package com.google.inject;
-import com.google.inject.commands.AddMessageErrorCommand;
-import com.google.inject.commands.AddThrowableErrorCommand;
+import com.google.inject.commands.AddMessageCommand;
import com.google.inject.internal.Errors;
+import com.google.inject.spi.Message;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* Handles {@link Binder#addError} commands.
@@ -28,17 +30,27 @@
*/
class ErrorsCommandProcessor extends CommandProcessor {
+ private static final Logger logger = Logger.getLogger(Guice.class.getName());
+
ErrorsCommandProcessor(Errors errors) {
super(errors);
}
- @Override public Boolean visitAddMessageError(AddMessageErrorCommand command) {
- errors.userReportedError(command.getMessage(), command.getArguments());
+ @Override public Boolean visitAddMessage(AddMessageCommand command) {
+ Message message = command.getMessage();
+ if (message.getCause() != null) {
+ String rootMessage = getRootMessage(message.getCause());
+ logger.log(Level.INFO,
+ "An exception was caught and reported. Message: " + rootMessage,
+ message.getCause());
+ }
+
+ errors.addMessage(message);
return true;
}
- @Override public Boolean visitAddError(AddThrowableErrorCommand command) {
- errors.exceptionReportedByModuleSeeLogs(command.getThrowable());
- return true;
+ public static String getRootMessage(Throwable t) {
+ Throwable cause = t.getCause();
+ return cause == null ? t.toString() : getRootMessage(cause);
}
}
diff --git a/src/com/google/inject/FactoryProxy.java b/src/com/google/inject/FactoryProxy.java
index 67f89e6..cf7fe4c 100644
--- a/src/com/google/inject/FactoryProxy.java
+++ b/src/com/google/inject/FactoryProxy.java
@@ -41,13 +41,10 @@
}
public void notify(final InjectorImpl injector, final Errors errors) {
- errors.pushSource(source);
try {
- targetFactory = injector.getInternalFactory(targetKey, errors);
+ targetFactory = injector.getInternalFactory(targetKey, errors.withSource(source));
} catch (ErrorsException e) {
errors.merge(e.getErrors());
- } finally {
- errors.popSource(source);
}
}
diff --git a/src/com/google/inject/InjectorImpl.java b/src/com/google/inject/InjectorImpl.java
index 55d47ea..f2180f0 100644
--- a/src/com/google/inject/InjectorImpl.java
+++ b/src/com/google/inject/InjectorImpl.java
@@ -149,7 +149,7 @@
/** Returns the binding for {@code key} */
public <T> BindingImpl<T> getBinding(Key<T> key) {
- Errors errors = new Errors();
+ Errors errors = new Errors(StackTraceElements.forType(key.getRawType()));
try {
BindingImpl<T> result = getBindingOrThrow(key, errors);
ProvisionException.throwNewIfNonEmpty(errors);
@@ -488,11 +488,11 @@
}
if (scope == null) {
- Class<? extends Annotation> scopeAnnotation = Scopes.getScopeAnnotation(errors, type);
+ Class<? extends Annotation> scopeAnnotation = Scopes.findScopeAnnotation(errors, type);
if (scopeAnnotation != null) {
scope = scopes.get(scopeAnnotation);
if (scope == null) {
- errors.at(StackTraceElements.forType(type)).scopeNotFound(scopeAnnotation);
+ errors.withSource(StackTraceElements.forType(type)).scopeNotFound(scopeAnnotation);
}
}
}
@@ -639,9 +639,9 @@
// Look for a binding without annotation attributes or return null.
if (key.hasAttributes()) {
try {
- return getBindingOrThrow(key.withoutAttributes(), new Errors());
- }
- catch (ErrorsException ignored) {
+ Errors ignored = new Errors();
+ return getBindingOrThrow(key.withoutAttributes(), ignored);
+ } catch (ErrorsException ignored) {
// throw with a more appropriate message below
}
}
@@ -659,7 +659,10 @@
return getBindingOrThrow(key, errors).internalFactory;
}
- /** Field and method injectors. */
+ /**
+ * Field and method injectors. Each value is either an Errors or a
+ * {@code List<SingleMemberInjector>}.
+ */
private final Map<Class<?>, Object> injectors = new ReferenceCache<Class<?>, Object>() {
protected Object create(Class<?> key) {
Errors errors = new Errors();
@@ -735,15 +738,14 @@
continue;
}
- Errors errorsForMember = inject.optional() ? new Errors() : errors;
Object source = StackTraceElements.forMember(member);
- errorsForMember.pushSource(source);
+ Errors errorsForMember = inject.optional()
+ ? new Errors(source)
+ : errors.withSource(source);
try {
injectors.add(injectorFactory.create(this, member, errorsForMember));
} catch (ErrorsException ignoredForNow) {
// if this was an optional injection, it is completely ignored
- } finally {
- errorsForMember.popSource(source);
}
}
}
@@ -795,12 +797,7 @@
final Key<?> key = Keys.get(field.getGenericType(), field, field.getAnnotations(), errors);
Object source = StackTraceElements.forMember(field);
- errors.pushSource(source);
- try {
- factory = injector.getInternalFactory(key, errors);
- } finally {
- errors.popSource(source);
- }
+ factory = injector.getInternalFactory(key, errors.withSource(source));
injectionPoint = InjectionPoint.newInstance(
field, Nullability.allowsNull(field.getAnnotations()), key);
@@ -863,12 +860,7 @@
Member member, final Errors errors) throws ErrorsException {
InternalFactory<? extends T> factory;
Object source = StackTraceElements.forMember(member);
- errors.pushSource(source);
- try {
- factory = getInternalFactory(parameter.getKey(), errors);
- } finally {
- errors.popSource(source);
- }
+ factory = getInternalFactory(parameter.getKey(), errors.withSource(source));
InjectionPoint<T> injectionPoint = InjectionPoint.newInstance(
member, parameter.getIndex(), parameter.allowsNull(), parameter.getKey());
@@ -947,7 +939,7 @@
final Map<Class<?>, Object> constructors = new ReferenceCache<Class<?>, Object>() {
@SuppressWarnings("unchecked")
protected Object create(Class<?> implementation) {
- Errors errors = new Errors();
+ Errors errors = new Errors(StackTraceElements.forType(implementation));
try {
ConstructorInjector result = new ConstructorInjector(
errors, InjectorImpl.this, implementation);
@@ -1018,8 +1010,7 @@
Errors errors = new Errors();
try {
injectMembersOrThrow(errors, o);
- }
- catch (ErrorsException e) {
+ } catch (ErrorsException e) {
errors.merge(e.getErrors());
}
@@ -1076,7 +1067,7 @@
}
public <T> Provider<T> getProvider(final Key<T> key) {
- Errors errors = new Errors();
+ Errors errors = new Errors(StackTraceElements.forType(key.getRawType()));
try {
Provider<T> result = getProviderOrThrow(key, errors);
errors.throwIfNecessary();
diff --git a/src/com/google/inject/ProviderMethods.java b/src/com/google/inject/ProviderMethods.java
index 258f81d..dfed20a 100644
--- a/src/com/google/inject/ProviderMethods.java
+++ b/src/com/google/inject/ProviderMethods.java
@@ -69,13 +69,12 @@
}
<T> void bindProviderMethod(final Method method) {
- Errors errors = new Errors()
- .pushSource(StackTraceElements.forMember(method));
+ Errors errors = new Errors(StackTraceElements.forMember(method));
method.setAccessible(true);
Class<? extends Annotation> scopeAnnotation
- = findScopeAnnotation(errors, method.getAnnotations());
+ = Scopes.findScopeAnnotation(errors, method.getAnnotations());
Annotation bindingAnnotation
= Keys.findBindingAnnotation(errors, method, method.getAnnotations());
@@ -98,8 +97,8 @@
try {
// We know this cast is safe becase T is the method's return type.
- @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" }) T result = (T) method
- .invoke(providers, parameters);
+ @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" })
+ T result = (T) method.invoke(providers, parameters);
return result;
}
catch (IllegalAccessException e) {
@@ -141,25 +140,5 @@
return parameterProviders;
}
-
- /**
- * Returns the scoping annotation, or null if there isn't one.
- */
- Class<? extends Annotation> findScopeAnnotation(Errors errors, Annotation[] annotations) {
- Class<? extends Annotation> found = null;
-
- for (Annotation annotation : annotations) {
- if (annotation.annotationType()
- .isAnnotationPresent(ScopeAnnotation.class)) {
- if (found != null) {
- errors.duplicateScopeAnnotations(found, annotation.annotationType());
- } else {
- found = annotation.annotationType();
- }
- }
- }
-
- return found;
- }
}
}
diff --git a/src/com/google/inject/ProxyFactory.java b/src/com/google/inject/ProxyFactory.java
index 07aca7c..48fc94f 100644
--- a/src/com/google/inject/ProxyFactory.java
+++ b/src/com/google/inject/ProxyFactory.java
@@ -23,6 +23,7 @@
import com.google.inject.internal.GuiceFastClass;
import com.google.inject.internal.GuiceNamingPolicy;
import com.google.inject.internal.ReferenceCache;
+import com.google.inject.internal.StackTraceElements;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -61,7 +62,7 @@
Map<Constructor<?>, Object> constructionProxies = new ReferenceCache<Constructor<?>, Object>() {
protected Object create(Constructor<?> constructor) {
- Errors errors = new Errors();
+ Errors errors = new Errors(StackTraceElements.forMember(constructor));
try {
ConstructionProxy<?> result = createConstructionProxy(errors, constructor);
errors.throwIfNecessary();
diff --git a/src/com/google/inject/RequestStaticInjectionCommandProcessor.java b/src/com/google/inject/RequestStaticInjectionCommandProcessor.java
index a2ba1a3..132ff54 100644
--- a/src/com/google/inject/RequestStaticInjectionCommandProcessor.java
+++ b/src/com/google/inject/RequestStaticInjectionCommandProcessor.java
@@ -68,15 +68,11 @@
}
void validate(final InjectorImpl injector) {
- errors.pushSource(source);
- try {
- injector.addSingleInjectorsForFields(
- type.getDeclaredFields(), true, memberInjectors, errors);
- injector.addSingleInjectorsForMethods(
- type.getDeclaredMethods(), true, memberInjectors, errors);
- } finally {
- errors.popSource(source);
- }
+ Errors errorsForMember = errors.withSource(source);
+ injector.addSingleInjectorsForFields(
+ type.getDeclaredFields(), true, memberInjectors, errorsForMember);
+ injector.addSingleInjectorsForMethods(
+ type.getDeclaredMethods(), true, memberInjectors, errorsForMember);
}
void injectMembers(InjectorImpl injector) {
diff --git a/src/com/google/inject/Scopes.java b/src/com/google/inject/Scopes.java
index f0bc525..52e36ec 100644
--- a/src/com/google/inject/Scopes.java
+++ b/src/com/google/inject/Scopes.java
@@ -89,11 +89,21 @@
/**
* Returns the scope annotation on {@code type}, or null if none is specified.
*/
- static Class<? extends Annotation> getScopeAnnotation(
+ static Class<? extends Annotation> findScopeAnnotation(
Errors errors, Class<?> implementation) {
+ return findScopeAnnotation(errors, implementation.getAnnotations());
+ }
+
+
+ /**
+ * Returns the scoping annotation, or null if there isn't one.
+ */
+ static Class<? extends Annotation> findScopeAnnotation(Errors errors, Annotation[] annotations) {
Class<? extends Annotation> found = null;
- for (Annotation annotation : implementation.getAnnotations()) {
- if (isScopeAnnotation(annotation)) {
+
+ for (Annotation annotation : annotations) {
+ if (annotation.annotationType()
+ .isAnnotationPresent(ScopeAnnotation.class)) {
if (found != null) {
errors.duplicateScopeAnnotations(found, annotation.annotationType());
} else {
diff --git a/src/com/google/inject/ScopesCommandProcessor.java b/src/com/google/inject/ScopesCommandProcessor.java
index 2f9a3a4..dc2199f 100644
--- a/src/com/google/inject/ScopesCommandProcessor.java
+++ b/src/com/google/inject/ScopesCommandProcessor.java
@@ -45,12 +45,12 @@
Class<? extends Annotation> annotationType = command.getAnnotationType();
if (!Scopes.isScopeAnnotation(annotationType)) {
- errors.at(StackTraceElements.forType(annotationType)).missingScopeAnnotation();
+ errors.withSource(StackTraceElements.forType(annotationType)).missingScopeAnnotation();
// Go ahead and bind anyway so we don't get collateral errors.
}
if (!Annotations.isRetainedAtRuntime(annotationType)) {
- errors.at(StackTraceElements.forType(annotationType))
+ errors.withSource(StackTraceElements.forType(annotationType))
.missingRuntimeRetention(command.getSource());
// Go ahead and bind anyway so we don't get collateral errors.
}
diff --git a/src/com/google/inject/commands/AddMessageCommand.java b/src/com/google/inject/commands/AddMessageCommand.java
new file mode 100644
index 0000000..7ed6145
--- /dev/null
+++ b/src/com/google/inject/commands/AddMessageCommand.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.inject.commands;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.Message;
+
+/**
+ * Immutable snapshot of a request to add a string message.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public final class AddMessageCommand implements Command {
+ private final Message message;
+
+ AddMessageCommand(Message message) {
+ this.message = message;
+ }
+
+ AddMessageCommand(Object source, String message, Object[] arguments) {
+ this.message = new Message(source, String.format(message, arguments));
+ }
+
+ AddMessageCommand(Object source, Throwable throwable) {
+ this.message = new Message(source,
+ "An exception was caught and reported. Message: " + throwable.getMessage(),
+ ImmutableList.<InjectionPoint>of(), throwable);
+ }
+
+ public Object getSource() {
+ return message.getSource();
+ }
+
+ public <T> T acceptVisitor(Visitor<T> visitor) {
+ return visitor.visitAddMessage(this);
+ }
+
+ public Message getMessage() {
+ return message;
+ }
+}
diff --git a/src/com/google/inject/commands/AddMessageErrorCommand.java b/src/com/google/inject/commands/AddMessageErrorCommand.java
deleted file mode 100644
index cd4a8cf..0000000
--- a/src/com/google/inject/commands/AddMessageErrorCommand.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright (C) 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.inject.commands;
-
-
-import java.util.Arrays;
-import static java.util.Collections.unmodifiableList;
-import java.util.List;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Immutable snapshot of a request to add a string message.
- *
- * @author jessewilson@google.com (Jesse Wilson)
- */
-public final class AddMessageErrorCommand implements Command {
- private final Object source;
- private final String message;
- private final List<Object> arguments;
-
- AddMessageErrorCommand(Object source, String message, Object[] arguments) {
- this.source = checkNotNull(source, "source");
- this.message = checkNotNull(message, "message");
- this.arguments = unmodifiableList(Arrays.asList(arguments.clone()));
- }
-
- public Object getSource() {
- return source;
- }
-
- public <T> T acceptVisitor(Visitor<T> visitor) {
- return visitor.visitAddMessageError(this);
- }
-
- public String getMessage() {
- return message;
- }
-
- public List<Object> getArguments() {
- return arguments;
- }
-}
diff --git a/src/com/google/inject/commands/AddThrowableErrorCommand.java b/src/com/google/inject/commands/AddThrowableErrorCommand.java
deleted file mode 100644
index 456af93..0000000
--- a/src/com/google/inject/commands/AddThrowableErrorCommand.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Copyright (C) 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.inject.commands;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Immutable snapshot of a request to add a throwable message.
- *
- * @author jessewilson@google.com (Jesse Wilson)
- */
-public final class AddThrowableErrorCommand implements Command {
- private final Object source;
- private final Throwable throwable;
-
- AddThrowableErrorCommand(Object source, Throwable throwable) {
- this.source = checkNotNull(source, "source");
- this.throwable = checkNotNull(throwable, "throwable");
- }
-
- public Object getSource() {
- return source;
- }
-
- public <T> T acceptVisitor(Visitor<T> visitor) {
- return visitor.visitAddError(this);
- }
-
- public Throwable getThrowable() {
- return throwable;
- }
-}
diff --git a/src/com/google/inject/commands/Command.java b/src/com/google/inject/commands/Command.java
index 862a77f..e87f67e 100644
--- a/src/com/google/inject/commands/Command.java
+++ b/src/com/google/inject/commands/Command.java
@@ -29,8 +29,7 @@
* Visit commands.
*/
public interface Visitor<V> {
- V visitAddMessageError(AddMessageErrorCommand command);
- V visitAddError(AddThrowableErrorCommand command);
+ V visitAddMessage(AddMessageCommand command);
V visitBindInterceptor(BindInterceptorCommand command);
V visitBindScope(BindScopeCommand command);
V visitRequestStaticInjection(RequestStaticInjectionCommand command);
diff --git a/src/com/google/inject/commands/CommandRecorder.java b/src/com/google/inject/commands/CommandRecorder.java
index f3bb7a2..42bb586 100644
--- a/src/com/google/inject/commands/CommandRecorder.java
+++ b/src/com/google/inject/commands/CommandRecorder.java
@@ -138,15 +138,15 @@
}
public void addError(String message, Object... arguments) {
- commands.add(new AddMessageErrorCommand(getSource(), message, arguments));
+ commands.add(new AddMessageCommand(getSource(), message, arguments));
}
public void addError(Throwable t) {
- commands.add(new AddThrowableErrorCommand(getSource(), t));
+ commands.add(new AddMessageCommand(getSource(), t));
}
public void addError(Message message) {
- throw new UnsupportedOperationException("TODO");
+ commands.add(new AddMessageCommand(message));
}
public <T> BindCommand<T>.BindingBuilder bind(Key<T> key) {
diff --git a/src/com/google/inject/commands/CommandReplayer.java b/src/com/google/inject/commands/CommandReplayer.java
index b40f793..a666737 100644
--- a/src/com/google/inject/commands/CommandReplayer.java
+++ b/src/com/google/inject/commands/CommandReplayer.java
@@ -54,16 +54,11 @@
checkNotNull(commands, "commands");
Command.Visitor<Void> visitor = new Command.Visitor<Void>() {
- public Void visitAddMessageError(AddMessageErrorCommand command) {
+ public Void visitAddMessage(AddMessageCommand command) {
replayAddMessageError(binder, command);
return null;
}
- public Void visitAddError(AddThrowableErrorCommand command) {
- replayAddError(binder, command);
- return null;
- }
-
public Void visitBindInterceptor(BindInterceptorCommand command) {
replayBindInterceptor(binder, command);
return null;
@@ -105,13 +100,8 @@
}
}
- public void replayAddMessageError(final Binder binder, final AddMessageErrorCommand command) {
- binder.withSource(command.getSource())
- .addError(command.getMessage(), command.getArguments().toArray());
- }
-
- public void replayAddError(final Binder binder, final AddThrowableErrorCommand command) {
- binder.withSource(command.getSource()).addError(command.getThrowable());
+ public void replayAddMessageError(final Binder binder, final AddMessageCommand command) {
+ binder.withSource(command.getSource()).addError(command.getMessage());
}
public void replayBindInterceptor(final Binder binder, final BindInterceptorCommand command) {
diff --git a/src/com/google/inject/commands/DefaultCommandVisitor.java b/src/com/google/inject/commands/DefaultCommandVisitor.java
index 08f433b..cf98592 100644
--- a/src/com/google/inject/commands/DefaultCommandVisitor.java
+++ b/src/com/google/inject/commands/DefaultCommandVisitor.java
@@ -34,11 +34,7 @@
return null;
}
- public V visitAddError(AddThrowableErrorCommand command) {
- return visitCommand(command);
- }
-
- public V visitAddMessageError(AddMessageErrorCommand command) {
+ public V visitAddMessage(AddMessageCommand command) {
return visitCommand(command);
}
diff --git a/src/com/google/inject/internal/Errors.java b/src/com/google/inject/internal/Errors.java
index 4da99f5..b80df00 100644
--- a/src/com/google/inject/internal/Errors.java
+++ b/src/com/google/inject/internal/Errors.java
@@ -21,7 +21,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.CreationException;
-import com.google.inject.Guice;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;
@@ -39,8 +38,6 @@
import java.util.Comparator;
import java.util.Formatter;
import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
/**
* A collection of error messages. If this type is passed as a method parameter, the method is
@@ -50,15 +47,42 @@
*/
public final class Errors implements Serializable {
- private static final Logger logger = Logger.getLogger(Guice.class.getName());
+ // TODO: Provide a policy on what the source line should be for a given member.
+ // Should we prefer the line where the binding was made?
+ // Should we prefer the member?
+ // For example, if we bind a class with two scope annotations, is that a problem
+ // with the binding, or a problem with the bound class? The catch being that if it's
+ // a problem with the binding, then we report a different source line if the class
+ // is retrieved via a JIT binding.
+ //
+ // What about a missing implementation? Is that at the caller?
+ // What about injection points?
- private Object sourceForNextError = null;
- private final List<Object> sources = Lists.newArrayList();
+ /** the stacktrace or member that will be the reference location for new errors */
+ private final Object source;
/** false indicates that new errors should not be added */
private boolean isMutable = true;
- private final List<Message> errors = Lists.newArrayList();
- private final List<InjectionPoint> injectionPoints = Lists.newArrayList();
+ private final List<Message> errors;
+ private final List<InjectionPoint> injectionPoints;
+
+ public Errors() {
+ this(SourceProvider.UNKNOWN_SOURCE);
+ }
+
+ public Errors(Object source) {
+ this.source = source;
+ isMutable = true;
+ errors = Lists.newArrayList();
+ injectionPoints = Lists.newArrayList();
+ }
+
+ public Errors(Errors parent, Object source) {
+ this.source = source;
+ isMutable = parent.isMutable;
+ errors = parent.errors;
+ injectionPoints = Lists.newArrayList(parent.injectionPoints);
+ }
public Errors userReportedError(String messageFormat, List<Object> arguments) {
return addMessage(messageFormat, arguments);
@@ -74,18 +98,11 @@
}
/**
- * Specifies the source for every error added until the matching call to
- * {@link #popSource(Object)}.
+ * Returns a new instance that uses {@code source} as a reference point for
+ * newly added errors.
*/
- public Errors pushSource(Object source) {
- sources.add(source);
- return this;
- }
-
- public Errors popSource(Object source) {
- Object popped = sources.remove(sources.size() - 1);
- checkArgument(popped == source);
- return this;
+ public Errors withSource(Object source) {
+ return new Errors(this, source);
}
/**
@@ -164,15 +181,6 @@
return addMessage("@ProvidedBy points to the same class it annotates.");
}
- public Errors exceptionReportedByModuleSeeLogs(Throwable throwable) {
- String rootMessage = getRootMessage(throwable);
-
- logger.log(Level.INFO, format("An exception was caught and reported. Message: %s", rootMessage),
- throwable);
- return addMessage(throwable,
- "An exception was caught and reported. See log for details. Message: %s", rootMessage);
- }
-
public Errors missingBindingAnnotation(Object source) {
return addMessage("Please annotate with @BindingAnnotation.%n"
+ " Bound at %s.", source);
@@ -302,14 +310,6 @@
expectedType);
}
- /**
- * Convenience method to set the source for a single error.
- */
- public Errors at(Object source) {
- sourceForNextError = source;
- return this;
- }
-
public Errors makeImmutable() {
isMutable = false;
return this;
@@ -327,7 +327,7 @@
public Errors merge(Errors moreErrors) {
checkState(isMutable);
- if (moreErrors != this) {
+ if (moreErrors.errors != this.errors) {
for (Message message : moreErrors.errors) {
List<InjectionPoint> injectionPoints = Lists.newArrayList();
injectionPoints.addAll(this.injectionPoints);
@@ -361,23 +361,17 @@
}
private Errors addMessage(Throwable cause, String messageFormat, Object... arguments) {
+ String message = format(messageFormat, arguments);
+ addMessage(new Message(source, message, ImmutableList.copyOf(injectionPoints), cause));
+ return this;
+ }
+
+ public Errors addMessage(Message message) {
if (!isMutable) {
throw new AssertionError();
}
- String message = format(messageFormat, arguments);
-
- Object source;
- if (sourceForNextError != null) {
- source = sourceForNextError;
- sourceForNextError = null;
- } else if (!sources.isEmpty()) {
- source = sources.get(sources.size() - 1);
- } else {
- source = SourceProvider.UNKNOWN_SOURCE;
- }
-
- errors.add(new Message(source, message, ImmutableList.copyOf(injectionPoints), cause));
+ errors.add(message);
return this;
}
@@ -442,7 +436,7 @@
return fmt.format("%s error[s]", errorMessages.size()).toString();
}
- static abstract class Converter<T> {
+ private static abstract class Converter<T> {
final Class<T> type;
@@ -461,12 +455,7 @@
abstract String toString(T t);
}
- public static String getRootMessage(Throwable t) {
- Throwable cause = t.getCause();
- return cause == null ? t.toString() : getRootMessage(cause);
- }
-
- static final Collection<Converter<?>> converters = ImmutableList.of(
+ private static final Collection<Converter<?>> converters = ImmutableList.of(
new Converter<MatcherAndConverter>(MatcherAndConverter.class) {
public String toString(MatcherAndConverter m) {
return m.toString();
diff --git a/src/com/google/inject/internal/LineNumbers.java b/src/com/google/inject/internal/LineNumbers.java
index 82aaf7b..4e46c93 100644
--- a/src/com/google/inject/internal/LineNumbers.java
+++ b/src/com/google/inject/internal/LineNumbers.java
@@ -52,9 +52,12 @@
*/
public LineNumbers(Class type) throws IOException {
this.type = type;
- InputStream in = type.getResourceAsStream("/" + type.getName().replace('.', '/') + ".class");
- checkArgument(in != null, "Cannot find bytecode for %s", type);
- new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES);
+
+ if (!type.isArray()) {
+ InputStream in = type.getResourceAsStream("/" + type.getName().replace('.', '/') + ".class");
+ checkArgument(in != null, "Cannot find bytecode for %s", type);
+ new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES);
+ }
}
/**