java support

GitOrigin-RevId: 1100eb4fd41061ddcaefa6d57d024f819c9f479b
This commit is contained in:
adelf
2021-06-03 00:18:10 +03:00
committed by intellij-monorepo-bot
parent 630094ca60
commit 5dc2eefe89
11 changed files with 354 additions and 0 deletions
+1
View File
@@ -39,6 +39,7 @@ intellij {
'Docker',
'pythonid:193.6015.28',
'org.jetbrains.plugins.ruby:193.6015.9',
'Kotlin',
'coverage',
'CSS',
'java-i18n',
@@ -0,0 +1,25 @@
package ru.adelf.idea.dotenv.java;
import com.intellij.codeInsight.completion.CompletionConfidence;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NotNull;
public class JavaCompletionConfidence extends CompletionConfidence {
@NotNull
@Override
public ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) {
PsiElement literal = contextElement.getContext();
if(!(literal instanceof PsiLiteralExpression)) {
return ThreeState.UNSURE;
}
if(JavaPsiHelper.isEnvStringLiteral((PsiLiteralExpression) literal)) {
return ThreeState.NO;
}
return ThreeState.UNSURE;
}
}
@@ -0,0 +1,76 @@
package ru.adelf.idea.dotenv.java;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionProvider;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.adelf.idea.dotenv.api.EnvironmentVariablesApi;
import ru.adelf.idea.dotenv.common.BaseEnvCompletionProvider;
public class JavaEnvCompletionContributor extends BaseEnvCompletionProvider implements GotoDeclarationHandler {
public JavaEnvCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement().withParent(PsiLiteralExpression.class), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters, @NotNull ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) {
PsiElement psiElement = completionParameters.getOriginalPosition();
if(psiElement == null || getStringLiteral(psiElement) == null) {
return;
}
fillCompletionResultSet(completionResultSet, psiElement.getProject());
}
});
}
@Nullable
@Override
public PsiElement[] getGotoDeclarationTargets(@Nullable PsiElement psiElement, int i, Editor editor) {
if(psiElement == null) {
return PsiElement.EMPTY_ARRAY;
}
PsiLiteralExpression stringLiteral = getStringLiteral(psiElement);
if(stringLiteral == null) {
return PsiElement.EMPTY_ARRAY;
}
Object value = stringLiteral.getValue();
if (!(value instanceof String)) {
return PsiElement.EMPTY_ARRAY;
}
return EnvironmentVariablesApi.getKeyDeclarations(psiElement.getProject(), (String)value);
}
@Nullable
private PsiLiteralExpression getStringLiteral(@NotNull PsiElement psiElement) {
PsiElement parent = psiElement.getParent();
if(!(parent instanceof PsiLiteralExpression)) {
return null;
}
if(!JavaPsiHelper.isEnvStringLiteral((PsiLiteralExpression) parent)) {
return null;
}
return (PsiLiteralExpression) parent;
}
@Nullable
@Override
public String getActionText(@NotNull DataContext dataContext) {
return null;
}
}
@@ -0,0 +1,39 @@
package ru.adelf.idea.dotenv.java;
import com.intellij.psi.JavaRecursiveElementWalkingVisitor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.psi.PsiMethodCallExpression;
import org.jetbrains.annotations.NotNull;
import ru.adelf.idea.dotenv.models.KeyUsagePsiElement;
import java.util.Collection;
import java.util.HashSet;
class JavaEnvironmentCallsVisitor extends JavaRecursiveElementWalkingVisitor {
final private Collection<KeyUsagePsiElement> collectedItems = new HashSet<>();
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
if (JavaPsiHelper.isEnvMethodCall(expression)) {
PsiElement[] parameters = expression.getArgumentList().getExpressions();
if (parameters.length == 0) return;
if (!(parameters[0] instanceof PsiLiteralExpression)) return;
Object value = ((PsiLiteralExpression) parameters[0]).getValue();
if (value instanceof String) {
collectedItems.add(new KeyUsagePsiElement((String) value, parameters[0]));
}
}
super.visitMethodCallExpression(expression);
}
@NotNull
Collection<KeyUsagePsiElement> getCollectedItems() {
return collectedItems;
}
}
@@ -0,0 +1,32 @@
package ru.adelf.idea.dotenv.java;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import org.jetbrains.annotations.NotNull;
import ru.adelf.idea.dotenv.api.EnvironmentVariablesUsagesProvider;
import ru.adelf.idea.dotenv.models.KeyUsagePsiElement;
import java.util.Collection;
import java.util.Collections;
public class JavaEnvironmentVariablesUsagesProvider implements EnvironmentVariablesUsagesProvider {
@Override
public boolean acceptFile(VirtualFile file) {
return file.getFileType().equals(JavaFileType.INSTANCE);
}
@NotNull
@Override
public Collection<KeyUsagePsiElement> getUsages(PsiFile psiFile) {
if (psiFile instanceof PsiJavaFile) {
JavaEnvironmentCallsVisitor visitor = new JavaEnvironmentCallsVisitor();
psiFile.acceptChildren(visitor);
return visitor.getCollectedItems();
}
return Collections.emptyList();
}
}
@@ -0,0 +1,137 @@
package ru.adelf.idea.dotenv.java;
import com.intellij.psi.*;
import com.jetbrains.php.lang.psi.elements.ArrayAccessExpression;
import com.jetbrains.php.lang.psi.elements.PhpPsiElement;
import com.jetbrains.php.lang.psi.elements.Variable;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
class JavaPsiHelper {
public static final List<String> ARRAY_NAMES = Arrays.asList("_ENV", "_SERVER");
/**
* Checks that this element environment string
*
* @param literal Checking psi element
*/
static boolean isEnvStringLiteral(PsiLiteralExpression literal) {
PsiElement parent = literal.getParent();
if (parent instanceof PsiExpressionList) {
PsiExpression[] expressions = ((PsiExpressionList) parent).getExpressions();
if (expressions.length < 1) return false;
if (expressions[0] != literal) return false;
PsiElement methodCall = parent.getParent();
if (!(methodCall instanceof PsiMethodCallExpression)) return false;
return isEnvMethodCall((PsiMethodCallExpression) methodCall);
}
return false;
}
/**
* Checks whether this function reference is reference for env functions, like env or getenv
*
* @param methodCallExpression Checking reference
* @return true if condition filled
*/
static boolean isEnvMethodCall(PsiMethodCallExpression methodCallExpression) {
PsiElement nameElement = methodCallExpression.getMethodExpression().getReferenceNameElement();
if (nameElement == null) {
return false;
}
String methodName = nameElement.getText();
if (isDirectMethodCall(methodName)) {
return true;
}
List<String> classNames = getClassNames(methodName);
if (classNames == null) {
return false;
}
for (ResolveResult result : methodCallExpression.getMethodExpression().multiResolve(true)) {
if (result.getElement() instanceof PsiMethod) {
PsiClass psiClass = ((PsiMethod) result.getElement()).getContainingClass();
if (psiClass != null && classNames.contains(psiClass.getName())) {
return true;
}
}
}
return false;
}
private static boolean isDirectMethodCall(String methodName) {
return methodName.equals("getenv") || methodName.equals("getEnv");
}
@Nullable
private static List<String> getClassNames(String methodName) {
switch (methodName) {
case "get":
return Arrays.asList("Dotenv", "DotEnv");
case "getProperty":
return Collections.singletonList("System");
}
return null;
}
/**
* Checks whether this array access is environment call
*
* @param arrayAccess Checking array
* @return true if condition filled
*/
static boolean isEnvArrayCall(ArrayAccessExpression arrayAccess) {
PhpPsiElement variable = arrayAccess.getValue();
if (!(variable instanceof Variable)) return false;
return (variable.getName() != null && ARRAY_NAMES.contains(variable.getName()));
}
/* @SuppressWarnings("SameParameterValue")
private static boolean isFunctionParameter(PsiElement psiElement, int parameterIndex, List<String> functions) {
PsiElement variableContext = psiElement.getContext();
if(!(variableContext instanceof ParameterList)) {
return false;
} else {
ParameterList parameterList = (ParameterList) variableContext;
PsiElement context = parameterList.getContext();
if(!(context instanceof FunctionReference)) {
return false;
} else {
FunctionReference methodReference = (FunctionReference) context;
String name = methodReference.getName();
return (name != null && functions.contains(name) && getParameterIndex(parameterList, psiElement) == parameterIndex);
}
}
}*/
/* private static int getParameterIndex(ParameterList parameterList, PsiElement parameter) {
PsiElement[] parameters = parameterList.getParameters();
for(int i = 0; i < parameters.length; i = i + 1) {
if(parameters[i].equals(parameter)) {
return i;
}
}
return -1;
}*/
}
@@ -0,0 +1,12 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<completion.contributor language="JAVA" implementationClass="ru.adelf.idea.dotenv.java.JavaEnvCompletionContributor"/>
<gotoDeclarationHandler implementation="ru.adelf.idea.dotenv.java.JavaEnvCompletionContributor"/>
<completion.confidence language="JAVA" implementationClass="ru.adelf.idea.dotenv.java.JavaCompletionConfidence"
id="envStringCompletionConfidence" order="first"/>
</extensions>
<extensions defaultExtensionNs="ru.adelf.idea.dotenv">
<environmentVariablesUsagesProvider implementation="ru.adelf.idea.dotenv.java.JavaEnvironmentVariablesUsagesProvider"/>
</extensions>
</idea-plugin>
@@ -65,6 +65,7 @@
<depends>com.intellij.modules.platform</depends>
<depends optional="true" config-file="java.xml">com.intellij.java</depends>
<depends optional="true" config-file="php.xml">com.jetbrains.php</depends>
<depends optional="true" config-file="ruby.xml">com.intellij.modules.ruby</depends>
<depends optional="true" config-file="python.xml">com.intellij.modules.python</depends>
@@ -0,0 +1,13 @@
package ru.adelf.idea.dotenv.tests.usages;
public class JavaUsagesTest extends BaseUsagesTest {
@Override
public void setUp() throws Exception {
super.setUp();
myFixture.copyDirectoryToProject("java", "src/java");
}
public void testGetEnvUsages() {
assertUsagesContains("JAVA_GET_ENV");
}
}
@@ -0,0 +1,11 @@
package ru.adelf.idea.dotenv.tests.usages.fixtures.java;
public class System {
public static String getenv(String key){
return "";
}
public static String getProperty(String key){
return "";
}
}
@@ -0,0 +1,7 @@
package ru.adelf.idea.dotenv.tests.usages.fixtures.java;
public class Usages {
public static void getEnv() {
System.getenv("JAVA_GET_ENV");
}
}