Fix new errors due to automatic annotation of Class<T> types
authorAlexandre Montplaisir <alexmonthy@efficios.com>
Sun, 29 Nov 2015 03:36:40 +0000 (22:36 -0500)
committerAlexandre Montplaisir <alexmonthy@efficios.com>
Thu, 3 Dec 2015 05:37:11 +0000 (00:37 -0500)
The null analysis now automatically assumes that generic class types
(the "T" in Class<T>) are always @NonNull. See bug 477719.
This clears a bunch of warnings we had due to using Something.class
as parameters. Great!

However, this introduces a new problem. When a generic type parameter
is used both as parameter and as return value, and the client specifies
an annotation on the parameter during a call, the default behaviour is
to assume this annotation on the return type too.

In some cases this assumption is correct:

    List<@NonNull String>.get() returns a @NonNull String

But in some others it is not:

    Map<@NonNull K, @NonNull V>.get() should *NOT* return a @NonNull V.

Now some methods of the form:

    V something(Class<V> type);

also follow this pattern, and the "automatic" @NonNull applied to V
also gets applies to the return value. In some (most?) cases this is
incorrect, and we have to supply external annotations to change the
return value to @Nullable. Just like we did for Map.get().

See bug 483143 for more information.

The return values of the following methods are now annotated as
@Nullable:

Class.getAnnotation()
DsfServicesTracker.getService()
IRemoteConnection.getService()
IRemoteConnectionType.getService()

and related null-checks were added.

Change-Id: I2c60835160a46e88ff293a5fd68774021c2b00a9
Signed-off-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-on: https://git.eclipse.org/r/61521
Reviewed-by: Hudson CI
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
14 files changed:
common/org.eclipse.tracecompass.common.core/annotations/java/lang/Class.eea [new file with mode: 0644]
common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/cdt/dsf/service/DsfServicesTracker.eea [new file with mode: 0644]
common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/remote/core/IRemoteConnection.eea [new file with mode: 0644]
common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/remote/core/IRemoteConnectionType.eea [new file with mode: 0644]
gdbtrace/org.eclipse.tracecompass.gdbtrace.core/src/org/eclipse/tracecompass/internal/gdbtrace/core/trace/DsfGdbAdaptor.java
lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/dialogs/NewConnectionDialog.java
lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/handlers/ImportHandler.java
lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/model/impl/TargetNodeComponent.java
lttng/org.eclipse.tracecompass.lttng2.control.ui/src/org/eclipse/tracecompass/internal/lttng2/control/ui/views/property/TargetNodePropertySource.java
releng/org.eclipse.tracecompass.alltests/build.properties
tmf/org.eclipse.tracecompass.tmf.remote.core/src/org/eclipse/tracecompass/internal/tmf/remote/core/messages/Messages.java
tmf/org.eclipse.tracecompass.tmf.remote.core/src/org/eclipse/tracecompass/internal/tmf/remote/core/messages/messages.properties
tmf/org.eclipse.tracecompass.tmf.remote.core/src/org/eclipse/tracecompass/internal/tmf/remote/core/shell/CommandShell.java
tmf/org.eclipse.tracecompass.tmf.remote.core/src/org/eclipse/tracecompass/tmf/remote/core/proxy/TmfRemoteConnectionFactory.java

diff --git a/common/org.eclipse.tracecompass.common.core/annotations/java/lang/Class.eea b/common/org.eclipse.tracecompass.common.core/annotations/java/lang/Class.eea
new file mode 100644 (file)
index 0000000..1d43218
--- /dev/null
@@ -0,0 +1,4 @@
+class java/lang/Class
+getAnnotation
+ <A::Ljava/lang/annotation/Annotation;>(Ljava/lang/Class<TA;>;)TA;
+ <A::Ljava/lang/annotation/Annotation;>(Ljava/lang/Class<TA;>;)T0A;
diff --git a/common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/cdt/dsf/service/DsfServicesTracker.eea b/common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/cdt/dsf/service/DsfServicesTracker.eea
new file mode 100644 (file)
index 0000000..b4c2276
--- /dev/null
@@ -0,0 +1,4 @@
+class org/eclipse/cdt/dsf/service/DsfServicesTracker
+getService
+ <V:Ljava/lang/Object;>(Ljava/lang/Class<TV;>;)TV;
+ <V:Ljava/lang/Object;>(Ljava/lang/Class<TV;>;)T0V;
diff --git a/common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/remote/core/IRemoteConnection.eea b/common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/remote/core/IRemoteConnection.eea
new file mode 100644 (file)
index 0000000..4430b1e
--- /dev/null
@@ -0,0 +1,4 @@
+class org/eclipse/remote/core/IRemoteConnection
+getService
+ <T::Lorg/eclipse/remote/core/IRemoteConnection$Service;>(Ljava/lang/Class<TT;>;)TT;
+ <T::Lorg/eclipse/remote/core/IRemoteConnection$Service;>(Ljava/lang/Class<TT;>;)T0T;
diff --git a/common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/remote/core/IRemoteConnectionType.eea b/common/org.eclipse.tracecompass.common.core/annotations/org/eclipse/remote/core/IRemoteConnectionType.eea
new file mode 100644 (file)
index 0000000..61f1b7f
--- /dev/null
@@ -0,0 +1,4 @@
+class org/eclipse/remote/core/IRemoteConnectionType
+getService
+ <T::Lorg/eclipse/remote/core/IRemoteConnectionType$Service;>(Ljava/lang/Class<TT;>;)TT;
+ <T::Lorg/eclipse/remote/core/IRemoteConnectionType$Service;>(Ljava/lang/Class<TT;>;)T0T;
index 307311b081aa6eb4bc790bdeb95d44f186ee8aed..8fe74a5e7e58f343df9115cff230724a51923243 100644 (file)
@@ -442,7 +442,14 @@ public class DsfGdbAdaptor {
                                 IContainerDMContext containerDMC = (IContainerDMContext)(getData()[0]);
                                 IBreakpointsTargetDMContext bpTargetDMC = DMContexts.getAncestorOfType(containerDMC , IBreakpointsTargetDMContext.class);
 
-                                CommandFactory cmdFactory = tracker.getService(IMICommandControl.class).getCommandFactory();
+                                IMICommandControl commandService = tracker.getService(IMICommandControl.class);
+                                if (commandService == null) {
+                                    drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
+                                    drm.done();
+                                    return;
+                                }
+
+                                CommandFactory cmdFactory = commandService.getCommandFactory();
                                 IBreakpoints bpService = tracker.getService(MIBreakpoints.class);
                                 if (cmdFactory == null || bpService == null) {
                                     drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
@@ -520,8 +527,12 @@ public class DsfGdbAdaptor {
                 final IGDBTraceControl traceControl = tracker
                         .getService(IGDBTraceControl.class);
 
-                final ICommandControlService commandControl = tracker
-                        .getService(ICommandControlService.class);
+                final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
+                if (commandControl == null) {
+                    queryRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
+                    queryRm.done();
+                    return;
+                }
                 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl
                         .getContext();
 
@@ -606,6 +617,12 @@ public class DsfGdbAdaptor {
                 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
 
                 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
+                if (commandControl == null) {
+                    queryRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
+                    queryRm.done();
+                    return;
+                }
+
                 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl.getContext();
 
                 if (traceControl != null) {
@@ -670,6 +687,11 @@ public class DsfGdbAdaptor {
                 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
 
                 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
+                if (commandControl == null) {
+                    rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
+                    rm.done();
+                    return;
+                }
                 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl.getContext();
 
                 if (traceControl != null) {
index 1f307491ce370aeafe54bcaa1218c8f5ef811395..1d1c17876d3b5e6d4c195fbddf53c5c404063ec0 100644 (file)
@@ -13,6 +13,7 @@
 package org.eclipse.tracecompass.internal.lttng2.control.ui.views.dialogs;
 
 import static java.text.MessageFormat.format;
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -392,7 +393,8 @@ public class NewConnectionDialog extends Dialog implements INewConnectionDialog
         StringBuffer label = new StringBuffer();
         label.append(rc.getName());
         if (rc.hasService(IRemoteConnectionHostService.class)) {
-            label.append(format(" [{0}]", rc.getService(IRemoteConnectionHostService.class).getHostname())); //$NON-NLS-1$
+            IRemoteConnectionHostService service = checkNotNull(rc.getService(IRemoteConnectionHostService.class));
+            label.append(format(" [{0}]", service.getHostname())); //$NON-NLS-1$
         }
         return label.toString();
     }
index 5f899e7e063d3d560c6af8fb21318edd8a06df4c..0485c6b3dccef9e9fd3e208df0dc4346495c5425 100644 (file)
@@ -14,6 +14,8 @@
  **********************************************************************/
 package org.eclipse.tracecompass.internal.lttng2.control.ui.views.handlers;
 
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Iterator;
@@ -161,7 +163,7 @@ public class ImportHandler extends BaseControlViewHandler {
         }
 
         String scheme = rc.getConnectionType().getScheme();
-        IRemoteConnectionHostService hostService = rc.getService(IRemoteConnectionHostService.class);
+        IRemoteConnectionHostService hostService = checkNotNull(rc.getService(IRemoteConnectionHostService.class));
         String address = hostService.getHostname();
         String user = hostService.getUsername();
         int port =  hostService.getPort();
index d8bd840a22de8c680d2f4f65ee445b62e66220ad..f9c755d31c2afcbcc6ff5d7cd5f3a850f815c901 100644 (file)
@@ -27,6 +27,7 @@ import org.eclipse.core.runtime.jobs.IJobChangeEvent;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.core.runtime.jobs.JobChangeAdapter;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jface.dialogs.ErrorDialog;
 import org.eclipse.remote.core.IRemoteConnection;
 import org.eclipse.remote.core.IRemoteConnectionChangeListener;
@@ -181,7 +182,7 @@ public class TargetNodeComponent extends TraceControlComponent implements IRemot
     }
 
     @Override
-    public <T> T getAdapter(Class<T> adapter) {
+    public <T> @Nullable T getAdapter(Class<T> adapter) {
         if (adapter == IPropertySource.class) {
             return adapter.cast(new TargetNodePropertySource(this));
         }
index b2850d61d3c5688fdec2ba4c548445bb30eb4af9..b48af66e6e65dd9f827e2a6b117d61e48c801d97 100644 (file)
  **********************************************************************/
 package org.eclipse.tracecompass.internal.lttng2.control.ui.views.property;
 
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import org.eclipse.remote.core.IRemoteConnection;
 import org.eclipse.remote.core.IRemoteConnectionHostService;
 import org.eclipse.tracecompass.internal.lttng2.control.ui.views.messages.Messages;
 import org.eclipse.tracecompass.internal.lttng2.control.ui.views.model.impl.TargetNodeComponent;
-import org.eclipse.tracecompass.tmf.remote.core.proxy.RemoteSystemProxy;
 import org.eclipse.tracecompass.tmf.ui.properties.ReadOnlyTextPropertyDescriptor;
 import org.eclipse.ui.views.properties.IPropertyDescriptor;
 
@@ -109,9 +111,10 @@ public class TargetNodePropertySource extends BasePropertySource {
             return fTargetNode.getName();
         }
         if (TARGET_NODE_ADDRESS_PROPERTY_ID.equals(id)) {
-            RemoteSystemProxy proxy = fTargetNode.getRemoteSystemProxy();
-            if (proxy.getRemoteConnection().hasService(IRemoteConnectionHostService.class)) {
-                return proxy.getRemoteConnection().getService(IRemoteConnectionHostService.class).getHostname();
+            IRemoteConnection connection = fTargetNode.getRemoteSystemProxy().getRemoteConnection();
+            if (connection.hasService(IRemoteConnectionHostService.class)) {
+                IRemoteConnectionHostService service = checkNotNull(connection.getService(IRemoteConnectionHostService.class));
+                return service.getHostname();
             }
             return LOCAL_CONNECTION_HOST_NAME;
         }
index 978a8de6ba3d467db42bfdee2726fbbd661048bb..09ad5c5423424ba67b6e1fb2cd23446c83167782 100644 (file)
@@ -17,3 +17,5 @@ bin.includes = META-INF/,\
                plugin.properties,\
                about.html
 src.includes = about.html
+additional.bundles = org.eclipse.jdt.annotation
+jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation
index 7872d4c3dd87abad018ea2f07da6032fdec51537..eba3ff1ab3c5283de033ba22c7d77d2798659a16 100644 (file)
@@ -29,6 +29,7 @@ public final class Messages extends NLS {
     public static String RemoteConnection_ExecutionTimeout;
     public static String RemoteConnection_ShellNotConnected;
     public static String RemoteConnection_CommandShellError;
+    public static String RemoteConnection_ServiceNotDefined;
 
     public static String RemoteConnection_ConnectionError;
     public static String RemoteConnection_DuplicateConnectionError;
index d62b41ae54c437195486a00422459687d3f6fe2f..8a1cfff6d17352016953613daab3703bbc24be17 100644 (file)
@@ -15,6 +15,7 @@ RemoteConnection_ExecutionFailure=Command Execution failed
 RemoteConnection_ExecutionTimeout=Command Execution timed-out
 RemoteConnection_ShellNotConnected=Command shell not connected
 RemoteConnection_CommandShellError=Could not create HostShellProcessAdapter
+RemoteConnection_ServiceNotDefined=Remote process service not defined
 
 RemoteConnection_ConnectionError=Connecting to node failed for ''{0}''
 RemoteConnection_DuplicateConnectionError=Node definition for node name ''{0}'' already exist: Address ''{1}'' and port ''{2}''
index 828070350ebbc85bd0e72b221c57f620d5f7cf25..5bea2d0e4ffa02eb4636e8578400f181d12cc489 100644 (file)
@@ -15,6 +15,7 @@
 package org.eclipse.tracecompass.internal.tmf.remote.core.shell;
 
 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
 
 import java.io.IOException;
 import java.util.concurrent.Callable;
@@ -92,7 +93,11 @@ public class CommandShell implements ICommandShell {
                         monitor = new NullProgressMonitor();
                     }
                     if (!monitor.isCanceled()) {
-                        IRemoteProcess process = fConnection.getService(IRemoteProcessService.class).getProcessBuilder(command.getInput()).start();
+                        IRemoteProcessService service = fConnection.getService(IRemoteProcessService.class);
+                        if (service == null) {
+                            return new CommandResult(1, new @NonNull String[0], new @NonNull String[] { nullToEmptyString(Messages.RemoteConnection_ServiceNotDefined) });
+                        }
+                        IRemoteProcess process = service.getProcessBuilder(command.getInput()).start();
                         InputReader stdout = new InputReader(checkNotNull(process.getInputStream()));
                         InputReader stderr = new InputReader(checkNotNull(process.getErrorStream()));
 
index 778791533fde1d9df156b7639baa7f15bb073c72..4b3f7349435822fe77591a8b2e82915089d85c7c 100644 (file)
@@ -12,6 +12,8 @@
 
 package org.eclipse.tracecompass.tmf.remote.core.proxy;
 
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
 import java.net.URI;
 import java.text.MessageFormat;
 import java.util.HashMap;
@@ -135,7 +137,7 @@ public class TmfRemoteConnectionFactory {
                 }
 
                 if (wc.hasService(IRemoteConnectionHostService.class)) {
-                    IRemoteConnectionHostService hostService = wc.getService(IRemoteConnectionHostService.class);
+                    IRemoteConnectionHostService hostService = checkNotNull(wc.getService(IRemoteConnectionHostService.class));
                     hostService.setHostname(hostUri.getHost());
                     hostService.setPort(hostUri.getPort());
                     String user = hostUri.getUserInfo();
This page took 0.031389 seconds and 5 git commands to generate.