Skip to content

Commit

Permalink
Ban the var keyword via error-prone VarUsage (#1788)
Browse files Browse the repository at this point in the history
Ban the var keyword via error-prone `VarUsage`
  • Loading branch information
carterkozak authored Jun 14, 2021
1 parent 4bd8764 commit 770175c
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* (c) Copyright 2020 Palantir Technologies Inc. All rights reserved.
*
* 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.palantir.baseline.errorprone;

import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.BugPattern.LinkType;
import com.google.errorprone.BugPattern.SeverityLevel;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.util.ASTHelpers;
import com.google.errorprone.util.ErrorProneToken;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.parser.Tokens.TokenKind;

@AutoService(BugChecker.class)
@BugPattern(
name = "VarUsage",
link = "https://github.com/palantir/gradle-baseline#baseline-error-prone-checks",
linkType = LinkType.CUSTOM,
severity = SeverityLevel.ERROR,
summary = "The `var` keyword results in illegible code in most cases and should not be used.")
public final class VarUsage extends BugChecker implements BugChecker.VariableTreeMatcher {

@Override
public Description matchVariable(VariableTree tree, VisitorState state) {
Tree typeTree = tree.getType();
// The AST doesn't differentiate between 'var' and a concrete type, so we check the source
// prior to tokenizing the variable tree.
String sourceType = state.getSourceForNode(typeTree);
if (sourceType != null) {
return Description.NO_MATCH;
}
for (ErrorProneToken token : state.getOffsetTokensForNode(tree)) {
if (token.kind() == TokenKind.IDENTIFIER
&& token.hasName()
&& token.name().contentEquals("var")) {
SuggestedFix.Builder fix = SuggestedFix.builder();
return buildDescription(typeTree)
.addFix(fix.replace(
token.pos(),
token.endPos(),
SuggestedFixes.prettyType(state, fix, ASTHelpers.getType(typeTree)))
.build())
.build();
}
}
return Description.NO_MATCH;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* (c) Copyright 2021 Palantir Technologies Inc. All rights reserved.
*
* 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.palantir.baseline.errorprone;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;

class VarUsageTest {

@Test
@EnabledForJreRange(min = JRE.JAVA_10)
void testSimple() {
fix().addInputLines(
"Test.java",
// format
"class Test {",
" void function() {",
" var x = 3;",
" }",
"}")
.addOutputLines(
"Test.java",
// format
"class Test {",
" void function() {",
" int x = 3;",
" }",
"}")
.doTest();
}

@Test
@EnabledForJreRange(min = JRE.JAVA_10)
void testWithFinalModifier() {
fix().addInputLines(
"Test.java",
// format
"class Test {",
" void function() {",
" final var x = 3;",
" }",
"}")
.addOutputLines(
"Test.java",
// format
"class Test {",
" void function() {",
" final int x = 3;",
" }",
"}")
.doTest();
}

private RefactoringValidator fix() {
return RefactoringValidator.of(VarUsage.class, getClass());
}
}
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-1788.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: Ban the var keyword via error-prone `VarUsage`
links:
- https://github.com/palantir/gradle-baseline/pull/1788
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class BaselineErrorProneExtension {
// TODO(ckozak): re-enable pending scala check
// "ThrowSpecificity",
"UnsafeGaugeRegistration",
"VarUsage",

// Built-in checks
"ArrayEquals",
Expand Down

0 comments on commit 770175c

Please sign in to comment.