Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2015-08-19 19:52:32 +02:00
59 changed files with 3534 additions and 500 deletions
@@ -143,40 +143,66 @@ public class JavaDocInfoGenerator {
}
interface DocTagLocator <T> {
T find(PsiDocComment comment);
T find(PsiDocCommentOwner owner, PsiDocComment comment);
}
private static DocTagLocator<PsiDocTag> parameterLocator(final String name) {
private static DocTagLocator<PsiDocTag> parameterLocator(final int parameterIndex) {
return new DocTagLocator<PsiDocTag>() {
@Override
public PsiDocTag find(PsiDocComment comment) {
if (comment == null) {
return null;
}
public PsiDocTag find(PsiDocCommentOwner owner, PsiDocComment comment) {
if (parameterIndex < 0 || comment == null || !(owner instanceof PsiMethod)) return null;
PsiDocTag[] tags = comment.findTagsByName("param");
for (PsiDocTag tag : tags) {
PsiDocTagValue value = tag.getValueElement();
if (value != null) {
String text = value.getText();
if (text != null && text.equals(name)) {
return tag;
}
}
}
return null;
PsiParameter[] parameters = ((PsiMethod)owner).getParameterList().getParameters();
if (parameterIndex >= parameters.length) return null;
String name = parameters[parameterIndex].getName();
return getParamTagByName(comment, name);
}
};
}
private static DocTagLocator<PsiDocTag> typeParameterLocator(final int parameterIndex) {
return new DocTagLocator<PsiDocTag>() {
@Override
public PsiDocTag find(PsiDocCommentOwner owner, PsiDocComment comment) {
if (parameterIndex < 0 || comment == null || !(owner instanceof PsiTypeParameterListOwner)) return null;
PsiTypeParameter[] parameters = ((PsiTypeParameterListOwner)owner).getTypeParameters();
if (parameterIndex >= parameters.length) return null;
String rawName = parameters[parameterIndex].getName();
if (rawName == null) return null;
String name = "<" + rawName + ">";
return getParamTagByName(comment, name);
}
};
}
private static PsiDocTag getParamTagByName(@NotNull PsiDocComment comment, String name) {
PsiDocTag[] tags = comment.findTagsByName("param");
return getTagByName(tags, name);
}
private static PsiDocTag getTagByName(@NotNull PsiDocTag[] tags, String name) {
for (PsiDocTag tag : tags) {
PsiDocTagValue value = tag.getValueElement();
if (value != null) {
String text = value.getText();
if (text != null && text.equals(name)) {
return tag;
}
}
}
return null;
}
private static DocTagLocator<PsiDocTag> exceptionLocator(final String name) {
return new DocTagLocator<PsiDocTag>() {
@Override
public PsiDocTag find(PsiDocComment comment) {
public PsiDocTag find(PsiDocCommentOwner owner, PsiDocComment comment) {
if (comment == null) {
return null;
}
@@ -467,23 +493,24 @@ public class JavaDocInfoGenerator {
}
private void generateTypeParametersSection(final StringBuilder buffer, final PsiClass aClass) {
final LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>> result =
new LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>>();
final LinkedList<ParamInfo> result = new LinkedList<ParamInfo>();
final PsiTypeParameter[] typeParameters = aClass.getTypeParameters();
for (PsiTypeParameter typeParameter : typeParameters) {
final DocTagLocator<PsiDocTag> locator = parameterLocator("<" + typeParameter.getName() + ">");
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter typeParameter = typeParameters[i];
String name = "<" + typeParameter.getName() + ">";
final DocTagLocator<PsiDocTag> locator = typeParameterLocator(i);
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> inClassComment = findInClassComment(aClass, locator);
if (inClassComment != null) {
result.add(inClassComment);
result.add(new ParamInfo(name, inClassComment));
}
else {
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> pair = findInHierarchy(aClass, locator);
if (pair != null) {
result.add(pair);
result.add(new ParamInfo(name, pair));
}
}
}
generateTypeParametersSection(buffer, result);
generateParametersSection(buffer, CodeInsightBundle.message("javadoc.type.parameters"), result);
}
@Nullable
@@ -500,7 +527,7 @@ public class JavaDocInfoGenerator {
}
private static Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> findInClassComment(final PsiClass psiClass, final DocTagLocator<PsiDocTag> locator) {
final PsiDocTag tag = locator.find(getDocComment(psiClass));
final PsiDocTag tag = locator.find(psiClass, getDocComment(psiClass));
if (tag != null) {
return new Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>(tag, new InheritDocProvider<PsiDocTag>() {
@Override
@@ -541,17 +568,7 @@ public class JavaDocInfoGenerator {
if (generatePrologueAndEpilogue)
generatePrologue(buffer);
PsiClass parentClass = field.getContainingClass();
if (parentClass != null) {
String qName = parentClass.getQualifiedName();
if (qName != null) {
buffer.append("<small><b>");
//buffer.append(qName);
generateLink(buffer, qName, qName, field, false);
buffer.append("</b></small>");
//buffer.append("<br>");
}
}
generateLinkToParentIfNeeded(buffer, field);
buffer.append("<PRE>");
generateFieldSignature(buffer, field, true);
@@ -929,8 +946,11 @@ public class JavaDocInfoGenerator {
}
private void generateMethodParameterJavaDoc(@NonNls StringBuilder buffer, PsiParameter parameter, boolean generatePrologueAndEpilogue) {
if (generatePrologueAndEpilogue)
String parameterName = parameter.getName();
if (generatePrologueAndEpilogue) {
generatePrologue(buffer);
}
buffer.append("<PRE>");
String modifiers = PsiFormatUtil.formatModifiers(parameter, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY);
@@ -942,7 +962,7 @@ public class JavaDocInfoGenerator {
generateType(buffer, parameter.getType(), parameter);
buffer.append(" ");
buffer.append("<b>");
buffer.append(parameter.getName());
buffer.append(parameterName);
appendInitializer(buffer, parameter);
buffer.append("</b>");
buffer.append("</PRE>");
@@ -950,14 +970,14 @@ public class JavaDocInfoGenerator {
final PsiElement method = PsiTreeUtil.getParentOfType(parameter, PsiMethod.class, PsiLambdaExpression.class);
if (method instanceof PsiMethod) {
final PsiDocComment docComment = getDocComment((PsiMethod)method);
PsiMethod psiMethod = (PsiMethod)method;
final PsiDocComment docComment = getDocComment(psiMethod);
final PsiDocTag[] localTags = docComment != null ? docComment.getTags() : PsiDocTag.EMPTY_ARRAY;
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tagInfoProvider =
findDocTag(localTags, parameter.getName(), (PsiMethod)method);
int parameterIndex = psiMethod.getParameterList().getParameterIndex(parameter);
final ParamInfo tagInfoProvider = findDocTag(localTags, parameterName, psiMethod, parameterLocator(parameterIndex));
if (tagInfoProvider != null) {
PsiElement[] elements = tagInfoProvider.first.getDataElements();
if (elements.length != 0) generateOneParameter(elements, buffer, tagInfoProvider);
generateOneParameter(buffer, tagInfoProvider);
}
}
@@ -969,17 +989,7 @@ public class JavaDocInfoGenerator {
if (generatePrologueAndEpilogue)
generatePrologue(buffer);
PsiClass parentClass = method.getContainingClass();
if (parentClass != null) {
String qName = parentClass.getQualifiedName();
if (qName != null) {
buffer.append("<small><b>");
generateLink(buffer, qName, qName, method, false);
//buffer.append(qName);
buffer.append("</b></small>");
//buffer.append("<br>");
}
}
generateLinkToParentIfNeeded(buffer, method);
buffer.append("<PRE>");
generateMethodSignature(buffer, method, true, false);
@@ -999,7 +1009,7 @@ public class JavaDocInfoGenerator {
}
generateParametersSection(buffer, method, comment);
generateTypeParametersSection(buffer, method);
generateTypeParametersSection(buffer, method, comment);
generateReturnsSection(buffer, method, comment);
generateThrowsSection(buffer, method, comment);
@@ -1013,6 +1023,18 @@ public class JavaDocInfoGenerator {
generateEpilogue(buffer);
}
private static void generateLinkToParentIfNeeded(StringBuilder buffer, PsiMember member) {
PsiClass parentClass = member.getContainingClass();
if (parentClass != null) {
String qName = parentClass.getQualifiedName();
if (qName != null) {
buffer.append("<small><b>");
generateLink(buffer, qName, qName, member, false);
buffer.append("</b></small>");
}
}
}
private static void generateMethodSignature(StringBuilder buffer, PsiMethod method, boolean generateLink, boolean useShortNames) {
generateAnnotations(buffer, method, generateLink, true, useShortNames);
String modifiers = PsiFormatUtil.formatModifiers(method, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY);
@@ -1218,7 +1240,7 @@ public class JavaDocInfoGenerator {
private void generateMethodDescription(@NonNls StringBuilder buffer, final PsiMethod method, final PsiDocComment comment) {
final DocTagLocator<PsiElement[]> descriptionLocator = new DocTagLocator<PsiElement[]>() {
@Override
public PsiElement[] find(PsiDocComment comment) {
public PsiElement[] find(PsiDocCommentOwner owner, PsiDocComment comment) {
if (comment == null) {
return null;
}
@@ -1537,113 +1559,86 @@ public class JavaDocInfoGenerator {
PsiParameter[] params = method.getParameterList().getParameters();
PsiDocTag[] localTags = comment != null ? comment.findTagsByName("param") : PsiDocTag.EMPTY_ARRAY;
LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>> collectedTags =
new LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>>();
LinkedList<ParamInfo> collectedTags = new LinkedList<ParamInfo>();
for (PsiParameter param : params) {
for (int i = 0; i < params.length; i++) {
PsiParameter param = params[i];
final String paramName = param.getName();
Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> parmTag = findDocTag(localTags, paramName, method);
DocTagLocator<PsiDocTag> tagLocator = parameterLocator(i);
ParamInfo parmTag = findDocTag(localTags, paramName, method, tagLocator);
if (parmTag != null) {
collectedTags.addLast(parmTag);
}
}
if (!collectedTags.isEmpty()) {
buffer.append("<DD><DL>");
buffer.append("<DT><b>").append(CodeInsightBundle.message("javadoc.parameters")).append("</b>");
for (Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tag : collectedTags) {
PsiElement[] elements = tag.first.getDataElements();
if (elements.length == 0) continue;
generateOneParameter(elements, buffer, tag);
}
buffer.append("</DD></DL></DD>");
}
generateParametersSection(buffer, CodeInsightBundle.message("javadoc.parameters"), collectedTags);
}
private void generateTypeParametersSection(final StringBuilder buffer, final PsiMethod method) {
final PsiDocComment docComment = method.getDocComment();
if (docComment == null) return;
final PsiDocTag[] localTags = docComment.findTagsByName("param");
private void generateTypeParametersSection(final StringBuilder buffer, final PsiMethod method, PsiDocComment comment) {
final PsiDocTag[] localTags = comment == null ? PsiDocTag.EMPTY_ARRAY : comment.findTagsByName("param");
final PsiTypeParameter[] typeParameters = method.getTypeParameters();
final LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>> collectedTags = new LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>>();
for (PsiTypeParameter typeParameter : typeParameters) {
final LinkedList<ParamInfo> collectedTags = new LinkedList<ParamInfo>();
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter typeParameter = typeParameters[i];
final String paramName = "<" + typeParameter.getName() + ">";
Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> parmTag = findDocTag(localTags, paramName, method);
DocTagLocator<PsiDocTag> tagLocator = typeParameterLocator(i);
ParamInfo parmTag = findDocTag(localTags, paramName, method, tagLocator);
if (parmTag != null) {
collectedTags.addLast(parmTag);
}
}
generateTypeParametersSection(buffer, collectedTags);
generateParametersSection(buffer, CodeInsightBundle.message("javadoc.type.parameters"), collectedTags);
}
private void generateTypeParametersSection(final StringBuilder buffer, final LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>> collectedTags) {
private void generateParametersSection(StringBuilder buffer, String titleMessage, LinkedList<ParamInfo> collectedTags) {
if (!collectedTags.isEmpty()) {
buffer.append("<DD><DL>");
buffer.append("<DT><b>").append(CodeInsightBundle.message("javadoc.type.parameters")).append("</b>");
for (Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tag : collectedTags) {
PsiElement[] elements = tag.first.getDataElements();
if (elements.length == 0) continue;
generateOneParameter(elements, buffer, tag);
buffer.append("<DT><b>").append(titleMessage).append("</b>");
for (ParamInfo tag : collectedTags) {
generateOneParameter(buffer, tag);
}
buffer.append("</DD></DL></DD>");
}
}
@Nullable private Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> findDocTag(final PsiDocTag[] localTags,
final String paramName,
final PsiMethod method) {
Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> parmTag = null;
for (PsiDocTag localTag : localTags) {
PsiDocTagValue value = localTag.getValueElement();
if (value != null) {
String tagName = value.getText();
if (tagName != null && tagName.equals(paramName)) {
parmTag =
new Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>
(localTag,
new InheritDocProvider<PsiDocTag>() {
@Override
public Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> getInheritDoc() {
return findInheritDocTag(method, parameterLocator(paramName));
}
@Override
public PsiClass getElement() {
return method.getContainingClass();
}
});
break;
@Nullable private ParamInfo findDocTag(final PsiDocTag[] localTags,
final String paramName, final PsiMethod method, final DocTagLocator<PsiDocTag> tagLocator) {
PsiDocTag localTag = getTagByName(localTags, paramName);
if (localTag != null) {
return new ParamInfo(paramName, localTag, new InheritDocProvider<PsiDocTag>() {
@Override
public Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> getInheritDoc() {
return findInheritDocTag(method, tagLocator);
}
}
}
if (parmTag == null) {
parmTag = findInheritDocTag(method, parameterLocator(paramName));
@Override
public PsiClass getElement() {
return method.getContainingClass();
}
});
}
return parmTag;
Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tag = findInheritDocTag(method, tagLocator);
return tag == null ? null : new ParamInfo(paramName, tag);
}
@SuppressWarnings({"HardCodedStringLiteral"})
private void generateOneParameter(final PsiElement[] elements,
final StringBuilder buffer,
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tag) {
private void generateOneParameter(StringBuilder buffer, ParamInfo tag) {
PsiElement[] elements = tag.docTag.getDataElements();
if (elements.length == 0) return;
String text = elements[0].getText();
buffer.append("<DD>");
int spaceIndex = text.indexOf(' ');
if (spaceIndex < 0) {
spaceIndex = text.length();
}
String parmName = text.substring(0, spaceIndex);
buffer.append("<code>");
buffer.append(StringUtil.escapeXml(parmName));
buffer.append(StringUtil.escapeXml(tag.name));
buffer.append("</code>");
buffer.append(" - ");
buffer.append(text.substring(spaceIndex));
generateValue(buffer, elements, 1, mapProvider(tag.second, true));
generateValue(buffer, elements, 1, mapProvider(tag.inheritDocTagProvider, true));
}
@SuppressWarnings({"HardCodedStringLiteral"})
@@ -2073,7 +2068,7 @@ public class JavaDocInfoGenerator {
final PsiMethod overriden = findMethodInSuperClass(method, aSuper);
if (overriden != null) {
T tag = loc.find(getDocComment(overriden));
T tag = loc.find(overriden, getDocComment(overriden));
if (tag != null) {
return new Pair<T, InheritDocProvider<T>>
@@ -2167,10 +2162,26 @@ public class JavaDocInfoGenerator {
return findInheritDocTagInClass(method, aClass, loc, new HashSet<PsiClass>());
}
private static class ParamInfo {
private final String name;
private final PsiDocTag docTag;
private final InheritDocProvider<PsiDocTag> inheritDocTagProvider;
private ParamInfo(String paramName, PsiDocTag tag, InheritDocProvider<PsiDocTag> provider) {
name = paramName;
docTag = tag;
inheritDocTagProvider = provider;
}
private ParamInfo(String paramName, @NotNull Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tagWithInheritProvider) {
this(paramName, tagWithInheritProvider.first, tagWithInheritProvider.second);
}
}
private static class ReturnTagLocator implements DocTagLocator<PsiDocTag> {
@Override
public PsiDocTag find(PsiDocComment comment) {
public PsiDocTag find(PsiDocCommentOwner owner, PsiDocComment comment) {
if (comment == null) {
return null;
}
@@ -21,13 +21,14 @@ import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class JavaGotoTargetRendererProvider implements GotoTargetRendererProvider {
@Override
public PsiElementListCellRenderer getRenderer(final PsiElement element, GotoTargetHandler.GotoData gotoData) {
public PsiElementListCellRenderer getRenderer(@NotNull final PsiElement element, @NotNull GotoTargetHandler.GotoData gotoData) {
if (element instanceof PsiMethod) {
return new MethodCellRenderer(gotoData.hasDifferentNames());
}
@@ -15,8 +15,6 @@
*/
package com.intellij.psi.impl.compiled;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectCoreUtil;
import com.intellij.psi.*;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.PsiFileStub;
@@ -45,10 +43,6 @@ public abstract class ClsRepositoryPsiElement<T extends StubElement> extends Cls
@Override
public PsiManager getManager() {
Project project = ProjectCoreUtil.theOnlyOpenProject();
if (project != null) {
return PsiManager.getInstance(project);
}
final PsiFile file = getContainingFile();
if (file == null) throw new PsiInvalidElementAccessException(this);
return file.getManager();
@@ -16,17 +16,21 @@
package com.intellij.psi.impl.light;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import static com.intellij.psi.PsiReferenceList.Role.EXTENDS_LIST;
import static com.intellij.psi.PsiReferenceList.Role.IMPLEMENTS_LIST;
public class LightPsiClassBuilder extends LightPsiClassBase implements OriginInfoAwareElement {
private final LightModifierList myModifierList = new LightModifierList(getManager());
private final LightReferenceListBuilder myImplementsList = new LightReferenceListBuilder(getManager(), PsiReferenceList.Role.EXTENDS_LIST);
private final LightReferenceListBuilder myExtendsList = new LightReferenceListBuilder(getManager(), PsiReferenceList.Role.EXTENDS_LIST);
private final LightReferenceListBuilder myImplementsList = new LightReferenceListBuilder(getManager(), IMPLEMENTS_LIST);
private final LightReferenceListBuilder myExtendsList = new LightReferenceListBuilder(getManager(), EXTENDS_LIST);
private final LightTypeParameterListBuilder myTypeParametersList = new LightTypeParameterListBuilder(getManager(), getLanguage());
private final Collection<PsiMethod> myMethods = ContainerUtil.newArrayList();
private PsiElement myScope;
@@ -104,6 +108,11 @@ public class LightPsiClassBuilder extends LightPsiClassBase implements OriginInf
return myTypeParametersList;
}
@Override
public boolean isEquivalentTo(PsiElement another) {
return PsiClassImplUtil.isClassEquivalentTo(this, another);
}
public LightPsiClassBuilder setOriginInfo(String originInfo) {
myOriginInfo = originInfo;
return this;
@@ -0,0 +1,70 @@
/*
* Copyright 2000-2015 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 com.intellij.psi.impl.light;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiTypeParameter;
import com.intellij.psi.PsiTypeParameterListOwner;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class LightTypeParameterBuilder extends LightPsiClassBuilder implements PsiTypeParameter {
private final PsiTypeParameterListOwner myOwner;
private final int myIndex;
public LightTypeParameterBuilder(@NotNull String name, PsiTypeParameterListOwner owner, int index) {
super(owner, name);
myOwner = owner;
myIndex = index;
}
@Nullable
@Override
public PsiTypeParameterListOwner getOwner() {
return myOwner;
}
@Override
public int getIndex() {
return myIndex;
}
@NotNull
@Override
public PsiAnnotation[] getAnnotations() {
return getModifierList().getAnnotations();
}
@NotNull
@Override
public PsiAnnotation[] getApplicableAnnotations() {
return getModifierList().getApplicableAnnotations();
}
@Nullable
@Override
public PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) {
return getModifierList().findAnnotation(qualifiedName);
}
@NotNull
@Override
public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
return getModifierList().addAnnotation(qualifiedName);
}
}
@@ -0,0 +1,2 @@
<html><head><base href="placeholder"> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><small><b><a href="psi_element://Bar"><code>Bar</code></a></b></small><PRE>
void&nbsp;<b>m</b>(int&nbsp;bar)</PRE><DD><DL><DT><b>Overrides:</b><DD><a href="psi_element://Foo#m(int)"><code>m</code></a> in class <a href="psi_element://Foo"><code>Foo</code></a></DD></DL></DD><DD><DL><DT><b>Parameters:</b><DD><code>bar</code> - description</DD></DL></DD></body></html>
@@ -0,0 +1,13 @@
import java.lang.Override;
class Foo {
/**
* @param foo description
*/
void m(int foo) {}
}
class Bar extends Foo {
@Override
void m(int bar) {}
}
@@ -0,0 +1,2 @@
<html><head><base href="placeholder"> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><small><b><a href="psi_element://Bar"><code>Bar</code></a></b></small><PRE>
&lt;U&gt;&nbsp;void&nbsp;<b>m</b>(U&nbsp;u)</PRE><DD><DL><DT><b>Overrides:</b><DD><a href="psi_element://Foo#m(java.lang.Object)"><code>m</code></a> in class <a href="psi_element://Foo"><code>Foo</code></a></DD></DL></DD><DD><DL><DT><b>Type parameters:</b><DD><code>&lt;U&gt;</code> - description</DD></DL></DD></body></html>
@@ -0,0 +1,13 @@
import java.lang.Override;
class Foo {
/**
* @param <T> description
*/
<T> void m(T t) {}
}
class Bar extends Foo {
@Override
<U> void m(U u) {}
}
@@ -677,7 +677,7 @@ interface TxANotAnno {}
public void testLiveTemplateOrdering() {
LiveTemplateCompletionContributor.setShowTemplatesInTests(true, getTestRootDisposable())
checkPreferredItems(0, 'return')
assert lookup.items[-1].lookupString == 'ritar'
assert lookup.items.find { it.lookupString == 'ritar'} != null
}
public void testPreferLocalToExpectedTypedMethod() {
@@ -277,6 +277,20 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase {
useJava7();
verifyJavaDoc(getTestClass());
}
public void testMatchingParameterNameFromParent() throws Exception {
configureByFile("/codeInsight/javadocIG/" + getTestName(true) + ".java");
PsiClass psiClass = ((PsiJavaFile)myFile).getClasses()[1];
PsiMethod method = psiClass.getMethods()[0];
verifyJavaDoc(method);
}
public void testMatchingTypeParameterNameFromParent() throws Exception {
configureByFile("/codeInsight/javadocIG/" + getTestName(true) + ".java");
PsiClass psiClass = ((PsiJavaFile)myFile).getClasses()[1];
PsiMethod method = psiClass.getMethods()[0];
verifyJavaDoc(method);
}
@Override
protected String getTestDataPath() {
@@ -85,7 +85,6 @@ public abstract class RecursiveLighterASTNodeWalkingVisitor extends LighterASTNo
parent.put(child, element);
}
parent.put(children.get(0), element);
ast.disposeChildren(children);
return children.get(0);
}
@@ -15,6 +15,7 @@
*/
package com.intellij.dvcs;
import com.intellij.dvcs.push.PushSupport;
import com.intellij.dvcs.repo.RepoStateException;
import com.intellij.dvcs.repo.Repository;
import com.intellij.dvcs.repo.RepositoryManager;
@@ -24,6 +25,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -422,4 +424,14 @@ public class DvcsUtil {
}
return groupedCommits;
}
@Nullable
public static PushSupport getPushSupport(@NotNull final AbstractVcs vcs) {
return ContainerUtil.find(Extensions.getExtensions(PushSupport.PUSH_SUPPORT_EP, vcs.getProject()), new Condition<PushSupport>() {
@Override
public boolean value(final PushSupport support) {
return support.getVcs().equals(vcs);
}
});
}
}
@@ -23,7 +23,6 @@ import com.intellij.dvcs.repo.VcsRepositoryManager;
import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
@@ -31,6 +30,7 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
@@ -62,7 +62,7 @@ public class PushController implements Disposable {
@NotNull private final Project myProject;
@NotNull private final List<? extends Repository> myPreselectedRepositories;
@NotNull private final VcsRepositoryManager myGlobalRepositoryManager;
@NotNull private final List<PushSupport<? extends Repository, ? extends PushSource, ? extends PushTarget>> myPushSupports;
@NotNull private final List<PushSupport<Repository, PushSource, PushTarget>> myPushSupports;
@NotNull private final PushLog myPushLog;
@NotNull private final VcsPushDialog myDialog;
@NotNull private final PushSettings myPushSettings;
@@ -83,7 +83,7 @@ public class PushController implements Disposable {
myExcludedRepositoryRoots = ContainerUtil.newHashSet(myPushSettings.getExcludedRepoRoots());
myPreselectedRepositories = preselectedRepositories;
myCurrentlyOpenedRepository = currentRepo;
myPushSupports = getAffectedSupports(myProject);
myPushSupports = getAffectedSupports();
mySingleRepoProject = isSingleRepoProject();
myDialog = dialog;
CheckedTreeNode rootNode = new CheckedTreeNode(null);
@@ -106,13 +106,12 @@ public class PushController implements Disposable {
private boolean isSyncStrategiesAllowed() {
return !mySingleRepoProject &&
ContainerUtil.and(getAffectedSupports(myProject),
new Condition<PushSupport<? extends Repository, ? extends PushSource, ? extends PushTarget>>() {
@Override
public boolean value(PushSupport<? extends Repository, ? extends PushSource, ? extends PushTarget> support) {
return support.mayChangeTargetsSync();
}
});
ContainerUtil.and(getAffectedSupports(), new Condition<PushSupport<Repository, PushSource, PushTarget>>() {
@Override
public boolean value(PushSupport<Repository, PushSource, PushTarget> support) {
return support.mayChangeTargetsSync();
}
});
}
private boolean isSingleRepoProject() {
@@ -120,17 +119,19 @@ public class PushController implements Disposable {
}
@NotNull
private List<PushSupport<? extends Repository, ? extends PushSource, ? extends PushTarget>> getAffectedSupports(@NotNull Project project) {
final Collection<Repository> repositories = myGlobalRepositoryManager.getRepositories();
return ContainerUtil.filter(Extensions.getExtensions(PushSupport.PUSH_SUPPORT_EP, project), new Condition<PushSupport>() {
private <R extends Repository, S extends PushSource, T extends PushTarget> List<PushSupport<R, S, T>> getAffectedSupports() {
Collection<Repository> repositories = myGlobalRepositoryManager.getRepositories();
Collection<AbstractVcs> vcss = ContainerUtil.map2Set(repositories, new Function<Repository, AbstractVcs>() {
@Override
public boolean value(final PushSupport support) {
return ContainerUtil.exists(repositories, new Condition<Repository>() {
@Override
public boolean value(Repository repository) {
return support.getVcs().equals(repository.getVcs());
}
});
public AbstractVcs fun(@NotNull Repository repository) {
return repository.getVcs();
}
});
return ContainerUtil.map(vcss, new Function<AbstractVcs, PushSupport<R, S, T>>() {
@Override
public PushSupport<R, S, T> fun(AbstractVcs vcs) {
//noinspection unchecked
return DvcsUtil.getPushSupport(vcs);
}
});
}
@@ -308,13 +309,12 @@ public class PushController implements Disposable {
public boolean isPushAllowed(final boolean force) {
JTree tree = myPushLog.getTree();
return !tree.isEditing() &&
ContainerUtil
.exists(myPushSupports, new Condition<PushSupport<? extends Repository, ? extends PushSource, ? extends PushTarget>>() {
@Override
public boolean value(PushSupport<? extends Repository, ? extends PushSource, ? extends PushTarget> support) {
return isPushAllowed(support, force);
}
});
ContainerUtil.exists(myPushSupports, new Condition<PushSupport<Repository, PushSource, PushTarget>>() {
@Override
public boolean value(PushSupport<Repository, PushSource, PushTarget> support) {
return isPushAllowed(support, force);
}
});
}
private boolean isPushAllowed(@NotNull PushSupport<?, ?, ?> pushSupport, boolean force) {
@@ -242,7 +242,8 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
};
}
public static PsiElementListCellRenderer createRenderer(GotoData gotoData, PsiElement eachTarget) {
@NotNull
public static PsiElementListCellRenderer createRenderer(@NotNull GotoData gotoData, @NotNull PsiElement eachTarget) {
PsiElementListCellRenderer renderer = null;
for (GotoTargetRendererProvider eachProvider : Extensions.getExtensions(GotoTargetRendererProvider.EP_NAME)) {
renderer = eachProvider.getRenderer(eachTarget, gotoData);
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.navigation;
import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -28,5 +29,5 @@ public interface GotoTargetRendererProvider {
ExtensionPointName<GotoTargetRendererProvider> EP_NAME = ExtensionPointName.create("com.intellij.gotoTargetRendererProvider");
@Nullable
PsiElementListCellRenderer getRenderer(PsiElement element, GotoTargetHandler.GotoData gotoData);
PsiElementListCellRenderer getRenderer(@NotNull PsiElement element, @NotNull GotoTargetHandler.GotoData gotoData);
}
@@ -0,0 +1,311 @@
/*
* Copyright 2000-2015 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 com.intellij.execution.startup;
import com.intellij.execution.Executor;
import com.intellij.execution.ExecutorRegistry;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ChooseRunConfigurationPopup;
import com.intellij.execution.actions.ExecutorProvider;
import com.intellij.execution.impl.EditConfigurationsDialog;
import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.icons.AllIcons;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBList;
import com.intellij.ui.popup.PopupFactoryImpl;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @author Irina.Chernushina on 8/19/2015.
*/
public class ProjectStartupConfigurable implements SearchableConfigurable, Configurable.NoScroll {
private final Project myProject;
private Tree myTree;
private ProjectStartupConfiguration myConfiguration;
private ToolbarDecorator myDecorator;
public ProjectStartupConfigurable(Project project) {
myProject = project;
myConfiguration = ProjectStartupConfiguration.getInstance(myProject);
}
@NotNull
@Override
public String getId() {
return "preferences.startup.tasks";
}
@Nullable
@Override
public Runnable enableSearch(String option) {
return null;
}
@Nls
@Override
public String getDisplayName() {
return "Project Startup Tasks";
}
@Nullable
@Override
public String getHelpTopic() {
return null;
}
@Nullable
@Override
public JComponent createComponent() {
myTree = new Tree();
installRenderer();
myDecorator = ToolbarDecorator.createDecorator(myTree)
.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
selectAndAddConfiguration(button);
}
})
.setEditAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
RunnerAndConfigurationSettings selected = getSelectedSettings();
if (selected == null) return;
final RunManager runManager = RunManagerImpl.getInstance(myProject);
final RunnerAndConfigurationSettings was = runManager.getSelectedConfiguration();
try {
runManager.setSelectedConfiguration(selected);
new EditConfigurationsDialog(myProject).showAndGet();
} finally {
runManager.setSelectedConfiguration(was);
}
}
})
.setEditActionUpdater(new AnActionButtonUpdater() {
@Override
public boolean isEnabled(AnActionEvent e) {
return getSelectedSettings() != null;
}
})
.setRemoveAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
RunnerAndConfigurationSettings selected = getSelectedSettings();
if (selected == null) return;
final ProjectStartupTasksTreeModel oldModel = (ProjectStartupTasksTreeModel)myTree.getModel();
final List<RunnerAndConfigurationSettings> configurations = oldModel.getConfigurations();
if (!configurations.contains(selected)) {
return;
}
configurations.remove(selected);
Collections.sort(configurations, new Comparator<RunnerAndConfigurationSettings>() {
@Override
public int compare(RunnerAndConfigurationSettings o1, RunnerAndConfigurationSettings o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
setModel(new ProjectStartupTasksTreeModel(configurations));
}
});
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
final JPanel tasksPanel = myDecorator.createPanel();
return FormBuilder.createFormBuilder() // todo bundle
.addLabeledComponentFillVertically("Tasks to be executed right after opening the project.", tasksPanel)
.getPanel();
}
@Nullable
private RunnerAndConfigurationSettings getSelectedSettings() {
final TreePath path = myTree.getSelectionPath();
if (path == null) return null;
if (! (path.getLastPathComponent() instanceof RunnerAndConfigurationSettings)) return null;
return (RunnerAndConfigurationSettings)path.getLastPathComponent();
}
private ChooseRunConfigurationPopup.ItemWrapper<Void> createEditWrapper() {
return new ChooseRunConfigurationPopup.ItemWrapper<Void>(null) {
@Override
public Icon getIcon() {
return AllIcons.Actions.EditSource;
}
@Override
public String getText() {
return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text"));
}
@Override
public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) {
if (new EditConfigurationsDialog(project).showAndGet()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
RunnerAndConfigurationSettings configuration = RunManager.getInstance(project).getSelectedConfiguration();
if (configuration != null) {
addConfigurationToList(configuration);
}
}
}, project.getDisposed());
}
}
@Override
public boolean available(Executor executor) {
return true;
}
};
}
private void selectAndAddConfiguration(final AnActionButton button) {
final Executor executor = ExecutorRegistry.getInstance().getExecutorById(ToolWindowId.DEBUG);
final List<ChooseRunConfigurationPopup.ItemWrapper> wrappers = new ArrayList<ChooseRunConfigurationPopup.ItemWrapper>();
wrappers.add(createEditWrapper());
final ChooseRunConfigurationPopup.ItemWrapper[] allSettings =
ChooseRunConfigurationPopup.createSettingsList(myProject, new ExecutorProvider() {
@Override
public Executor getExecutor() {
return executor;
}
}, false);
for (ChooseRunConfigurationPopup.ItemWrapper setting : allSettings) {
if (setting.getValue() instanceof RunnerAndConfigurationSettings) {
// todo maybe auto save temporary?
if (! ((RunnerAndConfigurationSettings)setting.getValue()).isTemporary()) {
wrappers.add(setting);
}
}
}
final JBList list = new JBList(wrappers);
list.setCellRenderer(new ColoredListCellRenderer() {
@Override
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
if (value instanceof ChooseRunConfigurationPopup.ItemWrapper) {
setIcon(((ChooseRunConfigurationPopup.ItemWrapper)value).getIcon());
append(((ChooseRunConfigurationPopup.ItemWrapper)value).getText());
}
}
});
final JBPopup popup = PopupFactoryImpl.getInstance()
.createListPopupBuilder(list)
.setItemChoosenCallback(new Runnable() {
@Override
public void run() {
final int index = list.getSelectedIndex();
if (index < 0) return;
final ChooseRunConfigurationPopup.ItemWrapper at = (ChooseRunConfigurationPopup.ItemWrapper)list.getModel().getElementAt(index);
if (at.getValue() instanceof RunnerAndConfigurationSettings) {
addConfigurationToList((RunnerAndConfigurationSettings)at.getValue());
} else {
at.perform(myProject, executor, button.getDataContext());
}
}
})
.createPopup();
popup.show(new RelativePoint(myDecorator.getActionsPanel(), new Point(10, 10)));
}
private void addConfigurationToList(final RunnerAndConfigurationSettings settings) {
if (settings != null) {
final ProjectStartupTasksTreeModel oldModel = (ProjectStartupTasksTreeModel)myTree.getModel();
final List<RunnerAndConfigurationSettings> configurations = oldModel.getConfigurations();
if (!configurations.contains(settings)) {
configurations.add(settings);
}
Collections.sort(configurations, new Comparator<RunnerAndConfigurationSettings>() {
@Override
public int compare(RunnerAndConfigurationSettings o1, RunnerAndConfigurationSettings o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
setModel(new ProjectStartupTasksTreeModel(configurations));
}
}
@Override
public boolean isModified() {
final List<RunnerAndConfigurationSettings> recorded = myConfiguration.getStartupConfigurations();
final List<RunnerAndConfigurationSettings> current = ((ProjectStartupTasksTreeModel)myTree.getModel()).getConfigurations();
return ! Comparing.equal(recorded, current);
}
@Override
public void apply() throws ConfigurationException {
myConfiguration.setStartupConfigurations(((ProjectStartupTasksTreeModel)myTree.getModel()).getConfigurations(), false);
}
@Override
public void reset() {
final ProjectStartupTasksTreeModel model = new ProjectStartupTasksTreeModel(myConfiguration.getStartupConfigurations());
setModel(model);
}
private void setModel(ProjectStartupTasksTreeModel model) {
myTree.setModel(model);
myTree.setShowsRootHandles(false);
myTree.setRootVisible(false);
}
@Override
public void disposeUIResources() {
}
private void installRenderer() {
myTree.setCellRenderer(new ColoredTreeCellRenderer() {
@Override
public void customizeCellRenderer(@NotNull JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
if (value instanceof RunnerAndConfigurationSettings) {
final RunnerAndConfigurationSettings settings = (RunnerAndConfigurationSettings)value;
setIcon(settings.getConfiguration().getIcon());
append(settings.getName());
}
}
});
}
}
@@ -0,0 +1,107 @@
/*
* Copyright 2000-2015 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 com.intellij.execution.startup;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunManagerEx;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* @author Irina.Chernushina on 8/19/2015.
*/
public class ProjectStartupConfiguration {
private final Project myProject;
private final ProjectStartupSharedConfiguration myShared;
private final ProjectStartupLocalConfiguration myLocal;
private final RunManagerEx myRunManager;
public static ProjectStartupConfiguration getInstance(@NotNull final Project project) {
return ServiceManager.getService(project, ProjectStartupConfiguration.class);
}
public ProjectStartupConfiguration(Project project, ProjectStartupSharedConfiguration shared, ProjectStartupLocalConfiguration local,
@NotNull RunManager runManager) {
myProject = project;
myShared = shared;
myLocal = local;
myRunManager = (RunManagerEx)runManager;
}
public List<RunnerAndConfigurationSettings> getStartupConfigurations() {
final List<RunnerAndConfigurationSettings> result = new ArrayList<RunnerAndConfigurationSettings>();
if (! myShared.isEmpty()) {
myLocal.clear();
return fillResult(result, myShared.getList());
}
return fillResult(result, myLocal.getList());
}
private List<RunnerAndConfigurationSettings> fillResult(List<RunnerAndConfigurationSettings> result, List<String> list) {
for (String s : list) {
final RunnerAndConfigurationSettings settings = myRunManager.findConfigurationByName(s);
if (settings != null) {
result.add(settings);
}
}
return result;
}
public void setStartupConfigurations(final @NotNull List<RunnerAndConfigurationSettings> list, final boolean shared) {
final List<String> names = ContainerUtil.map(list, new Function<RunnerAndConfigurationSettings, String>() {
@Override
public String fun(RunnerAndConfigurationSettings settings) {
return settings.getName();
}
});
if (shared) {
myLocal.clear();
myShared.setList(names);
} else {
myShared.clear();
myLocal.setList(names);
}
}
public boolean canBeShared() {
if (isShared()) return true;
if (isEmpty()) return true;
final List<String> list = myLocal.getList();
for (String s : list) {
final RunnerAndConfigurationSettings settings = myRunManager.findConfigurationByName(s);
if (settings != null) {
if (! myRunManager.isConfigurationShared(settings)) return false;
}
}
return true;
}
public boolean isShared() {
return ! myShared.isEmpty();
}
public boolean isEmpty() {
return myShared.isEmpty() && myLocal.isEmpty();
}
}
@@ -0,0 +1,106 @@
/*
* Copyright 2000-2015 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 com.intellij.execution.startup;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author Irina.Chernushina on 8/19/2015.
*/
public class ProjectStartupConfigurationBase implements PersistentStateComponent<Element> {
private final static String TOP_ELEMENT = "startup-tasks";
private final static String TASK = "task";
private final static String NAME = "name";
private final static String TYPE = "type";
private final List<String> myList;
protected ProjectStartupConfigurationBase() {
myList = new ArrayList<String>();
}
@Nullable
@Override
public Element getState() {
if (myList.isEmpty()) return null;
final Element element = new Element(TOP_ELEMENT);
for (String name : myList) {
final Element child = new Element(TASK);
child.setAttribute(NAME, name);
element.addContent(child);
}
return element;
}
@Override
public void loadState(Element state) {
myList.clear();
final List<Element> children = state.getChildren();
for (Element child : children) {
if (TASK.equals(child.getName())) {
final String name = child.getAttributeValue(NAME);
if (! StringUtil.isEmptyOrSpaces(name)) {
myList.add(name);
}
}
}
}
public void clear() {
myList.clear();
}
public List<String> getList() {
return myList;
}
public void setList(@NotNull final List<String> list) {
myList.clear();
myList.addAll(list);
}
public boolean isEmpty() {
return myList.isEmpty();
}
public static class ConfigurationDescriptor {
private final @NotNull String myTypeId;
private final @NotNull String myName;
public ConfigurationDescriptor(@NotNull String typeId, @NotNull String name) {
myTypeId = typeId;
myName = name;
}
@NotNull
public String getTypeId() {
return myTypeId;
}
@NotNull
public String getName() {
return myName;
}
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2000-2015 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 com.intellij.execution.startup;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
/**
* @author Irina.Chernushina on 8/19/2015.
*/
@State(
name = "ProjectStartupLocalConfiguration",
storages = {
@Storage(file = StoragePathMacros.WORKSPACE_FILE)
}
)
public class ProjectStartupLocalConfiguration extends ProjectStartupConfigurationBase {
}
@@ -0,0 +1,72 @@
/*
* Copyright 2000-2015 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 com.intellij.execution.startup;
import com.intellij.execution.Executor;
import com.intellij.execution.ProgramRunnerUtil;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.ide.startup.StartupManagerEx;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author Irina.Chernushina on 8/19/2015.
*/
public class ProjectStartupRunner implements StartupActivity {
public static final int DELAY_MILLIS = 200;
@Override
public void runActivity(@NotNull Project project) {
if (ProjectStartupConfiguration.getInstance(project).isEmpty()) return;
final Alarm alarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, project);
alarm.addRequest(createRequest(project, alarm), DELAY_MILLIS);
}
private Runnable createRequest(final Project project, final Alarm alarm) {
return new Runnable() {
@Override
public void run() {
if (! ((StartupManagerEx) StartupManager.getInstance(project)).postStartupActivityPassed()) {
alarm.addRequest(createRequest(project, alarm), DELAY_MILLIS);
} else {
runActivities(project);
}
}
};
}
private void runActivities(final Project project) {
final List<RunnerAndConfigurationSettings> configurations = ProjectStartupConfiguration.getInstance(project).getStartupConfigurations();
final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
for (final RunnerAndConfigurationSettings configuration : configurations) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
ProgramRunnerUtil.executeConfiguration(project, configuration, executor);
}
}, ModalityState.any());
}
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2000-2015 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 com.intellij.execution.startup;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.components.StorageScheme;
/**
* @author Irina.Chernushina on 8/19/2015.
*/
@State(
name = "ProjectStartupSharedConfiguration",
storages = {
@Storage(file = StoragePathMacros.PROJECT_FILE),
@Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/startup.xml", scheme = StorageScheme.DEFAULT)
}
)
public class ProjectStartupSharedConfiguration extends ProjectStartupConfigurationBase {
}
@@ -0,0 +1,92 @@
/*
* Copyright 2000-2015 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 com.intellij.execution.startup;
import com.intellij.execution.RunnerAndConfigurationSettings;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.util.List;
/**
* @author Irina.Chernushina on 8/19/2015.
*/
public class ProjectStartupTasksTreeModel implements TreeModel {
private final Object myRoot = new Object();
private final List<RunnerAndConfigurationSettings> myConfigurations;
public ProjectStartupTasksTreeModel(List<RunnerAndConfigurationSettings> configurations) {
myConfigurations = configurations;
}
@Override
public Object getRoot() {
return myRoot;
}
@Override
public Object getChild(Object parent, int index) {
if (parent == myRoot) {
return myConfigurations.get(index);
}
return null;
}
@Override
public int getChildCount(Object parent) {
if (parent == myRoot) {
return myConfigurations.size();
}
return 0;
}
@Override
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
}
@Override
public int getIndexOfChild(Object parent, Object child) {
if (parent == myRoot) {
for (int i = 0; i < myConfigurations.size(); i++) {
final RunnerAndConfigurationSettings configuration = myConfigurations.get(i);
if (configuration == child) {
return i;
}
}
}
return 0;
}
@Override
public void addTreeModelListener(TreeModelListener l) {
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
}
public List<RunnerAndConfigurationSettings> getConfigurations() {
return myConfigurations;
}
}
@@ -1182,7 +1182,7 @@ public abstract class DialogWrapper {
ensureEventDispatchThread();
myErrorText = new ErrorText();
myErrorText.setVisible(false);
myErrorText.myLabel.addComponentListener(new ComponentAdapter() {
final ComponentAdapter resizeListener = new ComponentAdapter() {
private int myHeight;
@Override
@@ -1203,6 +1203,13 @@ public abstract class DialogWrapper {
myResizeInProgress = false;
}
}
};
myErrorText.myLabel.addComponentListener(resizeListener);
Disposer.register(myDisposable, new Disposable() {
@Override
public void dispose() {
myErrorText.myLabel.removeComponentListener(resizeListener);
}
});
final JPanel root = new JPanel(createRootLayout());
@@ -29,6 +29,9 @@ import java.nio.charset.Charset;
public abstract class BaseOutputReader extends BaseDataReader {
protected final Reader myReader;
private final char[] myInputBuffer = new char[8192];
private final StringBuilder myLineBuffer = new StringBuilder();
public BaseOutputReader(@NotNull InputStream inputStream, @Nullable Charset charset) {
this(inputStream, charset, null);
}
@@ -62,18 +65,16 @@ public abstract class BaseOutputReader extends BaseDataReader {
* @throws IOException If an I/O error occurs
*/
protected final boolean readAvailableNonBlocking() throws IOException {
char[] buffer = new char[8192];
StringBuilder line = new StringBuilder();
boolean read = false;
int n;
while (myReader.ready() && (n = myReader.read(buffer)) > 0) {
while (myReader.ready() && (n = myReader.read(myInputBuffer)) > 0) {
read = true;
processLine(buffer, line, n);
processLine(myInputBuffer, myLineBuffer, n);
}
if (line.length() > 0) {
sendLine(line);
if (myLineBuffer.length() > 0) {
sendLine(myLineBuffer);
}
return read;
@@ -89,23 +90,21 @@ public abstract class BaseOutputReader extends BaseDataReader {
* @throws IOException If an I/O error occurs
*/
protected final boolean readAvailableBlocking() throws IOException {
char[] buffer = new char[8192];
StringBuilder line = new StringBuilder();
boolean read = false;
int n;
while ((n = myReader.read(buffer)) > 0) {
while ((n = myReader.read(myInputBuffer)) > 0) {
read = true;
processLine(buffer, line, n);
processLine(myInputBuffer, myLineBuffer, n);
if (!myReader.ready()) {
if (line.length() > 0) sendLine(line);
if (myLineBuffer.length() > 0) sendLine(myLineBuffer);
onBufferExhaustion();
}
}
if (line.length() > 0) {
sendLine(line);
if (myLineBuffer.length() > 0) {
sendLine(myLineBuffer);
}
return read;
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.versionBrowser;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.*;
import com.intellij.util.text.SyncDateFormat;
import com.intellij.util.xmlb.annotations.Transient;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,6 +55,8 @@ public class ChangeBrowserSettings implements JDOMExternalizable {
public String USER = "";
public boolean STOP_ON_COPY = false;
@Transient public boolean STRICTLY_AFTER = false;
public void readExternal(Element element) throws InvalidDataException {
DefaultJDOMExternalizer.readExternal(this, element);
}
@@ -84,7 +84,6 @@ public class CommittedChangesCache implements PersistentStateComponent<Committed
private final Set<CommittedChangeList> myNewIncomingChanges = new LinkedHashSet<CommittedChangeList>();
private final ProjectLevelVcsManager myVcsManager;
public static final Change[] ALL_CHANGES = new Change[0];
private MyRefreshRunnable myRefresnRunnable;
private final Map<String, Pair<Long, List<CommittedChangeList>>> myExternallyLoadedChangeLists;
@@ -538,7 +537,7 @@ public class CommittedChangesCache implements PersistentStateComponent<Committed
});
}
// todo: fix - would externally loaded nesseccerily for file? i.e. just not efficient now
// todo: fix - would externally loaded necessarily for file? i.e. just not efficient now
private List<CommittedChangeList> refreshCache(final ChangesCacheFile cacheFile) throws VcsException, IOException {
final List<CommittedChangeList> newLists = new ArrayList<CommittedChangeList>();
@@ -571,6 +570,7 @@ public class CommittedChangesCache implements PersistentStateComponent<Committed
defaultSettings.setDateAfter(date);
defaultSettings.USE_DATE_AFTER_FILTER = true;
}
defaultSettings.STRICTLY_AFTER = true;
final List<CommittedChangeList> newChanges = provider.getCommittedChanges(defaultSettings, location, maxCount);
debug("Loaded " + newChanges.size() + " new changelists");
newLists.addAll(appendLoadedChanges(cacheFile, location, newChanges));
@@ -22,11 +22,13 @@ import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diff.LineTokenizer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
import com.intellij.openapi.vcs.annotate.FileAnnotation;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache;
import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -160,6 +162,7 @@ public abstract class AbstractVcsTestCase {
protected void tearDownProject() throws Exception {
if (myProject != null) {
((ChangeListManagerImpl)ChangeListManager.getInstance(myProject)).stopEveryThingIfInTestMode();
CommittedChangesCache.getInstance(myProject).clearCaches(EmptyRunnable.INSTANCE);
myProject = null;
}
if (myProjectFixture != null) {
@@ -52,6 +52,12 @@ public class XDebuggerTreePanel implements DnDSource {
myMainPanel = new JPanel(new BorderLayout());
myMainPanel.add(ScrollPaneFactory.createScrollPane(myTree), BorderLayout.CENTER);
Disposer.register(parentDisposable, myTree);
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
myMainPanel.removeAll();
}
});
}
public XDebuggerTree getTree() {
+2 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -105,6 +105,7 @@ public interface IdeaPlugin extends DomElement {
@NotNull
@SubTagList("extensions")
@Stubbed
List<Extensions> getExtensions();
Extensions addExtensions();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -43,6 +43,6 @@ public class PluginXmlDomFileDescription extends DomFileDescription<IdeaPlugin>
@Override
public int getStubVersion() {
return 3;
return 4;
}
}
@@ -13,4 +13,6 @@
<extensionPoint qualifiedName="qualifiedName" beanClass="BeanClass"/>
</extensionPoints>
<extensions defaultExtensionNs="defaultExtensionNs" xmlns="extensionXmlNs"/>
</idea-plugin>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -40,7 +40,10 @@ public class PluginXmlDomStubsTest extends DomStubTest {
" Attribute:implements:SomeImplements\n" +
" Element:extensionPoint\n" +
" Attribute:qualifiedName:qualifiedName\n" +
" Attribute:beanClass:BeanClass\n");
" Attribute:beanClass:BeanClass\n" +
" Element:extensions\n" +
" Attribute:defaultExtensionNs:defaultExtensionNs\n" +
" Attribute:xmlns:extensionXmlNs\n");
}
public void testXInclude() throws Exception {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -224,6 +224,7 @@ public class GroovyConstructorUsagesSearcher extends QueryExecutorBase<PsiRefere
processImplicitConstructorCall(clazz, consumer, searchedConstructor);
}
for (PsiMethod constructor : constructors) {
if (!(constructor instanceof GrMethod)) continue;
final GrOpenBlock block = ((GrMethod)constructor).getBlock();
if (block != null) {
final GrStatement[] statements = block.getStatements();
@@ -116,7 +116,7 @@ public class GrTypeDefinitionMembersCache {
final List<PsiClass> result = ContainerUtil.newArrayList();
final GrTypeDefinitionBody body = myDefinition.getBody();
if (body != null) ContainerUtil.addAll(result, body.getInnerClasses());
result.addAll(AstTransformContributor.runContributorsForClasses(myDefinition));
result.addAll(AstTransformContributor.runContributors(myDefinition).getClasses());
return Result.create(result.toArray(new PsiClass[result.size()]), myTreeChangeTracker);
}
});
@@ -135,16 +135,17 @@ public class GrTypeDefinitionMembersCache {
private List<GrField> getFieldsImpl() {
List<GrField> fields = ContainerUtil.newArrayList(myDefinition.getCodeFields());
fields.addAll(new TraitCollector().collectFields());
fields.addAll(getSyntheticFields());
return fields;
}
private List<GrField> getSyntheticFields() {
return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<List<GrField>>() {
private Collection<GrField> getSyntheticFields() {
return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<Collection<GrField>>() {
@Nullable
@Override
public Result<List<GrField>> compute() {
return Result.create(AstTransformContributor.runContributorsForFields(myDefinition), myTreeChangeTracker,
public Result<Collection<GrField>> compute() {
return Result.create(AstTransformContributor.runContributors(myDefinition).getFields(), myTreeChangeTracker,
PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
}
});
@@ -154,10 +155,11 @@ public class GrTypeDefinitionMembersCache {
return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<PsiMethod[]>() {
@Override
public Result<PsiMethod[]> compute() {
List<PsiMethod> result = ContainerUtil.newArrayList();
GrClassImplUtil.collectMethodsFromBody(myDefinition, result);
Collection<PsiMethod> result = ContainerUtil.newLinkedHashSet();
for (PsiMethod method : AstTransformContributor.runContributorsForMethods(myDefinition)) {
GrClassImplUtil.collectMethodsFromBody(myDefinition, result);
result.addAll(new TraitCollector().collectMethods(result));
for (PsiMethod method : AstTransformContributor.runContributors(myDefinition).getMethods()) {
GrClassImplUtil.addExpandingReflectedMethods(result, method);
}
@@ -166,6 +168,9 @@ public class GrTypeDefinitionMembersCache {
ContainerUtil.addIfNotNull(result, field.getSetter());
Collections.addAll(result, field.getGetters());
}
result = GrClassImplUtil.filterOutAccessors(result);
return Result.create(result.toArray(new PsiMethod[result.size()]), myTreeChangeTracker,
PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
}
@@ -176,8 +181,8 @@ public class GrTypeDefinitionMembersCache {
myTreeChangeTracker.incModificationCount();
}
public static class TraitCollector extends AstTransformContributor {
private abstract static class TraitProcessor<T extends PsiElement> {
private class TraitCollector {
private abstract class TraitProcessor<T extends PsiElement> {
private final ArrayList<CandidateInfo> result = ContainerUtil.newArrayList();
private final Set<PsiClass> processed = ContainerUtil.newHashSet();
@@ -213,18 +218,17 @@ public class GrTypeDefinitionMembersCache {
}
}
@Override
public void collectMethods(@NotNull GrTypeDefinition clazz, Collection<PsiMethod> collector) {
if (clazz.isInterface() && !clazz.isTrait()) return;
@NotNull
public List<PsiMethod> collectMethods(@NotNull Collection<PsiMethod> codeMethods) {
if (myDefinition.isInterface() && !myDefinition.isTrait()) return Collections.emptyList();
GrImplementsClause clause = clazz.getImplementsClause();
if (clause == null) return;
GrImplementsClause clause = myDefinition.getImplementsClause();
if (clause == null) return Collections.emptyList();
PsiClassType[] types = clause.getReferencedTypes();
List<PsiClassType.ClassResolveResult> traits = getSuperTraitsByCorrectOrder(types);
if (traits.isEmpty()) return;
if (traits.isEmpty()) return Collections.emptyList();
PsiMethod[] codeMethods = clazz.getCodeMethods();
Set<MethodSignature> existingSignatures = ContainerUtil.newHashSet(ContainerUtil.map(codeMethods, new Function<PsiMethod, MethodSignature>() {
@Override
public MethodSignature fun(PsiMethod method) {
@@ -232,6 +236,8 @@ public class GrTypeDefinitionMembersCache {
}
}));
List<PsiMethod> result = ContainerUtil.newArrayList();
for (PsiClassType.ClassResolveResult resolveResult : traits) {
GrTypeDefinition trait = (GrTypeDefinition)resolveResult.getElement();
LOG.assertTrue(trait != null);
@@ -257,29 +263,31 @@ public class GrTypeDefinitionMembersCache {
}
}.getResult();
for (CandidateInfo candidateInfo : concreteTraitMethods) {
List<GrMethod> methodsToAdd = getExpandingMethods(clazz, candidateInfo);
List<GrMethod> methodsToAdd = getExpandingMethods(candidateInfo);
for (GrMethod impl : methodsToAdd) {
if (existingSignatures.add(impl.getSignature(PsiSubstitutor.EMPTY))) {
collector.add(impl);
result.add(impl);
}
}
}
}
return result;
}
@Override
public void collectFields(@NotNull GrTypeDefinition clazz, Collection<GrField> collector) {
if (clazz.isInterface() && !clazz.isTrait()) return;
@NotNull
public List<GrField> collectFields() {
if (myDefinition.isInterface() && !myDefinition.isTrait()) return Collections.emptyList();
if (clazz.isTrait()) {
for (GrField field : clazz.getCodeFields()) {
collector.add(new GrTraitField(field, clazz, PsiSubstitutor.EMPTY));
List<GrField> result = ContainerUtil.newArrayList();
if (myDefinition.isTrait()) {
for (GrField field : myDefinition.getCodeFields()) {
result.add(new GrTraitField(field, myDefinition, PsiSubstitutor.EMPTY));
}
}
GrImplementsClause clause = clazz.getImplementsClause();
if (clause == null) return;
GrImplementsClause clause = myDefinition.getImplementsClause();
if (clause == null) return result;
PsiClassType[] types = clause.getReferencedTypes();
List<PsiClassType.ClassResolveResult> traits = getSuperTraitsByCorrectOrder(types);
@@ -295,21 +303,17 @@ public class GrTypeDefinitionMembersCache {
}
}.getResult();
for (CandidateInfo candidateInfo : traitFields) {
collector.add(new GrTraitField(((PsiField)candidateInfo.getElement()), clazz, candidateInfo.getSubstitutor()));
result.add(new GrTraitField(((PsiField)candidateInfo.getElement()), myDefinition, candidateInfo.getSubstitutor()));
}
}
if (clazz.isTrait()) {
for (GrField field : clazz.getCodeFields()) {
collector.add(new GrTraitField(field, clazz, PsiSubstitutor.EMPTY));
}
}
return result;
}
@NotNull
private static List<GrMethod> getExpandingMethods(@NotNull GrTypeDefinition clazz, @NotNull CandidateInfo candidateInfo) {
private List<GrMethod> getExpandingMethods(@NotNull CandidateInfo candidateInfo) {
PsiMethod method = (PsiMethod)candidateInfo.getElement();
GrLightMethodBuilder implementation = GrTraitMethod.create(method, candidateInfo.getSubstitutor()).setContainingClass(clazz);
GrLightMethodBuilder implementation = GrTraitMethod.create(method, candidateInfo.getSubstitutor()).setContainingClass(myDefinition);
implementation.getModifierList().removeModifier(GrModifierFlags.ABSTRACT_MASK);
GrReflectedMethod[] reflectedMethods = implementation.getReflectedMethods();
@@ -317,7 +321,7 @@ public class GrTypeDefinitionMembersCache {
}
@NotNull
private static List<PsiClassType.ClassResolveResult> getSuperTraitsByCorrectOrder(@NotNull PsiClassType[] types) {
private List<PsiClassType.ClassResolveResult> getSuperTraitsByCorrectOrder(@NotNull PsiClassType[] types) {
List<PsiClassType.ClassResolveResult> traits = ContainerUtil.newArrayList();
for (int i = types.length - 1; i >= 0; i--) {
PsiClassType.ClassResolveResult resolveResult = types[i].resolveGenerics();
@@ -33,6 +33,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,7 +51,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGd
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
@@ -58,6 +58,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.GrTypeDefin
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrScriptField;
import org.jetbrains.plugins.groovy.lang.resolve.CollectClassMembersUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ast.AstTransformContributor;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint;
import java.util.*;
@@ -136,63 +137,15 @@ public class GrClassImplUtil {
@NotNull
public static PsiClassType[] getImplementsListTypes(GrTypeDefinition grType) {
Set<PsiClass> visited = new HashSet<PsiClass>();
List<PsiClassType> result = new ArrayList<PsiClassType>();
getImplementListsInner(grType, result, visited);
return result.toArray(new PsiClassType[result.size()]);
}
private static void getImplementListsInner(GrTypeDefinition grType, List<PsiClassType> result, Set<PsiClass> visited) {
if (!visited.add(grType)) return;
final Collection<PsiClassType> result = ContainerUtil.newLinkedHashSet();
final PsiClassType[] implementsTypes = getReferenceListTypes(grType.getImplementsClause());
List<PsiClassType> fromDelegates = getImplementsFromDelegate(grType, visited);
if (fromDelegates != null) {
result.addAll(fromDelegates);
}
final PsiClassType[] extendsTypes = getReferenceListTypes(grType.getExtendsClause());
result.addAll(Arrays.asList(implementsTypes));
if (!grType.isInterface() &&
!ContainerUtil.or(implementsTypes, IS_GROOVY_OBJECT) &&
!ContainerUtil.or(getReferenceListTypes(grType.getExtendsClause()), IS_GROOVY_OBJECT)) {
result.addAll(AstTransformContributor.runContributors(grType).getImplementsTypes());
if (!grType.isInterface() && !ContainerUtil.or(implementsTypes, IS_GROOVY_OBJECT) && !ContainerUtil.or(extendsTypes, IS_GROOVY_OBJECT)) {
result.add(getGroovyObjectType(grType));
}
}
@Nullable
private static List<PsiClassType> getImplementsFromDelegate(@NotNull final GrTypeDefinition grType, final Set<PsiClass> visited) {
return RecursionManager.doPreventingRecursion(grType, true, new Computable<List<PsiClassType>>() {
@Override
public List<PsiClassType> compute() {
List<PsiClassType> result = new ArrayList<PsiClassType>();
final GrField[] fields = grType.getCodeFields();
for (GrField field : fields) {
final PsiAnnotation delegate = PsiImplUtil.getAnnotation(field, GroovyCommonClassNames.GROOVY_LANG_DELEGATE);
if (delegate == null) continue;
final boolean shouldImplement = shouldImplementDelegatedInterfaces(delegate);
if (!shouldImplement) continue;
final PsiType type = field.getDeclaredType();
if (!(type instanceof PsiClassType)) continue;
final PsiClass psiClass = ((PsiClassType)type).resolve();
if (psiClass == null) continue;
if (psiClass instanceof GrTypeDefinition) {
getImplementListsInner((GrTypeDefinition)psiClass, result, visited);
}
else {
result.addAll(Arrays.asList(psiClass.getImplementsListTypes()));
}
if (psiClass.isInterface()) {
result.add((PsiClassType)type);
}
}
return result;
}
});
return result.toArray(new PsiClassType[result.size()]);
}
public static PsiClassType getGroovyObjectType(@NotNull PsiElement context) {
@@ -640,11 +593,6 @@ public class GrClassImplUtil {
return PsiClassImplUtil.isClassEquivalentTo(definition, another);
}
private static boolean shouldImplementDelegatedInterfaces(PsiAnnotation delegate) {
final Boolean result = GrAnnotationUtil.inferBooleanAttribute(delegate, "interfaces");
return result == null || result.booleanValue();
}
public static void addExpandingReflectedMethods(Collection<PsiMethod> result, PsiMethod method) {
if (method instanceof GrMethod) {
final GrReflectedMethod[] reflectedMethods = ((GrMethod)method).getReflectedMethods();
@@ -667,4 +615,25 @@ public class GrClassImplUtil {
ContainerUtil.addIfNotNull(result, field.getSetter());
}
}
public static Collection<PsiMethod> filterOutAccessors(Collection<PsiMethod> result) {
final TObjectIntHashMap<String> map = new TObjectIntHashMap<String>();
for (PsiMethod method : result) {
if (method instanceof GrAccessorMethod || GroovyPropertyUtils.isSimplePropertyAccessor(method)) {
final String methodName = method.getName();
if (map.containsKey(methodName)) {
map.adjustValue(methodName, 1);
}
else {
map.put(methodName, 1);
}
}
}
return ContainerUtil.filter(result, new Condition<PsiMethod>() {
@Override
public boolean value(PsiMethod method) {
return !(method instanceof GrAccessorMethod) || map.get(method.getName()) <= 1;
}
});
}
}
@@ -18,78 +18,54 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author Max Medvedev
*/
public abstract class AstTransformContributor {
public static final ExtensionPointName<AstTransformContributor> EP_NAME = ExtensionPointName.create("org.intellij.groovy.astTransformContributor");
@Deprecated
public void collectMethods(@NotNull final GrTypeDefinition clazz, Collection<PsiMethod> collector) {
}
@Deprecated
public void collectFields(@NotNull final GrTypeDefinition clazz, Collection<GrField> collector) {
}
public void collectClasses(@NotNull final GrTypeDefinition clazz, Collection<PsiClass> collector) {
/**
* Subclasses should override this method.
*/
@NotNull
@SuppressWarnings("deprecation")
public Members collect(@NotNull final GrTypeDefinition clazz) {
final Members members = Members.create();
collectMethods(clazz, members.getMethods());
collectFields(clazz, members.getFields());
return members;
}
@NotNull
public static Collection<PsiMethod> runContributorsForMethods(@NotNull final GrTypeDefinition clazz) {
Collection<PsiMethod> result = RecursionManager.doPreventingRecursion(clazz, true, new Computable<Collection<PsiMethod>>() {
public static Members runContributors(@NotNull final GrTypeDefinition clazz) {
Members result = RecursionManager.doPreventingRecursion(clazz, true, new Computable<Members>() {
@Override
public Collection<PsiMethod> compute() {
Collection<PsiMethod> collector = new ArrayList<PsiMethod>();
public Members compute() {
Members members = Members.create();
for (final AstTransformContributor contributor : EP_NAME.getExtensions()) {
contributor.collectMethods(clazz, collector);
members.addFrom(contributor.collect(clazz));
}
return collector;
return members;
}
});
return result == null ? Collections.<PsiMethod>emptyList() : result;
}
@NotNull
public static List<GrField> runContributorsForFields(@NotNull final GrTypeDefinition clazz) {
List<GrField> fields = RecursionManager.doPreventingRecursion(clazz, true, new Computable<List<GrField>>() {
@Override
public List<GrField> compute() {
List<GrField> collector = new ArrayList<GrField>();
for (final AstTransformContributor contributor : EP_NAME.getExtensions()) {
contributor.collectFields(clazz, collector);
}
return collector;
}
});
return fields != null ? fields : Collections.<GrField>emptyList();
}
@NotNull
public static List<PsiClass> runContributorsForClasses(@NotNull final GrTypeDefinition clazz) {
List<PsiClass> fields = RecursionManager.doPreventingRecursion(clazz, true, new Computable<List<PsiClass>>() {
@Override
public List<PsiClass> compute() {
List<PsiClass> collector = ContainerUtil.newArrayList();
for (final AstTransformContributor contributor : EP_NAME.getExtensions()) {
contributor.collectClasses(clazz, collector);
}
return collector;
}
});
return fields != null ? fields : Collections.<PsiClass>emptyList();
return result == null ? Members.EMPTY : result;
}
}
@@ -49,12 +49,21 @@ import java.util.*;
* @author Max Medvedev
*/
public class DelegatedMethodsContributor extends AstTransformContributor {
@NotNull
@Override
public void collectMethods(@NotNull final GrTypeDefinition clazz, @NotNull Collection<PsiMethod> collector) {
public Members collect(@NotNull GrTypeDefinition clazz) {
final Members result = Members.create();
doCollectMethods(clazz, result.getMethods());
doCollectImplementsTypes(clazz, result.getImplementsTypes());
return result;
}
private static void doCollectMethods(@NotNull final GrTypeDefinition clazz, @NotNull Collection<PsiMethod> collector) {
Set<PsiClass> processed = new HashSet<PsiClass>();
if (!checkForDelegate(clazz)) return;
Map<MethodSignature, PsiMethod> signatures = new THashMap<MethodSignature, PsiMethod>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
initializeSignatures(clazz, PsiSubstitutor.EMPTY, signatures, processed);
@@ -334,4 +343,31 @@ public class DelegatedMethodsContributor extends AstTransformContributor {
private static final Set<String> OBJECT_METHODS = ContainerUtil.newHashSet("equals", "hashCode", "getClass", "clone", "toString", "notify", "notifyAll", "wait", "finalize");
private static final Set<String> GROOVY_OBJECT_METHODS = ContainerUtil.newHashSet("invokeMethod", "getProperty", "setProperty", "getMetaClass", "setMetaClass");
private static void doCollectImplementsTypes(GrTypeDefinition grType, Collection<PsiClassType> result) {
final GrField[] fields = grType.getCodeFields();
for (GrField field : fields) {
final PsiAnnotation delegate = PsiImplUtil.getAnnotation(field, GroovyCommonClassNames.GROOVY_LANG_DELEGATE);
if (delegate == null) continue;
final boolean shouldImplement = shouldImplementDelegatedInterfaces(delegate);
if (!shouldImplement) continue;
final PsiType type = field.getDeclaredType();
if (!(type instanceof PsiClassType)) continue;
final PsiClass psiClass = ((PsiClassType)type).resolve();
if (psiClass == null) continue;
result.addAll(Arrays.asList(psiClass.getImplementsListTypes()));
if (psiClass.isInterface()) {
result.add((PsiClassType)type);
}
}
}
private static boolean shouldImplementDelegatedInterfaces(PsiAnnotation delegate) {
final Boolean result = GrAnnotationUtil.inferBooleanAttribute(delegate, "interfaces");
return result == null || result.booleanValue();
}
}
@@ -0,0 +1,118 @@
/*
* Copyright 2000-2015 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.lang.resolve.ast;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiMethod;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import java.util.Collection;
import java.util.Collections;
public abstract class Members {
@NotNull
public abstract Collection<PsiMethod> getMethods();
@NotNull
public abstract Collection<GrField> getFields();
@NotNull
public abstract Collection<PsiClass> getClasses();
@NotNull
public abstract Collection<PsiClassType> getImplementsTypes();
public abstract void addFrom(@NotNull Members other);
public static final Members EMPTY = new Members() {
@NotNull
@Override
public Collection<PsiMethod> getMethods() {
return Collections.emptyList();
}
@NotNull
@Override
public Collection<GrField> getFields() {
return Collections.emptyList();
}
@NotNull
@Override
public Collection<PsiClass> getClasses() {
return Collections.emptyList();
}
@NotNull
@Override
public Collection<PsiClassType> getImplementsTypes() {
return Collections.emptyList();
}
@Override
public void addFrom(@NotNull Members other) {
// do nothing
}
};
@NotNull
public static Members create() {
return new Members() {
private final Collection<PsiMethod> methods = ContainerUtil.newArrayList();
private final Collection<GrField> fields = ContainerUtil.newArrayList();
private final Collection<PsiClass> classes = ContainerUtil.newArrayList();
private final Collection<PsiClassType> implementsTypes = ContainerUtil.newArrayList();
@NotNull
@Override
public Collection<PsiMethod> getMethods() {
return methods;
}
@NotNull
@Override
public Collection<GrField> getFields() {
return fields;
}
@NotNull
@Override
public Collection<PsiClass> getClasses() {
return classes;
}
@NotNull
@Override
public Collection<PsiClassType> getImplementsTypes() {
return implementsTypes;
}
@Override
public void addFrom(@NotNull Members other) {
methods.addAll(other.getMethods());
fields.addAll(other.getFields());
classes.addAll(other.getClasses());
implementsTypes.addAll(other.getImplementsTypes());
}
};
}
}
@@ -15,48 +15,54 @@
*/
package org.jetbrains.plugins.groovy.lang.resolve.ast.builder;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.resolve.ast.AstTransformContributor;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.GrBuilderStrategySupport.Members;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.DefaultBuilderStrategySupport;
import java.util.Collection;
public abstract class BuilderAnnotationContributor extends AstTransformContributor {
public class BuilderAnnotationContributor extends AstTransformContributor {
public static final String BUILDER_PACKAGE = "groovy.transform.builder";
public static final String BUILDER_FQN = BUILDER_PACKAGE + ".Builder";
public static final String ORIGIN_INFO = "via @Builder";
public static final String STRATEGY_ATTRIBUTE = "builderStrategy";
@Override
public void collectMethods(@NotNull GrTypeDefinition clazz, final Collection<PsiMethod> collector) {
collector.addAll(collectAll(clazz).methods);
}
@Override
public void collectClasses(@NotNull GrTypeDefinition clazz, Collection<PsiClass> collector) {
collector.addAll(collectAll(clazz).classes);
}
@Override
public void collectFields(@NotNull GrTypeDefinition clazz, Collection<GrField> collector) {
collector.addAll(collectAll(clazz).fields);
}
private static Members collectAll(final GrTypeDefinition clazz) {
return CachedValuesManager.getCachedValue(clazz, new CachedValueProvider<Members>() {
@Nullable
@Override
public Result<Members> compute() {
final Members result = new Members();
for (GrBuilderStrategySupport strategySupport : GrBuilderStrategySupport.EP.getExtensions()) {
result.addFrom(strategySupport.process(clazz));
}
return Result.create(result, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
@Nullable
@Contract("null,_ -> null")
public static PsiClass getClassAttributeValue(@Nullable PsiAnnotation annotation, @NotNull String attributeName) {
if (annotation == null) return null;
final PsiAnnotationMemberValue value = annotation.findAttributeValue(attributeName);
if (value instanceof GrReferenceExpression) {
final PsiElement element = ((GrReferenceExpression)value).resolve();
return element instanceof PsiClass ? (PsiClass)element : null;
}
else if (value instanceof PsiClassObjectAccessExpression) {
PsiType type = ((PsiClassObjectAccessExpression)value).getOperand().getType();
if (type instanceof PsiClassType) {
return ((PsiClassType)type).resolve();
}
});
}
return null;
}
@Contract("null, _ -> false")
public static boolean isApplicable(@Nullable PsiAnnotation annotation, @NotNull String strategy) {
if (annotation == null) return false;
final PsiAnnotationMemberValue attributeValue = annotation.findDeclaredAttributeValue(STRATEGY_ATTRIBUTE);
if (attributeValue == null) {
return strategy == DefaultBuilderStrategySupport.DEFAULT_STRATEGY_NAME;
}
else {
final String value = attributeValue.getText();
return strategy.equals(value) || StringUtil.getQualifiedName(BUILDER_PACKAGE, strategy).equals(value);
}
}
public static PsiType createType(PsiClass clazz) {
return JavaPsiFacade.getElementFactory(clazz.getProject()).createType(clazz);
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.lang.resolve.ast.builder;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.impl.light.LightPsiClassBuilder;
@@ -24,24 +25,28 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
public class BuilderHelperLightPsiClass extends LightPsiClassBuilder {
private final @NotNull GrTypeDefinition myContainingClass;
public BuilderHelperLightPsiClass(@NotNull GrTypeDefinition containingClass, @NotNull String name) {
super(containingClass, name);
myContainingClass = containingClass;
setScope(myContainingClass);
setOriginInfo(GrBuilderStrategySupport.ORIGIN_INFO);
setScope(containingClass);
setContainingClass(containingClass);
setOriginInfo(BuilderAnnotationContributor.ORIGIN_INFO);
getModifierList().addModifier(PsiModifier.STATIC);
}
@Override
public PsiElement getParent() {
return getContainingClass();
}
@NotNull
@Override
public PsiClass getContainingClass() {
return myContainingClass;
//noinspection ConstantConditions
return super.getContainingClass();
}
@Override
public PsiFile getContainingFile() {
return myContainingClass.getContainingFile();
return getContainingClass().getContainingFile();
}
}
@@ -1,64 +0,0 @@
/*
* Copyright 2000-2015 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.lang.resolve.ast.builder;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.DefaultBuilderStrategySupport;
import java.util.Collection;
public abstract class GrBuilderStrategySupport {
public static final ExtensionPointName<GrBuilderStrategySupport> EP = ExtensionPointName.create("org.intellij.groovy.builderStrategySupport");
public static final String BUILDER_FQN = "groovy.transform.builder.Builder";
public static final String ORIGIN_INFO = "by @Builder";
public static class Members {
public final Collection<PsiMethod> methods = ContainerUtil.newArrayList();
public final Collection<GrField> fields = ContainerUtil.newArrayList();
public final Collection<PsiClass> classes = ContainerUtil.newArrayList();
public void addFrom(Members other) {
methods.addAll(other.methods);
fields.addAll(other.fields);
classes.addAll(other.classes);
}
}
@NotNull
public abstract Members process(GrTypeDefinition typeDefinition);
@Nullable
public static String getStrategy(PsiModifierListOwner annotatedMember) {
final PsiAnnotation annotation = PsiImplUtil.getAnnotation(annotatedMember, BUILDER_FQN);
if (annotation == null) return null;
final PsiAnnotationMemberValue strategy = annotation.findDeclaredAttributeValue("builderStrategy");
if (strategy instanceof GrReferenceExpression) {
final PsiElement element = ((GrReferenceExpression)strategy).resolve();
return element instanceof PsiClass ? ((PsiClass)element).getQualifiedName() : null;
}
return DefaultBuilderStrategySupport.DEFAULT_STRATEGY_FQN;
}
}
@@ -26,15 +26,17 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ast.Members;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.BuilderAnnotationContributor;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.BuilderHelperLightPsiClass;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.GrBuilderStrategySupport;
public class DefaultBuilderStrategySupport extends GrBuilderStrategySupport {
public class DefaultBuilderStrategySupport extends BuilderAnnotationContributor {
public static final String DEFAULT_STRATEGY_FQN = "groovy.transform.builder.DefaultStrategy";
public static final String DEFAULT_STRATEGY_NAME = "DefaultStrategy";
@NotNull
public Members process(@NotNull final GrTypeDefinition typeDefinition) {
@Override
public Members collect(@NotNull final GrTypeDefinition typeDefinition) {
return new DefaultBuilderStrategyHandler(typeDefinition).doProcess();
}
@@ -47,7 +49,7 @@ public class DefaultBuilderStrategySupport extends GrBuilderStrategySupport {
private DefaultBuilderStrategyHandler(@NotNull GrTypeDefinition typeDefinition) {
myContainingClass = typeDefinition;
myElementFactory = PsiElementFactory.SERVICE.getInstance(typeDefinition.getProject());
myMembers = new Members();
myMembers = Members.create();
}
@NotNull
@@ -64,11 +66,10 @@ public class DefaultBuilderStrategySupport extends GrBuilderStrategySupport {
private void processTypeDefinition() {
final PsiAnnotation builderAnno = PsiImplUtil.getAnnotation(myContainingClass, BUILDER_FQN);
if (builderAnno == null || !DEFAULT_STRATEGY_FQN.equals(getStrategy(myContainingClass))) return;
if (!isApplicable(builderAnno, DEFAULT_STRATEGY_NAME)) return;
final PsiClass builderClass = createBuilderClass(builderAnno, myContainingClass.getCodeFields());
final LightMethodBuilder builderMethod = createBuilderMethod(builderClass, builderAnno);
myMembers.classes.add(builderClass);
myMembers.methods.add(builderMethod);
myMembers.getMethods().add(createBuilderMethod(builderClass, builderAnno));
myMembers.getClasses().add(builderClass);
}
@NotNull
@@ -88,10 +89,9 @@ public class DefaultBuilderStrategySupport extends GrBuilderStrategySupport {
builderClass.addMethod(createFieldSetter(builderClass, field, annotation));
}
final LightMethodBuilder buildMethod = new LightMethodBuilder(getManager(), getBuildMethodName(annotation));
buildMethod.setContainingClass(builderClass);
buildMethod.setOriginInfo(ORIGIN_INFO);
buildMethod.setMethodReturnType(builtType == null ? myElementFactory.createType(myContainingClass) : builtType);
final LightMethodBuilder buildMethod = createBuildMethod(
annotation, builtType == null ? myElementFactory.createType(myContainingClass) : builtType, builderClass
);
return builderClass.addMethod(buildMethod);
}
@@ -114,7 +114,7 @@ public class DefaultBuilderStrategySupport extends GrBuilderStrategySupport {
private void processMethod(@NotNull GrMethod method) {
final PsiAnnotation annotation = PsiImplUtil.getAnnotation(method, BUILDER_FQN);
if (annotation == null || !DEFAULT_STRATEGY_FQN.equals(getStrategy(method))) return;
if (!isApplicable(annotation, DEFAULT_STRATEGY_NAME)) return;
if (method.isConstructor()) {
processConstructor(method, annotation);
}
@@ -125,52 +125,60 @@ public class DefaultBuilderStrategySupport extends GrBuilderStrategySupport {
private void processConstructor(@NotNull GrMethod method, PsiAnnotation annotation) {
PsiClass builderClass = createBuilderClass(annotation, method.getParameters());
LightMethodBuilder builderMethod = createBuilderMethod(builderClass, annotation);
myMembers.methods.add(builderMethod);
myMembers.classes.add(builderClass);
myMembers.getMethods().add(createBuilderMethod(builderClass, annotation));
myMembers.getClasses().add(builderClass);
}
private void processFactoryMethod(@NotNull GrMethod method, PsiAnnotation annotation) {
PsiClass builderClass = createBuilderClass(annotation, method.getParameters(), method.getReturnType());
LightMethodBuilder builderMethod = createBuilderMethod(builderClass, annotation);
myMembers.methods.add(builderMethod);
myMembers.classes.add(builderClass);
}
@NotNull
private LightMethodBuilder createFieldSetter(@NotNull PsiClass builderClass, @NotNull GrVariable field, @NotNull PsiAnnotation annotation) {
final String name = field.getName();
final LightMethodBuilder fieldSetter = new LightMethodBuilder(getManager(), getFieldMethodName(annotation, name));
fieldSetter.addModifier(PsiModifier.PUBLIC);
fieldSetter.addParameter(name, field.getType(), false);
fieldSetter.setContainingClass(builderClass);
fieldSetter.setMethodReturnType(myElementFactory.createType(builderClass));
fieldSetter.setNavigationElement(field);
return fieldSetter;
myMembers.getMethods().add(createBuilderMethod(builderClass, annotation));
myMembers.getClasses().add(builderClass);
}
@NotNull
private static String getBuilderMethodName(@NotNull PsiAnnotation annotation) {
final String builderMethodName = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "builderMethodName");
return builderMethodName == null ? "builder" : builderMethodName;
}
@NotNull
private static String getBuilderClassName(@NotNull PsiAnnotation annotation, @NotNull GrTypeDefinition clazz) {
final String builderClassName = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "builderClassName");
return builderClassName == null ? String.format("%s%s", clazz.getName(), "Builder") : builderClassName;
}
@NotNull
private static String getFieldMethodName(@NotNull PsiAnnotation annotation, @NotNull String fieldName) {
final String prefix = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "prefix");
return prefix == null ? fieldName : String.format("%s%s", prefix, StringUtil.capitalize(fieldName));
}
@NotNull
private static String getBuildMethodName(@NotNull PsiAnnotation annotation) {
final String buildMethodName = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "buildMethodName");
return buildMethodName == null ? "build" : buildMethodName;
return StringUtil.isEmpty(builderMethodName) ? "builder" : builderMethodName;
}
}
@NotNull
public static String getBuilderClassName(@NotNull PsiAnnotation annotation, @NotNull GrTypeDefinition clazz) {
final String builderClassName = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "builderClassName");
return builderClassName == null ? String.format("%s%s", clazz.getName(), "Builder") : builderClassName;
}
@NotNull
public static LightMethodBuilder createBuildMethod(@NotNull PsiAnnotation annotation, @NotNull PsiType builtType, PsiClass builderClass) {
final LightMethodBuilder buildMethod = new LightMethodBuilder(annotation.getManager(), getBuildMethodName(annotation));
buildMethod.setContainingClass(builderClass);
buildMethod.setOriginInfo(ORIGIN_INFO);
buildMethod.setMethodReturnType(builtType);
return buildMethod;
}
@NotNull
public static LightMethodBuilder createFieldSetter(@NotNull PsiClass builderClass, @NotNull GrVariable field, @NotNull PsiAnnotation annotation) {
final String name = field.getName();
final LightMethodBuilder fieldSetter = new LightMethodBuilder(builderClass.getManager(), getFieldMethodName(annotation, name));
fieldSetter.addModifier(PsiModifier.PUBLIC);
fieldSetter.addParameter(name, field.getType());
fieldSetter.setContainingClass(builderClass);
fieldSetter.setMethodReturnType(JavaPsiFacade.getElementFactory(builderClass.getProject()).createType(builderClass));
fieldSetter.setNavigationElement(field);
fieldSetter.setOriginInfo(ORIGIN_INFO);
return fieldSetter;
}
@NotNull
public static String getFieldMethodName(@NotNull PsiAnnotation annotation, @NotNull String fieldName) {
final String prefix = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "prefix");
return StringUtil.isEmpty(prefix) ? fieldName : String.format("%s%s", prefix, StringUtil.capitalize(fieldName));
}
@NotNull
private static String getBuildMethodName(@NotNull PsiAnnotation annotation) {
final String buildMethodName = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "buildMethodName");
return StringUtil.isEmpty(buildMethodName) ? "build" : buildMethodName;
}
}
@@ -0,0 +1,58 @@
/*
* Copyright 2000-2015 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.lang.resolve.ast.builder.strategy;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ast.Members;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.BuilderAnnotationContributor;
import static org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.DefaultBuilderStrategySupport.createBuildMethod;
import static org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.DefaultBuilderStrategySupport.createFieldSetter;
public class ExternalBuilderStrategySupport extends BuilderAnnotationContributor {
public static final String EXTERNAL_STRATEGY_NAME = "ExternalStrategy";
@NotNull
@Override
public Members collect(@NotNull GrTypeDefinition builderClass) {
Pair<PsiAnnotation, GrTypeDefinition> definitionPair = getConstructedClass(builderClass);
if (definitionPair == null) return Members.EMPTY;
final PsiAnnotation annotation = definitionPair.first;
final GrTypeDefinition typeDefinition = definitionPair.second;
final Members result = Members.create();
for (GrField field : typeDefinition.getCodeFields()) {
result.getMethods().add(createFieldSetter(builderClass, field, annotation));
}
result.getMethods().add(createBuildMethod(annotation, createType(typeDefinition), builderClass));
return result;
}
private static Pair<PsiAnnotation, GrTypeDefinition> getConstructedClass(GrTypeDefinition builderClass) {
final PsiAnnotation annotation = PsiImplUtil.getAnnotation(builderClass, BUILDER_FQN);
if (!isApplicable(annotation, EXTERNAL_STRATEGY_NAME)) return null;
final PsiClass constructedClass = getClassAttributeValue(annotation, "forClass");
if (!(constructedClass instanceof GrTypeDefinition)) return null;
return Pair.create(annotation, (GrTypeDefinition)constructedClass);
}
}
@@ -0,0 +1,197 @@
/*
* Copyright 2000-2015 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.lang.resolve.ast.builder.strategy;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightMethodBuilder;
import com.intellij.psi.impl.light.LightPsiClassBuilder;
import com.intellij.psi.impl.light.LightTypeParameterBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ast.Members;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.BuilderAnnotationContributor;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.BuilderHelperLightPsiClass;
import static org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.DefaultBuilderStrategySupport.getBuilderClassName;
import static org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.DefaultBuilderStrategySupport.getFieldMethodName;
public class InitializerBuilderStrategySupport extends BuilderAnnotationContributor {
public static final String INITIALIZER_STRATEGY_NAME = "InitializerStrategy";
public static final String SET_FQN = "groovy.transform.builder.InitializerStrategy.SET";
public static final String UNSET_FQN = "groovy.transform.builder.InitializerStrategy.UNSET";
@NotNull
@Override
public Members collect(@NotNull GrTypeDefinition clazz) {
return new InitializerBuilderStrategyHandler(clazz).doProcess();
}
private static class InitializerBuilderStrategyHandler {
private final @NotNull GrTypeDefinition myContainingClass;
private final @NotNull PsiElementFactory myElementFactory;
private final Members myMembers;
private InitializerBuilderStrategyHandler(@NotNull GrTypeDefinition typeDefinition) {
myContainingClass = typeDefinition;
myElementFactory = PsiElementFactory.SERVICE.getInstance(typeDefinition.getProject());
myMembers = Members.create();
}
@NotNull
private PsiManager getManager() {
return myContainingClass.getManager();
}
@NotNull
public Members doProcess() {
processTypeDefinition();
processConstructors();
return myMembers;
}
private void processTypeDefinition() {
final PsiAnnotation builderAnno = PsiImplUtil.getAnnotation(myContainingClass, BUILDER_FQN);
if (!isApplicable(builderAnno, INITIALIZER_STRATEGY_NAME)) return;
final PsiClass builderClass = createBuilderClass(builderAnno, myContainingClass.getCodeFields());
myMembers.getMethods().add(createBuilderMethod(builderClass, builderAnno));
myMembers.getMethods().add(createBuilderConstructor(myContainingClass, builderClass, builderAnno));
myMembers.getClasses().add(builderClass);
}
@NotNull
private LightPsiClassBuilder createBuilderClass(@NotNull final PsiAnnotation annotation,
@NotNull GrVariable[] setters) {
final LightPsiClassBuilder builderClass = new BuilderHelperLightPsiClass(
myContainingClass, getBuilderClassName(annotation, myContainingClass)
);
for (int i = 0; i < setters.length; i++) {
builderClass.getTypeParameterList().addParameter(new InitializerTypeParameter(builderClass, i));
}
for (int i = 0; i < setters.length; i++) {
builderClass.addMethod(createFieldSetter(builderClass, setters[i], annotation, i));
}
return builderClass.addMethod(createBuildMethod(annotation, builderClass));
}
@NotNull
private LightMethodBuilder createFieldSetter(@NotNull LightPsiClassBuilder builderClass,
@NotNull GrVariable field,
@NotNull PsiAnnotation annotation,
int currentField) {
final String name = field.getName();
final LightMethodBuilder fieldSetter = new LightMethodBuilder(builderClass.getManager(), getFieldMethodName(annotation, name));
final PsiSubstitutor substitutor = PsiSubstitutor.EMPTY.put(
builderClass.getTypeParameters()[currentField],
myElementFactory.createTypeByFQClassName(SET_FQN, annotation.getResolveScope())
);
fieldSetter.addModifier(PsiModifier.PUBLIC);
fieldSetter.addParameter(name, field.getType());
fieldSetter.setContainingClass(builderClass);
fieldSetter.setMethodReturnType(myElementFactory.createType(builderClass, substitutor));
fieldSetter.setNavigationElement(field);
fieldSetter.setOriginInfo(ORIGIN_INFO);
return fieldSetter;
}
private LightMethodBuilder createBuildMethod(@NotNull PsiAnnotation annotation, @NotNull PsiClass builderClass) {
LightMethodBuilder buildMethod = new LightMethodBuilder(annotation.getManager(), builderClass.getLanguage(), getBuildMethodName(annotation));
buildMethod.addModifier(PsiModifier.STATIC);
buildMethod.setContainingClass(builderClass);
buildMethod.setOriginInfo(ORIGIN_INFO);
buildMethod.setNavigationElement(annotation);
buildMethod.setMethodReturnType(createAllSetUnsetType(builderClass, false));
return buildMethod;
}
@NotNull
private LightMethodBuilder createBuilderMethod(@NotNull PsiClass builderClass, @NotNull PsiAnnotation annotation) {
final LightMethodBuilder builderMethod = new LightMethodBuilder(getManager(), getBuilderMethodName(annotation));
builderMethod.addModifier(PsiModifier.STATIC);
builderMethod.setContainingClass(myContainingClass);
builderMethod.setOriginInfo(ORIGIN_INFO);
builderMethod.setNavigationElement(annotation);
builderMethod.setMethodReturnType(createAllSetUnsetType(builderClass, false));
return builderMethod;
}
@NotNull
private LightMethodBuilder createBuilderConstructor(@NotNull PsiClass constructedClass, @NotNull PsiClass builderClass, PsiAnnotation annotation) {
final LightMethodBuilder constructor = new LightMethodBuilder(constructedClass, constructedClass.getLanguage()).addParameter(
"builder", createAllSetUnsetType(builderClass, true)
).setConstructor(true);
constructor.setNavigationElement(annotation);
constructor.setOriginInfo(ORIGIN_INFO);
return constructor;
}
private void processConstructors() {
for (GrMethod method : myContainingClass.getCodeMethods()) {
final PsiAnnotation annotation = PsiImplUtil.getAnnotation(method, BUILDER_FQN);
if (!isApplicable(annotation, INITIALIZER_STRATEGY_NAME)) return;
if (method.isConstructor()) {
processConstructor(method, annotation);
}
}
}
private void processConstructor(@NotNull GrMethod method, PsiAnnotation annotation) {
PsiClass builderClass = createBuilderClass(annotation, method.getParameters());
myMembers.getMethods().add(createBuilderMethod(builderClass, annotation));
myMembers.getMethods().add(createBuilderConstructor(myContainingClass, builderClass, annotation));
myMembers.getClasses().add(builderClass);
}
@NotNull
private static String getBuilderMethodName(@NotNull PsiAnnotation annotation) {
final String builderMethodName = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "builderMethodName");
return StringUtil.isEmpty(builderMethodName) ? "createInitializer" : builderMethodName;
}
@NotNull
private static String getBuildMethodName(@NotNull PsiAnnotation annotation) {
final String builderMethodName = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "buildMethodName");
return StringUtil.isEmpty(builderMethodName) ? "create" : builderMethodName;
}
@NotNull
private PsiType createAllSetUnsetType(@NotNull PsiClass builderClass, boolean setUnset) {
final PsiClassType type = myElementFactory.createTypeByFQClassName(
setUnset ? SET_FQN : UNSET_FQN,
builderClass.getResolveScope()
);
final PsiType[] mappings = PsiType.createArray(builderClass.getTypeParameters().length);
for (int i = 0; i < mappings.length; i++) {
mappings[i] = type;
}
return myElementFactory.createType(builderClass, mappings);
}
}
private static class InitializerTypeParameter extends LightTypeParameterBuilder {
public InitializerTypeParameter(PsiTypeParameterListOwner owner, int index) {
super("T" + index, owner, index);
}
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2000-2015 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.lang.resolve.ast.builder.strategy;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.impl.light.LightMethodBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ast.Members;
import org.jetbrains.plugins.groovy.lang.resolve.ast.builder.BuilderAnnotationContributor;
public class SimpleBuilderStrategySupport extends BuilderAnnotationContributor {
public static final String SIMPLE_STRATEGY_NAME = "SimpleStrategy";
@NotNull
@Override
public Members collect(@NotNull GrTypeDefinition typeDefinition) {
final PsiAnnotation annotation = PsiImplUtil.getAnnotation(typeDefinition, BUILDER_FQN);
if (!isApplicable(annotation, SIMPLE_STRATEGY_NAME)) return Members.EMPTY;
final Members result = Members.create();
for (GrField field : typeDefinition.getCodeFields()) {
result.getMethods().add(createFieldSetter(typeDefinition, field, annotation));
}
return result;
}
@NotNull
public static LightMethodBuilder createFieldSetter(@NotNull PsiClass builderClass, @NotNull GrVariable field, @NotNull PsiAnnotation annotation) {
final String name = field.getName();
final LightMethodBuilder fieldSetter = new LightMethodBuilder(builderClass.getManager(), getFieldMethodName(annotation, name));
fieldSetter.addModifier(PsiModifier.PUBLIC);
fieldSetter.addParameter(name, field.getType(), false);
fieldSetter.setContainingClass(builderClass);
fieldSetter.setMethodReturnType(createType(builderClass));
fieldSetter.setNavigationElement(field);
fieldSetter.setOriginInfo(ORIGIN_INFO);
return fieldSetter;
}
@NotNull
public static String getFieldMethodName(@NotNull PsiAnnotation annotation, @NotNull String fieldName) {
final String prefix = AnnotationUtil.getDeclaredStringAttributeValue(annotation, "prefix");
return prefix == null ? "set" + StringUtil.capitalize(fieldName)
: prefix.isEmpty() ? fieldName
: prefix + StringUtil.capitalize(fieldName);
}
}
+4 -3
View File
@@ -107,15 +107,16 @@
<closureMissingMethodContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.PluginXmlClosureMemberContributor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.GrTypeDefinitionMembersCache$TraitCollector"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.DelegatedMethodsContributor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.AutoExternalizeContributor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.AutoCloneContributor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.ConstructorAnnotationsProcessor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.GrInheritConstructorContributor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.LoggingContributor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.builder.BuilderAnnotationContributor"/>
<builderStrategySupport implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.DefaultBuilderStrategySupport"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.DefaultBuilderStrategySupport"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.SimpleBuilderStrategySupport"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.ExternalBuilderStrategySupport"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.builder.strategy.InitializerBuilderStrategySupport"/>
<positionManagerDelegate implementation="org.jetbrains.plugins.groovy.gant.GantPositionManagerHelper"/>
@@ -263,9 +263,9 @@ public class CreateParameterForFieldIntention extends Intention {
return findCandidatesCached(constructor, (GrTypeDefinition)clazz);
}
private static List<GrField> findCandidates(GrMethod constructor, final GrTypeDefinition clazz) {
private static List<GrField> findCandidates(PsiMethod constructor, final GrTypeDefinition clazz) {
final List<GrField> usedFields = new ArrayList<GrField>();
final GrOpenBlock block = constructor.getBlock();
final GrOpenBlock block = constructor instanceof GrMethod ? ((GrMethod)constructor).getBlock() : null;
if (block == null) {
return usedFields;
}
@@ -308,7 +308,7 @@ public class CreateParameterForFieldIntention extends Intention {
return fields;
}
private static List<GrField> findCandidatesCached(final GrMethod constructor, final GrTypeDefinition clazz) {
private static List<GrField> findCandidatesCached(final PsiMethod constructor, final GrTypeDefinition clazz) {
final CachedValue<List<GrField>> value = constructor.getUserData(FIELD_CANDIDATES);
if (value != null && value.getValue() != null) return value.getValue();
final CachedValue<List<GrField>> cachedValue =
@@ -335,7 +335,7 @@ public class CreateParameterForFieldIntention extends Intention {
final PsiMethod[] constructors = psiClass.getConstructors();
final PsiManager manager = field.getManager();
for (PsiMethod constructor : constructors) {
final List<GrField> fields = findCandidatesCached(((GrMethod)constructor), psiClass);
final List<GrField> fields = findCandidatesCached(constructor, psiClass);
if (ContainerUtil.find(fields, new Condition<GrField>() {
@Override
public boolean value(GrField grField) {
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2015 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.completion.builder
import com.intellij.testFramework.LightProjectDescriptor
import groovy.transform.CompileStatic
import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
import org.jetbrains.plugins.groovy.completion.CompletionResult
import org.jetbrains.plugins.groovy.completion.GroovyCompletionTestBase
import static com.intellij.codeInsight.completion.CompletionType.BASIC
@CompileStatic
abstract class GrBuilderTransformationCompletionTestBase extends GroovyCompletionTestBase {
@Override
@NotNull
protected LightProjectDescriptor getProjectDescriptor() {
return GroovyLightProjectDescriptor.GROOVY_2_3_9;
}
void doVariantableTest(String text, String... args) {
doVariantableTest(text, CompletionResult.contain, args)
}
void doVariantableTest(String text, CompletionResult cr, String... args) {
doVariantableTest(text, '', BASIC, cr, 1, args)
}
}
@@ -0,0 +1,254 @@
/*
* Copyright 2000-2015 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.completion.builder
import groovy.transform.CompileStatic
@CompileStatic
class GrDefaultBuilderStrategyOnConstructorTest extends GrBuilderTransformationCompletionTestBase {
void 'test no builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy)
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.<caret>
''', 'builder'
}
void 'test custom builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, builderMethodName = 'customBuilderMethod')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.<caret>
''', 'customBuilderMethod'
}
/**
* The class even won't be compiled.
* Separate inspection highlights such code and offers to remove the parameter.
*/
void 'test null builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, builderMethodName = null)
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.<caret>
''', 'builder'
}
/**
* Class will be compiled but there will be runtime error.
*/
void 'test empty builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, builderMethodName = '')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.<caret>
''', 'builder'
}
void 'test spaces builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, builderMethodName = ' ')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.<caret>
''', ' '
}
void 'test no prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy)
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test empty prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, prefix = '')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test custom prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, prefix = 'customPrefix')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', 'build', 'customPrefixName', 'customPrefixDynamic', 'customPrefixCounter'
}
void 'test spaces prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, prefix = ' ')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', 'build', ' Name', ' Dynamic', ' Counter'
}
void 'test null prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, prefix = null)
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test custom build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, buildMethodName = 'customBuild')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', 'customBuild', 'name', 'dynamic', 'counter'
}
void 'test null build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, buildMethodName = null)
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test empty build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, buildMethodName = '')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test spaces build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy, buildMethodName = ' ')
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().<caret>
''', ' ', 'name', 'dynamic', 'counter'
}
void 'test next setter'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy)
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().counter(1).<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test one more setter further'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class PojoConstructor {
@Builder(builderStrategy = DefaultStrategy)
PojoConstructor(def dynamic, int counter, String name) {}
}
PojoConstructor.builder().counter(1).name("Janet").<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
}
@@ -0,0 +1,260 @@
/*
* Copyright 2000-2015 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.completion.builder
class GrDefaultBuilderStrategyOnFactoryMethodTest extends GrBuilderTransformationCompletionTestBase {
void 'test no builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy)
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.<caret>
''', 'builder'
}
void 'test custom builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, builderMethodName = 'customBuilderMethod')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.<caret>
''', 'customBuilderMethod'
}
void 'test null builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, builderMethodName = null)
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.<caret>
''', 'builder'
}
void 'test empty builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, builderMethodName = '')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.<caret>
''', 'builder'
}
void 'test spaces builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, builderMethodName = ' ')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.<caret>
''', ' '
}
void 'test no prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy)
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test empty prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, prefix = '')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test custom prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, prefix = 'customPrefix')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', 'build', 'customPrefixName', 'customPrefixDynamic', 'customPrefixCounter'
}
void 'test spaces prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, prefix = ' ')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', 'build', ' Name', ' Dynamic', ' Counter'
}
void 'test null prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, prefix = null)
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test custom build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, buildMethodName = 'customBuild')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', 'customBuild', 'name', 'dynamic', 'counter'
}
void 'test null build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, buildMethodName = null)
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test empty build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, buildMethodName = '')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test spaces build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy, buildMethodName = ' ')
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().<caret>
''', ' ', 'name', 'dynamic', 'counter'
}
void 'test next setter'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy)
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().counter(1).<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test one more setter further'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class Pojo {
@Builder(builderStrategy = DefaultStrategy)
static Pojo someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().counter(1).name("Janet").<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test other return type'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.DefaultStrategy
class OtherClass { def a,b,c }
class Pojo {
@Builder(builderStrategy = DefaultStrategy)
static OtherClass someLongMethodName(def dynamic, int counter, String name) {}
}
Pojo.builder().build().<caret>
''', 'a', 'b', 'c'
}
}
@@ -0,0 +1,305 @@
/*
* Copyright 2000-2015 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.completion.builder
import groovy.transform.CompileStatic
@CompileStatic
class GrDefaultBuilderStrategyTest extends GrBuilderTransformationCompletionTestBase {
void "test no builder method"() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', 'builder')
}
void 'test custom builder method'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(builderMethodName = 'customBuilderMethod')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', 'customBuilderMethod')
}
/**
* The class even won't be compiled.
* Separate inspection highlights such code and offers to remove the parameter.
*/
void 'test null builder method'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(builderMethodName = null)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.b<caret>
''', 'builder')
}
/**
* Class will be compiled but there will be runtime error.
*/
void 'test empty builder method'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(builderMethodName = '')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', 'builder')
}
/**
* I do not know what to say here!
*/
void 'test spaces builder method'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(builderMethodName = ' ')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', ' ')
}
void 'test no prefix'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter')
}
void 'test empty prefix'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(prefix = '')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter')
}
void 'test custom prefix'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(prefix = 'customPrefix')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', 'build', 'customPrefixName', 'customPrefixDynamic', 'customPrefixCounter')
}
void 'test spaces prefix'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(prefix = ' ')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', 'build', ' Name', ' Dynamic', ' Counter')
}
void 'test null prefix'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(prefix = null)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter')
}
void 'test custom build method'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(buildMethodName = 'customBuild')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', 'customBuild', 'name', 'dynamic', 'counter')
}
void 'test null build method'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(buildMethodName = null)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter')
}
void 'test empty build method'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(buildMethodName = '')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', 'build', 'name', 'dynamic', 'counter')
}
void 'test spaces build method'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder(buildMethodName = ' ')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().<caret>
''', ' ', 'name', 'dynamic', 'counter')
}
void 'test next setter'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().counter(1).<caret>
''', 'build', 'name', 'dynamic', 'counter')
}
void 'test one more setter further'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
@Builder
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.builder().counter(1).name("Janet").<caret>
''', 'build', 'name', 'dynamic', 'counter')
}
}
@@ -0,0 +1,266 @@
/*
* Copyright 2000-2015 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.completion.builder
import groovy.transform.CompileStatic
import org.jetbrains.plugins.groovy.completion.CompletionResult
@CompileStatic
class GrExternalBuilderStrategyTest extends GrBuilderTransformationCompletionTestBase {
void 'test no class'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy)
class PojoBuilder {}
new PojoBuilder().<caret>
''', CompletionResult.notContain, 'build', 'name', 'dynamic', 'counter'
}
void 'test no prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo)
class PojoBuilder {}
new PojoBuilder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test empty prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo, prefix = '')
class PojoBuilder {}
new PojoBuilder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test custom prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo, prefix = 'customPrefix')
class PojoBuilder {}
new PojoBuilder().<caret>
''', 'build', 'customPrefixName', 'customPrefixDynamic', 'customPrefixCounter'
}
void 'test spaces prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo, prefix = ' ')
class PojoBuilder {}
new PojoBuilder().<caret>
''', 'build', ' Name', ' Dynamic', ' Counter'
}
void 'test null prefix'() {
doVariantableTest('''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo, prefix = null)
class PojoBuilder {}
new PojoBuilder().<caret>
''', 'build', 'name', 'dynamic', 'counter')
}
void 'test custom build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo, buildMethodName = 'customBuild')
class PojoBuilder {}
new PojoBuilder().<caret>
''', 'customBuild', 'name', 'dynamic', 'counter'
}
void 'test null build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo, buildMethodName = null)
class PojoBuilder {}
new PojoBuilder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test empty build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo, buildMethodName = '')
class PojoBuilder {}
new PojoBuilder().<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test spaces build method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo, buildMethodName = ' ')
class PojoBuilder {}
new PojoBuilder().<caret>
''', ' ', 'name', 'dynamic', 'counter'
}
void 'test next setter'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
@Builder
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo)
class PojoBuilder {}
new PojoBuilder().counter(1).<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
void 'test one more setter further'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.ExternalStrategy
@Builder
class Pojo {
String name
def dynamic
int counter
def method() {}
}
@Builder(builderStrategy = ExternalStrategy, forClass = Pojo)
class PojoBuilder {}
new PojoBuilder().counter(1).name("Janet").<caret>
''', 'build', 'name', 'dynamic', 'counter'
}
}
@@ -0,0 +1,180 @@
/*
* Copyright 2000-2015 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.completion.builder
import groovy.transform.CompileStatic
@CompileStatic
class GrInitializerBuilderStrategyOnConstructorTest extends GrBuilderTransformationCompletionTestBase {
void 'test no builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy)
Pojo(name, dynamic, counter) {}
}
Pojo.<caret>
''', 'createInitializer'
}
void 'test custom builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy, builderMethodName = 'customBuilderMethod')
Pojo(name, dynamic, counter) {}
}
Pojo.<caret>
''', 'customBuilderMethod'
}
void 'test null builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy, builderMethodName = null)
Pojo(name, dynamic, counter) {}
}
Pojo.<caret>
''', 'createInitializer'
}
void 'test empty builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy, builderMethodName = '')
Pojo(name, dynamic, counter) {}
}
Pojo.<caret>
''', 'createInitializer'
}
void 'test spaces builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy, builderMethodName = ' ')
Pojo(name, dynamic, counter) {}
}
Pojo.<caret>
''', ' '
}
void 'test empty prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy, prefix = '')
Pojo(name, dynamic, counter) {}
}
Pojo.createInitializer().<caret>
''', 'name', 'dynamic', 'counter'
}
void 'test custom prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy, prefix = 'customPrefix')
Pojo(name, dynamic, counter) {}
}
Pojo.createInitializer().<caret>
''', 'customPrefixName', 'customPrefixDynamic', 'customPrefixCounter'
}
void 'test spaces prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy, prefix = ' ')
Pojo(name, dynamic, counter) {}
}
Pojo.createInitializer().<caret>
''', ' Name', ' Dynamic', ' Counter'
}
void 'test null prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy, prefix = null)
Pojo(name, dynamic, counter) {}
}
Pojo.createInitializer().<caret>
''', 'name', 'dynamic', 'counter'
}
void 'test next setter'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy)
Pojo(name, dynamic, counter) {}
}
Pojo.createInitializer().counter(1).<caret>
''', 'name', 'dynamic', 'counter'
}
void 'test one more setter further'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
class Pojo {
@Builder(builderStrategy = InitializerStrategy)
Pojo(name, dynamic, counter) {}
}
Pojo.createInitializer().counter(1).name("Janet").<caret>
''', 'name', 'dynamic', 'counter'
}
}
@@ -0,0 +1,220 @@
/*
* Copyright 2000-2015 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.completion.builder
import groovy.transform.CompileStatic
@CompileStatic
class GrInitializerBuilderStrategyTest extends GrBuilderTransformationCompletionTestBase {
void 'test no builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', 'createInitializer'
}
void 'test custom builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy, builderMethodName = 'customBuilderMethod')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', 'customBuilderMethod'
}
void 'test null builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy, builderMethodName = null)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', 'createInitializer'
}
void 'test empty builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy, builderMethodName = '')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', 'createInitializer'
}
void 'test spaces builder method'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy, builderMethodName = ' ')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.<caret>
''', ' '
}
void 'test empty prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy, prefix = '')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.createInitializer().<caret>
''', 'name', 'dynamic', 'counter'
}
void 'test custom prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy, prefix = 'customPrefix')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.createInitializer().<caret>
''', 'customPrefixName', 'customPrefixDynamic', 'customPrefixCounter'
}
void 'test spaces prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy, prefix = ' ')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.createInitializer().<caret>
''', ' Name', ' Dynamic', ' Counter'
}
void 'test null prefix'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy, prefix = null)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.createInitializer().<caret>
''', 'name', 'dynamic', 'counter'
}
void 'test next setter'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.createInitializer().counter(1).<caret>
''', 'name', 'dynamic', 'counter'
}
void 'test one more setter further'() {
doVariantableTest '''\
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
Pojo.createInitializer().counter(1).name("Janet").<caret>
''', 'name', 'dynamic', 'counter'
}
}
@@ -0,0 +1,201 @@
/*
* Copyright 2000-2015 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.completion.builder
import groovy.transform.CompileStatic
import org.jetbrains.plugins.groovy.completion.CompletionResult
@CompileStatic
class GrSimpleBuilderStrategyTest extends GrBuilderTransformationCompletionTestBase {
void 'test no prefix'() {
doVariantableTest('''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().<caret>
''', 'setName', 'setDynamic', 'setCounter', 'method')
doVariantableTest('''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().<caret>
''', CompletionResult.notContain, 'build')
}
void 'test empty prefix'() {
doVariantableTest('''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy, prefix = '')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().<caret>
''', 'name', 'dynamic', 'counter', 'method')
}
void 'test custom prefix'() {
doVariantableTest '''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy, prefix = 'custom')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().<caret>
''', 'customName', 'customDynamic', 'customCounter', 'method'
}
void 'test null prefix'() {
doVariantableTest '''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy, prefix = null)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().<caret>
''', 'setName', 'setDynamic', 'setCounter', 'method'
}
void 'test spaces prefix'() {
doVariantableTest '''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy, prefix = ' ')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().<caret>
''', ' Name', ' Dynamic', ' Counter', 'method'
}
void 'test next setter'() {
doVariantableTest '''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().setName("Janet").<caret>
''', 'setName', 'setDynamic', 'setCounter', 'method'
}
void 'test one more setter further'() {
doVariantableTest '''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy)
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().setName("Janet").setCounter(35).<caret>
''', 'setName', 'setDynamic', 'setCounter', 'method'
}
void 'test next setter with prefix'() {
doVariantableTest '''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy, prefix = 'lol')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().lolName("Janet").<caret>
''', 'lolName', 'lolDynamic', 'lolCounter', 'method'
}
void 'test one more setter further with prefix'() {
doVariantableTest '''
import groovy.transform.builder.Builder
import groovy.transform.builder.SimpleStrategy
@Builder(builderStrategy = SimpleStrategy, prefix = 'lol')
class Pojo {
String name
def dynamic
int counter
def method() {}
}
new Pojo().lolName("Janet").lolCounter(35).<caret>
''', 'lolName', 'lolDynamic', 'lolCounter', 'method'
}
}
@@ -36,7 +36,7 @@ abstract class TypeInferenceTestBase extends GroovyResolveTestCase {
myFixture.addClass("package java.math; public class BigDecimal extends Number implements Comparable<BigDecimal> {}");
}
protected void doTest(@Language("Groovy") String text, @Nullable String type) {
protected void doTest(String text, @Nullable String type) {
def file = myFixture.configureByText('_.groovy', text)
def ref = file.findReferenceAt(myFixture.editor.caretModel.offset) as GrReferenceExpression
def actual = ref.type
@@ -21,12 +21,13 @@ import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.jetbrains.python.psi.PyElement;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class PyGotoTargetRendererProvider implements GotoTargetRendererProvider {
public PsiElementListCellRenderer getRenderer(final PsiElement element, GotoTargetHandler.GotoData gotoData) {
public PsiElementListCellRenderer getRenderer(@NotNull final PsiElement element, @NotNull GotoTargetHandler.GotoData gotoData) {
if (element instanceof PyElement && element instanceof PsiNamedElement) return new PyElementListCellRenderer();
return null;
}
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.xml.XmlTagImpl;
import com.intellij.psi.xml.XmlAttribute;
import org.jetbrains.annotations.NotNull;
/**
* Created with IntelliJ IDEA.
@@ -31,7 +32,7 @@ import com.intellij.psi.xml.XmlAttribute;
*/
public class GotoXmlSchemaTypeRendererProvider implements GotoTargetRendererProvider {
@Override
public PsiElementListCellRenderer getRenderer(PsiElement element, GotoTargetHandler.GotoData gotoData) {
public PsiElementListCellRenderer getRenderer(@NotNull PsiElement element, @NotNull GotoTargetHandler.GotoData gotoData) {
if (element instanceof XmlTagImpl) {
if (SchemaDefinitionsSearch.isTypeElement((XmlTagImpl)element)) {
return new MyRenderer("");