Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-43507] Remove gratuitous use of generics in the SPI
Since every implementation needs to cast anyway, the generics signature was unnecessary.

We could use generics at the class level to provide type safety, except that would basically force 5 or 6 generic type parameters which gets very ridicluous.

Instead we just provide the guarantee that casting is always pre-checked and safe
  • Loading branch information
stephenc committed May 8, 2017
1 parent f37b494 commit eaa2c04
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 63 deletions.
35 changes: 20 additions & 15 deletions src/main/java/jenkins/scm/api/trait/SCMNavigatorTrait.java
Expand Up @@ -47,21 +47,23 @@ public class SCMNavigatorTrait extends SCMTrait<SCMNavigatorTrait> {
* @param context the context.
*/
public final void applyToContext(SCMNavigatorContext<?, ?> context) {
if (getDescriptor().isApplicableToContext(context.getClass())) {
SCMNavigatorTraitDescriptor d = getDescriptor();
if (d.getContextClass().isInstance(context) && d.isApplicableToContext(context.getClass())) {
// guard against non-applicable
decorateContext((SCMNavigatorContext) context);
decorateContext(context);
}
}

/**
* SPI: Override this method to decorate a {@link SCMNavigatorContext}. You can assume that your
* {@link SCMNavigatorTraitDescriptor#isApplicableToContext(Class)} is {@code true} within this method.
* {@link SCMNavigatorTraitDescriptor#isApplicableToContext(Class)} is {@code true} within this method and that
* the provided context is an instance of {@link SCMNavigatorTraitDescriptor#getContextClass()}.
*
* @param context the context (invariant: {@link SCMNavigatorTraitDescriptor#isApplicableToContext(Class)} is {@code true})
* @param <B> generic type parameter to ensure type information available.
* @param <R> generic type parameter to ensure type information available.
* @param context the context (invariant: {@link SCMNavigatorTraitDescriptor#isApplicableToContext(Class)} is {@code
* true} and {@link SCMNavigatorTraitDescriptor#getContextClass()} {@link Class#isInstance(Object)})
* is {@code true})
*/
protected <B extends SCMNavigatorContext<B, R>, R extends SCMNavigatorRequest> void decorateContext(B context) {
protected void decorateContext(SCMNavigatorContext<?, ?> context) {
}

/**
Expand Down Expand Up @@ -92,22 +94,25 @@ protected SCMSourceObserver decorateObserver(@NonNull SCMSourceObserver observer
* @param builder the builder.
*/
public final void applyToBuilder(SCMSourceBuilder<?, ?> builder) {
if (!getDescriptor().isApplicableToBuilder(builder)) {
SCMNavigatorTraitDescriptor d = getDescriptor();
if (d.getBuilderClass().isInstance(builder) && d.isApplicableToBuilder(builder)) {
// guard against non-applicable
decorateBuilder(builder);
}
decorateBuilder((SCMSourceBuilder) builder);
}

/**
* SPI: Override this method to decorate a {@link SCMBuilder}. You can assume that your
* {@link SCMSourceTraitDescriptor#isApplicableToBuilder(SCMBuilder)} is {@code true} within this method.
* {@link SCMNavigatorTraitDescriptor#isApplicableToBuilder(SCMSourceBuilder)} is {@code true} within this method
* and that
* the provided builder is an instance of {@link SCMNavigatorTraitDescriptor#getBuilderClass()}.
*
* @param builder the builder (invariant: {@link SCMSourceTraitDescriptor#isApplicableToBuilder(SCMBuilder)} is
* {@code true})
* @param <B> generic type parameter to ensure type information available.
* @param <S> generic type parameter to ensure type information available.
* @param builder the builder (invariant:
* {@link SCMNavigatorTraitDescriptor#isApplicableToBuilder(SCMSourceBuilder)} is
* {@code true} and {@link SCMNavigatorTraitDescriptor#getBuilderClass()}
* {@link Class#isInstance(Object)}) is {@code true})
*/
protected <B extends SCMSourceBuilder<B, S>, S extends SCMSource> void decorateBuilder(B builder) {
protected void decorateBuilder(SCMSourceBuilder<?, ?> builder) {
}

/**
Expand Down
45 changes: 24 additions & 21 deletions src/main/java/jenkins/scm/api/trait/SCMSourceTrait.java
Expand Up @@ -24,12 +24,11 @@

package jenkins.scm.api.trait;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.DescriptorExtensionList;
import hudson.scm.SCM;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.CheckForNull;
import jenkins.scm.api.SCMHeadCategory;
import jenkins.scm.api.SCMHeadObserver;
import jenkins.scm.api.SCMSource;
Expand All @@ -48,22 +47,23 @@ public class SCMSourceTrait extends SCMTrait<SCMSourceTrait> {
* @param context the context.
*/
public final void applyToContext(SCMSourceContext<?, ?> context) {
if (getDescriptor().isApplicableToContext(context.getClass())) {
SCMSourceTraitDescriptor d = getDescriptor();
if (d.getContextClass().isInstance(context) && d.isApplicableToContext(context.getClass())) {
// guard against non-applicable
decorateContext((SCMSourceContext) context);
decorateContext(context);
}
}

/**
* SPI: Override this method to decorate a {@link SCMSourceContext}. You can assume that your
* {@link SCMSourceTraitDescriptor#isApplicableToContext(Class)} is {@code true} within this method.
* {@link SCMSourceTraitDescriptor#isApplicableToContext(Class)} is {@code true} within this method and that
* the provided context is an instance of {@link SCMSourceTraitDescriptor#getContextClass()}.
*
* @param context the context (invariant: {@link SCMSourceTraitDescriptor#isApplicableToContext(Class)} is {@code
* true})
* @param <B> generic type parameter to ensure type information available.
* @param <R> generic type parameter to ensure type information available.
* true} and {@link SCMSourceTraitDescriptor#getContextClass()} {@link Class#isInstance(Object)})
* is {@code true})
*/
protected <B extends SCMSourceContext<B, R>, R extends SCMSourceRequest> void decorateContext(B context) {
protected void decorateContext(SCMSourceContext<?, ?> context) {
}

/**
Expand Down Expand Up @@ -94,22 +94,23 @@ protected SCMHeadObserver decorateObserver(@NonNull SCMHeadObserver observer) {
* @param builder the builder.
*/
public final void applyToBuilder(SCMBuilder<?, ?> builder) {
if (!getDescriptor().isApplicableToBuilder(builder)) {
SCMSourceTraitDescriptor d = getDescriptor();
if (d.getBuilderClass().isInstance(builder) && d.isApplicableToBuilder(builder)) {
// guard against non-applicable
decorateBuilder(builder);
}
decorateBuilder((SCMBuilder) builder);
}

/**
* SPI: Override this method to decorate a {@link SCMBuilder}. You can assume that your
* {@link SCMSourceTraitDescriptor#isApplicableToBuilder(SCMBuilder)} is {@code true} within this method.
* {@link SCMSourceTraitDescriptor#isApplicableToBuilder(SCMBuilder)} is {@code true} within this method and that
* the provided builder is an instance of {@link SCMSourceTraitDescriptor#getBuilderClass()}.
*
* @param builder the builder (invariant: {@link SCMSourceTraitDescriptor#isApplicableToBuilder(SCMBuilder)} is
* {@code true})
* @param <B> generic type parameter to ensure type information available.
* @param <S> generic type parameter to ensure type information available.
* {@code true} and {@link SCMSourceTraitDescriptor#getBuilderClass()}
* {@link Class#isInstance(Object)}) is {@code true})
*/
protected <B extends SCMBuilder<B, S>, S extends SCM> void decorateBuilder(B builder) {
protected void decorateBuilder(SCMBuilder<?, ?> builder) {
}

/**
Expand Down Expand Up @@ -157,8 +158,9 @@ public static DescriptorExtensionList<SCMSourceTrait, SCMSourceTraitDescriptor>
* @param builderClass (optional) type of {@link SCMBuilder}.
* @return the list of matching {@link SCMSourceTraitDescriptor} instances.
*/
public static List<SCMSourceTraitDescriptor> _for(Class<? extends SCMSourceContext> contextClass,
Class<? extends SCMBuilder> builderClass) {
public static List<SCMSourceTraitDescriptor> _for(
@CheckForNull Class<? extends SCMSourceContext> contextClass,
@CheckForNull Class<? extends SCMBuilder> builderClass) {
return _for(null, contextClass, builderClass);
}

Expand All @@ -171,9 +173,10 @@ public static List<SCMSourceTraitDescriptor> _for(Class<? extends SCMSourceConte
* @param builderClass (optional) type of {@link SCMBuilder}.
* @return the list of matching {@link SCMSourceTraitDescriptor} instances.
*/
public static List<SCMSourceTraitDescriptor> _for(@CheckForNull SCMSourceDescriptor scmSource,
@CheckForNull Class<? extends SCMSourceContext> contextClass,
@CheckForNull Class<? extends SCMBuilder> builderClass) {
public static List<SCMSourceTraitDescriptor> _for(
@CheckForNull SCMSourceDescriptor scmSource,
@CheckForNull Class<? extends SCMSourceContext> contextClass,
@CheckForNull Class<? extends SCMBuilder> builderClass) {
List<SCMSourceTraitDescriptor> result = new ArrayList<SCMSourceTraitDescriptor>();
if (scmSource != null) {
for (SCMSourceTraitDescriptor d : all()) {
Expand Down
Expand Up @@ -34,7 +34,6 @@
import jenkins.scm.api.SCMSource;
import jenkins.scm.api.trait.SCMHeadPrefilter;
import jenkins.scm.api.trait.SCMSourceContext;
import jenkins.scm.api.trait.SCMSourceRequest;
import jenkins.scm.api.trait.SCMSourceTrait;
import jenkins.scm.api.trait.SCMSourceTraitDescriptor;
import org.kohsuke.accmod.Restricted;
Expand Down Expand Up @@ -100,7 +99,7 @@ private Pattern getPattern() {
* {@inheritDoc}
*/
@Override
protected <B extends SCMSourceContext<B, R>, R extends SCMSourceRequest> void decorateContext(B context) {
protected void decorateContext(SCMSourceContext<?, ?> context) {
context.withPrefilter(new SCMHeadPrefilter() {
@Override
public boolean isExcluded(@NonNull SCMSource source, @NonNull SCMHead head) {
Expand Down
Expand Up @@ -32,7 +32,6 @@
import java.util.regex.PatternSyntaxException;
import jenkins.scm.api.SCMNavigator;
import jenkins.scm.api.trait.SCMNavigatorContext;
import jenkins.scm.api.trait.SCMNavigatorRequest;
import jenkins.scm.api.trait.SCMNavigatorTrait;
import jenkins.scm.api.trait.SCMNavigatorTraitDescriptor;
import jenkins.scm.api.trait.SCMSourcePrefilter;
Expand Down Expand Up @@ -99,7 +98,7 @@ private Pattern getPattern() {
* {@inheritDoc}
*/
@Override
protected <B extends SCMNavigatorContext<B, R>, R extends SCMNavigatorRequest> void decorateContext(B context) {
protected void decorateContext(SCMNavigatorContext<?, ?> context) {
context.withPrefilter(new SCMSourcePrefilter() {
@Override
public boolean isExcluded(@NonNull SCMNavigator source, @NonNull String projectName) {
Expand Down
Expand Up @@ -32,7 +32,6 @@
import jenkins.scm.api.SCMSource;
import jenkins.scm.api.trait.SCMHeadPrefilter;
import jenkins.scm.api.trait.SCMSourceContext;
import jenkins.scm.api.trait.SCMSourceRequest;
import jenkins.scm.api.trait.SCMSourceTrait;
import jenkins.scm.api.trait.SCMSourceTraitDescriptor;
import org.apache.commons.lang.StringUtils;
Expand Down Expand Up @@ -92,7 +91,7 @@ public String getExcludes() {
* {@inheritDoc}
*/
@Override
protected <B extends SCMSourceContext<B, R>, R extends SCMSourceRequest> void decorateContext(B context) {
protected void decorateContext(SCMSourceContext<?, ?> context) {
context.withPrefilter(new SCMHeadPrefilter() {
@Override
public boolean isExcluded(@NonNull SCMSource request, @NonNull SCMHead head) {
Expand Down
Expand Up @@ -29,7 +29,6 @@
import java.util.regex.Pattern;
import jenkins.scm.api.SCMNavigator;
import jenkins.scm.api.trait.SCMNavigatorContext;
import jenkins.scm.api.trait.SCMNavigatorRequest;
import jenkins.scm.api.trait.SCMNavigatorTrait;
import jenkins.scm.api.trait.SCMNavigatorTraitDescriptor;
import jenkins.scm.api.trait.SCMSourcePrefilter;
Expand Down Expand Up @@ -90,7 +89,7 @@ public String getExcludes() {
* {@inheritDoc}
*/
@Override
protected <B extends SCMNavigatorContext<B, R>, R extends SCMNavigatorRequest> void decorateContext(B context) {
protected void decorateContext(SCMNavigatorContext<?, ?> context) {
context.withPrefilter(new SCMSourcePrefilter() {
@Override
public boolean isExcluded(@NonNull SCMNavigator source, @NonNull String projectName) {
Expand Down
Expand Up @@ -26,9 +26,8 @@

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import jenkins.scm.api.trait.SCMBuilder;
import jenkins.scm.api.SCMHeadCategory;
import jenkins.scm.api.trait.SCMSourceRequest;
import jenkins.scm.api.trait.SCMBuilder;
import jenkins.scm.api.trait.SCMSourceContext;
import jenkins.scm.api.trait.SCMSourceTrait;
import jenkins.scm.api.trait.SCMSourceTraitDescriptor;
Expand All @@ -41,10 +40,8 @@ public MockSCMDiscoverBranches() {
}

@Override
protected <B extends SCMSourceContext<B, R>, R extends SCMSourceRequest> void decorateContext(B context) {
if (context instanceof MockSCMSourceContext) {
((MockSCMSourceContext) context).withBranches(true);
}
protected void decorateContext(SCMSourceContext<?, ?> context) {
((MockSCMSourceContext) context).withBranches(true);
}

@Override
Expand Down
Expand Up @@ -30,11 +30,10 @@
import java.util.Collection;
import java.util.EnumSet;
import java.util.Set;
import jenkins.scm.api.trait.SCMBuilder;
import jenkins.scm.api.SCMHeadCategory;
import jenkins.scm.api.mixin.ChangeRequestCheckoutStrategy;
import jenkins.scm.api.trait.SCMBuilder;
import jenkins.scm.api.trait.SCMSourceContext;
import jenkins.scm.api.trait.SCMSourceRequest;
import jenkins.scm.api.trait.SCMSourceTrait;
import jenkins.scm.api.trait.SCMSourceTraitDescriptor;
import jenkins.scm.impl.ChangeRequestSCMHeadCategory;
Expand Down Expand Up @@ -81,11 +80,10 @@ public String getStrategiesStr() {


@Override
protected <B extends SCMSourceContext<B, R>, R extends SCMSourceRequest> void decorateContext(B context) {
if (context instanceof MockSCMSourceContext) {
((MockSCMSourceContext) context).withChangeRequests(true);
((MockSCMSourceContext) context).withCheckoutStrategies(strategies);
}
protected void decorateContext(SCMSourceContext<?, ?> context) {
MockSCMSourceContext ctx = (MockSCMSourceContext) context;
ctx.withChangeRequests(true);
ctx.withCheckoutStrategies(strategies);
}

@Override
Expand Down
9 changes: 3 additions & 6 deletions src/test/java/jenkins/scm/impl/mock/MockSCMDiscoverTags.java
Expand Up @@ -26,10 +26,9 @@

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import jenkins.scm.api.trait.SCMBuilder;
import jenkins.scm.api.SCMHeadCategory;
import jenkins.scm.api.trait.SCMBuilder;
import jenkins.scm.api.trait.SCMSourceContext;
import jenkins.scm.api.trait.SCMSourceRequest;
import jenkins.scm.api.trait.SCMSourceTrait;
import jenkins.scm.api.trait.SCMSourceTraitDescriptor;
import jenkins.scm.impl.TagSCMHeadCategory;
Expand All @@ -42,10 +41,8 @@ public MockSCMDiscoverTags() {
}

@Override
protected <B extends SCMSourceContext<B, R>, R extends SCMSourceRequest> void decorateContext(B context) {
if (context instanceof MockSCMSourceContext) {
((MockSCMSourceContext) context).withTags(true);
}
protected void decorateContext(SCMSourceContext<?, ?> context) {
((MockSCMSourceContext) context).withTags(true);
}

@Override
Expand Down

0 comments on commit eaa2c04

Please sign in to comment.