Merge branch 'master' of git@git.labs.intellij.net:idea/community

This commit is contained in:
Eugene Kudelevsky
2010-07-12 17:29:54 +04:00
47 changed files with 666 additions and 273 deletions
@@ -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());
}
}
}
}
@@ -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) {
@@ -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;
}
@@ -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();
@@ -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);
@@ -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;
}
}
@@ -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]);
}
@@ -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;
@@ -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) {
@@ -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
@@ -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();
@@ -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 {
@@ -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);
}
}
@@ -43,7 +43,7 @@ public interface GrCallExpression extends GrExpression, GrCall {
PsiMethod resolveMethod();
@NotNull
GroovyResolveResult[] getMethodVariants();
GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument);
//PsiElement addNamedArgument(GrNamedArgument argument);
}
@@ -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;
@@ -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]));
}
@@ -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);
@@ -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);
}
@@ -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) {
@@ -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;
}
}
@@ -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) {
@@ -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.
@@ -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);
}
}
}
@@ -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
@@ -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));
@@ -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;
}