Skip to content

Commit

Permalink
Enforce Google Java Format for PiranhaJava (#34)
Browse files Browse the repository at this point in the history
This patch:

1. Runs GJF on all existing Java files under `java/`
2. Updates the sample app original and expected output under 
    `sample/src/main/resources/com/uber/mylib/`
3. Sets up the build so that GJF is added as a git pre-commit hook
    whenever `./gradlew` is run under `java/`
4. Adds `verGJF` to the travis build for PiranhaJava, which will 
    fail the build on any non-GJF formatted java files.
  • Loading branch information
lazaroclapp committed Apr 20, 2020
1 parent c8c5965 commit dd050f8
Show file tree
Hide file tree
Showing 16 changed files with 651 additions and 532 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ matrix:
before_script:
- cd java/
script:
- ./gradlew build
- ./gradlew verGJF build
after_success:
- ./gradlew jacocoTestReport coveralls
cache:
Expand Down
14 changes: 14 additions & 0 deletions java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ subprojects { project ->
errorproneJavac deps.build.errorProneJavac
}
project.tasks.withType(JavaCompile) {
dependsOn(installGitHooks)
options.compilerArgs += [
"-Xlint:unchecked",
"-Xlint:rawtypes"
Expand All @@ -57,3 +58,16 @@ subprojects { project ->
googleJavaFormat {
toolVersion = "1.6"
}

////////////////////////////////////////////////////////////////////////
//
// Google Java Format pre-commit hook installation
//

tasks.register('installGitHooks', Copy) {
from(file('config/hooks/pre-commit-stub')) {
rename 'pre-commit-stub', 'pre-commit'
}
into file('../.git/hooks')
fileMode 0777
}
14 changes: 14 additions & 0 deletions java/config/hooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

set -e

REPO_ROOT_DIR="$(git rev-parse --show-toplevel)"

pushd "${REPO_ROOT_DIR}/java" > /dev/null
files=$((git diff --cached --name-only --diff-filter=ACMR | grep -Ei "\.java$" | sed -e 's/^java\///') || true)
if [ ! -z "${files}" ]; then
comma_files=$(echo "$files" | paste -s -d "," -)
"${REPO_ROOT_DIR}/java/gradlew" goJF -DgoogleJavaFormat.include="$comma_files" &>/dev/null
git add $(echo "$files" | paste -s -d " " -)
fi
popd > /dev/null
15 changes: 15 additions & 0 deletions java/config/hooks/pre-commit-stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

# stub pre-commit hook
# just a runner for the real pre-commit script
# if script cannot be found, exit without error
# (to not block local commits)

set -e

REPO_ROOT_DIR="$(git rev-parse --show-toplevel)"
PRE_COMMIT_SCRIPT="${REPO_ROOT_DIR}/java/config/hooks/pre-commit"

if [ -f $PRE_COMMIT_SCRIPT ]; then
source $PRE_COMMIT_SCRIPT
fi
19 changes: 8 additions & 11 deletions java/piranha/src/main/java/com/uber/piranha/PiranhaUtils.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
/**
* Copyright (c) 2019 Uber Technologies, Inc.
* Copyright (c) 2019 Uber Technologies, Inc.
*
* 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
* <p>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
* <p>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.
* <p>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.uber.piranha;

Expand All @@ -20,5 +18,4 @@ public class PiranhaUtils {
"//[PIRANHA_DELETE_FILE_SEQ] Delete this class.\n";

public static final String HELPER_CLASS = "// [PIRANHA_STALE_PLUGIN_HELPER_CLASS]";

}
256 changes: 126 additions & 130 deletions java/piranha/src/main/java/com/uber/piranha/UsageCounter.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
/**
* Copyright (c) 2019 Uber Technologies, Inc.
* Copyright (c) 2019 Uber Technologies, Inc.
*
* 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
* <p>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
* <p>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.
* <p>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.uber.piranha;

Expand All @@ -34,147 +32,145 @@
import java.util.Map;
import java.util.Set;

/**
* Originally from com.uber.errorprone.checker.dagger.UsageCounter
*/
/** Originally from com.uber.errorprone.checker.dagger.UsageCounter */
public final class UsageCounter {

private UsageCounter() {
/* Helper class only, not instantiable */
private UsageCounter() {
/* Helper class only, not instantiable */
}

private static boolean symbolHasSuppressUnusedCheckerWarningsAnnotation(
Symbol symbol, String checkerName) {
SuppressWarnings annotation = symbol.getAnnotation(SuppressWarnings.class);
if (annotation != null) {
for (String s : annotation.value()) {
if (s.equals(checkerName)) return true;
}
}

private static boolean symbolHasSuppressUnusedCheckerWarningsAnnotation(
Symbol symbol, String checkerName) {
SuppressWarnings annotation = symbol.getAnnotation(SuppressWarnings.class);
if (annotation != null) {
for (String s : annotation.value()) {
if (s.equals(checkerName)) return true;
}
}
return false;
return false;
}

public static ImmutableMap<Symbol, CounterData> getUsageCounts(VisitorState state) {
return getUsageCounts(state, state.getPath());
}

public static ImmutableMap<Symbol, CounterData> getUsageCounts(
VisitorState state, TreePath path) {
UsageCounter.CallScanner callScanner = new UsageCounter.CallScanner(state);
callScanner.scan(path, null);
ImmutableMap.Builder<Symbol, CounterData> builder = ImmutableMap.builder();
for (VariableTree decl : callScanner.declaredInjectVars) {
Symbol s = ASTHelpers.getSymbol(decl);
CounterData counterData =
new CounterData(
DeclType.FIELD,
decl,
(callScanner.usedVars.containsKey(s) ? callScanner.usedVars.get(s) : 0));
builder.put(s, counterData);
}

public static ImmutableMap<Symbol, CounterData> getUsageCounts(VisitorState state) {
return getUsageCounts(state, state.getPath());
for (VariableTree decl : callScanner.declaredParamVars.keySet()) {
Symbol s = ASTHelpers.getSymbol(decl);
Symbol.MethodSymbol mSym = callScanner.declaredParamVars.get(decl);
CounterData counterData =
new CounterData(
DeclType.PARAM,
decl,
(callScanner.usedVars.containsKey(s) ? callScanner.usedVars.get(s) : 0));
builder.put(s, counterData);
}
return builder.build();
}

public static ImmutableMap<Symbol, Integer> getRawUsageCounts(Tree tree) {
RawUsageCountsScanner scanner = new RawUsageCountsScanner();
scanner.scan(tree, null);
return ImmutableMap.copyOf(scanner.usedVars);
}

private static void addUse(Map<Symbol, Integer> usedVars, Symbol symbol) {
if (usedVars.containsKey(symbol)) {
usedVars.put(symbol, usedVars.get(symbol) + 1);
} else {
usedVars.put(symbol, 1);
}
}

public static ImmutableMap<Symbol, CounterData> getUsageCounts(
VisitorState state, TreePath path) {
UsageCounter.CallScanner callScanner = new UsageCounter.CallScanner(state);
callScanner.scan(path, null);
ImmutableMap.Builder<Symbol, CounterData> builder = ImmutableMap.builder();
for (VariableTree decl : callScanner.declaredInjectVars) {
Symbol s = ASTHelpers.getSymbol(decl);
CounterData counterData =
new CounterData(
DeclType.FIELD,
decl,
(callScanner.usedVars.containsKey(s) ? callScanner.usedVars.get(s) : 0));
builder.put(s, counterData);
}
static class CallScanner extends TreePathScanner<Void, Void> {
final Set<VariableTree> declaredInjectVars = new LinkedHashSet<>();
final HashMap<VariableTree, Symbol.MethodSymbol> declaredParamVars =
new HashMap<VariableTree, Symbol.MethodSymbol>();
final Map<Symbol, Integer> usedVars = new LinkedHashMap<>();
final VisitorState state;

for (VariableTree decl : callScanner.declaredParamVars.keySet()) {
Symbol s = ASTHelpers.getSymbol(decl);
Symbol.MethodSymbol mSym = callScanner.declaredParamVars.get(decl);
CounterData counterData =
new CounterData(
DeclType.PARAM,
decl,
(callScanner.usedVars.containsKey(s) ? callScanner.usedVars.get(s) : 0));
builder.put(s, counterData);
}
return builder.build();
CallScanner(VisitorState state) {
this.state = state;
}

public static ImmutableMap<Symbol, Integer> getRawUsageCounts(Tree tree) {
RawUsageCountsScanner scanner = new RawUsageCountsScanner();
scanner.scan(tree, null);
return ImmutableMap.copyOf(scanner.usedVars);
@Override
public Void visitMemberSelect(MemberSelectTree tree, Void unused) {
addUse(usedVars, ASTHelpers.getSymbol(tree));
return super.visitMemberSelect(tree, null);
}

private static void addUse(Map<Symbol, Integer> usedVars, Symbol symbol) {
if (usedVars.containsKey(symbol)) {
usedVars.put(symbol, usedVars.get(symbol) + 1);
} else {
usedVars.put(symbol, 1);
}
@Override
public Void visitIdentifier(IdentifierTree tree, Void unused) {
addUse(usedVars, ASTHelpers.getSymbol(tree));
return super.visitIdentifier(tree, null);
}

static class CallScanner extends TreePathScanner<Void, Void> {
final Set<VariableTree> declaredInjectVars = new LinkedHashSet<>();
final HashMap<VariableTree, Symbol.MethodSymbol> declaredParamVars =
new HashMap<VariableTree, Symbol.MethodSymbol>();
final Map<Symbol, Integer> usedVars = new LinkedHashMap<>();
final VisitorState state;

CallScanner(VisitorState state) {
this.state = state;
}

@Override
public Void visitMemberSelect(MemberSelectTree tree, Void unused) {
addUse(usedVars, ASTHelpers.getSymbol(tree));
return super.visitMemberSelect(tree, null);
}

@Override
public Void visitIdentifier(IdentifierTree tree, Void unused) {
addUse(usedVars, ASTHelpers.getSymbol(tree));
return super.visitIdentifier(tree, null);
}

@Override
public Void visitMethod(MethodTree tree, Void unused) {
Symbol.MethodSymbol mSym = ASTHelpers.getSymbol(tree);
if (ASTHelpers.hasAnnotation(mSym, "dagger.Provides", state)) {
for (VariableTree vt : tree.getParameters()) {
declaredParamVars.put(vt, mSym);
}
}
return super.visitMethod(tree, null);
@Override
public Void visitMethod(MethodTree tree, Void unused) {
Symbol.MethodSymbol mSym = ASTHelpers.getSymbol(tree);
if (ASTHelpers.hasAnnotation(mSym, "dagger.Provides", state)) {
for (VariableTree vt : tree.getParameters()) {
declaredParamVars.put(vt, mSym);
}
}
return super.visitMethod(tree, null);
}

@Override
public Void visitVariable(VariableTree tree, Void unused) {
Symbol.VarSymbol vSym = ASTHelpers.getSymbol(tree);
if (ASTHelpers.hasAnnotation(vSym, "javax.inject.Inject", state)) {
declaredInjectVars.add(tree);
}
return super.visitVariable(tree, null);
}
@Override
public Void visitVariable(VariableTree tree, Void unused) {
Symbol.VarSymbol vSym = ASTHelpers.getSymbol(tree);
if (ASTHelpers.hasAnnotation(vSym, "javax.inject.Inject", state)) {
declaredInjectVars.add(tree);
}
return super.visitVariable(tree, null);
}
}

static class RawUsageCountsScanner extends TreeScanner<Void, Void> {
final Map<Symbol, Integer> usedVars = new LinkedHashMap<>();
static class RawUsageCountsScanner extends TreeScanner<Void, Void> {
final Map<Symbol, Integer> usedVars = new LinkedHashMap<>();

@Override
public Void visitMemberSelect(MemberSelectTree tree, Void unused) {
addUse(usedVars, ASTHelpers.getSymbol(tree));
return super.visitMemberSelect(tree, null);
}

@Override
public Void visitIdentifier(IdentifierTree tree, Void unused) {
addUse(usedVars, ASTHelpers.getSymbol(tree));
return super.visitIdentifier(tree, null);
}
@Override
public Void visitMemberSelect(MemberSelectTree tree, Void unused) {
addUse(usedVars, ASTHelpers.getSymbol(tree));
return super.visitMemberSelect(tree, null);
}

public enum DeclType {
FIELD,
PARAM,
@Override
public Void visitIdentifier(IdentifierTree tree, Void unused) {
addUse(usedVars, ASTHelpers.getSymbol(tree));
return super.visitIdentifier(tree, null);
}

public static class CounterData {
public final DeclType declType;
public final VariableTree declaration;
public final int count;

public CounterData(DeclType declType, VariableTree declaration, int count) {
Preconditions.checkArgument(count >= 0, "Count must be positive.");
this.declType = declType;
this.declaration = declaration;
this.count = count;
}
}

public enum DeclType {
FIELD,
PARAM,
}

public static class CounterData {
public final DeclType declType;
public final VariableTree declaration;
public final int count;

public CounterData(DeclType declType, VariableTree declaration, int count) {
Preconditions.checkArgument(count >= 0, "Count must be positive.");
this.declType = declType;
this.declaration = declaration;
this.count = count;
}
}
}
Loading

0 comments on commit dd050f8

Please sign in to comment.