Skip to content

Commit

Permalink
Merge pull request #1690 from mockito/opensource-mockito-internal-usage
Browse files Browse the repository at this point in the history
Add ErrorProne MockitoInternalUsage checker
  • Loading branch information
TimvdLippe committed Apr 30, 2019
2 parents 340ef34 + 82d2ade commit 87a012b
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2017 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.errorprone.bugpatterns;

import static com.google.errorprone.matchers.Matchers.packageStartsWith;

import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.BugPattern.ProvidesFix;
import com.google.errorprone.BugPattern.SeverityLevel;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.MemberSelectTreeMatcher;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Symbol;

/**
* {@link com.google.errorprone.bugpatterns.BugChecker} that detects usages of
* org.mockito.internal.*
*/
@AutoService(BugChecker.class)
@BugPattern(
name = "MockitoInternalUsage",
summary = "org.mockito.internal.* is a private API and should not be used by clients",
explanation =
"Classes under `org.mockito.internal.*` are internal implementation details and are"
+ " not part of Mockito's public API. Mockito team does not support them, and they"
+ " may change at any time. Depending on them may break your code when you upgrade"
+ " to new versions of Mockito."
+ "This checker ensures that your code will not break with future Mockito upgrades."
+ "Mockito's public API is documented at"
+ " https://www.javadoc.io/doc/org.mockito/mockito-core/. If you believe that there"
+ " is no replacement available in the public API for your use-case, contact the"
+ " Mockito team at https://github.com/mockito/mockito/issues.",
severity = SeverityLevel.WARNING,
providesFix = ProvidesFix.REQUIRES_HUMAN_ATTENTION)
public class MockitoInternalUsage extends BugChecker implements MemberSelectTreeMatcher {

private static final Matcher<Tree> INSIDE_MOCKITO = packageStartsWith("org.mockito");

@Override
public Description matchMemberSelect(MemberSelectTree tree, VisitorState state) {
if (INSIDE_MOCKITO.matches(tree, state)) {
return Description.NO_MATCH;
}
Symbol symbol = ASTHelpers.getSymbol(tree);
if (symbol != null && symbol.getQualifiedName().toString().startsWith("org.mockito.internal")) {
return describeMatch(tree);
}
return Description.NO_MATCH;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2017 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.errorprone.bugpatterns;

import com.google.errorprone.CompilationTestHelper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
* Verify that there are no usages of Mockito internal implementations.
*
* @author tvanderlippe@google.com (Tim van der Lippe)
*/
@RunWith(JUnit4.class)
public class MockitoInternalUsageTest {

private CompilationTestHelper compilationHelper;

@Before
public void setUp() {
compilationHelper = CompilationTestHelper.newInstance(MockitoInternalUsage.class, getClass());
}

@Test
public void testPositiveCases() {
compilationHelper
.addSourceLines(
"Test.java",
"import java.io.Serializable;",
"class MockitoInternalUsagePositiveCases {",
" public void newObject() {",
" // BUG: Diagnostic contains:",
" new org.mockito.internal.MockitoCore();",
" // BUG: Diagnostic contains:",
" new InternalConsumer(new org.mockito.internal.MockitoCore());",
" }",
" public void staticMethodInvocation() {",
" // BUG: Diagnostic contains:",
" org.mockito.internal.configuration.GlobalConfiguration.validate();",
" }",
" public void variableTypeDeclaration() {",
" // BUG: Diagnostic contains:",
" org.mockito.internal.stubbing.InvocationContainerImpl container = null;",
" }",
" // BUG: Diagnostic contains:",
" class ExtendsClause extends org.mockito.internal.MockitoCore {}",
" // BUG: Diagnostic contains:",
" abstract class ImplementsClause implements"
+ " org.mockito.internal.junit.MockitoTestListener {}",
" abstract class SecondImplementsClause",
" // BUG: Diagnostic contains:",
" implements Serializable, org.mockito.internal.junit.MockitoTestListener {}",
" // BUG: Diagnostic contains:",
" class ExtendsGeneric<T extends org.mockito.internal.stubbing.InvocationContainerImpl>"
+ " {}",
" // BUG: Diagnostic contains:",
" class SecondExtendsGeneric<R, T extends"
+ " org.mockito.internal.stubbing.InvocationContainerImpl> {}",
" class FieldClause {",
" // BUG: Diagnostic contains:",
" org.mockito.internal.MockitoCore core;",
" }",
" class MethodArgumentClause {",
" // BUG: Diagnostic contains:",
" public void methodArgument(org.mockito.internal.MockitoCore core) {}",
" }",
" static class InternalConsumer {",
" // BUG: Diagnostic contains:",
" InternalConsumer(org.mockito.internal.MockitoCore core) {}",
" }",
"}")
.doTest();
}

@Test
public void testPositiveImportsCases() {
compilationHelper
.addSourceLines(
"Test.java",
"package foo;",
"// BUG: Diagnostic contains:",
"import org.mockito.internal.MockitoCore;",
"// BUG: Diagnostic contains:",
"import org.mockito.internal.stubbing.InvocationContainerImpl;",
"// BUG: Diagnostic contains:",
"import org.mockito.internal.*;",
"class Test {}")
.doTest();
}

@Test
public void testNegativeCases() {
compilationHelper
.addSourceLines(
"Test.java",
"package org.mockito;",
"import org.mockito.internal.MockitoCore;",
"class Mockito {}")
.doTest();
}
}

0 comments on commit 87a012b

Please sign in to comment.