Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserving nullability contracts in runtime #422

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
plugins {
id 'tech.harmonysoft.oss.traute' version '1.1.8'
}

subprojects {
buildscript {
repositories {
Expand All @@ -11,6 +15,11 @@ subprojects {
}

plugins.apply('checkstyle')
apply plugin: 'tech.harmonysoft.oss.traute'

traute {
exceptionTexts = [ 'parameter': '${PARAMETER_NAME} == null' ]
}

task('checkstyle', type: Checkstyle) {
configFile rootProject.file('checkstyle.xml')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ open class ValidateBindingsTask : SourceTask() {
verifyMethodAnnotations(n)
verifyParameters(n)
verifyReturnType(n)
verifyNullChecks(n)
// Explicitly avoid going deeper, we only care about top level methods. Otherwise
// we'd hit anonymous inner classes and whatnot
}
Expand Down Expand Up @@ -88,32 +87,6 @@ open class ValidateBindingsTask : SourceTask() {
}
}

/** Validates that reference type parameters have corresponding checkNotNull calls at the beginning of the body */
fun verifyNullChecks(method: MethodDeclaration) {

val parameters = method.parameters
val statements = method.body.stmts

parameters
.filter { it.type is ReferenceType }
.map { it.id.name }
.zip(statements, { param, stmt -> Pair(param, stmt) })
.forEach {
val pName = it.first
val expected = "checkNotNull($pName, \"$pName == null\");"
val found = it.second.toString()
if (!expected.equals(found)) {
throw IllegalStateException("Missing proper checkNotNull call on parameter "
+ pName
+ " in "
+ prettyMethodSignature(method)
+ "\nExpected:\t" + expected
+ "\nFound:\t" + found
)
}
}
}

/** Generates a nice String representation of the method signature (e.g. RxView#clicks(View)) */
fun prettyMethodSignature(method: MethodDeclaration): String {
val parameterTypeNames = method.parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import android.view.MenuItem;
import io.reactivex.Observable;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} for
* {@link android.widget.ActionMenuView}.
Expand All @@ -22,7 +20,6 @@ public final class RxActionMenuView {
*/
@CheckResult @NonNull
public static Observable<MenuItem> itemClicks(@NonNull ActionMenuView view) {
checkNotNull(view, "view == null");
return new ActionMenuViewItemClickObservable(view);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import android.view.MenuItem;
import io.reactivex.Observable;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} for {@link PopupMenu}.
*/
Expand All @@ -23,7 +21,6 @@ public final class RxPopupMenu {
*/
@CheckResult @NonNull
public static Observable<MenuItem> itemClicks(@NonNull PopupMenu view) {
checkNotNull(view, "view == null");
return new PopupMenuItemClickObservable(view);
}

Expand All @@ -39,7 +36,6 @@ public static Observable<MenuItem> itemClicks(@NonNull PopupMenu view) {
*/
@CheckResult @NonNull
public static Observable<Object> dismisses(@NonNull PopupMenu view) {
checkNotNull(view, "view == null");
return new PopupMenuDismissObservable(view);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} and {@linkplain Action1
* actions} for {@link SearchView}.
Expand All @@ -26,7 +24,6 @@ public final class RxSearchView {
@CheckResult @NonNull
public static InitialValueObservable<SearchViewQueryTextEvent> queryTextChangeEvents(
@NonNull SearchView view) {
checkNotNull(view, "view == null");
return new SearchViewQueryTextChangeEventsObservable(view);
}

Expand All @@ -40,7 +37,6 @@ public static InitialValueObservable<SearchViewQueryTextEvent> queryTextChangeEv
*/
@CheckResult @NonNull
public static InitialValueObservable<CharSequence> queryTextChanges(@NonNull SearchView view) {
checkNotNull(view, "view == null");
return new SearchViewQueryTextChangesObservable(view);
}

Expand All @@ -55,7 +51,6 @@ public static InitialValueObservable<CharSequence> queryTextChanges(@NonNull Sea
@CheckResult @NonNull
public static Consumer<? super CharSequence> query(@NonNull final SearchView view,
final boolean submit) {
checkNotNull(view, "view == null");
return new Consumer<CharSequence>() {
@Override public void accept(CharSequence text) {
view.setQuery(text, submit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} for {@link Toolbar}.
*/
Expand All @@ -22,7 +20,6 @@ public final class RxToolbar {
*/
@CheckResult @NonNull
public static Observable<MenuItem> itemClicks(@NonNull Toolbar view) {
checkNotNull(view, "view == null");
return new ToolbarItemClickObservable(view);
}

Expand All @@ -38,7 +35,6 @@ public static Observable<MenuItem> itemClicks(@NonNull Toolbar view) {
*/
@CheckResult @NonNull
public static Observable<Object> navigationClicks(@NonNull Toolbar view) {
checkNotNull(view, "view == null");
return new ToolbarNavigationClickObservable(view);
}

Expand All @@ -50,7 +46,6 @@ public static Observable<Object> navigationClicks(@NonNull Toolbar view) {
*/
@CheckResult @NonNull @GenericTypeNullable
public static Consumer<? super CharSequence> title(@NonNull final Toolbar view) {
checkNotNull(view, "view == null");
return new Consumer<CharSequence>() {
@Override public void accept(CharSequence title) {
view.setTitle(title);
Expand All @@ -66,7 +61,6 @@ public static Consumer<? super CharSequence> title(@NonNull final Toolbar view)
*/
@CheckResult @NonNull
public static Consumer<? super Integer> titleRes(@NonNull final Toolbar view) {
checkNotNull(view, "view == null");
return new Consumer<Integer>() {
@Override public void accept(Integer titleRes) {
view.setTitle(titleRes);
Expand All @@ -82,7 +76,6 @@ public static Consumer<? super Integer> titleRes(@NonNull final Toolbar view) {
*/
@CheckResult @NonNull @GenericTypeNullable
public static Consumer<? super CharSequence> subtitle(@NonNull final Toolbar view) {
checkNotNull(view, "view == null");
return new Consumer<CharSequence>() {
@Override public void accept(CharSequence subtitle) {
view.setSubtitle(subtitle);
Expand All @@ -98,7 +91,6 @@ public static Consumer<? super CharSequence> subtitle(@NonNull final Toolbar vie
*/
@CheckResult @NonNull
public static Consumer<? super Integer> subtitleRes(@NonNull final Toolbar view) {
checkNotNull(view, "view == null");
return new Consumer<Integer>() {
@Override public void accept(Integer subtitleRes) {
view.setSubtitle(subtitleRes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import android.support.design.widget.AppBarLayout;
import io.reactivex.Observable;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} for {@link AppBarLayout}.
*/
Expand All @@ -20,7 +18,6 @@ public final class RxAppBarLayout {
*/
@CheckResult @NonNull
public static Observable<Integer> offsetChanges(@NonNull AppBarLayout view) {
checkNotNull(view, "view == null");
return new AppBarLayoutOffsetChangeObservable(view);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import android.view.MenuItem;
import io.reactivex.Observable;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} for
* {@link BottomNavigationView}.
Expand All @@ -24,7 +22,6 @@ public final class RxBottomNavigationView {
*/
@CheckResult @NonNull public static Observable<MenuItem> itemSelections(
@NonNull BottomNavigationView view) {
checkNotNull(view, "view == null");
return new BottomNavigationViewItemSelectionsObservable(view);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import android.view.MenuItem;
import io.reactivex.Observable;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} for
* {@link NavigationView}.
Expand All @@ -24,7 +22,6 @@ public final class RxNavigationView {
*/
@CheckResult @NonNull
public static Observable<MenuItem> itemSelections(@NonNull NavigationView view) {
checkNotNull(view, "view == null");
return new NavigationViewItemSelectionsObservable(view);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import android.support.design.widget.Snackbar;
import io.reactivex.Observable;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} for {@link Snackbar}.
*/
Expand All @@ -19,7 +17,6 @@ public final class RxSnackbar {
*/
@CheckResult @NonNull
public static Observable<Integer> dismisses(@NonNull Snackbar view) {
checkNotNull(view, "view == null");
return new SnackbarDismissesObservable(view);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import android.view.View;
import io.reactivex.Observable;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables}
* for {@link SwipeDismissBehavior} on (@link View).
Expand All @@ -22,7 +20,6 @@ public final class RxSwipeDismissBehavior {
*/
@CheckResult @NonNull
public static Observable<View> dismisses(@NonNull View view) {
checkNotNull(view, "view == null");
return new SwipeDismissBehaviorObservable(view);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Observable observables} and {@linkplain Consumer
* actions} for {@link TabLayout}.
Expand All @@ -24,7 +22,6 @@ public final class RxTabLayout {
*/
@CheckResult @NonNull
public static Observable<Tab> selections(@NonNull TabLayout view) {
checkNotNull(view, "view == null");
return new TabLayoutSelectionsObservable(view);
}

Expand All @@ -39,7 +36,6 @@ public static Observable<Tab> selections(@NonNull TabLayout view) {
*/
@CheckResult @NonNull
public static Observable<TabLayoutSelectionEvent> selectionEvents(@NonNull TabLayout view) {
checkNotNull(view, "view == null");
return new TabLayoutSelectionEventObservable(view);
}

Expand All @@ -51,7 +47,6 @@ public static Observable<TabLayoutSelectionEvent> selectionEvents(@NonNull TabLa
*/
@CheckResult @NonNull
public static Consumer<? super Integer> select(@NonNull final TabLayout view) {
checkNotNull(view, "view == null");
return new Consumer<Integer>() {
@Override public void accept(Integer index) {
if (index < 0 || index >= view.getTabCount()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import com.jakewharton.rxbinding2.internal.GenericTypeNullable;
import io.reactivex.functions.Consumer;

import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull;

/**
* Static factory methods for creating {@linkplain Consumer actions} for {@link TextInputLayout}.
*/
Expand All @@ -21,7 +19,6 @@ public final class RxTextInputLayout {
*/
@CheckResult @NonNull
public static Consumer<? super Boolean> counterEnabled(@NonNull final TextInputLayout view) {
checkNotNull(view, "view == null");
return new Consumer<Boolean>() {
@Override public void accept(Boolean enable) {
view.setCounterEnabled(enable);
Expand All @@ -37,7 +34,6 @@ public static Consumer<? super Boolean> counterEnabled(@NonNull final TextInputL
*/
@CheckResult @NonNull
public static Consumer<? super Integer> counterMaxLength(@NonNull final TextInputLayout view) {
checkNotNull(view, "view == null");
return new Consumer<Integer>() {
@Override public void accept(Integer maxLength) {
view.setCounterMaxLength(maxLength);
Expand All @@ -53,7 +49,6 @@ public static Consumer<? super Integer> counterMaxLength(@NonNull final TextInpu
*/
@CheckResult @NonNull @GenericTypeNullable
public static Consumer<? super CharSequence> error(@NonNull final TextInputLayout view) {
checkNotNull(view, "view == null");
return new Consumer<CharSequence>() {
@Override
public void accept(CharSequence error) {
Expand All @@ -70,7 +65,6 @@ public void accept(CharSequence error) {
*/
@CheckResult @NonNull @GenericTypeNullable
public static Consumer<? super Integer> errorRes(@NonNull final TextInputLayout view) {
checkNotNull(view, "view == null");
return new Consumer<Integer>() {
@Override
public void accept(Integer errorRes) {
Expand All @@ -87,7 +81,6 @@ public void accept(Integer errorRes) {
*/
@CheckResult @NonNull
public static Consumer<? super CharSequence> hint(@NonNull final TextInputLayout view) {
checkNotNull(view, "view == null");
return new Consumer<CharSequence>() {
@Override public void accept(CharSequence hint) {
view.setHint(hint);
Expand All @@ -103,7 +96,6 @@ public static Consumer<? super CharSequence> hint(@NonNull final TextInputLayout
*/
@CheckResult @NonNull
public static Consumer<? super Integer> hintRes(@NonNull final TextInputLayout view) {
checkNotNull(view, "view == null");
return new Consumer<Integer>() {
@Override public void accept(Integer hintRes) {
view.setHint(view.getContext().getResources().getText(hintRes));
Expand Down