mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Attempt to make PythonRegexpInjector more readable
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,6 @@ import com.intellij.lang.injection.MultiHostRegistrar;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiPolyVariantReference;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.impl.source.tree.injected.MultiHostRegistrarImpl;
|
||||
import com.intellij.psi.impl.source.tree.injected.Place;
|
||||
@@ -72,33 +71,40 @@ public class PythonRegexpInjector implements MultiHostInjector {
|
||||
|
||||
@Override
|
||||
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
|
||||
final PsiElement contextParent = context.getParent();
|
||||
if (PyInjectionUtil.getLargestStringLiteral(context) == context && contextParent instanceof PyArgumentList) {
|
||||
final PyExpression[] args = ((PyArgumentList)contextParent).getArguments();
|
||||
int index = ArrayUtil.indexOf(args, context);
|
||||
PyCallExpression call = PsiTreeUtil.getParentOfType(context, PyCallExpression.class);
|
||||
final PyArgumentList argumentList = PyUtil.as(context.getParent(), PyArgumentList.class);
|
||||
if (PyInjectionUtil.getLargestStringLiteral(context) == context && argumentList != null) {
|
||||
final PyCallExpression call = PsiTreeUtil.getParentOfType(context, PyCallExpression.class);
|
||||
if (call != null) {
|
||||
final PyExpression callee = call.getCallee();
|
||||
if (callee instanceof PyReferenceExpression && canBeRegexpCall(callee)) {
|
||||
final PsiPolyVariantReference ref = ((PyReferenceExpression)callee).getReference(PyResolveContext.noImplicits());
|
||||
if (ref != null) {
|
||||
final PsiElement element = ref.resolve();
|
||||
if (element != null && ScopeUtil.getScopeOwner(element) instanceof PyFile &&
|
||||
element.getContainingFile().getName().equals("re.py") && isRegexpMethod(element, index)) {
|
||||
final Language language = isVerbose(call) ? PythonVerboseRegexpLanguage.INSTANCE : PythonRegexpLanguage.INSTANCE;
|
||||
registrar.startInjecting(language);
|
||||
final PyInjectionUtil.InjectionResult result = PyInjectionUtil.registerStringLiteralInjection(context, registrar);
|
||||
if (result.isInjected()) {
|
||||
registrar.doneInjecting();
|
||||
if (!result.isStrict()) {
|
||||
final PsiFile file = getInjectedFile(registrar);
|
||||
if (file != null) {
|
||||
file.putUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final RegexpMethodDescriptor methodDescriptor = findRegexpMethodDescriptor(resolvePossibleRegexpCall(call));
|
||||
if (methodDescriptor != null && methodDescriptor.argIndex == ArrayUtil.indexOf(argumentList.getArguments(), context)) {
|
||||
injectRegexpLanguage(registrar, context, isVerbose(call));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiElement resolvePossibleRegexpCall(@NotNull PyCallExpression call) {
|
||||
final PyExpression callee = call.getCallee();
|
||||
|
||||
if (callee instanceof PyReferenceExpression && canBeRegexpCall(callee)) {
|
||||
final PyReferenceExpression referenceExpression = (PyReferenceExpression)callee;
|
||||
return referenceExpression.getReference(PyResolveContext.noImplicits()).resolve();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void injectRegexpLanguage(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context, boolean verbose) {
|
||||
final Language language = verbose ? PythonVerboseRegexpLanguage.INSTANCE : PythonRegexpLanguage.INSTANCE;
|
||||
registrar.startInjecting(language);
|
||||
final PyInjectionUtil.InjectionResult result = PyInjectionUtil.registerStringLiteralInjection(context, registrar);
|
||||
if (result.isInjected()) {
|
||||
registrar.doneInjecting();
|
||||
if (!result.isStrict()) {
|
||||
final PsiFile file = getInjectedFile(registrar);
|
||||
if (file != null) {
|
||||
file.putUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,7 +113,7 @@ public class PythonRegexpInjector implements MultiHostInjector {
|
||||
@Nullable
|
||||
private static PsiFile getInjectedFile(@NotNull MultiHostRegistrar registrar) {
|
||||
// Don't add a dependency on IntelliLang here now, but this injector should become IntelliLang-based in the future
|
||||
final List<Pair<Place,PsiFile>> result = ((MultiHostRegistrarImpl)registrar).getResult();
|
||||
final List<Pair<Place, PsiFile>> result = ((MultiHostRegistrarImpl)registrar).getResult();
|
||||
return result == null || result.isEmpty() ? null : result.get(result.size() - 1).second;
|
||||
}
|
||||
|
||||
@@ -119,51 +125,47 @@ public class PythonRegexpInjector implements MultiHostInjector {
|
||||
}
|
||||
|
||||
private static boolean isVerbose(@NotNull PyCallExpression call) {
|
||||
PyExpression[] arguments = call.getArguments();
|
||||
if (arguments.length <= 1) {
|
||||
return false;
|
||||
}
|
||||
return isVerbose(arguments[arguments.length-1]);
|
||||
final PyExpression[] arguments = call.getArguments();
|
||||
return arguments.length > 1 && isVerbose(arguments[arguments.length - 1]);
|
||||
}
|
||||
|
||||
private static boolean isVerbose(@Nullable PyExpression expr) {
|
||||
if (expr instanceof PyKeywordArgument) {
|
||||
PyKeywordArgument keywordArgument = (PyKeywordArgument)expr;
|
||||
if (!"flags".equals(keywordArgument.getName())) {
|
||||
return false;
|
||||
}
|
||||
return isVerbose(keywordArgument.getValueExpression());
|
||||
private static boolean isVerbose(@Nullable PyExpression expression) {
|
||||
if (expression instanceof PyKeywordArgument) {
|
||||
final PyKeywordArgument keywordArgument = (PyKeywordArgument)expression;
|
||||
return "flags".equals(keywordArgument.getName()) && isVerbose(keywordArgument.getValueExpression());
|
||||
}
|
||||
if (expr instanceof PyReferenceExpression) {
|
||||
final String flagName = ((PyReferenceExpression)expr).getReferencedName();
|
||||
if (expression instanceof PyReferenceExpression) {
|
||||
final String flagName = ((PyReferenceExpression)expression).getReferencedName();
|
||||
return "VERBOSE".equals(flagName) || "X".equals(flagName);
|
||||
}
|
||||
if (expr instanceof PyBinaryExpression) {
|
||||
return isVerbose(((PyBinaryExpression)expr).getLeftExpression()) || isVerbose(((PyBinaryExpression)expr).getRightExpression());
|
||||
if (expression instanceof PyBinaryExpression) {
|
||||
final PyBinaryExpression binaryExpression = (PyBinaryExpression)expression;
|
||||
return isVerbose(binaryExpression.getLeftExpression()) || isVerbose(binaryExpression.getRightExpression());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isRegexpMethod(@NotNull PsiElement element, int index) {
|
||||
if (!(element instanceof PyFunction)) {
|
||||
return false;
|
||||
@Nullable
|
||||
private RegexpMethodDescriptor findRegexpMethodDescriptor(@Nullable PsiElement element) {
|
||||
if (element == null ||
|
||||
!(ScopeUtil.getScopeOwner(element) instanceof PyFile) ||
|
||||
!element.getContainingFile().getName().equals("re.py") ||
|
||||
!(element instanceof PyFunction)) {
|
||||
return null;
|
||||
}
|
||||
final String name = ((PyFunction)element).getName();
|
||||
for (RegexpMethodDescriptor descriptor : myDescriptors) {
|
||||
if (descriptor.methodName.equals(name) && descriptor.argIndex == index) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
final String functionName = ((PyFunction)element).getName();
|
||||
return myDescriptors
|
||||
.stream()
|
||||
.filter(descriptor -> descriptor.methodName.equals(functionName))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private boolean canBeRegexpCall(@NotNull PyExpression callee) {
|
||||
String text = callee.getText();
|
||||
for (RegexpMethodDescriptor descriptor : myDescriptors) {
|
||||
if (text.endsWith(descriptor.methodName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
final String text = callee.getText();
|
||||
return myDescriptors
|
||||
.stream()
|
||||
.anyMatch(descriptor -> text.endsWith(descriptor.methodName));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user