Skip to content

Commit

Permalink
add NegativeBoolean check
Browse files Browse the repository at this point in the history
Limited to local variables beginning with 'no' or 'not', and only flag on changed lines.

Local run on //java/com/google/common: unknown commit
Flume run: unknown commit

PiperOrigin-RevId: 707232893
  • Loading branch information
java-team-github-bot authored and Error Prone Team committed Dec 17, 2024
1 parent e514b70 commit a6b2442
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2024 The Error Prone Authors.
*
* 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.errorprone.bugpatterns;

import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.util.ASTHelpers.getSymbol;

import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
import com.google.errorprone.matchers.Description;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Symbol;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.lang.model.element.ElementKind;
import javax.lang.model.type.TypeKind;

/** Discourages the use of negative boolean names. */
@BugPattern(summary = "Prefer positive boolean names", severity = WARNING)
public final class NegativeBoolean extends BugChecker implements VariableTreeMatcher {

// Match names beginning with 'no' or 'not'
private static final Pattern NEGATIVE_NAME = Pattern.compile("^not?[A-Z].*$");

@Override
public Description matchVariable(VariableTree node, VisitorState state) {
// Only consider local variables of type boolean
Symbol symbol = getSymbol(node);
if (!symbol.getKind().equals(ElementKind.LOCAL_VARIABLE)) {
return Description.NO_MATCH;
}
if (!symbol.asType().getKind().equals(TypeKind.BOOLEAN)) {
return Description.NO_MATCH;
}

if (isNegativeName(symbol.getSimpleName().toString())) {
return describeMatch(node);
}
return Description.NO_MATCH;
}

private static boolean isNegativeName(String name) {
Matcher m = NEGATIVE_NAME.matcher(name);
return m.matches();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@
import com.google.errorprone.bugpatterns.NamedLikeContextualKeyword;
import com.google.errorprone.bugpatterns.NarrowCalculation;
import com.google.errorprone.bugpatterns.NarrowingCompoundAssignment;
import com.google.errorprone.bugpatterns.NegativeBoolean;
import com.google.errorprone.bugpatterns.NegativeCharLiteral;
import com.google.errorprone.bugpatterns.NestedInstanceOfConditions;
import com.google.errorprone.bugpatterns.NewFileSystem;
Expand Down Expand Up @@ -1216,6 +1217,7 @@ public static ScannerSupplier warningChecks() {
MultiVariableDeclaration.class,
MultipleTopLevelClasses.class,
MutableGuiceModule.class,
NegativeBoolean.class,
NoAllocationChecker.class,
NonCanonicalStaticMemberImport.class,
NonFinalStaticField.class, // Intentionally disabled in OSS.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright 2024 The Error Prone Authors.
*
* 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.errorprone.bugpatterns;

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

@RunWith(JUnit4.class)
public final class NegativeBooleanTest {

private final CompilationTestHelper testHelper =
CompilationTestHelper.newInstance(NegativeBoolean.class, getClass());

@Test
public void prefix_no_isFlagged() {
testHelper
.addSourceLines(
"Test.java",
"""
class Test {
void foo() {
// BUG: Diagnostic contains: Prefer positive
boolean noBar;
}
}
""")
.doTest();
}

@Test
public void prefix_not_isFlagged() {
testHelper
.addSourceLines(
"Test.java",
"""
class Test {
void foo() {
// BUG: Diagnostic contains: Prefer positive
boolean notBar;
}
}
""")
.doTest();
}

@Test
public void prefix_notable_isNotFlagged() {
testHelper
.addSourceLines(
"Test.java",
"""
class Test {
void foo() {
boolean notableBar;
}
}
""")
.doTest();
}

@Test
public void integer_isNotFlagged() {
testHelper
.addSourceLines(
"Test.java",
"""
class Test {
void foo() {
int notBar;
}
}
""")
.doTest();
}

@Test
public void parameter_isNotFlagged() {
testHelper
.addSourceLines(
"Test.java",
"""
class Test {
void foo(boolean notBar) {
return;
}
}
""")
.doTest();
}
}

0 comments on commit a6b2442

Please sign in to comment.