mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
@@ -207,16 +207,18 @@ public class RequestHint {
|
||||
|
||||
if (myDepth == StepRequest.STEP_INTO) {
|
||||
final DebuggerSettings settings = DebuggerSettings.getInstance();
|
||||
if (settings.SKIP_SYNTHETIC_METHODS) {
|
||||
final StackFrameProxyImpl frameProxy = context.getFrameProxy();
|
||||
Location location = frameProxy.location();
|
||||
Method method = location.method();
|
||||
final StackFrameProxyImpl frameProxy = context.getFrameProxy();
|
||||
|
||||
if (settings.SKIP_SYNTHETIC_METHODS && frameProxy != null) {
|
||||
final Location location = frameProxy.location();
|
||||
final Method method = location.method();
|
||||
if (method != null) {
|
||||
if (myVirtualMachineProxy.canGetSyntheticAttribute()? method.isSynthetic() : method.name().indexOf('$') >= 0) {
|
||||
return myDepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!myIgnoreFilters) {
|
||||
if(settings.SKIP_GETTERS) {
|
||||
boolean isGetter = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>(){
|
||||
@@ -231,18 +233,20 @@ public class RequestHint {
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.SKIP_CONSTRUCTORS) {
|
||||
Location location = context.getFrameProxy().location();
|
||||
Method method = location.method();
|
||||
if (method != null && method.isConstructor()) {
|
||||
return StepRequest.STEP_OUT;
|
||||
if (frameProxy != null) {
|
||||
if (settings.SKIP_CONSTRUCTORS) {
|
||||
final Location location = frameProxy.location();
|
||||
final Method method = location.method();
|
||||
if (method != null && method.isConstructor()) {
|
||||
return StepRequest.STEP_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.SKIP_CLASSLOADERS) {
|
||||
Location location = context.getFrameProxy().location();
|
||||
if (DebuggerUtilsEx.isAssignableFrom("java.lang.ClassLoader", location.declaringType())) {
|
||||
return StepRequest.STEP_OUT;
|
||||
if (settings.SKIP_CLASSLOADERS) {
|
||||
final Location location = frameProxy.location();
|
||||
if (DebuggerUtilsEx.isAssignableFrom("java.lang.ClassLoader", location.declaringType())) {
|
||||
return StepRequest.STEP_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +102,11 @@ public class ShowContainerInfoHandler implements CodeInsightActionHandler {
|
||||
final PsiElement _container = container;
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
LightweightHint hint = EditorFragmentComponent.showEditorFragmentHint(editor, range, true);
|
||||
hint.putUserData(CONTAINER_KEY, _container);
|
||||
editor.putUserData(MY_LAST_HINT_KEY, new WeakReference<LightweightHint>(hint));
|
||||
LightweightHint hint = EditorFragmentComponent.showEditorFragmentHint(editor, range, true, true);
|
||||
if (hint != null) {
|
||||
hint.putUserData(CONTAINER_KEY, _container);
|
||||
editor.putUserData(MY_LAST_HINT_KEY, new WeakReference<LightweightHint>(hint));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package com.intellij.ide;
|
||||
|
||||
import com.intellij.application.options.codeStyle.LanguageCodeStyleSettingsProvider;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -25,8 +25,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider {
|
||||
@Override
|
||||
public LanguageFileType getLanguageFileType() {
|
||||
return StdFileTypes.JAVA;
|
||||
public Language getLanguage() {
|
||||
return StdLanguages.JAVA;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.augment.PsiAugmentProvider;
|
||||
import com.intellij.psi.impl.InheritanceImplUtil;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
@@ -50,6 +51,7 @@ import com.intellij.psi.stubs.IStubElementType;
|
||||
import com.intellij.psi.stubs.PsiFileStub;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -300,12 +302,16 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
|
||||
|
||||
@NotNull
|
||||
public PsiField[] getFields() {
|
||||
return getStubOrPsiChildren(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY);
|
||||
final PsiField[] owns = getStubOrPsiChildren(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY);
|
||||
final List<PsiField> augments = PsiAugmentProvider.collectAugments(this, PsiField.class);
|
||||
return ArrayUtil.mergeArrayAndCollection(owns, augments, PsiField.ARRAY_FACTORY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiMethod[] getMethods() {
|
||||
return getStubOrPsiChildren(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY);
|
||||
final PsiMethod[] owns = getStubOrPsiChildren(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY);
|
||||
final List<PsiMethod> augments = PsiAugmentProvider.collectAugments(this, PsiMethod.class);
|
||||
return ArrayUtil.mergeArrayAndCollection(owns, augments, PsiMethod.ARRAY_FACTORY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -93,7 +93,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public final PsiIdentifier getNameIdentifier(){
|
||||
public PsiIdentifier getNameIdentifier() {
|
||||
return (PsiIdentifier)getNode().findChildByRoleAsPsiElement(ChildRole.NAME);
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -545,7 +545,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
|
||||
final boolean preserveQualification = CodeStyleSettingsManager.getSettings(getProject()).USE_FQ_CLASS_NAMES && isFullyQualified();
|
||||
final PsiManager manager = aClass.getManager();
|
||||
String text = qName + getParameterList().getText();
|
||||
final PsiReferenceParameterList parameterList = getParameterList();
|
||||
String text = (parameterList != null ? qName + parameterList.getText() : qName);
|
||||
ASTNode ref = Parsing.parseJavaCodeReferenceText(manager, text, SharedImplUtil.findCharTableByTree(this));
|
||||
LOG.assertTrue(ref != null, "Failed to parse reference from text '" + text + "'");
|
||||
getTreeParent().replaceChildInternal(this, (TreeElement)ref);
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.daemon.impl.analysis.AnnotationsHighlightUtil;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.augment.PsiAugmentProvider;
|
||||
import com.intellij.psi.impl.CheckUtil;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.cache.ModifierFlags;
|
||||
@@ -29,6 +30,7 @@ import com.intellij.psi.impl.source.tree.Factory;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -254,7 +256,9 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
|
||||
|
||||
@NotNull
|
||||
public PsiAnnotation[] getAnnotations() {
|
||||
return getStubOrPsiChildren(JavaStubElementTypes.ANNOTATION, PsiAnnotation.ARRAY_FACTORY);
|
||||
final PsiAnnotation[] owns = getStubOrPsiChildren(JavaStubElementTypes.ANNOTATION, PsiAnnotation.ARRAY_FACTORY);
|
||||
final List<PsiAnnotation> augments = PsiAugmentProvider.collectAugments(this, PsiAnnotation.class);
|
||||
return ArrayUtil.mergeArrayAndCollection(owns, augments, PsiAnnotation.ARRAY_FACTORY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -18,13 +18,17 @@ package com.intellij.psi.impl.source;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.augment.PsiAugmentProvider;
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassReferenceListStub;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.stubs.IStubElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class PsiReferenceListImpl extends JavaStubPsiElement<PsiClassReferenceListStub> implements PsiReferenceList {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiReferenceListImpl");
|
||||
private static final TokenSet REFERENCE_BIT_SET = TokenSet.create(Constants.JAVA_CODE_REFERENCE);
|
||||
@@ -39,7 +43,10 @@ public final class PsiReferenceListImpl extends JavaStubPsiElement<PsiClassRefer
|
||||
|
||||
@NotNull
|
||||
public PsiJavaCodeReferenceElement[] getReferenceElements() {
|
||||
return calcTreeElement().getChildrenAsPsiElements(REFERENCE_BIT_SET, Constants.PSI_REFERENCE_ELEMENT_ARRAY_CONSTRUCTOR);
|
||||
final PsiJavaCodeReferenceElement[] owns =
|
||||
calcTreeElement().getChildrenAsPsiElements(REFERENCE_BIT_SET, Constants.PSI_REFERENCE_ELEMENT_ARRAY_CONSTRUCTOR);
|
||||
final List<PsiJavaCodeReferenceElement> augments = PsiAugmentProvider.collectAugments(this, PsiJavaCodeReferenceElement.class);
|
||||
return ArrayUtil.mergeArrayAndCollection(owns, augments, PsiJavaCodeReferenceElement.ARRAY_FACTORY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -469,6 +469,20 @@ public class DeclarationParsing extends Parsing {
|
||||
return first;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CompositeElement parseAnnotationParamsFromText(PsiManager manager, CharSequence text, final LanguageLevel languageLevel) {
|
||||
Lexer originalLexer = new JavaLexer(languageLevel);
|
||||
FilterLexer lexer = new FilterLexer(originalLexer, new FilterLexer.SetFilter(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET));
|
||||
lexer.start(text);
|
||||
CompositeElement first = parseAnnotationParameterList(lexer);
|
||||
|
||||
final FileElement dummyRoot = DummyHolderFactory.createHolder(manager, null, myContext.getCharTable()).getTreeElement();
|
||||
dummyRoot.rawAddChildren(first);
|
||||
|
||||
ParseUtil.insertMissingTokens(dummyRoot, originalLexer, 0, text.length(), -1, WhiteSpaceAndCommentsProcessor.INSTANCE, myContext);
|
||||
return first;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
CompositeElement parseAnnotation(Lexer lexer) {
|
||||
CompositeElement annotation = ASTFactory.composite(JavaElementType.ANNOTATION);
|
||||
|
||||
@@ -54,7 +54,6 @@ public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> imp
|
||||
return (PsiJavaCodeReferenceElement)getMirrorTreeElement().findChildByRoleAsPsiElement(ChildRole.CLASS_REFERENCE);
|
||||
}
|
||||
|
||||
|
||||
private CompositeElement getMirrorTreeElement() {
|
||||
final PsiAnnotationStub stub = getStub();
|
||||
if (stub != null) {
|
||||
|
||||
@@ -126,8 +126,8 @@ public class PsiNameValuePairImpl extends CompositePsiElement implements PsiName
|
||||
public PsiReference getReference() {
|
||||
return new PsiReference() {
|
||||
private PsiClass getReferencedClass () {
|
||||
LOG.assertTrue(getTreeParent().getElementType() == ANNOTATION_PARAMETER_LIST && getTreeParent().getTreeParent().getElementType() == ANNOTATION);
|
||||
PsiAnnotationImpl annotation = (PsiAnnotationImpl)getTreeParent().getTreeParent().getPsi();
|
||||
LOG.assertTrue(getParent() instanceof PsiAnnotationParameterList && getParent().getParent() instanceof PsiAnnotation);
|
||||
PsiAnnotation annotation = (PsiAnnotation)getParent().getParent();
|
||||
PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
|
||||
return nameRef == null ? null : (PsiClass)nameRef.resolve();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.util.ArrayFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -28,6 +29,12 @@ public interface PsiJavaCodeReferenceElement extends PsiJavaReference, PsiQualif
|
||||
*/
|
||||
PsiJavaCodeReferenceElement[] EMPTY_ARRAY = new PsiJavaCodeReferenceElement[0];
|
||||
|
||||
ArrayFactory<PsiJavaCodeReferenceElement> ARRAY_FACTORY = new ArrayFactory<PsiJavaCodeReferenceElement>() {
|
||||
public PsiJavaCodeReferenceElement[] create(int count) {
|
||||
return count == 0 ? EMPTY_ARRAY : new PsiJavaCodeReferenceElement[count];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the element representing the name of the referenced element.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.augment;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public abstract class PsiAugmentProvider {
|
||||
public static final ExtensionPointName<PsiAugmentProvider> EP_NAME = ExtensionPointName.create("com.intellij.lang.psiAugmentProvider");
|
||||
|
||||
private static final PsiAugmentProvider[] PROVIDERS = Extensions.getExtensions(EP_NAME);
|
||||
|
||||
@NotNull
|
||||
public abstract <Psi extends PsiElement> List<Psi> getAugments(@NotNull PsiElement element, @NotNull Class<Psi> type);
|
||||
|
||||
@NotNull
|
||||
public static <Psi extends PsiElement> List<Psi> collectAugments(@NotNull final PsiElement element, @NotNull final Class<Psi> type) {
|
||||
final List<Psi> augments = new ArrayList<Psi>();
|
||||
for (PsiAugmentProvider provider : PROVIDERS) {
|
||||
final List<Psi> list = provider.getAugments(element, type);
|
||||
augments.addAll(list);
|
||||
}
|
||||
|
||||
return augments;
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,13 @@ package com.intellij.codeInspection;
|
||||
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.ExternallyDefinedPsiElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -58,11 +62,17 @@ public class ProblemsHolder {
|
||||
}
|
||||
|
||||
public void registerProblem(@NotNull ProblemDescriptor problemDescriptor) {
|
||||
if (myProblems == null) {
|
||||
myProblems = new ArrayList<ProblemDescriptor>(1);
|
||||
}
|
||||
PsiElement element = problemDescriptor.getPsiElement();
|
||||
if (element != null && !isInPsiFile(element)) {
|
||||
ExternallyDefinedPsiElement external = PsiTreeUtil.getParentOfType(element, ExternallyDefinedPsiElement.class, false);
|
||||
if (external != null) {
|
||||
PsiElement newTarget = external.getProblemTarget();
|
||||
if (newTarget != null) {
|
||||
redirectProblem(problemDescriptor, newTarget);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PsiFile containingFile = element.getContainingFile();
|
||||
PsiElement context = containingFile.getContext();
|
||||
PsiElement myContext = myFile.getContext();
|
||||
@@ -71,6 +81,10 @@ public class ProblemsHolder {
|
||||
+"Inspection invoked for file: "+ myFile +"; context: "+(myContext == null ? null : myContext.getContainingFile())+"\n"
|
||||
);
|
||||
}
|
||||
|
||||
if (myProblems == null) {
|
||||
myProblems = new ArrayList<ProblemDescriptor>(1);
|
||||
}
|
||||
myProblems.add(problemDescriptor);
|
||||
}
|
||||
|
||||
@@ -79,6 +93,31 @@ public class ProblemsHolder {
|
||||
return ArrayUtil.indexOf(myFile.getPsiRoots(), file) != -1;
|
||||
}
|
||||
|
||||
private void redirectProblem(@NotNull final ProblemDescriptor problem, @NotNull final PsiElement target) {
|
||||
final PsiElement original = problem.getPsiElement();
|
||||
final VirtualFile vFile = original.getContainingFile().getVirtualFile();
|
||||
assert vFile != null;
|
||||
final String path = FileUtil.toSystemIndependentName(vFile.getPath());
|
||||
|
||||
String description = problem.getDescriptionTemplate();
|
||||
if (description.startsWith("<html>")) {
|
||||
description = description.replace("<html>", "").replace("</html>", "");
|
||||
}
|
||||
if (description.startsWith("<body>")) {
|
||||
description = description.replace("<body>", "").replace("</body>", "");
|
||||
}
|
||||
|
||||
final String template =
|
||||
InspectionsBundle.message("inspection.redirect.template",
|
||||
description, path, original.getTextRange().getStartOffset(), vFile.getName());
|
||||
|
||||
|
||||
final InspectionManager manager = InspectionManager.getInstance(original.getProject());
|
||||
final ProblemDescriptor newProblem =
|
||||
manager.createProblemDescriptor(target, template, (LocalQuickFix)null, problem.getHighlightType(), isOnTheFly());
|
||||
registerProblem(newProblem);
|
||||
}
|
||||
|
||||
public void registerProblem(@NotNull PsiReference reference, String descriptionTemplate, ProblemHighlightType highlightType) {
|
||||
LocalQuickFix[] fixes = null;
|
||||
if (reference instanceof LocalQuickFixProvider) {
|
||||
|
||||
@@ -68,7 +68,7 @@ public class PsiFilePattern<T extends PsiFile, Self extends PsiFilePattern<T, Se
|
||||
super(aClass);
|
||||
}
|
||||
|
||||
protected Capture(@NotNull final InitialPatternCondition<T> condition) {
|
||||
public Capture(@NotNull final InitialPatternCondition<T> condition) {
|
||||
super(condition);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,15 @@ public class VirtualFilePattern extends TreeElementPattern<VirtualFile, VirtualF
|
||||
public VirtualFilePattern withName(final String name) {
|
||||
return withName(PlatformPatterns.string().equalTo(name));
|
||||
}
|
||||
|
||||
|
||||
public VirtualFilePattern withExtension(@NotNull final String extension) {
|
||||
return with(new PatternCondition<VirtualFile>("withExtension") {
|
||||
public boolean accepts(@NotNull final VirtualFile virtualFile, final ProcessingContext context) {
|
||||
return extension.equals(virtualFile.getExtension());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public VirtualFilePattern withName(final ElementPattern<String> namePattern) {
|
||||
return with(new PatternCondition<VirtualFile>("withName") {
|
||||
public boolean accepts(@NotNull final VirtualFile virtualFile, final ProcessingContext context) {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for PSI elements which may be injected into other elements but physically belongs
|
||||
* to other file - like AspectJ inter-type fields/methods.
|
||||
*/
|
||||
public interface ExternallyDefinedPsiElement extends PsiElement, SyntheticElement {
|
||||
/**
|
||||
* If inspection started for files with injections founds any problem in them (or their child)
|
||||
* it should be able to display them locally. This method allows to define such substitution element.
|
||||
* E.g. it may be a class name identifier element for fields/methods injected in that class.<br/>
|
||||
* See <code>ProblemsHolder.redirectProblem()</code> for details.
|
||||
*
|
||||
* @return PSI element to which problem descriptions should be redirected
|
||||
*/
|
||||
@Nullable
|
||||
PsiElement getProblemTarget();
|
||||
}
|
||||
@@ -172,6 +172,13 @@ public class PsiTreeUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull public static <T extends PsiElement> T getRequiredChildOfType(@NotNull PsiElement element, @NotNull Class<T> aClass) {
|
||||
final T child = getChildOfType(element, aClass);
|
||||
assert child != null: "Missing required child of type " + aClass.getName();
|
||||
return child;
|
||||
}
|
||||
|
||||
@Nullable public static <T extends PsiElement> T[] getChildrenOfType(@NotNull PsiElement element, @NotNull Class<T> aClass) {
|
||||
List<T> result = null;
|
||||
for(PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()){
|
||||
|
||||
+10
-6
@@ -161,11 +161,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable {
|
||||
myTextToReformat = myEditor.getDocument().getText();
|
||||
}
|
||||
|
||||
Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
|
||||
if (project == null) {
|
||||
project = ProjectManager.getInstance().getDefaultProject();
|
||||
}
|
||||
final Project finalProject = project;
|
||||
final Project finalProject = getCurrentProject();
|
||||
CommandProcessor.getInstance().executeCommand(finalProject, new Runnable() {
|
||||
public void run() {
|
||||
replaceText(finalProject);
|
||||
@@ -218,6 +214,14 @@ public abstract class CodeStyleAbstractPanel implements Disposable {
|
||||
return psiFile;
|
||||
}
|
||||
|
||||
protected Project getCurrentProject() {
|
||||
Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
|
||||
if (project == null) {
|
||||
project = ProjectManager.getInstance().getDefaultProject();
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract FileType getFileType();
|
||||
|
||||
@@ -249,7 +253,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable {
|
||||
|
||||
public abstract JComponent getPanel();
|
||||
|
||||
public final void dispose() {
|
||||
public void dispose() {
|
||||
myUpdateAlarm.cancelAllRequests();
|
||||
EditorFactory.getInstance().releaseEditor(myEditor);
|
||||
}
|
||||
|
||||
+6
-6
@@ -19,9 +19,9 @@ package com.intellij.application.options.codeStyle;
|
||||
import com.intellij.application.options.ExportSchemeAction;
|
||||
import com.intellij.application.options.SaveSchemeDialog;
|
||||
import com.intellij.application.options.SchemesToImportPopup;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.options.SchemesManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.codeStyle.CodeStyleScheme;
|
||||
@@ -166,8 +166,8 @@ public class CodeStyleSchemesPanel{
|
||||
});
|
||||
}
|
||||
});
|
||||
for(LanguageFileType fileType : LanguageCodeStyleSettingsProvider.getLanguageFileTypes()) {
|
||||
myLanguageCombo.addItem(fileType.getLanguage().getDisplayName());
|
||||
for(Language language : LanguageCodeStyleSettingsProvider.getLanguagesWithCodeStyleSettings()) {
|
||||
myLanguageCombo.addItem(language.getDisplayName());
|
||||
}
|
||||
myLanguageLabel.setVisible(false);
|
||||
myLanguageCombo.setVisible(false);
|
||||
@@ -334,9 +334,9 @@ public class CodeStyleSchemesPanel{
|
||||
private void onLanguageCombo() {
|
||||
Object selection = myLanguageCombo.getSelectedItem();
|
||||
if (selection instanceof String) {
|
||||
LanguageFileType fileType = LanguageCodeStyleSettingsProvider.getFileType((String)selection);
|
||||
if (fileType != null && mySettingsPanel != null) {
|
||||
mySettingsPanel.setLanguage(fileType.getLanguage());
|
||||
Language language = LanguageCodeStyleSettingsProvider.getLanguage((String)selection);
|
||||
if (language != null && mySettingsPanel != null) {
|
||||
mySettingsPanel.setLanguage(language);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-10
@@ -18,7 +18,6 @@ package com.intellij.application.options.codeStyle;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -38,31 +37,31 @@ public abstract class LanguageCodeStyleSettingsProvider {
|
||||
public static final ExtensionPointName<LanguageCodeStyleSettingsProvider> EP_NAME =
|
||||
ExtensionPointName.create("com.intellij.langCodeStyleSettingsProvider");
|
||||
|
||||
public abstract LanguageFileType getLanguageFileType();
|
||||
public abstract Language getLanguage();
|
||||
|
||||
public abstract String getCodeSample(@NotNull SettingsType settingsType);
|
||||
|
||||
public static LanguageFileType[] getLanguageFileTypes() {
|
||||
ArrayList<LanguageFileType> langFileTypes = new ArrayList<LanguageFileType>();
|
||||
public static Language[] getLanguagesWithCodeStyleSettings() {
|
||||
ArrayList<Language> langs = new ArrayList<Language>();
|
||||
for (LanguageCodeStyleSettingsProvider provider : Extensions.getExtensions(EP_NAME)) {
|
||||
langFileTypes.add(provider.getLanguageFileType());
|
||||
langs.add(provider.getLanguage());
|
||||
}
|
||||
return langFileTypes.toArray(new LanguageFileType[langFileTypes.size()]);
|
||||
return langs.toArray(new Language[langs.size()]);
|
||||
}
|
||||
|
||||
public static @Nullable String getCodeSample(Language lang, @NotNull SettingsType settingsType) {
|
||||
for (LanguageCodeStyleSettingsProvider provider : Extensions.getExtensions(EP_NAME)) {
|
||||
if (provider.getLanguageFileType().getLanguage().equals(lang)) {
|
||||
if (provider.getLanguage().equals(lang)) {
|
||||
return provider.getCodeSample(settingsType);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static @Nullable LanguageFileType getFileType(String langName) {
|
||||
public static @Nullable Language getLanguage(String langName) {
|
||||
for (LanguageCodeStyleSettingsProvider provider : Extensions.getExtensions(EP_NAME)) {
|
||||
if (langName.equals(provider.getLanguageFileType().getLanguage().getDisplayName())) {
|
||||
return provider.getLanguageFileType();
|
||||
if (langName.equals(provider.getLanguage().getDisplayName())) {
|
||||
return provider.getLanguage();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
+50
-4
@@ -30,6 +30,8 @@ import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
@@ -39,6 +41,8 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Base class for code style settings panels supporting multiple programming languages.
|
||||
*
|
||||
@@ -48,9 +52,13 @@ public abstract class MultilanguageCodeStyleAbstractPanel extends CodeStyleAbstr
|
||||
|
||||
private Language myLanguage;
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.codeStyle.MultilanguageCodeStyleAbstractPanel");
|
||||
private static Project mySettingsProject;
|
||||
private static int myInstanceCount;
|
||||
|
||||
protected MultilanguageCodeStyleAbstractPanel(CodeStyleSettings settings) {
|
||||
super(settings);
|
||||
createSettingsProject();
|
||||
myInstanceCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,10 +88,11 @@ public abstract class MultilanguageCodeStyleAbstractPanel extends CodeStyleAbstr
|
||||
if (myLanguage != null) {
|
||||
return myLanguage.getAssociatedFileType();
|
||||
}
|
||||
LanguageFileType availTypes[] = LanguageCodeStyleSettingsProvider.getLanguageFileTypes();
|
||||
if (availTypes.length > 0) {
|
||||
myLanguage = availTypes[0].getLanguage();
|
||||
return availTypes[0];
|
||||
Language langs[] = LanguageCodeStyleSettingsProvider.getLanguagesWithCodeStyleSettings();
|
||||
if (langs.length > 0) {
|
||||
myLanguage = langs[0];
|
||||
FileType type = langs[0].getAssociatedFileType();
|
||||
if (type != null) return type;
|
||||
}
|
||||
return StdFileTypes.JAVA;
|
||||
}
|
||||
@@ -130,4 +139,41 @@ public abstract class MultilanguageCodeStyleAbstractPanel extends CodeStyleAbstr
|
||||
manager.commitDocument(doc);
|
||||
return psiFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final synchronized Project getCurrentProject() {
|
||||
return mySettingsProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
myInstanceCount--;
|
||||
if (myInstanceCount == 0) {
|
||||
disposeSettingsProject();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* A physical settings project is created to ensure that all formatters in preview panels work correctly.
|
||||
*/
|
||||
private synchronized static void createSettingsProject() {
|
||||
if (mySettingsProject != null) return;
|
||||
try {
|
||||
File tempFile = File.createTempFile("idea-", "-settings.tmp");
|
||||
tempFile.deleteOnExit();
|
||||
mySettingsProject = ProjectManagerEx.getInstanceEx().newProject("settings.tmp", tempFile.getPath(), true, false);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void disposeSettingsProject() {
|
||||
if (mySettingsProject == null) return;
|
||||
Disposer.dispose(mySettingsProject);
|
||||
mySettingsProject = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec
|
||||
myCurrentHint = null;
|
||||
}
|
||||
TextRange textRange = new TextRange(textOffset, fold.getStartOffset());
|
||||
hint = EditorFragmentComponent.showEditorFragmentHint(editor, textRange, true);
|
||||
hint = EditorFragmentComponent.showEditorFragmentHint(editor, textRange, true, true);
|
||||
myCurrentFold = fold;
|
||||
myCurrentHint = hint;
|
||||
}
|
||||
|
||||
+1
-1
@@ -393,7 +393,7 @@ public class BraceHighlightingHandler {
|
||||
int line2 = myDocument.getLineNumber(range.getEndOffset());
|
||||
line1 = Math.max(line1, line2 - 5);
|
||||
range = new TextRange(myDocument.getLineStartOffset(line1), range.getEndOffset());
|
||||
EditorFragmentComponent.showEditorFragmentHint(myEditor, range, true);
|
||||
EditorFragmentComponent.showEditorFragmentHint(myEditor, range, true, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.codeInsight.hint;
|
||||
|
||||
import com.intellij.codeInsight.highlighting.TooltipLinkHandler;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
||||
/**
|
||||
* Handles tooltip links in format <code>#navigation/file path:offset</code>.
|
||||
*/
|
||||
public class NavigationLinkHandler extends TooltipLinkHandler {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.hint.NavigationLinkHandler");
|
||||
|
||||
@Override
|
||||
public void handleLink(@NotNull final String suffix, @NotNull final Editor editor, @NotNull final JEditorPane tooltip) {
|
||||
final int pos = suffix.lastIndexOf(':');
|
||||
if (pos <= 0 || pos == suffix.length()-1) {
|
||||
LOG.error("Malformed suffix: " + suffix);
|
||||
return;
|
||||
}
|
||||
|
||||
final String path = suffix.substring(0, pos);
|
||||
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(path);
|
||||
if (vFile == null) {
|
||||
LOG.error("Unknown file: " + path);
|
||||
return;
|
||||
}
|
||||
|
||||
final int offset;
|
||||
try {
|
||||
offset = Integer.parseInt(suffix.substring(pos+1));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
LOG.error("Malformed suffix: " + suffix);
|
||||
return;
|
||||
}
|
||||
|
||||
tooltip.setVisible(false);
|
||||
new OpenFileDescriptor(editor.getProject(), vFile, offset).navigate(true);
|
||||
}
|
||||
}
|
||||
@@ -204,4 +204,8 @@ class LazyEditor extends UserDataHolderBase implements Editor {
|
||||
public JComponent getHeaderComponent() {
|
||||
return getEditor().getHeaderComponent();
|
||||
}
|
||||
|
||||
public IndentGuideDescriptor getCaretIndentGuide() {
|
||||
return getEditor().getCaretIndentGuide();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,4 +596,8 @@ public class EditorWindow implements EditorEx, UserDataHolderEx {
|
||||
int hostOffset = myDocumentWindow.injectedToHost(offset);
|
||||
return myDelegate.calcColumnNumber(myDelegate.getDocument().getText(), hostStart, hostOffset, tabSize);
|
||||
}
|
||||
}
|
||||
|
||||
public IndentGuideDescriptor getCaretIndentGuide() {
|
||||
return null; // Caret guide is purely text-based thing so it is handled at top editor level.
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -24,21 +24,21 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author lesya
|
||||
*/
|
||||
public class AbstractPostFormatProcessor {
|
||||
protected final CodeStyleSettings mySettings;
|
||||
public final CodeStyleSettings mySettings;
|
||||
private TextRange myResultTextRange;
|
||||
|
||||
public AbstractPostFormatProcessor(final CodeStyleSettings settings) {
|
||||
mySettings = settings;
|
||||
}
|
||||
|
||||
protected void updateResultRange(final int oldTextLength, final int newTextLength) {
|
||||
public void updateResultRange(final int oldTextLength, final int newTextLength) {
|
||||
if (myResultTextRange == null) return;
|
||||
|
||||
myResultTextRange = new TextRange(myResultTextRange.getStartOffset(),
|
||||
myResultTextRange.getEndOffset() - oldTextLength + newTextLength);
|
||||
}
|
||||
|
||||
protected boolean checkElementContainsRange(final PsiElement element) {
|
||||
public boolean checkElementContainsRange(final PsiElement element) {
|
||||
if (myResultTextRange == null) return true;
|
||||
|
||||
final TextRange elementRange = element.getTextRange();
|
||||
@@ -47,7 +47,7 @@ public class AbstractPostFormatProcessor {
|
||||
|
||||
}
|
||||
|
||||
protected boolean checkRangeContainsElement(final PsiElement element) {
|
||||
public boolean checkRangeContainsElement(final PsiElement element) {
|
||||
if (myResultTextRange == null) return true;
|
||||
|
||||
final TextRange elementRange = element.getTextRange();
|
||||
@@ -56,7 +56,7 @@ public class AbstractPostFormatProcessor {
|
||||
&& elementRange.getEndOffset() <= myResultTextRange.getEndOffset();
|
||||
}
|
||||
|
||||
protected static boolean isMultiline(@Nullable PsiElement statement) {
|
||||
public static boolean isMultiline(@Nullable PsiElement statement) {
|
||||
if (statement == null) {
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@@ -308,4 +308,7 @@ public interface Editor extends UserDataHolder {
|
||||
*/
|
||||
@Nullable
|
||||
JComponent getHeaderComponent();
|
||||
|
||||
@Nullable
|
||||
IndentGuideDescriptor getCaretIndentGuide();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.openapi.editor;
|
||||
|
||||
public class IndentGuideDescriptor {
|
||||
public final int indentLevel;
|
||||
public final int startLine;
|
||||
public final int endLine;
|
||||
|
||||
public IndentGuideDescriptor(int indentLevel, int startLine, int endLine) {
|
||||
this.indentLevel = indentLevel;
|
||||
this.startLine = startLine;
|
||||
this.endLine = endLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
IndentGuideDescriptor other = (IndentGuideDescriptor)obj;
|
||||
return indentLevel == other.indentLevel && startLine == other.startLine && endLine == other.endLine;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -72,7 +72,7 @@ public class DocumentFragmentTooltipRenderer implements TooltipRenderer {
|
||||
FoldingModelEx foldingModel = (FoldingModelEx)editor.getFoldingModel();
|
||||
foldingModel.setFoldingEnabled(false);
|
||||
TextRange textRange = new TextRange(startOffset, endOffset);
|
||||
hint = EditorFragmentComponent.showEditorFragmentHintAt(editor, textRange, p.x, p.y, false, false);
|
||||
hint = EditorFragmentComponent.showEditorFragmentHintAt(editor, textRange, p.x, p.y, false, false, true);
|
||||
foldingModel.setFoldingEnabled(true);
|
||||
return hint;
|
||||
}
|
||||
|
||||
+12
-10
@@ -121,15 +121,17 @@ public class EditorFragmentComponent extends JPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hideByAnyKey
|
||||
* @param x <code>x</code> coordinate in layered pane coordinate system.
|
||||
* @param y <code>y</code> coordinate in layered pane coordinate system.
|
||||
*/
|
||||
public static LightweightHint showEditorFragmentHintAt(
|
||||
Editor editor,
|
||||
TextRange range,
|
||||
int x,
|
||||
int y,
|
||||
boolean showUpward, boolean showFolding) {
|
||||
public static LightweightHint showEditorFragmentHintAt(Editor editor,
|
||||
TextRange range,
|
||||
int x,
|
||||
int y,
|
||||
boolean showUpward,
|
||||
boolean showFolding,
|
||||
boolean hideByAnyKey) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return null;
|
||||
|
||||
int startLine = editor.offsetToLogicalPosition(range.getStartOffset()).line;
|
||||
@@ -147,7 +149,7 @@ public class EditorFragmentComponent extends JPanel {
|
||||
|
||||
Point p = new Point(x, y);
|
||||
LightweightHint hint = new MyComponentHint(fragmentComponent);
|
||||
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, p, HintManagerImpl.HIDE_BY_ANY_KEY | HintManagerImpl.HIDE_BY_TEXT_CHANGE, 0, false);
|
||||
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, p, (hideByAnyKey ? HintManagerImpl.HIDE_BY_ANY_KEY : 0) | HintManagerImpl.HIDE_BY_TEXT_CHANGE, 0, false);
|
||||
return hint;
|
||||
}
|
||||
|
||||
@@ -166,7 +168,7 @@ public class EditorFragmentComponent extends JPanel {
|
||||
return fragmentComponent;
|
||||
}
|
||||
|
||||
public static LightweightHint showEditorFragmentHint(Editor editor,TextRange range, boolean showFolding){
|
||||
public static LightweightHint showEditorFragmentHint(Editor editor, TextRange range, boolean showFolding, boolean hideByAnyKey){
|
||||
int x = -2;
|
||||
int y = 0;
|
||||
|
||||
@@ -174,7 +176,7 @@ public class EditorFragmentComponent extends JPanel {
|
||||
JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane();
|
||||
Point point = SwingUtilities.convertPoint(editorComponent, x, y, layeredPane);
|
||||
|
||||
return showEditorFragmentHintAt(editor, range, point.x, point.y, true, showFolding);
|
||||
return showEditorFragmentHintAt(editor, range, point.x, point.y, true, showFolding, hideByAnyKey);
|
||||
}
|
||||
|
||||
public static Color getBackgroundColor(Editor editor){
|
||||
@@ -204,4 +206,4 @@ public class EditorFragmentComponent extends JPanel {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public class EditorSettingsExternalizable implements NamedJDOMExternalizable, Ex
|
||||
|
||||
public boolean IS_BLOCK_CURSOR = false;
|
||||
public boolean IS_WHITESPACES_SHOWN = false;
|
||||
public boolean IS_INDENT_GUIDES_SHOWN = false;
|
||||
public boolean IS_INDENT_GUIDES_SHOWN = true;
|
||||
public boolean IS_ANIMATED_SCROLLING = true;
|
||||
public boolean IS_CAMEL_WORDS = false;
|
||||
public boolean ADDITIONAL_PAGE_AT_BOTTOM = false;
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.Patches;
|
||||
import com.intellij.codeInsight.hint.DocumentFragmentTooltipRenderer;
|
||||
import com.intellij.codeInsight.hint.EditorFragmentComponent;
|
||||
import com.intellij.codeInsight.hint.TooltipController;
|
||||
import com.intellij.codeInsight.hint.TooltipGroup;
|
||||
import com.intellij.concurrency.JobScheduler;
|
||||
@@ -60,6 +61,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.ui.GuiUtils;
|
||||
import com.intellij.ui.JScrollPane2;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.IJSwingUtilities;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -224,6 +226,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
private char[] myPrefixText;
|
||||
private TextAttributes myPrefixAttributes;
|
||||
private IndentGuideDescriptor myCaretIndentGuide = null;
|
||||
|
||||
static {
|
||||
ourCaretBlinkingCommand = new RepaintCursorCommand();
|
||||
@@ -282,6 +285,36 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myDocument.addDocumentListener(mySelectionModel);
|
||||
myDocument.addDocumentListener(myEditorDocumentAdapter);
|
||||
|
||||
myCaretModel.addCaretListener(new CaretListener() {
|
||||
LightweightHint myCurrentHint = null;
|
||||
|
||||
public void caretPositionChanged(CaretEvent e) {
|
||||
|
||||
final IndentGuideDescriptor newGuide = getCaretIndentGuide();
|
||||
if (!Comparing.equal(newGuide, myCaretIndentGuide)) {
|
||||
repaintGuide(newGuide);
|
||||
repaintGuide(myCaretIndentGuide);
|
||||
myCaretIndentGuide = newGuide;
|
||||
|
||||
if (myCurrentHint != null) {
|
||||
myCurrentHint.hide();
|
||||
myCurrentHint = null;
|
||||
}
|
||||
|
||||
if (newGuide != null) {
|
||||
final Rectangle visibleArea = getScrollingModel().getVisibleArea();
|
||||
final int line = newGuide.startLine - 1;
|
||||
if (logicalLineToY(line) < visibleArea.y) {
|
||||
TextRange textRange = new TextRange(myDocument.getLineStartOffset(line),
|
||||
myDocument.getLineEndOffset(line));
|
||||
|
||||
myCurrentHint = EditorFragmentComponent.showEditorFragmentHint(EditorImpl.this, textRange, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myCaretCursor = new CaretCursor();
|
||||
|
||||
myFoldingModel.flushCaretShift();
|
||||
@@ -342,6 +375,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
}
|
||||
|
||||
private void repaintGuide(IndentGuideDescriptor guide) {
|
||||
if (guide != null) {
|
||||
repaintLines(guide.startLine, guide.endLine);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPrefixTextAndAttributes(String prefixText, TextAttributes attributes) {
|
||||
myPrefixText = prefixText == null? null: prefixText.toCharArray();
|
||||
myPrefixAttributes = attributes;
|
||||
@@ -1190,7 +1229,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
int y = clip.y;
|
||||
int line = xyToLogicalPosition(new Point(0, y)).line;
|
||||
|
||||
int gapWidth = EditorUtil.getSpaceWidth(Font.PLAIN, this) * getIndentSize();
|
||||
final int indentSize = getIndentSize();
|
||||
int gapWidth = EditorUtil.getSpaceWidth(Font.PLAIN, this) * indentSize;
|
||||
|
||||
do {
|
||||
final int indents = getIndents(line);
|
||||
@@ -1203,9 +1243,46 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
y = logicalLineToY(line);
|
||||
}
|
||||
while (y < clip.y + clip.height);
|
||||
|
||||
if (myCaretIndentGuide != null) {
|
||||
int x = myCaretIndentGuide.indentLevel * gapWidth + 1;
|
||||
int y1 = logicalLineToY(myCaretIndentGuide.startLine);
|
||||
int y2 = logicalLineToY(myCaretIndentGuide.endLine);
|
||||
UIUtil.drawDottedLine((Graphics2D)g, x, y1, x, y2, getBackroundColor(), getForegroundColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IndentGuideDescriptor getCaretIndentGuide() {
|
||||
final int indentSize = getIndentSize();
|
||||
|
||||
final LogicalPosition caretPosition = myCaretModel.getLogicalPosition();
|
||||
int startLine = caretPosition.line;
|
||||
int endLine = startLine;
|
||||
int indents = caretPosition.column / indentSize;
|
||||
|
||||
if (indents > 0 && caretPosition.column % indentSize == 0) {
|
||||
while (startLine > 0) {
|
||||
if (getIndents(startLine - 1) <= indents) break;
|
||||
startLine--;
|
||||
}
|
||||
|
||||
if (getIndents(endLine + 1) > indents) endLine++;
|
||||
|
||||
while (endLine < myDocument.getLineCount() - 1) {
|
||||
if (getIndents(endLine) <= indents) break;
|
||||
endLine++;
|
||||
}
|
||||
|
||||
if (indents > 0 && startLine < endLine) {
|
||||
return new IndentGuideDescriptor(indents, startLine, endLine);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setHeaderComponent(JComponent header) {
|
||||
myHeaderPanel.removeAll();
|
||||
if (header != null) {
|
||||
|
||||
+4
@@ -226,4 +226,8 @@ public class TextComponentEditor extends UserDataHolderBase implements Editor {
|
||||
public JComponent getHeaderComponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public IndentGuideDescriptor getCaretIndentGuide() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -185,8 +185,9 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
|
||||
for (String name : names) {
|
||||
findChild(name, false, false);
|
||||
}
|
||||
|
||||
return ensureAsMap().values();
|
||||
|
||||
// important: should return a copy here for safe iterations
|
||||
return new ArrayList<VirtualFile>(ensureAsMap().values());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -617,3 +617,5 @@ inspection.application.chosen.profile.log\ message=Inspecting with profile ''{0}
|
||||
detach.library.quickfix.name=Detach library
|
||||
detach.library.roots.quickfix.name=Detach unused library roots
|
||||
inspection.javadoc.problem.pointing.to.itself=Javadoc pointing to itself
|
||||
|
||||
inspection.redirect.template=<html><body>Injected element has problem: {0} (in <a href=\"#navigation/{1}:{2}\">{3}</a>). </body></html>
|
||||
|
||||
@@ -115,6 +115,8 @@
|
||||
<extensionPoint name="lang.treePatcher" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
<extensionPoint name="lang.tokenSeparatorGenerator" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
|
||||
<extensionPoint name="lang.psiAugmentProvider" interface="com.intellij.psi.augment.PsiAugmentProvider"/>
|
||||
|
||||
<extensionPoint name="lang.fileViewProviderFactory" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
<extensionPoint name="fileType.fileViewProviderFactory" beanClass="com.intellij.openapi.fileTypes.FileTypeExtensionPoint"/>
|
||||
<extensionPoint name="multiLangCommenter"
|
||||
|
||||
@@ -395,6 +395,7 @@
|
||||
<enterHandlerDelegate implementation="com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesHandler" id="EnterBetweenBracesHandler"/>
|
||||
|
||||
<codeInsight.linkHandler prefix="#inspection/" handlerClass="com.intellij.codeInsight.hint.InspectionDescriptionLinkHandler"/>
|
||||
<codeInsight.linkHandler prefix="#navigation/" handlerClass="com.intellij.codeInsight.hint.NavigationLinkHandler"/>
|
||||
|
||||
<codeFoldingOptionsProvider implementation="com.intellij.application.options.editor.BaseCodeFoldingOptionsProvider" order="first"/>
|
||||
<editorOptionsProvider implementation="com.intellij.application.options.editor.EditorSmartKeysConfigurable"/>
|
||||
|
||||
+2
-1
@@ -33,6 +33,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.testFramework.TestDataFile;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -156,7 +157,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
|
||||
* @see #getReferenceAtCaretPositionWithAssertion(String...)
|
||||
*/
|
||||
@Nullable
|
||||
PsiReference getReferenceAtCaretPosition(@NonNls String... filePaths) throws Exception;
|
||||
PsiReference getReferenceAtCaretPosition(@TestDataFile @NonNls String... filePaths) throws Exception;
|
||||
|
||||
/**
|
||||
* Finds the reference in position marked by {@link #CARET_MARKER}.
|
||||
|
||||
@@ -155,6 +155,32 @@ public class ArrayUtil {
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates new array of size <code>array.length + collection.size()</code> and copies elements of <code>array</code> and
|
||||
* <code>collection</code> to it.
|
||||
* @param array source array
|
||||
* @param collection source collection
|
||||
* @param factory array factory used to create destination array of type <code>T</code>
|
||||
* @return destination array
|
||||
*/
|
||||
@NotNull
|
||||
public static <T> T[] mergeArrayAndCollection(@NotNull T[] array, @NotNull Collection<T> collection,
|
||||
@NotNull final ArrayFactory<T> factory) {
|
||||
if (collection.size() == 0) {
|
||||
return array;
|
||||
}
|
||||
|
||||
final T[] array2 = collection.toArray(factory.create(collection.size()));
|
||||
if (array.length == 0) {
|
||||
return array2;
|
||||
}
|
||||
|
||||
final T[] result = factory.create(array.length + collection.size());
|
||||
System.arraycopy(array, 0, result, 0, array.length);
|
||||
System.arraycopy(array2, 0, result, array.length, array2.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends <code>element</code> to the <code>src</code> array. As you can
|
||||
* imagine the appended element will be the last one in the returned result.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
def gdslScriptContext = context(scope: scriptScope(), filetypes: ["gdsl"])
|
||||
def gdslScriptContext = context(scope: scriptScope(), filetypes:['gdsl'])
|
||||
|
||||
contributor([gdslScriptContext]) {
|
||||
method name: "context", params: [args: [:]], type: "java.lang.Object"
|
||||
@@ -7,15 +7,15 @@ contributor([gdslScriptContext]) {
|
||||
method name: "contributor", params: [contexts: "java.lang.Object", body: {}], type: void
|
||||
|
||||
// scopes
|
||||
property name: "closureScope", type: {}
|
||||
property name: "scriptScope", type: {}
|
||||
property name: "closureScope", params: [contexts: "java.util.Map"], type: {}
|
||||
property name: "scriptScope", params: [contexts: "java.util.Map"], type: {}
|
||||
|
||||
method name: "hasAnnotation", params:[fqn: "java.lang.String"], type: "java.lang.Object"
|
||||
method name: "hasMethod", params:[memberPattern: "java.lang.Object"], type: "java.lang.Object"
|
||||
method name: "hasField", params:[memberPattern: "java.lang.Object"], type: "java.lang.Object"
|
||||
}
|
||||
|
||||
def contributorBody = context(scope: closureScope(isArg: true))
|
||||
def contributorBody = context(scope: closureScope(isArg: true), filetypes:['gdsl'])
|
||||
|
||||
contributor([contributorBody]) {
|
||||
if (enclosingCall("contributor")) {
|
||||
@@ -39,41 +39,38 @@ contributor([contributorBody]) {
|
||||
}
|
||||
}
|
||||
|
||||
def psiClassContext = context(scope: closureScope(isArg: true), ctype: "com.intellij.psi.PsiClass")
|
||||
contributor([psiClassContext]) {
|
||||
def enrich(String className) {
|
||||
context(scope: closureScope(isArg: true), ctype: className, filetypes:['gdsl'])
|
||||
}
|
||||
|
||||
contributor(enrich("com.intellij.psi.PsiClass")) {
|
||||
method name: "getMethods", type: "java.util.Collection"
|
||||
method name: "getQualName", type: "java.lang.String"
|
||||
}
|
||||
|
||||
def psiMemberContext = context(scope: closureScope(isArg: true), ctype: "com.intellij.psi.PsiMember")
|
||||
contributor([psiMemberContext]) {
|
||||
contributor(enrich("com.intellij.psi.PsiMember")) {
|
||||
method name: "hasAnnotation", params: [name: "java.lang.String"], type: "boolean"
|
||||
method name: "hasAnnotation", type: "boolean"
|
||||
method name: "getAnnotation", params: [name: "java.lang.String"], type: "com.intellij.psi.PsiAnnotation"
|
||||
method name: "getAnnotations", params: [name: "java.lang.String"], type: "java.util.Collection<com.intellij.psi.PsiAnnotation>"
|
||||
}
|
||||
|
||||
def psiFieldContext = context(scope: closureScope(isArg: true), ctype: "com.intellij.psi.PsiField")
|
||||
contributor([psiFieldContext]) {
|
||||
contributor(enrich("com.intellij.psi.PsiField")) {
|
||||
method name: "getClassType", type: "com.intellij.psi.PsiClass"
|
||||
}
|
||||
|
||||
def psiMethodContext = context(scope: closureScope(isArg: true), ctype: "com.intellij.psi.PsiMethod")
|
||||
contributor([psiMethodContext]) {
|
||||
contributor(enrich("com.intellij.psi.PsiMethod")) {
|
||||
method name: "getParamStringVector", type: "java.util.Map"
|
||||
}
|
||||
|
||||
def psiElementContext = context(scope: closureScope(isArg: true), ctype: "com.intellij.psi.PsiElement")
|
||||
contributor([psiElementContext]) {
|
||||
contributor(enrich("com.intellij.psi.PsiElement")) {
|
||||
method name: "bind", type: "com.intellij.psi.PsiElement"
|
||||
method name: "eval", type: "java.lang.Object"
|
||||
method name: "asList", type: "java.util.collection<com.intellij.psi.PsiElement>"
|
||||
method name: "getQualifier", type: "com.intellij.psi.PsiElement"
|
||||
}
|
||||
|
||||
def expressionContext = context(scope: closureScope(isArg: true),
|
||||
ctype: "org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression")
|
||||
contributor([expressionContext]) {
|
||||
contributor(enrich("org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression")) {
|
||||
method name: "getArguments", type: "java.util.Collection"
|
||||
method name: "getClassType", type: "com.intellij.psi.PsiClass"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
contributor(context()) {
|
||||
// For methods
|
||||
def memb = enclosingMember()
|
||||
// For classes
|
||||
def clazz = enclosingClass()
|
||||
if (memb) {
|
||||
// For classes
|
||||
def newifyName = "groovy.lang.Newify"
|
||||
for (a in memb?.getAnnotations(newifyName) + clazz?.getAnnotations(newifyName)) {
|
||||
def refs = a?.findAttributeValue("value")
|
||||
def auto = a?.findAttributeValue("auto")
|
||||
def annotated = memb.getAnnotations(newifyName)
|
||||
|
||||
def clazz = enclosingClass()
|
||||
if (clazz) {
|
||||
annotated += clazz.getAnnotations(newifyName)
|
||||
}
|
||||
for (a in annotated) {
|
||||
def refs = a.findAttributeValue("value")
|
||||
def auto = a.findAttributeValue("auto")
|
||||
//For Python-like style
|
||||
if (refs && !place.qualifier) {
|
||||
for (c in refs.asList()) {
|
||||
|
||||
@@ -1148,29 +1148,47 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
private static void checkMethodApplicability(GroovyResolveResult methodResolveResult, PsiElement place, AnnotationHolder holder) {
|
||||
final PsiElement element = methodResolveResult.getElement();
|
||||
if (!(element instanceof PsiMethod)) return;
|
||||
|
||||
final PsiMethod method = (PsiMethod)element;
|
||||
PsiType[] argumentTypes = PsiUtil.getArgumentTypes(place, method.isConstructor(), true);
|
||||
if (argumentTypes != null &&
|
||||
!PsiUtil.isApplicable(argumentTypes, method, methodResolveResult.getSubstitutor(),
|
||||
methodResolveResult.getCurrentFileResolveContext() instanceof GrMethodCallExpression)) {
|
||||
PsiElement elementToHighlight = PsiUtil.getArgumentsElement(place);
|
||||
if (elementToHighlight == null) {
|
||||
elementToHighlight = place;
|
||||
if ("call".equals(method.getName()) && place instanceof GrReferenceExpression) {
|
||||
final GrExpression qualifierExpression = ((GrReferenceExpression)place).getQualifierExpression();
|
||||
if (qualifierExpression != null) {
|
||||
final PsiType type = qualifierExpression.getType();
|
||||
if (type instanceof GrClosureType) {
|
||||
if (!PsiUtil.isApplicable(argumentTypes, (GrClosureType)type, element.getManager())) {
|
||||
highlightInapplicableMethodUsage(methodResolveResult, place, holder, method, argumentTypes);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String typesString = buildArgTypesList(argumentTypes);
|
||||
String message;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final PsiClassType containingType = JavaPsiFacade.getInstance(method.getProject()).getElementFactory()
|
||||
.createType(containingClass, methodResolveResult.getSubstitutor());
|
||||
message = GroovyBundle.message("cannot.apply.method1", method.getName(), containingType.getInternalCanonicalText(), typesString);
|
||||
}
|
||||
else {
|
||||
message = GroovyBundle.message("cannot.apply.method.or.closure", method.getName(), typesString);
|
||||
}
|
||||
holder.createWarningAnnotation(elementToHighlight, message);
|
||||
}
|
||||
if (argumentTypes != null &&
|
||||
!PsiUtil.isApplicable(argumentTypes, method, methodResolveResult.getSubstitutor(),
|
||||
methodResolveResult.getCurrentFileResolveContext() instanceof GrMethodCallExpression)) {
|
||||
highlightInapplicableMethodUsage(methodResolveResult, place, holder, method, argumentTypes);
|
||||
}
|
||||
}
|
||||
|
||||
private static void highlightInapplicableMethodUsage(GroovyResolveResult methodResolveResult, PsiElement place, AnnotationHolder holder,
|
||||
PsiMethod method, PsiType[] argumentTypes) {
|
||||
PsiElement elementToHighlight = PsiUtil.getArgumentsElement(place);
|
||||
if (elementToHighlight == null) {
|
||||
elementToHighlight = place;
|
||||
}
|
||||
|
||||
final String typesString = buildArgTypesList(argumentTypes);
|
||||
String message;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final PsiClassType containingType = JavaPsiFacade.getInstance(method.getProject()).getElementFactory()
|
||||
.createType(containingClass, methodResolveResult.getSubstitutor());
|
||||
message = GroovyBundle.message("cannot.apply.method1", method.getName(), containingType.getInternalCanonicalText(), typesString);
|
||||
}
|
||||
else {
|
||||
message = GroovyBundle.message("cannot.apply.method.or.closure", method.getName(), typesString);
|
||||
}
|
||||
holder.createWarningAnnotation(elementToHighlight, message);
|
||||
}
|
||||
|
||||
public static boolean isDeclarationAssignment(GrReferenceExpression refExpr) {
|
||||
|
||||
@@ -77,7 +77,7 @@ public class CustomMembersGenerator implements GdslMembersHolderConsumer {
|
||||
public CustomMembersHolder getMembersHolder() {
|
||||
// Add non-code members holder
|
||||
if (myClassText.length() > 0) {
|
||||
addMemberHolder(new NonCodeMembersHolder(myClassText.toString(), myProject));
|
||||
addMemberHolder(NonCodeMembersHolder.fromText(myClassText.toString(), myProject));
|
||||
}
|
||||
return myDepot;
|
||||
}
|
||||
|
||||
+22
-1
@@ -16,11 +16,17 @@
|
||||
package org.jetbrains.plugins.groovy.dsl.holders;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.scope.NameHint;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
@@ -30,8 +36,23 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
|
||||
*/
|
||||
public class NonCodeMembersHolder implements CustomMembersHolder {
|
||||
private final GrTypeDefinition myPsiClass;
|
||||
private static final Key<CachedValue<ConcurrentFactoryMap<String, NonCodeMembersHolder>>> CACHED_HOLDERS = Key.create("CACHED_HOLDERS");
|
||||
|
||||
public NonCodeMembersHolder(@NotNull String classText, Project project) {
|
||||
public static NonCodeMembersHolder fromText(@NotNull String classText, final Project project) {
|
||||
return CachedValuesManager.getManager(project).getCachedValue(project, CACHED_HOLDERS, new CachedValueProvider<ConcurrentFactoryMap<String, NonCodeMembersHolder>>() {
|
||||
public Result<ConcurrentFactoryMap<String, NonCodeMembersHolder>> compute() {
|
||||
final ConcurrentFactoryMap<String, NonCodeMembersHolder> map = new ConcurrentFactoryMap<String, NonCodeMembersHolder>() {
|
||||
@Override
|
||||
protected NonCodeMembersHolder create(String key) {
|
||||
return new NonCodeMembersHolder(key, project);
|
||||
}
|
||||
};
|
||||
return Result.create(map, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}, false).get(classText);
|
||||
}
|
||||
|
||||
private NonCodeMembersHolder(@NotNull String classText, Project project) {
|
||||
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
|
||||
myPsiClass = factory.createGroovyFile("class GroovyEnhanced {\n" + classText + "}", false, null).getTypeDefinitions()[0];
|
||||
}
|
||||
|
||||
@@ -54,7 +54,11 @@ class Context {
|
||||
def scope = (ScriptScope) args.scope
|
||||
|
||||
//first, it should be inside groovy script
|
||||
addFilter new PlaceContextFilter(PlatformPatterns.psiElement().inFile(GroovyPatterns.groovyScript()))
|
||||
def scriptPattern = GroovyPatterns.groovyScript()
|
||||
if (scope.extension) {
|
||||
scriptPattern = scriptPattern.withVirtualFile(PlatformPatterns.virtualFile().withExtension(scope.extension))
|
||||
}
|
||||
addFilter new PlaceContextFilter(PlatformPatterns.psiElement().inFile(scriptPattern))
|
||||
|
||||
// Name matcher
|
||||
def namePattern = scope.namePattern
|
||||
|
||||
@@ -37,10 +37,15 @@ class ClosureScope extends Scope {
|
||||
|
||||
class ScriptScope extends Scope {
|
||||
final String namePattern
|
||||
final String extension
|
||||
|
||||
ScriptScope(Map args) {
|
||||
if (args && args.name) {
|
||||
namePattern = args.name
|
||||
if (args) {
|
||||
if (args.name) {
|
||||
namePattern = args.name
|
||||
} else if (args.extension) {
|
||||
extension = args.extension
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ package org.jetbrains.plugins.groovy.lang.psi.impl;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.UserDataCache;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
@@ -32,6 +34,9 @@ import com.intellij.psi.scope.NameHint;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -69,6 +74,7 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile {
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl");
|
||||
private static final Object lock = new Object();
|
||||
|
||||
private volatile Boolean myScript;
|
||||
private GroovyScriptClass myScriptClass;
|
||||
private static final String SYNTHETIC_PARAMETER_NAME = "args";
|
||||
private GrParameter mySyntheticArgsParameter = null;
|
||||
@@ -368,12 +374,26 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile {
|
||||
if (stub instanceof GrFileStub) {
|
||||
return ((GrFileStub)stub).isScript();
|
||||
}
|
||||
GrTopStatement[] top = findChildrenByClass(GrTopStatement.class);
|
||||
for (GrTopStatement st : top) {
|
||||
if (!(st instanceof GrTypeDefinition || st instanceof GrImportStatement || st instanceof GrPackageDefinition)) return true;
|
||||
|
||||
Boolean isScript = myScript;
|
||||
if (isScript == null) {
|
||||
isScript = Boolean.FALSE;
|
||||
for (GrTopStatement st : findChildrenByClass(GrTopStatement.class)) {
|
||||
if (!(st instanceof GrTypeDefinition || st instanceof GrImportStatement || st instanceof GrPackageDefinition)) {
|
||||
isScript = Boolean.TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
myScript = isScript;
|
||||
}
|
||||
|
||||
return false;
|
||||
return isScript;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subtreeChanged() {
|
||||
myScript = null;
|
||||
super.subtreeChanged();
|
||||
}
|
||||
|
||||
public GroovyScriptClass getScriptClass() {
|
||||
@@ -490,15 +510,26 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile {
|
||||
return this;
|
||||
}
|
||||
|
||||
private static final UserDataCache<CachedValue<GlobalSearchScope>, GroovyFile, GlobalSearchScope> RESOLVE_SCOPE_CACHE = new UserDataCache<CachedValue<GlobalSearchScope>, GroovyFile, GlobalSearchScope>("RESOLVE_SCOPE_CACHE") {
|
||||
@Override
|
||||
protected CachedValue<GlobalSearchScope> compute(final GroovyFile file, final GlobalSearchScope baseScope) {
|
||||
return CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<GlobalSearchScope>() {
|
||||
public Result<GlobalSearchScope> compute() {
|
||||
GlobalSearchScope scope = GroovyScriptType.getScriptType(file).patchResolveScope(file, baseScope);
|
||||
return Result.create(scope, file, ProjectRootManager.getInstance(file.getProject()));
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
};
|
||||
public GlobalSearchScope getFileResolveScope() {
|
||||
final VirtualFile vFile = getOriginalFile().getVirtualFile();
|
||||
final VirtualFile vFile = getOriginalFile().getVirtualFile();
|
||||
if (vFile == null) {
|
||||
return GlobalSearchScope.allScope(getProject());
|
||||
}
|
||||
|
||||
final GlobalSearchScope baseScope = ((FileManagerImpl)((PsiManagerEx)getManager()).getFileManager()).getDefaultResolveScope(vFile);
|
||||
if (isScript()) {
|
||||
return GroovyScriptType.getScriptType(this).patchResolveScope(this, baseScope);
|
||||
return RESOLVE_SCOPE_CACHE.get(this, baseScope).getValue();
|
||||
}
|
||||
return baseScope;
|
||||
}
|
||||
|
||||
+1
-1
@@ -407,7 +407,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private void resolveImpl(GrReferenceExpressionImpl refExpr, ResolverProcessor processor) {
|
||||
private static void resolveImpl(GrReferenceExpressionImpl refExpr, ResolverProcessor processor) {
|
||||
GrExpression qualifier = refExpr.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
ResolveUtil.treeWalkUp(refExpr, processor, true);
|
||||
|
||||
+18
-20
@@ -327,33 +327,30 @@ public abstract class GrTypeDefinitionImpl extends GroovyBaseElementImpl<GrTypeD
|
||||
|
||||
@NotNull
|
||||
public PsiMethod[] getMethods() {
|
||||
if (myMethods == null) {
|
||||
List<PsiMethod> methods = new ArrayList<PsiMethod>();
|
||||
List<PsiMethod> cached = myMethods;
|
||||
if (cached == null) {
|
||||
cached = new ArrayList<PsiMethod>();
|
||||
GrTypeDefinitionBody body = getBody();
|
||||
if (body != null) {
|
||||
methods.addAll(body.getMethods());
|
||||
cached.addAll(body.getMethods());
|
||||
}
|
||||
|
||||
myMethods = methods;
|
||||
myMethods = cached;
|
||||
}
|
||||
|
||||
List<PsiMethod> result = new ArrayList<PsiMethod>(myMethods);
|
||||
List<PsiMethod> result = new ArrayList<PsiMethod>(cached);
|
||||
GrClassImplUtil.addGroovyObjectMethods(this, result);
|
||||
return result.toArray(new PsiMethod[result.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GrMethod[] getGroovyMethods() {
|
||||
if (myGroovyMethods == null) {
|
||||
GrMethod[] cached = myGroovyMethods;
|
||||
if (cached == null) {
|
||||
GrTypeDefinitionBody body = getBody();
|
||||
if (body != null) {
|
||||
myGroovyMethods = body.getGroovyMethods();
|
||||
}
|
||||
else {
|
||||
myGroovyMethods = GrMethod.EMPTY_ARRAY;
|
||||
}
|
||||
myGroovyMethods = cached = body != null ? body.getGroovyMethods() : GrMethod.EMPTY_ARRAY;
|
||||
}
|
||||
return myGroovyMethods;
|
||||
return cached;
|
||||
}
|
||||
|
||||
public void subtreeChanged() {
|
||||
@@ -366,7 +363,8 @@ public abstract class GrTypeDefinitionImpl extends GroovyBaseElementImpl<GrTypeD
|
||||
|
||||
@NotNull
|
||||
public PsiMethod[] getConstructors() {
|
||||
if (myConstructors == null) {
|
||||
GrMethod[] cached = myConstructors;
|
||||
if (cached == null) {
|
||||
List<GrMethod> result = new ArrayList<GrMethod>();
|
||||
for (final PsiMethod method : getMethods()) {
|
||||
if (method.isConstructor()) {
|
||||
@@ -374,20 +372,20 @@ public abstract class GrTypeDefinitionImpl extends GroovyBaseElementImpl<GrTypeD
|
||||
}
|
||||
}
|
||||
|
||||
myConstructors = result.toArray(new GrMethod[result.size()]);
|
||||
return myConstructors;
|
||||
myConstructors = cached = result.toArray(new GrMethod[result.size()]);
|
||||
}
|
||||
return myConstructors;
|
||||
return cached;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiClass[] getInnerClasses() {
|
||||
if (myInnerClasses == null) {
|
||||
PsiClass[] inners = myInnerClasses;
|
||||
if (inners == null) {
|
||||
final GrTypeDefinitionBody body = getBody();
|
||||
myInnerClasses = body != null ? body.getInnerClasses() : PsiClass.EMPTY_ARRAY;
|
||||
myInnerClasses = inners = body != null ? body.getInnerClasses() : PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
return myInnerClasses;
|
||||
return inners;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+11
@@ -26,6 +26,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.params.GrParameterImpl;
|
||||
|
||||
@@ -93,4 +94,14 @@ public class ClosureSyntheticParameter extends LightParameter implements Navigat
|
||||
public PsiElement getContext() {
|
||||
return myClosure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrExpression getDefaultInitializer() {
|
||||
return GroovyPsiElementFactory.getInstance(getProject()).createExpressionFromText("null");
|
||||
}
|
||||
}
|
||||
|
||||
+47
-2
@@ -18,12 +18,18 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightVariableBase;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class LightParameter extends LightVariableBase implements PsiParameter {
|
||||
public class LightParameter extends LightVariableBase implements GrParameter {
|
||||
public static final LightParameter[] EMPTY_ARRAY = new LightParameter[0];
|
||||
private final String myName;
|
||||
|
||||
@@ -34,7 +40,7 @@ public class LightParameter extends LightVariableBase implements PsiParameter {
|
||||
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor) visitor).visitParameter(this);
|
||||
((JavaElementVisitor)visitor).visitParameter(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,4 +61,43 @@ public class LightParameter extends LightVariableBase implements PsiParameter {
|
||||
public String getName() {
|
||||
return StringUtil.notNullize(myName);
|
||||
}
|
||||
|
||||
public GrTypeElement getTypeElementGroovy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public GrExpression getDefaultInitializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public GrExpression getInitializerGroovy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setType(@Nullable PsiType type) throws IncorrectOperationException {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement getNameIdentifierGroovy() {
|
||||
return myNameIdentifier;
|
||||
}
|
||||
|
||||
public PsiType getTypeGroovy() {
|
||||
return getType();
|
||||
}
|
||||
|
||||
public PsiType getDeclaredType() {
|
||||
return getType();
|
||||
}
|
||||
|
||||
public void accept(GroovyElementVisitor visitor) {
|
||||
}
|
||||
|
||||
public void acceptChildren(GroovyElementVisitor visitor) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.patterns;
|
||||
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.patterns.InitialPatternCondition;
|
||||
import com.intellij.patterns.PsiFilePattern;
|
||||
import com.intellij.patterns.PsiJavaPatterns;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -47,8 +48,8 @@ public class GroovyPatterns extends PsiJavaPatterns {
|
||||
});
|
||||
}
|
||||
|
||||
public static GroovyElementPattern.Capture<GroovyFile> groovyScript() {
|
||||
return new GroovyElementPattern.Capture<GroovyFile>(new InitialPatternCondition<GroovyFile>(GroovyFile.class) {
|
||||
public static PsiFilePattern.Capture<GroovyFile> groovyScript() {
|
||||
return new PsiFilePattern.Capture<GroovyFile>(new InitialPatternCondition<GroovyFile>(GroovyFile.class) {
|
||||
@Override
|
||||
public boolean accepts(@Nullable Object o, ProcessingContext context) {
|
||||
return o instanceof GroovyFile && ((GroovyFile)o).isScript();
|
||||
|
||||
+18
-25
@@ -22,6 +22,7 @@ import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -37,42 +38,34 @@ public class CollectClassMembersUtil {
|
||||
|
||||
private static final Key<CachedValue<Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>>> CACHED_MEMBERS_INCLUDING_SYNTHETIC = Key.create("CACHED_MEMBERS_INCLUDING_SYNTHETIC");
|
||||
|
||||
private CollectClassMembersUtil() {
|
||||
}
|
||||
|
||||
|
||||
public static Map<String, List<CandidateInfo>> getAllMethods(final PsiClass aClass, boolean includeSynthetic) {
|
||||
Key<CachedValue<Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>>> key = includeSynthetic ?
|
||||
CACHED_MEMBERS_INCLUDING_SYNTHETIC : CACHED_MEMBERS;
|
||||
return getCachedMembers(aClass, includeSynthetic).getSecond();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>> getCachedMembers(
|
||||
PsiClass aClass,
|
||||
boolean includeSynthetic) {
|
||||
Key<CachedValue<Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>>> key =
|
||||
includeSynthetic ? CACHED_MEMBERS_INCLUDING_SYNTHETIC : CACHED_MEMBERS;
|
||||
CachedValue<Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>> cachedValue = aClass.getUserData(key);
|
||||
if (cachedValue == null) {
|
||||
cachedValue = buildCache(aClass, includeSynthetic);
|
||||
aClass.putUserData(key, cachedValue);
|
||||
}
|
||||
|
||||
Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>> value = cachedValue.getValue();
|
||||
assert value != null;
|
||||
return value.getSecond();
|
||||
return cachedValue.getValue();
|
||||
}
|
||||
|
||||
public static Map<String, CandidateInfo> getAllInnerClasses(final PsiClass aClass, boolean includeSynthetic) {
|
||||
Key<CachedValue<Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>>> key = includeSynthetic ?
|
||||
CACHED_MEMBERS_INCLUDING_SYNTHETIC : CACHED_MEMBERS;
|
||||
CachedValue<Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>> cachedValue = aClass.getUserData(key);
|
||||
if (cachedValue == null) {
|
||||
cachedValue = buildCache(aClass, includeSynthetic);
|
||||
}
|
||||
|
||||
Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>> value = cachedValue.getValue();
|
||||
assert value != null;
|
||||
return value.getThird();
|
||||
return getCachedMembers(aClass, includeSynthetic).getThird();
|
||||
}
|
||||
|
||||
public static Map<String, CandidateInfo> getAllFields(final PsiClass aClass) {
|
||||
CachedValue<Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>> cachedValue = aClass.getUserData(CACHED_MEMBERS);
|
||||
if (cachedValue == null) {
|
||||
cachedValue = buildCache(aClass, false);
|
||||
}
|
||||
|
||||
Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>> value = cachedValue.getValue();
|
||||
assert value != null;
|
||||
return value.getFirst();
|
||||
return getCachedMembers(aClass, false).getFirst();
|
||||
}
|
||||
|
||||
private static CachedValue<Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>> buildCache(final PsiClass aClass, final boolean includeSynthetic) {
|
||||
@@ -83,7 +76,7 @@ public class CollectClassMembersUtil {
|
||||
Map<String, CandidateInfo> allInnerClasses = new HashMap<String, CandidateInfo>();
|
||||
|
||||
processClass(aClass, allFields, allMethods, allInnerClasses, new HashSet<PsiClass>(), PsiSubstitutor.EMPTY, includeSynthetic);
|
||||
return Result.create(new Trinity<Map<String, CandidateInfo>, Map<String, List<CandidateInfo>>, Map<String, CandidateInfo>>(allFields, allMethods, allInnerClasses), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
return Result.create(Trinity.create(allFields, allMethods, allInnerClasses), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
+18
-14
@@ -34,6 +34,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssign
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
@@ -83,16 +84,19 @@ public class MethodResolverProcessor extends ResolverProcessor {
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (element instanceof PsiVariable) {
|
||||
if (element instanceof GrField && ((GrField) element).isProperty() ||
|
||||
isClosure((PsiVariable) element)) {
|
||||
return super.execute(element, state);
|
||||
} else {
|
||||
myInapplicableCandidates.add(new GroovyResolveResultImpl(element, myCurrentFileResolveContext, substitutor, isAccessible((PsiVariable)element), isStaticsOK((PsiVariable)element)));
|
||||
}
|
||||
else if (element instanceof PsiVariable) {
|
||||
if (isApplicableClosure((PsiVariable)element)) {
|
||||
myCandidates.add(new GroovyResolveResultImpl(element, myCurrentFileResolveContext, substitutor, isAccessible((PsiVariable)element),
|
||||
isStaticsOK((PsiVariable)element)));
|
||||
}
|
||||
else {
|
||||
myInapplicableCandidates.add(
|
||||
new GroovyResolveResultImpl(element, myCurrentFileResolveContext, substitutor, isAccessible((PsiVariable)element),
|
||||
isStaticsOK((PsiVariable)element)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -126,10 +130,14 @@ public class MethodResolverProcessor extends ResolverProcessor {
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
private static boolean isClosure(PsiVariable variable) {
|
||||
private boolean isApplicableClosure(PsiVariable variable) {
|
||||
if (variable instanceof GrVariable) {
|
||||
final PsiType type = ((GrVariable) variable).getTypeGroovy();
|
||||
return type != null && type.equalsToText(GrClosableBlock.GROOVY_LANG_CLOSURE);
|
||||
final PsiType type = ((GrVariable)variable).getTypeGroovy();
|
||||
if (type == null) return false;
|
||||
if (type instanceof GrClosureType) {
|
||||
return PsiUtil.isApplicable(myArgumentTypes, (GrClosureType)type, variable.getManager());
|
||||
}
|
||||
if (type.equalsToText(GrClosableBlock.GROOVY_LANG_CLOSURE)) return true;
|
||||
}
|
||||
return variable.getType().equalsToText(GrClosableBlock.GROOVY_LANG_CLOSURE);
|
||||
}
|
||||
@@ -317,10 +325,6 @@ public class MethodResolverProcessor extends ResolverProcessor {
|
||||
return myArgumentTypes;
|
||||
}
|
||||
|
||||
public void setArgumentTypes(@Nullable PsiType[] argumentTypes) {
|
||||
myArgumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(Event event, Object associated) {
|
||||
super.handleEvent(event, associated);
|
||||
|
||||
@@ -194,6 +194,7 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
public void testMethodCallWithDefaultParameters() throws Exception {doTest();}
|
||||
public void testClosureWithDefaultParameters() throws Exception {doTest();}
|
||||
public void testClosureCallMethodWithInapplicableArguments() throws Exception {doTest();}
|
||||
|
||||
public void testOverlyLongMethodInspection() throws Exception {
|
||||
doTest(new GroovyOverlyLongMethodInspection());
|
||||
|
||||
@@ -546,4 +546,10 @@ public class ResolveMethodTest extends GroovyResolveTestCase {
|
||||
final PsiElement resolved = ref.resolve();
|
||||
assertInstanceOf(resolved, PsiMethod.class);
|
||||
}
|
||||
|
||||
public void testMethodVsField() throws Exception {
|
||||
final PsiReference ref = configureByFile("methodVsField/A.groovy");
|
||||
final PsiElement element = ref.resolve();
|
||||
assertInstanceOf(element, PsiMethod.class);
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
def foo={x, y->}
|
||||
|
||||
print foo.call<warning descr="'call' in 'groovy.lang.Closure' cannot be applied to '(java.lang.Integer)'">(1)</warning>
|
||||
|
||||
def bar={3}
|
||||
print bar.call()
|
||||
print bar.call(3)
|
||||
@@ -0,0 +1,17 @@
|
||||
class Foo {
|
||||
|
||||
|
||||
def bar = { 2}
|
||||
}
|
||||
|
||||
class Bar extends Foo {
|
||||
def bar(def it) { 3 }
|
||||
|
||||
public static void main(String[] args) {
|
||||
def f = new Bar()
|
||||
|
||||
|
||||
println f.ba<ref>r(3)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -133,7 +133,7 @@ public class XmlFoldingBuilder implements FoldingBuilder, DumbAware {
|
||||
if (tagNameElement == null) return null;
|
||||
|
||||
int nameEnd = tagNameElement.getTextRange().getEndOffset();
|
||||
int end = tagNode.getLastChildNode().getTextRange().getStartOffset();
|
||||
int end = tagNode.getLastChildNode().getTextRange().getEndOffset() - 1; // last child node can be another tag in unbalanced tree
|
||||
ASTNode[] attributes = tagNode.getChildren(XML_ATTRIBUTE_SET);
|
||||
|
||||
if (attributes.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user