mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
+26
-3
@@ -161,14 +161,16 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
synchronized (mySourcesToRecompile) {
|
||||
final TIntHashSet pathsToRecompile = mySourcesToRecompile.get(projectId);
|
||||
if (_forceCompile || pathsToRecompile != null && !pathsToRecompile.isEmpty()) {
|
||||
if (ourDebugMode) {
|
||||
System.out.println("Analysing potentially recompilable files for " + compiler.getDescription());
|
||||
}
|
||||
while (scopeSrcIterator.hasNext()) {
|
||||
final VirtualFile file = scopeSrcIterator.next();
|
||||
if (!file.isValid()) {
|
||||
if (LOG.isDebugEnabled() || ourDebugMode) {
|
||||
final String message = "Skipping invalid file " + file.getPresentableUrl();
|
||||
LOG.debug(message);
|
||||
LOG.debug("Skipping invalid file " + file.getPresentableUrl());
|
||||
if (ourDebugMode) {
|
||||
System.out.println(message);
|
||||
System.out.println("\t SKIPPED(INVALID) " + file.getPresentableUrl());
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -177,17 +179,38 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
if (_forceCompile) {
|
||||
if (compiler.isCompilableFile(file, context) && !configuration.isExcludedFromCompilation(file)) {
|
||||
toCompile.add(file);
|
||||
if (ourDebugMode) {
|
||||
System.out.println("\t INCLUDED " + file.getPresentableUrl());
|
||||
}
|
||||
selectedForRecompilation.add(file);
|
||||
if (pathsToRecompile == null || !pathsToRecompile.contains(fileId)) {
|
||||
addSourceForRecompilation(projectId, file, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ourDebugMode) {
|
||||
System.out.println("\t NOT COMPILABLE OR EXCLUDED " + file.getPresentableUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pathsToRecompile.contains(fileId)) {
|
||||
if (compiler.isCompilableFile(file, context) && !configuration.isExcludedFromCompilation(file)) {
|
||||
toCompile.add(file);
|
||||
if (ourDebugMode) {
|
||||
System.out.println("\t INCLUDED " + file.getPresentableUrl());
|
||||
}
|
||||
selectedForRecompilation.add(file);
|
||||
}
|
||||
else {
|
||||
if (ourDebugMode) {
|
||||
System.out.println("\t NOT COMPILABLE OR EXCLUDED " + file.getPresentableUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ourDebugMode) {
|
||||
System.out.println("\t NOT INCLUDED " + file.getPresentableUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-2
@@ -28,9 +28,13 @@ import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class CreateConstructorParameterFromFieldFix implements IntentionAction {
|
||||
private final SmartPsiElementPointer<PsiField> myField;
|
||||
|
||||
@@ -76,8 +80,22 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
|
||||
aClass = getField().getContainingClass();
|
||||
constructors = aClass.getConstructors();
|
||||
}
|
||||
for (int i = 0; i < constructors.length; i++){
|
||||
if (!addParameterToConstructor(project, file, editor, getField().getContainingClass().getConstructors()[i])) break;
|
||||
Arrays.sort(constructors, new Comparator<PsiMethod>() {
|
||||
@Override
|
||||
public int compare(PsiMethod c1, PsiMethod c2) {
|
||||
final PsiMethod cc1 = RefactoringUtil.getChainedConstructor(c1);
|
||||
final PsiMethod cc2 = RefactoringUtil.getChainedConstructor(c2);
|
||||
if (cc1 == c2) return 1;
|
||||
if (cc2 == c1) return -1;
|
||||
if (cc1 == null) {
|
||||
return cc2 == null ? 0 : compare(c1, cc2);
|
||||
} else {
|
||||
return cc2 == null ? compare(cc1, c2) : compare(cc1, cc2);
|
||||
}
|
||||
}
|
||||
});
|
||||
for (PsiMethod constructor : constructors) {
|
||||
if (!addParameterToConstructor(project, file, editor, constructor)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -339,7 +339,10 @@ public class JavaDocInfoGenerator {
|
||||
generateTypeParametersSection(buffer, result);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> findInHierarchy(PsiClass psiClass, final DocTagLocator<PsiDocTag> locator) {
|
||||
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> inClassComment = findInClassComment(psiClass, locator);
|
||||
if (inClassComment != null) return inClassComment;
|
||||
for (final PsiClass superClass : psiClass.getSupers()) {
|
||||
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> pair = findInClassComment(superClass, locator);
|
||||
if (pair != null) return pair;
|
||||
@@ -348,7 +351,7 @@ public class JavaDocInfoGenerator {
|
||||
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> pair = findInClassComment(superInterface, locator);
|
||||
if (pair != null) return pair;
|
||||
}
|
||||
return findInClassComment(psiClass, locator);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> findInClassComment(final PsiClass psiClass, final DocTagLocator<PsiDocTag> locator) {
|
||||
|
||||
+3
@@ -127,6 +127,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
correctedOffset = offset;
|
||||
}
|
||||
else if (!Character.isJavaIdentifierPart(text.charAt(correctedOffset))) {
|
||||
if (text.charAt(correctedOffset) == ';') {//initially caret on the end of line
|
||||
correctedOffset--;
|
||||
}
|
||||
if (text.charAt(correctedOffset) != ')') {
|
||||
correctedOffset = offset;
|
||||
}
|
||||
|
||||
+2
-20
@@ -25,7 +25,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -51,7 +51,7 @@ public class ParameterData {
|
||||
initParameterData(parameter, result);
|
||||
}
|
||||
|
||||
final PsiMethod chainedConstructor = getChainedConstructor(constructor);
|
||||
final PsiMethod chainedConstructor = RefactoringUtil.getChainedConstructor(constructor);
|
||||
if (chainedConstructor != null) {
|
||||
final PsiCodeBlock constructorBody = constructor.getBody();
|
||||
LOG.assertTrue(constructorBody != null);
|
||||
@@ -68,24 +68,6 @@ public class ParameterData {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getChainedConstructor(PsiMethod constructor) {
|
||||
final PsiCodeBlock constructorBody = constructor.getBody();
|
||||
LOG.assertTrue(constructorBody != null);
|
||||
final PsiStatement[] statements = constructorBody.getStatements();
|
||||
if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
|
||||
final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpr = methodCallExpression.getMethodExpression();
|
||||
if ("this".equals(methodExpr.getReferenceName())) {
|
||||
return (PsiMethod)methodExpr.resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ParameterData initParameterData(PsiParameter parameter, Map<String, ParameterData> result) {
|
||||
JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(parameter.getProject());
|
||||
final String paramName = parameter.getName();
|
||||
|
||||
+3
-2
@@ -40,6 +40,7 @@ import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.replaceConstructorWithBuilder.usageInfo.ReplaceConstructorWithSettersChainInfo;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -234,7 +235,7 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
if (myConstructors.length == 1) return myConstructors[0];
|
||||
PsiMethod commonConstructor = null;
|
||||
for (PsiMethod constructor : myConstructors) {
|
||||
final PsiMethod chainedConstructor = ParameterData.getChainedConstructor(constructor);
|
||||
final PsiMethod chainedConstructor = RefactoringUtil.getChainedConstructor(constructor);
|
||||
if (chainedConstructor == null) {
|
||||
if (commonConstructor != null) {
|
||||
if (!isChained(commonConstructor, constructor)) {
|
||||
@@ -258,7 +259,7 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
private static boolean isChained(PsiMethod first, PsiMethod last) {
|
||||
if (first == null) return false;
|
||||
if (first == last) return true;
|
||||
return isChained(ParameterData.getChainedConstructor(first), last);
|
||||
return isChained(RefactoringUtil.getChainedConstructor(first), last);
|
||||
}
|
||||
|
||||
private String createMethodName() {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.refactoring.util;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
@@ -113,6 +114,13 @@ public class FieldConflictsResolver {
|
||||
final PsiMember member,
|
||||
@Nullable final PsiClass qualifyingClass) throws IncorrectOperationException {
|
||||
PsiManager manager = referenceExpression.getManager();
|
||||
PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(referenceExpression, PsiMethodCallExpression.class, true);
|
||||
while ((methodCallExpression) != null) {
|
||||
if (HighlightUtil.isSuperOrThisMethodCall(methodCallExpression)) {
|
||||
return referenceExpression;
|
||||
}
|
||||
methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression.class, true);
|
||||
}
|
||||
PsiReferenceExpression expressionFromText;
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
|
||||
if (qualifyingClass == null) {
|
||||
|
||||
@@ -53,6 +53,7 @@ import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.PackageWrapper;
|
||||
import com.intellij.refactoring.introduceField.ElementToWorkOn;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
|
||||
import com.intellij.refactoring.replaceConstructorWithBuilder.ParameterData;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
@@ -913,6 +914,24 @@ public class RefactoringUtil {
|
||||
return array;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getChainedConstructor(PsiMethod constructor) {
|
||||
final PsiCodeBlock constructorBody = constructor.getBody();
|
||||
LOG.assertTrue(constructorBody != null);
|
||||
final PsiStatement[] statements = constructorBody.getStatements();
|
||||
if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
|
||||
final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpr = methodCallExpression.getMethodExpression();
|
||||
if ("this".equals(methodExpr.getReferenceName())) {
|
||||
return (PsiMethod)methodExpr.resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static interface ImplicitConstructorUsageVisitor {
|
||||
void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor);
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Add constructor parameter" "true"
|
||||
class A {
|
||||
private final int field;
|
||||
private int j;
|
||||
|
||||
A(int field) {
|
||||
this(0, field);
|
||||
}
|
||||
|
||||
A(int j, int field) {
|
||||
this.j = j;
|
||||
this.field = field;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// "Add constructor parameter" "true"
|
||||
class A {
|
||||
private final int <caret>field;
|
||||
private int j;
|
||||
|
||||
A() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
A(int j) {
|
||||
this.j = j;
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,8 @@ import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class RunConfigurable extends BaseConfigurable {
|
||||
private static final Icon ICON = IconLoader.getIcon("/general/configurableRunDebug.png");
|
||||
@@ -646,8 +648,8 @@ class RunConfigurable extends BaseConfigurable {
|
||||
}
|
||||
}
|
||||
|
||||
private static String createUniqueName(DefaultMutableTreeNode typeNode) {
|
||||
String str = ExecutionBundle.message("run.configuration.unnamed.name.prefix");
|
||||
private static String createUniqueName(DefaultMutableTreeNode typeNode, @Nullable String baseName) {
|
||||
String str = (baseName == null) ? ExecutionBundle.message("run.configuration.unnamed.name.prefix") : baseName;
|
||||
final ArrayList<String> currentNames = new ArrayList<String>();
|
||||
for (int i = 0; i < typeNode.getChildCount(); i++) {
|
||||
final Object userObject = ((DefaultMutableTreeNode)typeNode.getChildAt(i)).getUserObject();
|
||||
@@ -659,9 +661,13 @@ class RunConfigurable extends BaseConfigurable {
|
||||
}
|
||||
}
|
||||
if (!currentNames.contains(str)) return str;
|
||||
|
||||
final Matcher matcher = Pattern.compile("(.*?)\\s*\\(\\d+\\)").matcher(str);
|
||||
final String originalName = (matcher.matches()) ? matcher.group(1) : str;
|
||||
int i = 1;
|
||||
while (true) {
|
||||
if (!currentNames.contains(str + i)) return str + i;
|
||||
final String newName = String.format("%s (%d)", originalName, i);
|
||||
if (!currentNames.contains(newName)) return newName;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -692,7 +698,7 @@ class RunConfigurable extends BaseConfigurable {
|
||||
sortTree(myRoot);
|
||||
((DefaultTreeModel)myTree.getModel()).reload();
|
||||
}
|
||||
final RunnerAndConfigurationSettings settings = getRunManager().createConfiguration(createUniqueName(node), factory);
|
||||
final RunnerAndConfigurationSettings settings = getRunManager().createConfiguration(createUniqueName(node, null), factory);
|
||||
if (factory instanceof ConfigurationFactoryEx) {
|
||||
((ConfigurationFactoryEx)factory).onNewConfigurationCreated(settings.getConfiguration());
|
||||
}
|
||||
@@ -901,7 +907,7 @@ class RunConfigurable extends BaseConfigurable {
|
||||
try {
|
||||
final DefaultMutableTreeNode typeNode = getSelectedConfigurationTypeNode();
|
||||
final RunnerAndConfigurationSettings settings = configuration.getSnapshot();
|
||||
final String copyName = createUniqueName(typeNode);
|
||||
final String copyName = createUniqueName(typeNode, configuration.getNameText());
|
||||
settings.setName(copyName);
|
||||
final ConfigurationFactory factory = settings.getFactory();
|
||||
if (factory instanceof ConfigurationFactoryEx) {
|
||||
|
||||
@@ -112,6 +112,14 @@ public class ProjectUtil {
|
||||
virtualFile.isDirectory() && virtualFile.findChild(DIRECTORY_BASED_PROJECT_DIR) != null) {
|
||||
return openProject(path, projectToClose, forceOpenInNewFrame);
|
||||
}
|
||||
if (virtualFile.isDirectory()) {
|
||||
for (VirtualFile child : virtualFile.getChildren()) {
|
||||
final String childPath = child.getPath();
|
||||
if (childPath.endsWith(ProjectFileType.DOT_DEFAULT_EXTENSION)) {
|
||||
return openProject(childPath, projectToClose, forceOpenInNewFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
ProjectOpenProcessor provider = ProjectOpenProcessor.getImportProvider(virtualFile);
|
||||
if (provider != null) {
|
||||
return provider.doOpenProject(virtualFile, projectToClose, forceOpenInNewFrame);
|
||||
|
||||
@@ -148,8 +148,8 @@ public class ContainerUtil {
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
public static <K, V> HashMap<K, Set<V>> classify(Iterator<V> iterator, Convertor<V, K> keyConvertor) {
|
||||
HashMap<K, Set<V>> hashMap = new HashMap<K, Set<V>>();
|
||||
public static <K, V> Map<K, Set<V>> classify(Iterator<V> iterator, Convertor<V, K> keyConvertor) {
|
||||
Map<K, Set<V>> hashMap = new LinkedHashMap<K, Set<V>>();
|
||||
while (iterator.hasNext()) {
|
||||
V value = iterator.next();
|
||||
final K key = keyConvertor.convert(value);
|
||||
|
||||
@@ -47,7 +47,7 @@ public abstract class WeaksTestCase extends TestCase {
|
||||
System.gc();
|
||||
try {
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
while (Runtime.getRuntime().freeMemory() > 10000) {
|
||||
while (Runtime.getRuntime().freeMemory() > 100000) {
|
||||
list.add(new byte[1000]);
|
||||
}
|
||||
|
||||
|
||||
+15
-5
@@ -45,6 +45,7 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.impl.source.resolve.FileContextUtil;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.impl.source.tree.injected.Place;
|
||||
@@ -292,7 +293,12 @@ public class QuickEditAction implements IntentionAction {
|
||||
new WriteCommandAction.Simple(myProject, origFile) {
|
||||
@Override
|
||||
protected void run() throws Throwable {
|
||||
commitToOriginalInner();
|
||||
PostprocessReformattingAspect.getInstance(myProject).disablePostprocessFormattingInside(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
commitToOriginalInner();
|
||||
}
|
||||
});
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@@ -307,11 +313,14 @@ public class QuickEditAction implements IntentionAction {
|
||||
.classify(myMarkers.entrySet().iterator(),
|
||||
new Convertor<Map.Entry<SmartPsiElementPointer, Pair<RangeMarker, RangeMarker>>, PsiLanguageInjectionHost>() {
|
||||
public PsiLanguageInjectionHost convert(final Map.Entry<SmartPsiElementPointer, Pair<RangeMarker, RangeMarker>> o) {
|
||||
return (PsiLanguageInjectionHost)o.getKey().getElement();
|
||||
final PsiElement element = o.getKey().getElement();
|
||||
return (PsiLanguageInjectionHost)element;
|
||||
}
|
||||
});
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(myOrigDocument);
|
||||
int localInsideFileCursor = 0;
|
||||
for (PsiLanguageInjectionHost host : map.keySet()) {
|
||||
if (host == null) continue;
|
||||
final String hostText = host.getText();
|
||||
TextRange insideHost = null;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
@@ -321,12 +330,13 @@ public class QuickEditAction implements IntentionAction {
|
||||
final TextRange localInsideHost =
|
||||
new TextRange(origMarker.getStartOffset() - hostOffset, origMarker.getEndOffset() - hostOffset);
|
||||
final RangeMarker rangeMarker = entry.getValue().second;
|
||||
final TextRange localInsideFile = new TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset());
|
||||
final TextRange localInsideFile = new TextRange(Math.max(localInsideFileCursor, rangeMarker.getStartOffset()), rangeMarker.getEndOffset());
|
||||
if (insideHost != null) {
|
||||
//append unchanged inter-markers fragment
|
||||
sb.append(hostText.substring(insideHost.getEndOffset(), localInsideHost.getStartOffset()));
|
||||
}
|
||||
sb.append(localInsideFile.getEndOffset() <= text.length()? localInsideFile.substring(text) : "");
|
||||
|
||||
sb.append(localInsideFile.getEndOffset() <= text.length() && !localInsideFile.isEmpty()? localInsideFile.substring(text) : "");
|
||||
localInsideFileCursor = localInsideFile.getEndOffset();
|
||||
insideHost = insideHost == null ? localInsideHost : insideHost.union(localInsideHost);
|
||||
}
|
||||
assert insideHost != null;
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ public class XmlAttributeInjection extends AbstractTagInjection {
|
||||
if (StringUtil.isNotEmpty(name)) appendStringPattern(result, ".withLocalName(", name, ")");
|
||||
if (StringUtil.isNotEmpty(namespace)) appendStringPattern(result, ".withNamespace(", namespace, ")");
|
||||
if (StringUtil.isNotEmpty(injection.getTagName()) || StringUtil.isNotEmpty(injection.getTagNamespace())) {
|
||||
result.append(".inside(").append(XmlTagInjection.getPatternString(injection)).append(")");
|
||||
result.append(".withParent(").append(XmlTagInjection.getPatternString(injection)).append(")");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
</injection>
|
||||
<injection language="XPath" injector-id="xml">
|
||||
<display-name>JAXB attribute node</display-name>
|
||||
<place><![CDATA[xmlAttribute().withLocalName(string().equalTo("node")).inside(xmlTag().withLocalName(string().equalTo("bindings")).withNamespace(string().equalTo("http://java.sun.com/xml/ns/jaxb")))]]></place>
|
||||
<place><![CDATA[xmlAttribute().withLocalName(string().equalTo("node")).withParent(xmlTag().withLocalName(string().equalTo("bindings")).withNamespace(string().equalTo("http://java.sun.com/xml/ns/jaxb")))]]></place>
|
||||
</injection>
|
||||
<injection language="JavaScript" injector-id="xml">
|
||||
<display-name>*/@href</display-name>
|
||||
<value-pattern>^javascript:(.+)</value-pattern>
|
||||
<place><![CDATA[xmlAttribute().withLocalName(string().equalTo("href")).inside(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
|
||||
<place><![CDATA[xmlAttribute().withLocalName(string().equalTo("href")).withParent(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
|
||||
</injection>
|
||||
<injection language="JavaScript" injector-id="xml">
|
||||
<display-name>*/@on.*</display-name>
|
||||
<place><![CDATA[xmlAttribute().withLocalName(string().matches("on.*")).inside(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
|
||||
<place><![CDATA[xmlAttribute().withLocalName(string().matches("on.*")).withParent(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
|
||||
</injection>
|
||||
<injection language="CSS" injector-id="xml">
|
||||
<display-name>*/@style</display-name>
|
||||
|
||||
@@ -44,18 +44,17 @@ public class GppTypeConverter extends GrTypeConverter {
|
||||
@Override
|
||||
public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
|
||||
if (rType instanceof GrTupleType) {
|
||||
final PsiType type = PsiUtil.extractIterableTypeParameter(lType, false);
|
||||
if (type == null || TypesUtil.isAssignable(type, ((GrTupleType)rType).getParameters()[0], context)) {
|
||||
final PsiType[] componentTypes = ((GrTupleType)rType).getComponentTypes();
|
||||
final GrTupleType tupleType = (GrTupleType)rType;
|
||||
|
||||
final PsiType expectedComponent = PsiUtil.extractIterableTypeParameter(lType, false);
|
||||
if (expectedComponent != null && hasDefaultConstructor(lType)) {
|
||||
return true;
|
||||
}
|
||||
final PsiType expectedComponent = PsiUtil.extractIterableTypeParameter(lType, false);
|
||||
if (expectedComponent != null &&
|
||||
isMethodCallConversion(context) && TypesUtil.isAssignable(expectedComponent, tupleType.getParameters()[0], context) &&
|
||||
hasDefaultConstructor(lType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lType instanceof PsiClassType && hasConstructor((PsiClassType)lType, componentTypes, context)) {
|
||||
return true;
|
||||
}
|
||||
if (lType instanceof PsiClassType && hasConstructor((PsiClassType)lType, tupleType.getComponentTypes(), context)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (rType instanceof GrMapType) {
|
||||
|
||||
+5
-1
@@ -36,6 +36,11 @@ public class ExcludeFromStubGenerationAction extends AnAction implements DumbAwa
|
||||
final PsiFile file = e.getData(DataKeys.PSI_FILE);
|
||||
|
||||
assert file != null && file.getLanguage() == GroovyFileType.GROOVY_LANGUAGE;
|
||||
|
||||
doExcludeFromStubGeneration(file);
|
||||
}
|
||||
|
||||
public static void doExcludeFromStubGeneration(PsiFile file) {
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
assert virtualFile != null;
|
||||
final Project project = file.getProject();
|
||||
@@ -46,7 +51,6 @@ public class ExcludeFromStubGenerationAction extends AnAction implements DumbAwa
|
||||
configurable.getExcludes().addEntry(new ExcludeEntryDescription(virtualFile, false, true, project));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void update(AnActionEvent e) {
|
||||
|
||||
@@ -17,9 +17,16 @@ package org.jetbrains.plugins.groovy.compiler;
|
||||
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.compiler.generator.GroovycStubGenerator;
|
||||
@@ -47,6 +54,47 @@ public class GroovyCompilerLoader extends AbstractProjectComponent {
|
||||
compilerManager.addTranslatingCompiler(new GroovyCompiler(myProject),
|
||||
new HashSet<FileType>(Arrays.asList(GroovyFileType.GROOVY_FILE_TYPE, StdFileTypes.CLASS)),
|
||||
new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
|
||||
|
||||
myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
|
||||
@Override
|
||||
public void fileOpened(FileEditorManager source, final VirtualFile file) {
|
||||
if (file.getName().endsWith(".java") && file.getPath().contains(GroovycStubGenerator.GROOVY_STUBS)) {
|
||||
final PsiClass psiClass = GroovycStubGenerator.findClassByStub(myProject, file);
|
||||
if (psiClass != null) {
|
||||
final FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
|
||||
final FileEditor[] editors = fileEditorManager.getEditors(file);
|
||||
if (editors.length != 0) {
|
||||
decorateStubFile(file, fileEditorManager, editors[0]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void decorateStubFile(final VirtualFile file, FileEditorManager fileEditorManager, FileEditor editor) {
|
||||
final EditorNotificationPanel panel = new EditorNotificationPanel();
|
||||
panel.setText("This stub is generated for Groovy class to make Groovy-Java cross-compilation possible");
|
||||
panel.createActionLabel("Go to the Groovy class", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final PsiClass original = GroovycStubGenerator.findClassByStub(myProject, file);
|
||||
if (original != null) {
|
||||
original.navigate(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
panel.createActionLabel("Exclude from stub generation", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final PsiClass psiClass = GroovycStubGenerator.findClassByStub(myProject, file);
|
||||
if (psiClass != null) {
|
||||
ExcludeFromStubGenerationAction.doExcludeFromStubGeneration(psiClass.getContainingFile());
|
||||
}
|
||||
}
|
||||
});
|
||||
fileEditorManager.addTopComponent(editor, panel);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+68
-31
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.compiler.generator;
|
||||
|
||||
import com.intellij.codeInsight.generation.OverrideImplementUtil;
|
||||
import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
@@ -33,7 +34,9 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightMethodBuilder;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -43,6 +46,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
@@ -269,7 +273,7 @@ public class GroovyToJavaGenerator {
|
||||
}
|
||||
|
||||
for (final GrTypeDefinition typeDefinition : file.getTypeDefinitions()) {
|
||||
generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, typeDefinition, packageDefinition));
|
||||
generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, GrClassSubstitutor.getSubstitutedClass(typeDefinition), packageDefinition));
|
||||
}
|
||||
|
||||
return generatedItemsRelativePaths;
|
||||
@@ -351,20 +355,16 @@ public class GroovyToJavaGenerator {
|
||||
|
||||
writePackageStatement(text, packageDefinition);
|
||||
|
||||
GrMembersDeclaration[] membersDeclarations = typeDefinition instanceof GrTypeDefinition
|
||||
? ((GrTypeDefinition)typeDefinition).getMemberDeclarations()
|
||||
: GrMembersDeclaration.EMPTY_ARRAY; //todo
|
||||
|
||||
boolean isClassDef = typeDefinition instanceof GrClassDefinition;
|
||||
boolean isInterface = typeDefinition instanceof GrInterfaceDefinition;
|
||||
boolean isEnum = typeDefinition instanceof GrEnumTypeDefinition;
|
||||
boolean isAtInterface = typeDefinition instanceof GrAnnotationTypeDefinition;
|
||||
boolean isEnum = typeDefinition.isEnum();
|
||||
boolean isAnnotationType = typeDefinition.isAnnotationType();
|
||||
boolean isInterface = !isAnnotationType && typeDefinition.isInterface();
|
||||
boolean isClassDef = !isInterface && !isEnum && !isAnnotationType && !isScript;
|
||||
|
||||
writeClassModifiers(text, typeDefinition.getModifierList(), typeDefinition.isInterface(), toplevel);
|
||||
|
||||
if (isInterface) text.append("interface");
|
||||
else if (isEnum) text.append("enum");
|
||||
else if (isAtInterface) text.append("@interface");
|
||||
else if (isAnnotationType) text.append("@interface");
|
||||
else text.append("class");
|
||||
|
||||
text.append(" ").append(typeDefinition.getName());
|
||||
@@ -376,7 +376,7 @@ public class GroovyToJavaGenerator {
|
||||
if (isScript) {
|
||||
text.append("extends groovy.lang.Script ");
|
||||
}
|
||||
else if (!isEnum && !isAtInterface) {
|
||||
else if (!isEnum && !isAnnotationType) {
|
||||
final PsiClassType[] extendsClassesTypes = typeDefinition.getExtendsListTypes();
|
||||
|
||||
if (extendsClassesTypes.length > 0) {
|
||||
@@ -401,28 +401,32 @@ public class GroovyToJavaGenerator {
|
||||
writeEnumConstants(text, (GrEnumTypeDefinition)typeDefinition);
|
||||
}
|
||||
|
||||
Set<MethodSignature> methodSignatures = new HashSet<MethodSignature>();
|
||||
writeAllMethods(text, collectMethods(typeDefinition, isClassDef), typeDefinition);
|
||||
|
||||
|
||||
List<PsiMethod> methods = new ArrayList<PsiMethod>();
|
||||
ContainerUtil.addAll(methods, typeDefinition.getMethods());
|
||||
if (isClassDef) {
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
|
||||
methods.add(factory.createMethodFromText("public groovy.lang.MetaClass getMetaClass() {}", null));
|
||||
methods.add(factory.createMethodFromText("public void setMetaClass(groovy.lang.MetaClass mc) {}", null));
|
||||
methods.add(factory.createMethodFromText("public Object invokeMethod(String name, Object args) {}", null));
|
||||
methods.add(factory.createMethodFromText("public Object getProperty(String propertyName) {}", null));
|
||||
methods.add(factory.createMethodFromText("public void setProperty(String propertyName, Object newValue) {}", null));
|
||||
if (typeDefinition instanceof GrTypeDefinition) {
|
||||
for (GrMembersDeclaration declaration : ((GrTypeDefinition)typeDefinition).getMemberDeclarations()) {
|
||||
if (declaration instanceof GrVariableDeclaration) {
|
||||
writeVariableDeclarations(text, (GrVariableDeclaration)declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (PsiClass inner : typeDefinition.getInnerClasses()) {
|
||||
writeTypeDefinition(text, inner, null, false);
|
||||
text.append("\n");
|
||||
}
|
||||
|
||||
text.append("}");
|
||||
}
|
||||
|
||||
private static void writeAllMethods(StringBuffer text, List<PsiMethod> methods, PsiClass aClass) {
|
||||
Set<MethodSignature> methodSignatures = new HashSet<MethodSignature>();
|
||||
for (PsiMethod method : methods) {
|
||||
if (LightMethodBuilder.isLightMethod(method, GrClassImplUtil.SYNTHETIC_METHOD_IMPLEMENTATION)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method instanceof GrConstructor) {
|
||||
writeConstructor(text, (GrConstructor)method, isEnum);
|
||||
writeConstructor(text, (GrConstructor)method, aClass.isEnum());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -455,18 +459,51 @@ public class GroovyToJavaGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (GrMembersDeclaration declaration : membersDeclarations) {
|
||||
if (declaration instanceof GrVariableDeclaration) {
|
||||
writeVariableDeclarations(text, (GrVariableDeclaration)declaration);
|
||||
private List<PsiMethod> collectMethods(PsiClass typeDefinition, boolean classDef) {
|
||||
List<PsiMethod> methods = new ArrayList<PsiMethod>();
|
||||
ContainerUtil.addAll(methods, typeDefinition.getMethods());
|
||||
if (classDef) {
|
||||
final Collection<MethodSignature> toOverride = OverrideImplementUtil.getMethodSignaturesToOverride(typeDefinition);
|
||||
for (MethodSignature signature : toOverride) {
|
||||
if (signature instanceof MethodSignatureBackedByPsiMethod) {
|
||||
final PsiMethod method = ((MethodSignatureBackedByPsiMethod)signature).getMethod();
|
||||
final PsiClass baseClass = method.getContainingClass();
|
||||
if (isAbstractInJava(method) && baseClass != null && typeDefinition.isInheritor(baseClass, true)) {
|
||||
final LightMethodBuilder builder = new LightMethodBuilder(method.getManager(), method.getName());
|
||||
final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, typeDefinition, PsiSubstitutor.EMPTY);
|
||||
for (PsiParameter parameter : method.getParameterList().getParameters()) {
|
||||
builder.addParameter(parameter.getName(), substitutor.substitute(parameter.getType()));
|
||||
}
|
||||
builder.setReturnType(substitutor.substitute(method.getReturnType()));
|
||||
for (String modifier : JAVA_MODIFIERS) {
|
||||
if (method.hasModifierProperty(modifier)) {
|
||||
builder.addModifier(modifier);
|
||||
}
|
||||
}
|
||||
methods.add(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
|
||||
methods.add(factory.createMethodFromText("public groovy.lang.MetaClass getMetaClass() {}", null));
|
||||
methods.add(factory.createMethodFromText("public void setMetaClass(groovy.lang.MetaClass mc) {}", null));
|
||||
methods.add(factory.createMethodFromText("public Object invokeMethod(String name, Object args) {}", null));
|
||||
methods.add(factory.createMethodFromText("public Object getProperty(String propertyName) {}", null));
|
||||
methods.add(factory.createMethodFromText("public void setProperty(String propertyName, Object newValue) {}", null));
|
||||
}
|
||||
for (PsiClass inner : typeDefinition.getInnerClasses()) {
|
||||
writeTypeDefinition(text, inner, null, false);
|
||||
text.append("\n");
|
||||
return methods;
|
||||
}
|
||||
|
||||
private static boolean isAbstractInJava(PsiMethod method) {
|
||||
if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
text.append("}");
|
||||
final PsiClass psiClass = method.getContainingClass();
|
||||
return psiClass != null && GrClassSubstitutor.getSubstitutedClass(psiClass).isInterface();
|
||||
}
|
||||
|
||||
private static void appendTypeParameters(StringBuffer text, PsiTypeParameterListOwner typeParameterListOwner) {
|
||||
@@ -670,7 +707,7 @@ public class GroovyToJavaGenerator {
|
||||
if (!JavaPsiFacade.getInstance(method.getProject()).getNameHelper().isIdentifier(name))
|
||||
return; //does not have a java image
|
||||
|
||||
boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
boolean isAbstract = isAbstractInJava(method);
|
||||
|
||||
PsiModifierList modifierList = method.getModifierList();
|
||||
|
||||
|
||||
+30
-2
@@ -26,13 +26,19 @@ import com.intellij.openapi.compiler.ex.CompileContextEx;
|
||||
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.Chunk;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerBase;
|
||||
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
|
||||
@@ -40,6 +46,7 @@ import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -47,6 +54,8 @@ import java.util.List;
|
||||
*/
|
||||
public class GroovycStubGenerator extends GroovyCompilerBase {
|
||||
|
||||
public static final String GROOVY_STUBS = "groovyStubs";
|
||||
|
||||
public GroovycStubGenerator(Project project) {
|
||||
super(project);
|
||||
}
|
||||
@@ -93,8 +102,7 @@ public class GroovycStubGenerator extends GroovyCompilerBase {
|
||||
@Override
|
||||
protected void compileFiles(CompileContext compileContext, Module module,
|
||||
final List<VirtualFile> toCompile, OutputSink sink, boolean tests) {
|
||||
final String rootPath = CompilerPaths.getGeneratedDataDirectory(myProject) + "/groovyStubs/";
|
||||
final File outDir = new File(rootPath + myProject.getLocationHash() + "/" + module.getName() + "/" + (tests ? "tests" : "production") + "/");
|
||||
final File outDir = getStubOutput(module, tests);
|
||||
outDir.mkdirs();
|
||||
|
||||
final VirtualFile tempOutput = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(outDir);
|
||||
@@ -119,6 +127,26 @@ public class GroovycStubGenerator extends GroovyCompilerBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static File getStubOutput(Module module, boolean tests) {
|
||||
final Project project = module.getProject();
|
||||
final String rootPath = CompilerPaths.getGeneratedDataDirectory(project).getPath() + "/" + GROOVY_STUBS + "/";
|
||||
return new File(rootPath + project.getLocationHash() + "/" + module.getName() + "/" + (tests ? "tests" : "production") + "/");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClass findClassByStub(Project project, VirtualFile stubFile) {
|
||||
final String[] components = StringUtil.trimEnd(stubFile.getPath(), ".java").split("[\\\\/]");
|
||||
final int stubs = Arrays.asList(components).indexOf(GROOVY_STUBS);
|
||||
if (stubs < 0 || stubs >= components.length - 4) return null;
|
||||
|
||||
final String moduleName = components[stubs + 2];
|
||||
final Module module = ModuleManager.getInstance(project).findModuleByName(moduleName);
|
||||
if (module == null) return null;
|
||||
|
||||
final String fqn = StringUtil.join(Arrays.asList(components).subList(stubs + 4, components.length), ".");
|
||||
return JavaPsiFacade.getInstance(project).findClass(fqn, GlobalSearchScope.moduleScope(module));
|
||||
}
|
||||
|
||||
private void cleanDirectory(final VirtualFile dir) {
|
||||
new WriteCommandAction(myProject) {
|
||||
protected void run(Result result) throws Throwable {
|
||||
|
||||
+1
-1
@@ -261,7 +261,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
else if (call instanceof GrCallExpression) {
|
||||
GrCallExpression constructorCall = (GrCallExpression)call;
|
||||
ContainerUtil.addAll(results, constructorCall.getMethodVariants());
|
||||
ContainerUtil.addAll(results, constructorCall.getMethodVariants(null));
|
||||
final PsiType type = ((GrCallExpression)call).getType();
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClass psiClass = ((PsiClassType)type).resolve();
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -12,7 +13,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
public abstract class GrTypeConverter {
|
||||
public static final ExtensionPointName<GrTypeConverter> EP_NAME = ExtensionPointName.create("org.intellij.groovy.typeConverter");
|
||||
|
||||
protected static boolean isMethodCallConversion(GroovyPsiElement context) {
|
||||
return context.getParent() instanceof GrMethodCall;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ public interface GrCallExpression extends GrExpression, GrCall {
|
||||
PsiMethod resolveMethod();
|
||||
|
||||
@NotNull
|
||||
GroovyResolveResult[] getMethodVariants();
|
||||
GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument);
|
||||
|
||||
//PsiElement addNamedArgument(GrNamedArgument argument);
|
||||
}
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ public class GroovyExpectedTypesProvider {
|
||||
final int closureIndex = closureArgs.indexOf(myExpression);
|
||||
if (closureIndex >= 0) {
|
||||
List<TypeConstraint> constraints = new ArrayList<TypeConstraint>();
|
||||
for (GroovyResolveResult variant : methodCall.getMethodVariants()) {
|
||||
for (GroovyResolveResult variant : ResolveUtil.getMethodVariants(myExpression)) {
|
||||
PsiParameter[] parameters = getCallParameters(variant);
|
||||
if (parameters == null || parameters.length == 0) continue;
|
||||
|
||||
|
||||
+4
@@ -32,6 +32,10 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt
|
||||
public class GrContainerTypeConverter extends GrTypeConverter {
|
||||
@Override
|
||||
public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
|
||||
if (isMethodCallConversion(context)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isCollectionOrArray(lType) || !isCollectionOrArray(rType)) return null;
|
||||
|
||||
final PsiType lComponentType = extractComponentType(lType);
|
||||
|
||||
@@ -115,7 +115,9 @@ public class GrMapType extends GrLiteralClassType {
|
||||
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
|
||||
components.add(getInternalCanonicalText(entry.first) + ":" + getInternalCanonicalText(entry.second));
|
||||
}
|
||||
return "[" + StringUtil.join(components, ", ") + "]";
|
||||
boolean tooMany = components.size() > 2;
|
||||
final List<String> theFirst = components.subList(0, Math.min(2, components.size()));
|
||||
return "[" + StringUtil.join(theFirst, ", ") + (tooMany ? ",..." : "") + "]";
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
|
||||
@@ -59,6 +59,11 @@ public class GrTupleType extends GrLiteralClassType {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
for (int i = 0; i < myComponentTypes.length; i++) {
|
||||
if (i >= 2) {
|
||||
builder.append(",...");
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > 0) builder.append(", ");
|
||||
builder.append(getInternalCanonicalText(myComponentTypes[i]));
|
||||
}
|
||||
|
||||
+1
-2
@@ -42,7 +42,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -183,7 +182,7 @@ public class GrNewExpressionImpl extends GrCallExpressionImpl implements GrNewEx
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GroovyResolveResult[] getMethodVariants() {
|
||||
public GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument) {
|
||||
final GrCodeReferenceElement referenceElement = getReferenceElement();
|
||||
if (referenceElement == null) return GroovyResolveResult.EMPTY_ARRAY;
|
||||
final GroovyResolveResult[] classResults = referenceElement.multiResolve(false);
|
||||
|
||||
+151
-138
@@ -28,7 +28,10 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -61,7 +64,6 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.processors.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
@@ -413,7 +415,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
|
||||
Kind kind = refExpr.getKind();
|
||||
if (incompleteCode) {
|
||||
ResolverProcessor processor = CompletionProcessor.createRefSameNameProcessor(refExpr, name);
|
||||
resolveImpl(refExpr, processor);
|
||||
refExpr.resolveImpl(processor);
|
||||
GroovyResolveResult[] propertyCandidates = processor.getCandidates();
|
||||
if (propertyCandidates.length > 0) return propertyCandidates;
|
||||
}
|
||||
@@ -436,7 +438,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
|
||||
GroovyResolveResult[] classCandidates = GroovyResolveResult.EMPTY_ARRAY;
|
||||
if (!hasAt) {
|
||||
ResolverProcessor classProcessor = new ClassResolverProcessor(refExpr.getReferenceName(), refExpr, kinds);
|
||||
resolveImpl(refExpr, classProcessor);
|
||||
refExpr.resolveImpl(classProcessor);
|
||||
classCandidates = classProcessor.getCandidates();
|
||||
for (GroovyResolveResult classCandidate : classCandidates) {
|
||||
final PsiElement element = classCandidate.getElement();
|
||||
@@ -447,7 +449,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
|
||||
}
|
||||
|
||||
ResolverProcessor processor = new PropertyResolverProcessor(name, refExpr);
|
||||
resolveImpl(refExpr, processor);
|
||||
refExpr.resolveImpl(processor);
|
||||
final GroovyResolveResult[] fieldCandidates = processor.getCandidates();
|
||||
|
||||
if (refExpr.hasAt()) {
|
||||
@@ -471,7 +473,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
|
||||
List<GroovyResolveResult> accessorResults = new ArrayList<GroovyResolveResult>();
|
||||
for (String getterName : names) {
|
||||
AccessorResolverProcessor accessorResolver = new AccessorResolverProcessor(getterName, refExpr, !isLValue);
|
||||
resolveImpl(refExpr, accessorResolver);
|
||||
refExpr.resolveImpl(accessorResolver);
|
||||
final GroovyResolveResult[] candidates = accessorResolver.getCandidates(); //can be only one candidate
|
||||
if (candidates.length == 1 && candidates[0].isStaticsOK()) {
|
||||
return candidates;
|
||||
@@ -488,18 +490,15 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
|
||||
|
||||
private static GroovyResolveResult[] resolveMethodOrProperty(GrReferenceExpressionImpl refExpr, String name) {
|
||||
final PsiType[] argTypes = PsiUtil.getArgumentTypes(refExpr, false);
|
||||
PsiType thisType = getThisType(refExpr);
|
||||
|
||||
MethodResolverProcessor methodResolver =
|
||||
new MethodResolverProcessor(name, refExpr, false, thisType, argTypes, refExpr.getTypeArguments());
|
||||
resolveImpl(refExpr, methodResolver);
|
||||
MethodResolverProcessor methodResolver = refExpr.runMethodResolverProcessor(argTypes, false);
|
||||
assert methodResolver != null;
|
||||
if (methodResolver.hasApplicableCandidates()) return methodResolver.getCandidates();
|
||||
|
||||
final String[] names = GroovyPropertyUtils.suggestGettersName(name);
|
||||
List<GroovyResolveResult> list = new ArrayList<GroovyResolveResult>();
|
||||
for (String getterName : names) {
|
||||
AccessorResolverProcessor getterResolver = new AccessorResolverProcessor(getterName, refExpr, true);
|
||||
resolveImpl(refExpr, getterResolver);
|
||||
refExpr.resolveImpl(getterResolver);
|
||||
final GroovyResolveResult[] candidates = getterResolver.getCandidates(); //can be only one candidate
|
||||
if (candidates.length == 1 && candidates[0].isStaticsOK()) {
|
||||
refExpr.putUserData(IS_RESOLVED_TO_GETTER, true);
|
||||
@@ -511,7 +510,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
|
||||
}
|
||||
|
||||
PropertyResolverProcessor propertyResolver = new PropertyResolverProcessor(name, refExpr);
|
||||
resolveImpl(refExpr, propertyResolver);
|
||||
refExpr.resolveImpl(propertyResolver);
|
||||
if (propertyResolver.hasCandidates()) return propertyResolver.getCandidates();
|
||||
|
||||
if (methodResolver.hasCandidates()) {
|
||||
@@ -525,144 +524,158 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void resolveImpl(GrReferenceExpressionImpl refExpr, ResolverProcessor processor) {
|
||||
GrExpression qualifier = refExpr.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
ResolveUtil.treeWalkUp(refExpr, processor, true);
|
||||
if (!processor.hasCandidates()) {
|
||||
qualifier = PsiImplUtil.getRuntimeQualifier(refExpr);
|
||||
if (qualifier != null) {
|
||||
processQualifier(refExpr, processor, qualifier);
|
||||
}
|
||||
private void resolveImpl(ResolverProcessor processor) {
|
||||
GrExpression qualifier = getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
ResolveUtil.treeWalkUp(this, processor, true);
|
||||
if (!processor.hasCandidates()) {
|
||||
qualifier = PsiImplUtil.getRuntimeQualifier(this);
|
||||
if (qualifier != null) {
|
||||
processQualifier(processor, qualifier);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
|
||||
processQualifier(processor, qualifier);
|
||||
} else {
|
||||
if (refExpr.getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
|
||||
processQualifier(refExpr, processor, qualifier);
|
||||
} else {
|
||||
processQualifierForSpreadDot(refExpr, processor, qualifier);
|
||||
}
|
||||
|
||||
if (qualifier instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)qualifier).getReferenceName())) {
|
||||
processIfJavaLangClass(refExpr, processor, qualifier.getType());
|
||||
} else if (qualifier instanceof GrThisReferenceExpression) {
|
||||
processIfJavaLangClass(refExpr, processor, qualifier.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processIfJavaLangClass(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, PsiType type) {
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClass psiClass = ((PsiClassType)type).resolve();
|
||||
if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
|
||||
final PsiType[] params = ((PsiClassType)type).getParameters();
|
||||
if (params.length == 1) {
|
||||
processClassQualifierType(refExpr, processor, params[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processQualifierForSpreadDot(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, GrExpression qualifier) {
|
||||
PsiType qualifierType = qualifier.getType();
|
||||
if (qualifierType instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult result = ((PsiClassType) qualifierType).resolveGenerics();
|
||||
PsiClass clazz = result.getElement();
|
||||
if (clazz != null) {
|
||||
PsiClass listClass = ResolveUtil.findListClass(refExpr.getManager(), refExpr.getResolveScope());
|
||||
if (listClass != null && listClass.getTypeParameters().length == 1) {
|
||||
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(listClass, clazz, result.getSubstitutor());
|
||||
if (substitutor != null) {
|
||||
PsiType componentType = substitutor.substitute(listClass.getTypeParameters()[0]);
|
||||
if (componentType != null) {
|
||||
processClassQualifierType(refExpr, processor, componentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (qualifierType instanceof PsiArrayType) {
|
||||
processClassQualifierType(refExpr, processor, ((PsiArrayType) qualifierType).getComponentType());
|
||||
}
|
||||
}
|
||||
|
||||
private static void processQualifier(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, GrExpression qualifier) {
|
||||
PsiType qualifierType = qualifier.getType();
|
||||
if (qualifierType == null) {
|
||||
if (qualifier instanceof GrReferenceExpression) {
|
||||
PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
|
||||
if (resolved instanceof PsiPackage) {
|
||||
if (!resolved.processDeclarations(processor, ResolveState.initial(), null, refExpr)) //noinspection UnnecessaryReturnStatement
|
||||
return;
|
||||
}
|
||||
else {
|
||||
qualifierType = JavaPsiFacade.getInstance(refExpr.getProject()).getElementFactory()
|
||||
.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, refExpr.getResolveScope());
|
||||
processClassQualifierType(refExpr, processor, qualifierType);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (qualifierType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
|
||||
processClassQualifierType(refExpr, processor, conjunct);
|
||||
}
|
||||
} else {
|
||||
processClassQualifierType(refExpr, processor, qualifierType);
|
||||
if (qualifier instanceof GrReferenceExpression) {
|
||||
PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
|
||||
if (resolved instanceof PsiClass) { //omitted .class
|
||||
PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, refExpr.getResolveScope());
|
||||
if (javaLangClass != null) {
|
||||
ResolveState state = ResolveState.initial();
|
||||
PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters();
|
||||
PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
|
||||
if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
|
||||
if (typeParameters.length == 1) {
|
||||
substitutor = substitutor.put(typeParameters[0], qualifierType);
|
||||
state = state.put(PsiSubstitutor.KEY, substitutor);
|
||||
}
|
||||
if (!javaLangClass.processDeclarations(processor, state, null, refExpr)) return;
|
||||
PsiType javaLangClassType = JavaPsiFacade.getInstance(refExpr.getProject()).getElementFactory().createType(javaLangClass, substitutor);
|
||||
ResolveUtil.processNonCodeMethods(javaLangClassType, processor, refExpr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processClassQualifierType(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, PsiType qualifierType) {
|
||||
Project project = refExpr.getProject();
|
||||
if (qualifierType instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType) qualifierType).resolveGenerics();
|
||||
PsiClass qualifierClass = qualifierResult.getElement();
|
||||
if (qualifierClass != null) {
|
||||
if (!qualifierClass.processDeclarations(processor,
|
||||
ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor()), null, refExpr))
|
||||
return;
|
||||
}
|
||||
if (!ResolveUtil.processCategoryMembers(refExpr, processor)) return;
|
||||
} else if (qualifierType instanceof PsiArrayType) {
|
||||
final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project).getArrayClass();
|
||||
if (!arrayClass.processDeclarations(processor, ResolveState.initial(), null, refExpr)) return;
|
||||
} else if (qualifierType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
|
||||
processClassQualifierType(refExpr, processor, conjunct);
|
||||
}
|
||||
return;
|
||||
processQualifierForSpreadDot(processor, qualifier);
|
||||
}
|
||||
|
||||
ResolveUtil.processNonCodeMethods(qualifierType, processor, refExpr, false);
|
||||
if (qualifier instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)qualifier).getReferenceName())) {
|
||||
processIfJavaLangClass(processor, qualifier.getType());
|
||||
} else if (qualifier instanceof GrThisReferenceExpression) {
|
||||
processIfJavaLangClass(processor, qualifier.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiType getThisType(GrReferenceExpression refExpr) {
|
||||
GrExpression qualifier = refExpr.getQualifierExpression();
|
||||
private void processIfJavaLangClass(ResolverProcessor processor, PsiType type) {
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClass psiClass = ((PsiClassType)type).resolve();
|
||||
if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
|
||||
final PsiType[] params = ((PsiClassType)type).getParameters();
|
||||
if (params.length == 1) {
|
||||
processClassQualifierType(processor, params[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processQualifierForSpreadDot(ResolverProcessor processor, GrExpression qualifier) {
|
||||
PsiType qualifierType = qualifier.getType();
|
||||
if (qualifierType instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult result = ((PsiClassType) qualifierType).resolveGenerics();
|
||||
PsiClass clazz = result.getElement();
|
||||
if (clazz != null) {
|
||||
PsiClass listClass = ResolveUtil.findListClass(getManager(), getResolveScope());
|
||||
if (listClass != null && listClass.getTypeParameters().length == 1) {
|
||||
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(listClass, clazz, result.getSubstitutor());
|
||||
if (substitutor != null) {
|
||||
PsiType componentType = substitutor.substitute(listClass.getTypeParameters()[0]);
|
||||
if (componentType != null) {
|
||||
processClassQualifierType(processor, componentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (qualifierType instanceof PsiArrayType) {
|
||||
processClassQualifierType(processor, ((PsiArrayType) qualifierType).getComponentType());
|
||||
}
|
||||
}
|
||||
|
||||
private void processQualifier(ResolverProcessor processor, GrExpression qualifier) {
|
||||
PsiType qualifierType = qualifier.getType();
|
||||
if (qualifierType == null) {
|
||||
if (qualifier instanceof GrReferenceExpression) {
|
||||
PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
|
||||
if (resolved instanceof PsiPackage) {
|
||||
if (!resolved.processDeclarations(processor, ResolveState.initial(), null, this)) //noinspection UnnecessaryReturnStatement
|
||||
return;
|
||||
}
|
||||
else {
|
||||
qualifierType = JavaPsiFacade.getInstance(getProject()).getElementFactory()
|
||||
.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, getResolveScope());
|
||||
processClassQualifierType(processor, qualifierType);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (qualifierType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
|
||||
processClassQualifierType(processor, conjunct);
|
||||
}
|
||||
} else {
|
||||
processClassQualifierType(processor, qualifierType);
|
||||
if (qualifier instanceof GrReferenceExpression) {
|
||||
PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
|
||||
if (resolved instanceof PsiClass) { //omitted .class
|
||||
PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, getResolveScope());
|
||||
if (javaLangClass != null) {
|
||||
ResolveState state = ResolveState.initial();
|
||||
PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters();
|
||||
PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
|
||||
if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
|
||||
if (typeParameters.length == 1) {
|
||||
substitutor = substitutor.put(typeParameters[0], qualifierType);
|
||||
state = state.put(PsiSubstitutor.KEY, substitutor);
|
||||
}
|
||||
if (!javaLangClass.processDeclarations(processor, state, null, this)) return;
|
||||
PsiType javaLangClassType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createType(javaLangClass, substitutor);
|
||||
ResolveUtil.processNonCodeMethods(javaLangClassType, processor, this, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processClassQualifierType(ResolverProcessor processor, PsiType qualifierType) {
|
||||
Project project = getProject();
|
||||
if (qualifierType instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType) qualifierType).resolveGenerics();
|
||||
PsiClass qualifierClass = qualifierResult.getElement();
|
||||
if (qualifierClass != null) {
|
||||
if (!qualifierClass.processDeclarations(processor,
|
||||
ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor()), null, this))
|
||||
return;
|
||||
}
|
||||
if (!ResolveUtil.processCategoryMembers(this, processor)) return;
|
||||
} else if (qualifierType instanceof PsiArrayType) {
|
||||
final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project).getArrayClass();
|
||||
if (!arrayClass.processDeclarations(processor, ResolveState.initial(), null, this)) return;
|
||||
} else if (qualifierType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
|
||||
processClassQualifierType(processor, conjunct);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ResolveUtil.processNonCodeMethods(qualifierType, processor, this, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MethodResolverProcessor runMethodResolverProcessor(PsiType[] argTypes, final boolean allVariants) {
|
||||
final String name = getReferenceName();
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiType thisType = getThisType();
|
||||
|
||||
MethodResolverProcessor methodResolver = new MethodResolverProcessor(name, this, false, thisType, argTypes, getTypeArguments(), allVariants);
|
||||
resolveImpl(methodResolver);
|
||||
return methodResolver;
|
||||
}
|
||||
|
||||
private PsiType getThisType() {
|
||||
GrExpression qualifier = getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
PsiType qType = qualifier.getType();
|
||||
if (qType != null) return qType;
|
||||
}
|
||||
|
||||
return TypesUtil.getJavaLangObject(refExpr);
|
||||
return TypesUtil.getJavaLangObject(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+31
-1
@@ -233,6 +233,23 @@ public class TypesUtil {
|
||||
}
|
||||
|
||||
public static boolean isAssignable(PsiType lType, PsiType rType, GroovyPsiElement context, boolean allowConversion) {
|
||||
if (rType instanceof PsiIntersectionType) {
|
||||
for (PsiType child : ((PsiIntersectionType)rType).getConjuncts()) {
|
||||
if (isAssignable(lType, child, context, allowConversion)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (lType instanceof PsiIntersectionType) {
|
||||
for (PsiType child : ((PsiIntersectionType)lType).getConjuncts()) {
|
||||
if (!isAssignable(child, rType, context, allowConversion)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (allowConversion && lType != null && rType != null) {
|
||||
for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) {
|
||||
final Boolean result = converter.isConvertible(lType, rType, context);
|
||||
@@ -267,7 +284,20 @@ public class TypesUtil {
|
||||
}
|
||||
|
||||
public static boolean isAssignableByMethodCallConversion(PsiType lType, PsiType rType, GroovyPsiElement context) {
|
||||
return isAssignableByMethodCallConversion(lType, rType, context.getManager(), context.getResolveScope());
|
||||
if (lType == null || rType == null) return false;
|
||||
|
||||
if (isAssignableByMethodCallConversion(lType, rType, context.getManager(), context.getResolveScope())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) {
|
||||
final Boolean result = converter.isConvertible(lType, rType, context);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAssignableByMethodCallConversion(PsiType lType, PsiType rType, PsiManager manager, GlobalSearchScope scope) {
|
||||
|
||||
+9
-13
@@ -41,9 +41,9 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrRefer
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -187,21 +187,17 @@ public class GrMethodCallExpressionImpl extends GrCallExpressionImpl implements
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GroovyResolveResult[] getMethodVariants() {
|
||||
public GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument) {
|
||||
final GrExpression invoked = getInvokedExpression();
|
||||
if (!(invoked instanceof GrReferenceExpression)) return GroovyResolveResult.EMPTY_ARRAY;
|
||||
final ArrayList<GroovyResolveResult> res = new ArrayList<GroovyResolveResult>();
|
||||
if (!(invoked instanceof GrReferenceExpressionImpl)) return GroovyResolveResult.EMPTY_ARRAY;
|
||||
|
||||
for (PsiReference ref : invoked.getReferences()) {
|
||||
if (ref instanceof PsiPolyVariantReference) {
|
||||
for (ResolveResult result : ((PsiPolyVariantReference)ref).multiResolve(true)) {
|
||||
if (result instanceof GroovyResolveResult) {
|
||||
res.add((GroovyResolveResult)result);
|
||||
}
|
||||
}
|
||||
}
|
||||
final PsiType[] partialArgs = PsiUtil.getArgumentTypes(invoked, false, upToArgument);
|
||||
final MethodResolverProcessor processor = ((GrReferenceExpressionImpl)invoked).runMethodResolverProcessor(partialArgs, true);
|
||||
if (processor != null) {
|
||||
return processor.getCandidates();
|
||||
}
|
||||
return res.toArray(new GroovyResolveResult[res.size()]);
|
||||
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ public class GroovyExpressionPattern<T extends GrExpression, Self extends Groovy
|
||||
public GroovyMethodCallPattern methodCall(final ElementPattern<? extends PsiMethod> method) {
|
||||
return new GroovyMethodCallPattern().and(this).with(new PatternCondition<GrCallExpression>("methodCall") {
|
||||
public boolean accepts(@NotNull GrCallExpression callExpression, ProcessingContext context) {
|
||||
final GroovyResolveResult[] results = callExpression.getMethodVariants();
|
||||
final GroovyResolveResult[] results = callExpression.getMethodVariants(null);
|
||||
for (GroovyResolveResult result : results) {
|
||||
if (method.getCondition().accepts(result.getElement(), context)) {
|
||||
return true;
|
||||
@@ -72,4 +72,4 @@ public class GroovyExpressionPattern<T extends GrExpression, Self extends Groovy
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +175,10 @@ public class PsiUtil {
|
||||
|
||||
@Nullable
|
||||
public static PsiType[] getArgumentTypes(PsiElement place, boolean nullAsBottom) {
|
||||
return getArgumentTypes(place, nullAsBottom, null);
|
||||
}
|
||||
@Nullable
|
||||
public static PsiType[] getArgumentTypes(PsiElement place, boolean nullAsBottom, @Nullable GrExpression stopAt) {
|
||||
PsiElement parent = place.getParent();
|
||||
if (parent instanceof GrCallExpression) {
|
||||
List<PsiType> result = new ArrayList<PsiType>();
|
||||
@@ -193,6 +197,9 @@ public class PsiUtil {
|
||||
} else {
|
||||
result.add(type);
|
||||
}
|
||||
if (stopAt == expression) {
|
||||
return result.toArray(new PsiType[result.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
GrClosableBlock[] closures = call.getClosureArguments();
|
||||
@@ -201,6 +208,9 @@ public class PsiUtil {
|
||||
if (closureType != null) {
|
||||
result.add(closureType);
|
||||
}
|
||||
if (stopAt == closure) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.toArray(new PsiType[result.size()]);
|
||||
@@ -224,6 +234,9 @@ public class PsiUtil {
|
||||
} else {
|
||||
result.add(type);
|
||||
}
|
||||
if (stopAt == expression) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.toArray(new PsiType[result.size()]);
|
||||
@@ -245,6 +258,10 @@ public class PsiUtil {
|
||||
else {
|
||||
result.add(argType);
|
||||
}
|
||||
if (stopAt == arg) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return result.toArray(new PsiType[result.size()]);
|
||||
} else if (parent instanceof GrConstructorInvocation || parent instanceof GrEnumConstant) {
|
||||
@@ -264,6 +281,10 @@ public class PsiUtil {
|
||||
} else {
|
||||
result.add(type);
|
||||
}
|
||||
if (stopAt == expression) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result.toArray(new PsiType[result.size()]);
|
||||
@@ -603,7 +624,7 @@ public class PsiUtil {
|
||||
}
|
||||
|
||||
public static boolean isRawMethodCall(GrMethodCallExpression call) {
|
||||
final GroovyResolveResult[] resolveResults = call.getMethodVariants();
|
||||
final GroovyResolveResult[] resolveResults = call.getMethodVariants(null);
|
||||
if (resolveResults.length == 0) return false;
|
||||
final PsiElement element = resolveResults[0].getElement();
|
||||
if (element instanceof PsiMethod) {
|
||||
|
||||
@@ -444,7 +444,7 @@ public class ResolveUtil {
|
||||
final PsiElement parent = place.getParent();
|
||||
GroovyResolveResult[] variants = GroovyResolveResult.EMPTY_ARRAY;
|
||||
if (parent instanceof GrCallExpression) {
|
||||
variants = ((GrCallExpression) parent).getMethodVariants();
|
||||
variants = ((GrCallExpression) parent).getMethodVariants(place instanceof GrExpression ? (GrExpression)place : null);
|
||||
} else if (parent instanceof GrConstructorInvocation) {
|
||||
final PsiClass clazz = ((GrConstructorInvocation) parent).getDelegatedClass();
|
||||
if (clazz != null) {
|
||||
|
||||
+10
-1
@@ -50,6 +50,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
|
||||
@Nullable
|
||||
private final PsiType[] myArgumentTypes;
|
||||
private final PsiType[] myTypeArguments;
|
||||
private final boolean myAllVariants;
|
||||
|
||||
private final Set<GroovyResolveResult> myInapplicableCandidates = new LinkedHashSet<GroovyResolveResult>();
|
||||
private final boolean myIsConstructor;
|
||||
@@ -57,11 +58,15 @@ public class MethodResolverProcessor extends ResolverProcessor {
|
||||
private boolean myStopExecuting = false;
|
||||
|
||||
public MethodResolverProcessor(String name, GroovyPsiElement place, boolean isConstructor, PsiType thisType, @Nullable PsiType[] argumentTypes, PsiType[] typeArguments) {
|
||||
this(name, place, isConstructor, thisType, argumentTypes, typeArguments, false);
|
||||
}
|
||||
public MethodResolverProcessor(String name, GroovyPsiElement place, boolean isConstructor, PsiType thisType, @Nullable PsiType[] argumentTypes, PsiType[] typeArguments, boolean allVariants) {
|
||||
super(name, EnumSet.of(ResolveKind.METHOD, ResolveKind.PROPERTY), place, PsiType.EMPTY_ARRAY);
|
||||
myIsConstructor = isConstructor;
|
||||
myThisType = thisType;
|
||||
myArgumentTypes = argumentTypes;
|
||||
myTypeArguments = typeArguments;
|
||||
myAllVariants = allVariants;
|
||||
}
|
||||
|
||||
public boolean execute(PsiElement element, ResolveState state) {
|
||||
@@ -78,7 +83,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
|
||||
boolean isAccessible = isAccessible(method);
|
||||
GroovyPsiElement fileResolveContext = state.get(RESOLVE_CONTEXT);
|
||||
boolean isStaticsOK = isStaticsOK(method, fileResolveContext);
|
||||
if (PsiUtil.isApplicable(myArgumentTypes, method, substitutor, fileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace) && isStaticsOK) {
|
||||
if (!myAllVariants && PsiUtil.isApplicable(myArgumentTypes, method, substitutor, fileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace) && isStaticsOK) {
|
||||
myCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK));
|
||||
} else {
|
||||
myInapplicableCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK));
|
||||
@@ -213,6 +218,10 @@ public class MethodResolverProcessor extends ResolverProcessor {
|
||||
|
||||
@NotNull
|
||||
public GroovyResolveResult[] getCandidates() {
|
||||
if (myAllVariants) {
|
||||
return myInapplicableCandidates.toArray(new GroovyResolveResult[myInapplicableCandidates.size()]);
|
||||
}
|
||||
|
||||
if (!myCandidates.isEmpty()) {
|
||||
return filterCandidates();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.
|
||||
* 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 org.jetbrains.plugins.groovy.compiler;
|
||||
|
||||
|
||||
import com.intellij.testFramework.PsiTestUtil
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GppCompilerTest extends GroovyCompilerTestCase {
|
||||
@Override protected void setUp() {
|
||||
super.setUp();
|
||||
PsiTestUtil.addLibrary myFixture.module, "gpp", TestUtils.absoluteTestDataPath + "/realGroovypp/", "groovypp-all-0.2.13.jar"
|
||||
}
|
||||
|
||||
public void testTraitStubs() throws Throwable {
|
||||
myFixture.addFileToProject("A.groovy", """
|
||||
@Trait
|
||||
abstract class SomeTrait {
|
||||
abstract def some()
|
||||
def concrete() {}
|
||||
}
|
||||
|
||||
@Trait
|
||||
abstract class AnotherTrait extends SomeTrait {
|
||||
abstract def another()
|
||||
}
|
||||
|
||||
class Goo implements SomeTrait {
|
||||
def some() {}
|
||||
}
|
||||
class Bar implements AnotherTrait {
|
||||
def some() {}
|
||||
def another() {}
|
||||
}
|
||||
""");
|
||||
myFixture.addClass("""
|
||||
class Foo implements SomeTrait {
|
||||
public Object some() { return null; }
|
||||
public Object concrete() { return null; }
|
||||
}""")
|
||||
assertEmpty(make());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,10 @@ import junit.framework.AssertionFailedError
|
||||
* @author peter
|
||||
*/
|
||||
public class GroovyCompilerTest extends GroovyCompilerTestCase {
|
||||
@Override protected void setUp() {
|
||||
super.setUp();
|
||||
addGroovyLibrary(myModule, getName().contains("1_7"));
|
||||
}
|
||||
|
||||
public void testPlainGroovy() throws Throwable {
|
||||
myFixture.addFileToProject("A.groovy", "println '239'");
|
||||
|
||||
@@ -71,8 +71,6 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
|
||||
CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(myMainOutput.findOrCreateDir("out").getUrl());
|
||||
}
|
||||
}.execute();
|
||||
|
||||
addGroovyLibrary(myModule, getName().contains("1_7"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,17 +36,17 @@ class GppFunctionalTest extends LightCodeInsightFixtureTestCase {
|
||||
super.setUp()
|
||||
}
|
||||
|
||||
public void _testCastListToIterable() throws Exception {
|
||||
public void testCastListToIterable() throws Exception {
|
||||
myFixture.addClass("class X extends java.util.ArrayList<Integer> {}")
|
||||
testAssignability """
|
||||
X ints = [239, 4.2d]
|
||||
"""
|
||||
}
|
||||
|
||||
public void _testCastListToAnything() throws Exception {
|
||||
public void testCastListToAnything() throws Exception {
|
||||
testAssignability """
|
||||
File f1 = ['path']
|
||||
File f2 = <warning descr="Cannot assign 'List' to 'File'">['path', 2, true, 42]</warning>
|
||||
File f2 = <warning descr="Cannot assign 'List<Serializable>' to 'File'">['path', 2, true, 42]</warning>
|
||||
"""
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ class BarImpl extends Bar {}
|
||||
return myFixture.file.findReferenceAt(myFixture.editor.caretModel.offset).resolve()
|
||||
}
|
||||
|
||||
public void _testMethodTypeParameterInference() throws Exception {
|
||||
public void testMethodTypeParameterInference() throws Exception {
|
||||
configureScript """
|
||||
@Typed package aaa
|
||||
|
||||
@@ -334,7 +334,7 @@ r.apply { it.intV<caret>i }
|
||||
assertSameElements myFixture.getLookupElementStrings(), "intValue"
|
||||
}
|
||||
|
||||
public void _testMethodTypeParameterInference2() throws Exception {
|
||||
public void testMethodTypeParameterInference2() throws Exception {
|
||||
configureScript """
|
||||
@Typed package aaa
|
||||
|
||||
@@ -385,4 +385,4 @@ class GppProjectDescriptor extends DefaultLightProjectDescriptor {
|
||||
modifiableModel.addRoot(JarFileSystem.instance.refreshAndFindFileByPath(TestUtils.mockGroovy1_7LibraryName + "!/"), OrderRootType.CLASSES);
|
||||
modifiableModel.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
def foo(int... i) {}
|
||||
def list = [1, 2, 3]
|
||||
foo<warning descr="'foo' in 'SignatureIsNotApplicableToList' cannot be applied to '([java.lang.Integer, java.lang.Integer, java.lang.Integer])'">(list)</warning>
|
||||
foo<warning descr="'foo' in 'SignatureIsNotApplicableToList' cannot be applied to '([java.lang.Integer, java.lang.Integer,...])'">(list)</warning>
|
||||
Binary file not shown.
+3
-1
@@ -80,6 +80,8 @@ public class JUnitUnusedCodeExtension extends UnusedCodeExtension {
|
||||
}
|
||||
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
DefaultJDOMExternalizer.writeExternal(this, element);
|
||||
if (!ADD_JUNIT_TO_ENTRIES) {
|
||||
DefaultJDOMExternalizer.writeExternal(this, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -68,7 +68,9 @@ public class TestNGUnusedCodeExtension extends UnusedCodeExtension {
|
||||
}
|
||||
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
DefaultJDOMExternalizer.writeExternal(this, element);
|
||||
if (!ADD_TESTNG_TO_ENTRIES) {
|
||||
DefaultJDOMExternalizer.writeExternal(this, element);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+4
-1
@@ -86,7 +86,10 @@ public class ConvertSchemaPrefixToDefaultIntention extends PsiElementBaseIntenti
|
||||
protected void run(Result result) throws Throwable {
|
||||
final int index = ns.length() + 1;
|
||||
for (XmlTag tag : tags) {
|
||||
tag.setName(tag.getName().substring(index));
|
||||
final String s = tag.getName().substring(index);
|
||||
if (s.length() > 0) {
|
||||
tag.setName(s);
|
||||
}
|
||||
}
|
||||
for (XmlAttribute attr : attrs) {
|
||||
attr.setValue(attr.getValue().substring(index));
|
||||
|
||||
+23
-8
@@ -16,8 +16,10 @@
|
||||
|
||||
package com.intellij.psi.impl.source.resolve.reference.impl.manipulators;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.AbstractElementManipulator;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.xml.XmlText;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
@@ -27,14 +29,27 @@ import com.intellij.util.IncorrectOperationException;
|
||||
public class XmlTextManipulator extends AbstractElementManipulator<XmlText> {
|
||||
|
||||
public XmlText handleContentChange(XmlText text, TextRange range, String newContent) throws IncorrectOperationException {
|
||||
|
||||
final StringBuilder replacement = new StringBuilder(text.getValue());
|
||||
replacement.replace(
|
||||
range.getStartOffset(),
|
||||
range.getEndOffset(),
|
||||
newContent
|
||||
);
|
||||
text.setValue(replacement.toString());
|
||||
final String newValue;
|
||||
final String value = text.getValue();
|
||||
if (range.equals(getRangeInElement(text))) {
|
||||
newValue = newContent;
|
||||
}
|
||||
else {
|
||||
final StringBuilder replacement = new StringBuilder(value);
|
||||
replacement.replace(
|
||||
range.getStartOffset(),
|
||||
range.getEndOffset(),
|
||||
newContent
|
||||
);
|
||||
newValue = replacement.toString();
|
||||
}
|
||||
if (Comparing.equal(value, newValue)) return text;
|
||||
if (newValue.length() > 0) {
|
||||
text.setValue(newValue);
|
||||
}
|
||||
else {
|
||||
text.deleteChildRange(text.getFirstChild(), text.getLastChild());
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user