diff --git a/src/main/java/com/bartek/esa/core/di/PluginModule.java b/src/main/java/com/bartek/esa/core/di/PluginModule.java index 8117ed9..01c3ed8 100644 --- a/src/main/java/com/bartek/esa/core/di/PluginModule.java +++ b/src/main/java/com/bartek/esa/core/di/PluginModule.java @@ -86,8 +86,8 @@ public class PluginModule { @Provides @IntoSet - public Plugin externalStoragePlugin(ParentNodeFinder parentNodeFinder) { - return new ExternalStoragePlugin(parentNodeFinder); + public Plugin externalStoragePlugin(ParentNodeFinder parentNodeFinder, StaticScopeHelper staticScopeHelper) { + return new ExternalStoragePlugin(parentNodeFinder, staticScopeHelper); } @Provides diff --git a/src/main/java/com/bartek/esa/core/helper/NodeUtil.java b/src/main/java/com/bartek/esa/core/helper/NodeUtil.java new file mode 100644 index 0000000..d5accbe --- /dev/null +++ b/src/main/java/com/bartek/esa/core/helper/NodeUtil.java @@ -0,0 +1,39 @@ +package com.bartek.esa.core.helper; + +import com.github.javaparser.Position; +import com.github.javaparser.ast.Node; + +import static java.lang.String.format; + +public class NodeUtil { + private Node first; + + private NodeUtil(Node node) { + this.first = node; + } + + public static NodeUtil is(Node node) { + return new NodeUtil(node); + } + + public boolean after(Node second) { + Position firstPosition = getPosition(first); + Position secondPosition = getPosition(second); + return firstPosition.isAfter(secondPosition); + } + + private Position getPosition(Node node) { + return node.getRange() + .map(r -> r.begin) + .orElseGet(() -> { + System.err.println(format("Cannot determine position of:\n%s\nProduced results might not be reliable.")); + return new Position(0, 0); + }); + } + + public boolean before(Node second) { + Position firstPosition = getPosition(first); + Position secondPosition = getPosition(second); + return firstPosition.isBefore(secondPosition); + } +} diff --git a/src/main/java/com/bartek/esa/core/helper/StaticScopeHelper.java b/src/main/java/com/bartek/esa/core/helper/StaticScopeHelper.java index 67c0951..e430fed 100644 --- a/src/main/java/com/bartek/esa/core/helper/StaticScopeHelper.java +++ b/src/main/java/com/bartek/esa/core/helper/StaticScopeHelper.java @@ -20,6 +20,12 @@ public class StaticScopeHelper { public Predicate isFromScope(CompilationUnit compilationUnit, String methodName, String scope, String importScope) { return expr -> { + if(!expr.getName().getIdentifier().matches(methodName)) { + return false; + } + + // is called with scope + // Class.method() boolean isFromScope = expr.getScope() .filter(Expression::isNameExpr) .map(Expression::asNameExpr) @@ -28,6 +34,9 @@ public class StaticScopeHelper { .map(s -> s.equals(scope)) .orElse(false); + // is from static import + // import static a.b.Class.method + // method() if(!isFromScope) { isFromScope = compilationUnit.findAll(ImportDeclaration.class).stream() .filter(ImportDeclaration::isStatic) @@ -39,6 +48,9 @@ public class StaticScopeHelper { .anyMatch(q -> q.equals(format("%s.%s", importScope, scope))); } + // is from import + // import static a.b.Class.* + // method() if(!isFromScope) { isFromScope = compilationUnit.findAll(ImportDeclaration.class).stream() .filter(ImportDeclaration::isStatic) diff --git a/src/main/java/com/bartek/esa/core/plugin/ExternalStoragePlugin.java b/src/main/java/com/bartek/esa/core/plugin/ExternalStoragePlugin.java index 3b38627..0fb9b86 100644 --- a/src/main/java/com/bartek/esa/core/plugin/ExternalStoragePlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/ExternalStoragePlugin.java @@ -3,6 +3,7 @@ package com.bartek.esa.core.plugin; import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.helper.ParentNodeFinder; +import com.bartek.esa.core.helper.StaticScopeHelper; import com.bartek.esa.core.model.enumeration.Severity; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.MethodDeclaration; @@ -11,18 +12,22 @@ import com.github.javaparser.ast.expr.MethodCallExpr; import javax.inject.Inject; import java.util.function.Consumer; +import static com.bartek.esa.core.helper.NodeUtil.is; + public class ExternalStoragePlugin extends JavaPlugin { private final ParentNodeFinder parentNodeFinder; + private final StaticScopeHelper staticScopeHelper; @Inject - public ExternalStoragePlugin(ParentNodeFinder parentNodeFinder) { + public ExternalStoragePlugin(ParentNodeFinder parentNodeFinder, StaticScopeHelper staticScopeHelper) { this.parentNodeFinder = parentNodeFinder; + this.staticScopeHelper = staticScopeHelper; } @Override public void run(Source java) { java.getModel().findAll(MethodCallExpr.class).stream() - .filter(expr -> expr.getName().getIdentifier().matches("getExternalStorageDirectory|getExternalStoragePublicDirectory")) + .filter(staticScopeHelper.isFromScope(java.getModel(), "getExternalStorageDirectory|getExternalStoragePublicDirectory", "Environment", "android.os")) .forEach(findCheckingStorageStateForAccessingExternalStorage(java)); } @@ -36,7 +41,8 @@ public class ExternalStoragePlugin extends JavaPlugin { private void findCheckingStorageStateInMethodDeclaration(Source java, MethodCallExpr accessingToExternalStorage, MethodDeclaration methodDeclaration) { boolean isStateBeingChecked = methodDeclaration.findAll(MethodCallExpr.class).stream() - .anyMatch(e -> e.getName().getIdentifier().equals("getExternalStorageState")); + .filter(staticScopeHelper.isFromScope(java.getModel(), "getExternalStorageState", "Environment", "android.os")) + .anyMatch(checkingMethod -> is(accessingToExternalStorage).after(checkingMethod)); if (!isStateBeingChecked) { addJavaIssue(Severity.WARNING, java.getFile(), accessingToExternalStorage);