mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-26 19:06:24 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
@@ -973,7 +973,7 @@ public class CompileDriver {
|
||||
if (context.getProgressIndicator().isCanceled()) {
|
||||
throw new ExitException(ExitStatus.CANCELLED);
|
||||
}
|
||||
|
||||
context.getProgressIndicator().setText("Preparing sources for " + compiler.getDescription());
|
||||
DumbService.getInstance(myProject).waitForSmartMode();
|
||||
|
||||
if (round == 0) {
|
||||
|
||||
+4
@@ -76,6 +76,10 @@ public class AnnotationProcessingCompiler implements TranslatingCompiler{
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
return path != null? lfs.findFileByPath(path) : null;
|
||||
}
|
||||
|
||||
public VirtualFile getModuleOutputDirectoryForTests(Module module) {
|
||||
return getModuleOutputDirectory(module);
|
||||
}
|
||||
};
|
||||
final JavacCompiler javacCompiler = getBackEndCompiler();
|
||||
final boolean processorMode = javacCompiler.setAnnotationProcessorMode(true);
|
||||
|
||||
-5
@@ -21,7 +21,6 @@
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.editor.EditorBundle;
|
||||
import com.intellij.openapi.editor.HectorComponentPanel;
|
||||
import com.intellij.openapi.editor.HectorComponentPanelsProvider;
|
||||
@@ -30,13 +29,11 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ui.DialogUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
|
||||
public class ImportPopupHectorComponentProvider implements HectorComponentPanelsProvider {
|
||||
|
||||
@@ -48,8 +45,6 @@ public class ImportPopupHectorComponentProvider implements HectorComponentPanels
|
||||
assert virtualFile != null;
|
||||
final boolean notInLibrary =
|
||||
!fileIndex.isInLibrarySource(virtualFile) && !fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInContent(virtualFile);
|
||||
final FileViewProvider viewProvider = file.getViewProvider();
|
||||
final Set<Language> languages = viewProvider.getLanguages();
|
||||
|
||||
return new HectorComponentPanel() {
|
||||
private JCheckBox myImportPopupCheckBox = new JCheckBox(EditorBundle.message("hector.import.popup.checkbox"));
|
||||
|
||||
+21
-47
@@ -3,17 +3,15 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightMemberReference;
|
||||
import com.intellij.psi.search.PsiSearchScopeUtil;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import com.intellij.util.Processor;
|
||||
|
||||
/**
|
||||
@@ -30,38 +28,29 @@ public class ConstructorReferencesSearchHelper {
|
||||
final PsiMethod constructor,
|
||||
final SearchScope searchScope,
|
||||
boolean ignoreAccessScope,
|
||||
final boolean isStrictSignatureSearch) {
|
||||
final Ref<Boolean> result = new Ref<Boolean>();
|
||||
PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
public PsiClass compute() {
|
||||
PsiClass aClass = constructor.getContainingClass();
|
||||
if (aClass == null) {
|
||||
result.set(true);
|
||||
return null;
|
||||
}
|
||||
final boolean isStrictSignatureSearch, SearchRequestCollector collector) {
|
||||
PsiClass aClass = constructor.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aClass.isEnum()) {
|
||||
PsiField[] fields = aClass.getFields();
|
||||
for (PsiField field : fields) {
|
||||
if (field instanceof PsiEnumConstant) {
|
||||
PsiReference reference = field.getReference();
|
||||
if (reference != null && reference.isReferenceTo(constructor)) {
|
||||
if (!processor.process(reference)) {
|
||||
result.set(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (aClass.isEnum()) {
|
||||
for (PsiField field : aClass.getFields()) {
|
||||
if (field instanceof PsiEnumConstant) {
|
||||
PsiReference reference = field.getReference();
|
||||
if (reference != null && reference.isReferenceTo(constructor)) {
|
||||
if (!processor.process(reference)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return aClass;
|
||||
}
|
||||
});
|
||||
if (!result.isNull()) return result.get();
|
||||
}
|
||||
|
||||
// search usages like "new XXX(..)"
|
||||
Processor<PsiReference> processor1 = new ReadActionProcessor<PsiReference>() {
|
||||
public boolean processInReadAction(final PsiReference reference) {
|
||||
PairProcessor<PsiReference, SearchRequestCollector> processor1 = new PairProcessor<PsiReference, SearchRequestCollector>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference, SearchRequestCollector collector) {
|
||||
PsiElement parent = reference.getElement().getParent();
|
||||
if (parent instanceof PsiAnonymousClass) {
|
||||
parent = parent.getParent();
|
||||
@@ -85,12 +74,12 @@ public class ConstructorReferencesSearchHelper {
|
||||
}
|
||||
};
|
||||
|
||||
if (!ReferencesSearch.search(aClass, searchScope, ignoreAccessScope).forEach(processor1)) return false;
|
||||
ReferencesSearch.searchOptimized(aClass, searchScope, ignoreAccessScope, collector, true, processor1);
|
||||
|
||||
final boolean constructorCanBeCalledImplicitly = constructor.getParameterList().getParametersCount() == 0;
|
||||
// search usages like "this(..)"
|
||||
if (!processSuperOrThis(processor, aClass, constructor, constructorCanBeCalledImplicitly, searchScope, isStrictSignatureSearch,
|
||||
PsiKeyword.THIS)) {
|
||||
PsiKeyword.THIS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -98,7 +87,7 @@ public class ConstructorReferencesSearchHelper {
|
||||
Processor<PsiClass> processor2 = new Processor<PsiClass>() {
|
||||
public boolean process(PsiClass inheritor) {
|
||||
return processSuperOrThis(processor, (PsiClass)inheritor.getNavigationElement(), constructor, constructorCanBeCalledImplicitly, searchScope, isStrictSignatureSearch,
|
||||
PsiKeyword.SUPER);
|
||||
PsiKeyword.SUPER);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -110,21 +99,6 @@ public class ConstructorReferencesSearchHelper {
|
||||
final PsiMethod constructor, final boolean constructorCanBeCalledImplicitly, final SearchScope searchScope,
|
||||
final boolean isStrictSignatureSearch,
|
||||
final String superOrThisKeyword) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
return processSuperOrThisInReadAction(inheritor, searchScope, superOrThisKeyword, isStrictSignatureSearch, constructor,
|
||||
constructorCanBeCalledImplicitly, processor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean processSuperOrThisInReadAction(final PsiClass inheritor,
|
||||
final SearchScope searchScope,
|
||||
final String superOrThisKeyword,
|
||||
final boolean isStrictSignatureSearch,
|
||||
final PsiMethod constructor,
|
||||
final boolean constructorCanBeCalledImplicitly,
|
||||
final Processor<PsiReference> processor) {
|
||||
PsiMethod[] constructors = inheritor.getConstructors();
|
||||
if (constructors.length == 0 && constructorCanBeCalledImplicitly) {
|
||||
processImplicitConstructorCall(inheritor, processor, constructor, inheritor);
|
||||
|
||||
@@ -3,24 +3,28 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.openapi.application.QueryExecutorBase;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class ConstructorReferencesSearcher implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
public boolean execute(final ReferencesSearch.SearchParameters p, final Processor<PsiReference> consumer) {
|
||||
public class ConstructorReferencesSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
protected ConstructorReferencesSearcher() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processQuery(ReferencesSearch.SearchParameters p, Processor<PsiReference> consumer) {
|
||||
final PsiElement element = p.getElementToSearch();
|
||||
if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) {
|
||||
return new ConstructorReferencesSearchHelper(PsiManager.getInstance(element.getProject()))
|
||||
.processConstructorReferences(consumer, (PsiMethod)p.getElementToSearch(), p.getScope(), p.isIgnoreAccessScope(), true);
|
||||
new ConstructorReferencesSearchHelper(PsiManager.getInstance(element.getProject()))
|
||||
.processConstructorReferences(consumer, (PsiMethod)p.getElementToSearch(), p.getScope(), p.isIgnoreAccessScope(), true, p.getOptimizer());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.QueryExecutorBase;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
@@ -18,6 +16,9 @@ import com.intellij.util.Processor;
|
||||
* @author max
|
||||
*/
|
||||
public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, MethodReferencesSearch.SearchParameters> {
|
||||
protected MethodUsagesSearcher() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processQuery(MethodReferencesSearch.SearchParameters p, Processor<PsiReference> consumer) {
|
||||
@@ -28,60 +29,42 @@ public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, Method
|
||||
|
||||
final PsiManager psiManager = PsiManager.getInstance(method.getProject());
|
||||
|
||||
final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
public PsiClass compute() {
|
||||
return method.isValid() ? method.getContainingClass() : null;
|
||||
}
|
||||
});
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return;
|
||||
|
||||
final boolean strictSignatureSearch = p.isStrictSignatureSearch();
|
||||
|
||||
if (method.isConstructor()) {
|
||||
collector.searchCustom(new Processor<Processor<PsiReference>>() {
|
||||
public boolean process(Processor<PsiReference> consumer) {
|
||||
return new ConstructorReferencesSearchHelper(psiManager).
|
||||
processConstructorReferences(consumer, method, searchScope, !strictSignatureSearch, strictSignatureSearch);
|
||||
}
|
||||
});
|
||||
new ConstructorReferencesSearchHelper(psiManager).
|
||||
processConstructorReferences(consumer, method, searchScope, !strictSignatureSearch, strictSignatureSearch, collector);
|
||||
}
|
||||
|
||||
boolean needStrictSignatureSearch = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
return method.isValid() && strictSignatureSearch && (aClass instanceof PsiAnonymousClass
|
||||
boolean needStrictSignatureSearch = strictSignatureSearch && (aClass instanceof PsiAnonymousClass
|
||||
|| aClass.hasModifierProperty(PsiModifier.FINAL)
|
||||
|| method.hasModifierProperty(PsiModifier.STATIC)
|
||||
|| method.hasModifierProperty(PsiModifier.FINAL)
|
||||
|| method.hasModifierProperty(PsiModifier.PRIVATE));
|
||||
}
|
||||
});
|
||||
if (needStrictSignatureSearch) {
|
||||
ReferencesSearch.search(new ReferencesSearch.SearchParameters(method, searchScope, false, collector)).forEach(consumer);
|
||||
ReferencesSearch.searchOptimized(method, searchScope, false, collector, consumer);
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
if (!method.isValid()) return;
|
||||
final String textToSearch = method.getName();
|
||||
final PsiMethod[] methods = strictSignatureSearch ? new PsiMethod[]{method} : aClass.findMethodsByName(textToSearch, false);
|
||||
|
||||
final String textToSearch = method.getName();
|
||||
final PsiMethod[] methods = strictSignatureSearch ? new PsiMethod[]{method} : aClass.findMethodsByName(textToSearch, false);
|
||||
SearchScope accessScope = methods[0].getUseScope();
|
||||
for (int i = 1; i < methods.length; i++) {
|
||||
PsiMethod method1 = methods[i];
|
||||
accessScope = accessScope.union(method1.getUseScope());
|
||||
}
|
||||
|
||||
SearchScope accessScope = methods[0].getUseScope();
|
||||
for (int i = 1; i < methods.length; i++) {
|
||||
PsiMethod method1 = methods[i];
|
||||
accessScope = accessScope.union(method1.getUseScope());
|
||||
}
|
||||
final SearchScope restrictedByAccess = searchScope.intersectWith(accessScope);
|
||||
|
||||
final SearchScope restrictedByAccess = searchScope.intersectWith(accessScope);
|
||||
short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_COMMENTS | UsageSearchContext.IN_FOREIGN_LANGUAGES;
|
||||
collector.searchWord(textToSearch, restrictedByAccess, searchContext, true,
|
||||
new MethodTextOccurrenceProcessor(aClass, strictSignatureSearch, methods));
|
||||
|
||||
short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_COMMENTS | UsageSearchContext.IN_FOREIGN_LANGUAGES;
|
||||
collector.searchWord(textToSearch, restrictedByAccess, searchContext, true,
|
||||
new MethodTextOccurrenceProcessor(aClass, strictSignatureSearch, methods));
|
||||
|
||||
SimpleAccessorReferenceSearcher.addPropertyAccessUsages(method, restrictedByAccess, collector);
|
||||
}
|
||||
});
|
||||
SimpleAccessorReferenceSearcher.addPropertyAccessUsages(method, restrictedByAccess, collector);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,10 @@ package com.intellij.psi.search.searches;
|
||||
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchRequestQuery;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.util.MergeQuery;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.UniqueResultsQuery;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.util.*;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -75,6 +71,21 @@ public class MethodReferencesSearch extends ExtensibleQueryFactory<PsiReference,
|
||||
return search(new SearchParameters(method, scope, strictSignatureSearch));
|
||||
}
|
||||
|
||||
public static void searchOptimized(final PsiMethod method, SearchScope scope, final boolean strictSignatureSearch,
|
||||
@NotNull SearchRequestCollector collector, final Processor<PsiReference> processor) {
|
||||
searchOptimized(method, scope, strictSignatureSearch, collector, false, new PairProcessor<PsiReference, SearchRequestCollector>() {
|
||||
@Override
|
||||
public boolean process(PsiReference psiReference, SearchRequestCollector collector) {
|
||||
return processor.process(psiReference);
|
||||
}
|
||||
});
|
||||
}
|
||||
public static void searchOptimized(final PsiMethod method, SearchScope scope, final boolean strictSignatureSearch, SearchRequestCollector collector, final boolean inReadAction, PairProcessor<PsiReference, SearchRequestCollector> processor) {
|
||||
final SearchRequestCollector nested = new SearchRequestCollector();
|
||||
collector.searchQuery(new QuerySearchRequest(search(new SearchParameters(method, scope, strictSignatureSearch, nested)), nested,
|
||||
inReadAction, processor));
|
||||
}
|
||||
|
||||
public static Query<PsiReference> search(final SearchParameters parameters) {
|
||||
final Query<PsiReference> result = INSTANCE.createQuery(parameters);
|
||||
if (parameters.isSharedOptimizer) {
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
package com.intellij.execution.ui;
|
||||
|
||||
import com.intellij.openapi.ui.ComponentContainer;
|
||||
|
||||
import javax.swing.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: Apr 20, 2004
|
||||
*/
|
||||
public interface ExecutionConsole extends ComponentContainer {
|
||||
|
||||
@NonNls String CONSOLE_CONTENT_ID = "ConsoleContent";
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.lang.documentation;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
|
||||
/**
|
||||
* User: spLeaner
|
||||
*/
|
||||
public interface ExternalDocumentationHandler {
|
||||
boolean handleExternal(PsiElement element, PsiElement originalElement);
|
||||
boolean handleExternalLink(PsiManager psiManager, String link, PsiElement context);
|
||||
}
|
||||
@@ -45,6 +45,7 @@ public interface CustomHighlighterTokenType {
|
||||
IElementType MULTI_LINE_COMMENT = new CustomElementType("MULTI_LINE_COMMENT");
|
||||
IElementType WHITESPACE = new CustomElementType("WHITESPACE");
|
||||
IElementType CHARACTER = new CustomElementType("CHARACTER");
|
||||
IElementType PUNCTUATION = new CustomElementType("PUNCTUATION");
|
||||
|
||||
IElementType L_BRACE = new CustomElementType("L_BRACE");
|
||||
IElementType R_BRACE = new CustomElementType("R_BRACE");
|
||||
|
||||
@@ -107,23 +107,11 @@ public abstract class PsiReferenceBase<T extends PsiElement> implements PsiRefer
|
||||
}
|
||||
|
||||
public static <T extends PsiElement> PsiReferenceBase<T> createSelfReference(T element, final PsiElement resolveTo) {
|
||||
return new Immediate<T>(element, true, resolveTo);
|
||||
}
|
||||
|
||||
return new PsiReferenceBase<T>(element,true) {
|
||||
//do nothing. the element will be renamed via PsiMetaData (com.intellij.refactoring.rename.RenameUtil.doRenameGenericNamedElement())
|
||||
public PsiElement handleElementRename(final String newElementName) throws IncorrectOperationException {
|
||||
return getElement();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement resolve() {
|
||||
return resolveTo;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Object[] getVariants() {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
};
|
||||
public static <T extends PsiElement> PsiReferenceBase<T> createSelfReference(T element, TextRange range, final PsiElement resolveTo) {
|
||||
return new Immediate<T>(element, range, resolveTo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -165,4 +153,43 @@ public abstract class PsiReferenceBase<T extends PsiElement> implements PsiRefer
|
||||
return resolveResults.length == 1 ? resolveResults[0].getElement() : null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Immediate<T extends PsiElement> extends PsiReferenceBase<T> {
|
||||
private final PsiElement myResolveTo;
|
||||
|
||||
public Immediate(T element, TextRange range, boolean soft, PsiElement resolveTo) {
|
||||
super(element, range, soft);
|
||||
myResolveTo = resolveTo;
|
||||
}
|
||||
|
||||
public Immediate(T element, TextRange range, PsiElement resolveTo) {
|
||||
super(element, range);
|
||||
myResolveTo = resolveTo;
|
||||
}
|
||||
|
||||
public Immediate(T element, boolean soft, PsiElement resolveTo) {
|
||||
super(element, soft);
|
||||
myResolveTo = resolveTo;
|
||||
}
|
||||
|
||||
public Immediate(@NotNull T element, PsiElement resolveTo) {
|
||||
super(element);
|
||||
myResolveTo = resolveTo;
|
||||
}
|
||||
|
||||
//do nothing. the element will be renamed via PsiMetaData (com.intellij.refactoring.rename.RenameUtil.doRenameGenericNamedElement())
|
||||
public PsiElement handleElementRename(final String newElementName) throws IncorrectOperationException {
|
||||
return getElement();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement resolve() {
|
||||
return myResolveTo;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Object[] getVariants() {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,8 @@ public class PsiSearchRequest {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiSearchRequest: " + word + "; " + processor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.intellij.psi.search;
|
||||
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.Query;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class QuerySearchRequest {
|
||||
public final Query<PsiReference> query;
|
||||
public final SearchRequestCollector collector;
|
||||
public final Processor<PsiReference> processor;
|
||||
|
||||
public QuerySearchRequest(Query<PsiReference> query,
|
||||
final SearchRequestCollector collector,
|
||||
boolean inReadAction, final PairProcessor<PsiReference, SearchRequestCollector> processor) {
|
||||
this.query = query;
|
||||
this.collector = collector;
|
||||
if (inReadAction) {
|
||||
this.processor = new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(PsiReference psiReference) {
|
||||
return processor.process(psiReference, collector);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
this.processor = new Processor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference psiReference) {
|
||||
return processor.process(psiReference, collector);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void runQuery() {
|
||||
query.forEach(processor);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.intellij.psi.search;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -12,8 +13,10 @@ import java.util.List;
|
||||
* @author peter
|
||||
*/
|
||||
public class SearchRequestCollector {
|
||||
private final List<PsiSearchRequest> myRequests = new ArrayList<PsiSearchRequest>();
|
||||
private final List<Processor<Processor<PsiReference>>> myCustomSearchActions = new ArrayList<Processor<Processor<PsiReference>>>();
|
||||
private final Object lock = new Object();
|
||||
private final List<PsiSearchRequest> myWordRequests = CollectionFactory.arrayList();
|
||||
private final List<QuerySearchRequest> myQueryRequests = CollectionFactory.arrayList();
|
||||
private final List<Processor<Processor<PsiReference>>> myCustomSearchActions = CollectionFactory.arrayList();
|
||||
|
||||
public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, boolean caseSensitive, @NotNull PsiElement searchTarget) {
|
||||
final short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_FOREIGN_LANGUAGES | UsageSearchContext.IN_COMMENTS;
|
||||
@@ -29,18 +32,48 @@ public class SearchRequestCollector {
|
||||
return;
|
||||
}
|
||||
|
||||
myRequests.add(new PsiSearchRequest(searchScope, word, searchContext, caseSensitive, processor));
|
||||
synchronized (lock) {
|
||||
myWordRequests.add(new PsiSearchRequest(searchScope, word, searchContext, caseSensitive, processor));
|
||||
}
|
||||
}
|
||||
|
||||
public void searchQuery(QuerySearchRequest request) {
|
||||
assert request.collector != this;
|
||||
synchronized (lock) {
|
||||
myQueryRequests.add(request);
|
||||
}
|
||||
}
|
||||
|
||||
public void searchCustom(Processor<Processor<PsiReference>> searchAction) {
|
||||
myCustomSearchActions.add(searchAction);
|
||||
synchronized (lock) {
|
||||
myCustomSearchActions.add(searchAction);
|
||||
}
|
||||
}
|
||||
|
||||
public List<PsiSearchRequest> getSearchRequests() {
|
||||
return myRequests;
|
||||
public boolean hasRequests() {
|
||||
synchronized (lock) {
|
||||
return !myWordRequests.isEmpty() || !myCustomSearchActions.isEmpty() || !myQueryRequests.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Processor<Processor<PsiReference>>> getCustomSearchActions() {
|
||||
return myCustomSearchActions;
|
||||
public List<QuerySearchRequest> takeQueryRequests() {
|
||||
return takeRequests(myQueryRequests);
|
||||
}
|
||||
|
||||
private <T> List<T> takeRequests(List<T> list) {
|
||||
synchronized (lock) {
|
||||
final List<T> requests = new ArrayList<T>(list);
|
||||
requests.addAll(list);
|
||||
list.clear();
|
||||
return requests;
|
||||
}
|
||||
}
|
||||
|
||||
public List<PsiSearchRequest> takeSearchRequests() {
|
||||
return takeRequests(myWordRequests);
|
||||
}
|
||||
|
||||
public List<Processor<Processor<PsiReference>>> takeCustomSearchActions() {
|
||||
return takeRequests(myCustomSearchActions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,7 @@ package com.intellij.psi.search.searches;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchRequestQuery;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.util.*;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -111,4 +108,21 @@ public class ReferencesSearch extends ExtensibleQueryFactory<PsiReference, Refer
|
||||
return new UniqueResultsQuery(composite, TObjectHashingStrategy.CANONICAL, ReferenceDescriptor.MAPPER);
|
||||
}
|
||||
|
||||
public static void searchOptimized(@NotNull PsiElement element, @NotNull SearchScope searchScope, boolean ignoreAccessScope,
|
||||
@NotNull SearchRequestCollector collector, final Processor<PsiReference> processor) {
|
||||
searchOptimized(element, searchScope, ignoreAccessScope, collector, false, new PairProcessor<PsiReference, SearchRequestCollector>() {
|
||||
@Override
|
||||
public boolean process(PsiReference psiReference, SearchRequestCollector collector) {
|
||||
return processor.process(psiReference);
|
||||
}
|
||||
});
|
||||
}
|
||||
public static void searchOptimized(@NotNull PsiElement element, @NotNull SearchScope searchScope, boolean ignoreAccessScope,
|
||||
@NotNull SearchRequestCollector collector, final boolean inReadAction, PairProcessor<PsiReference, SearchRequestCollector> processor) {
|
||||
final SearchRequestCollector nested = new SearchRequestCollector();
|
||||
collector.searchQuery(new QuerySearchRequest(search(new SearchParameters(element, searchScope, ignoreAccessScope, nested)), nested,
|
||||
inReadAction, processor));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.daemon;
|
||||
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.openapi.editor.HectorComponentPanel;
|
||||
import com.intellij.openapi.editor.HectorComponentPanelsProvider;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PowerSaveHectorProvider implements HectorComponentPanelsProvider {
|
||||
@Override
|
||||
public HectorComponentPanel createConfigurable(@NotNull PsiFile file) {
|
||||
return new HectorComponentPanel() {
|
||||
private JCheckBox myCheckBox = new JCheckBox("Power Save Mode");
|
||||
|
||||
@Override
|
||||
public JComponent createComponent() {
|
||||
return myCheckBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return myCheckBox.isSelected() != PowerSaveMode.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
PowerSaveMode.setEnabled(myCheckBox.isSelected());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
myCheckBox.setSelected(PowerSaveMode.isEnabled());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeUIResources() {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+2
@@ -27,6 +27,7 @@ import com.intellij.codeInsight.daemon.ReferenceImporter;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.codeInsight.intention.impl.IntentionHintComponent;
|
||||
import com.intellij.concurrency.Job;
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -586,6 +587,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
if (!myUpdateByTimerEnabled) return;
|
||||
if (PowerSaveMode.isEnabled()) return;
|
||||
if (myDisposed || myProject.isDisposed()) return;
|
||||
final Collection<FileEditor> activeEditors = myDaemonListeners.getSelectedEditors();
|
||||
if (activeEditors.isEmpty()) return;
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.daemon.impl;
|
||||
import com.intellij.ProjectTopics;
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeInsight.hint.TooltipController;
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.ide.todo.TodoConfiguration;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
@@ -195,6 +196,13 @@ public class DaemonListeners implements Disposable {
|
||||
}
|
||||
});
|
||||
|
||||
connection.subscribe(PowerSaveMode.TOPIC, new PowerSaveMode.Listener() {
|
||||
@Override
|
||||
public void powerSaveStateChanged() {
|
||||
stopDaemon(true);
|
||||
}
|
||||
});
|
||||
|
||||
CommandProcessor.getInstance().addCommandListener(new MyCommandListener(), this);
|
||||
ApplicationManager.getApplication().addApplicationListener(myApplicationListener);
|
||||
EditorColorsManager.getInstance().addEditorColorsListener(myEditorColorsListener);
|
||||
|
||||
+8
-2
@@ -20,6 +20,7 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.codeInsight.daemon.DaemonBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightLevelUtil;
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.markup.ErrorStripeRenderer;
|
||||
@@ -109,7 +110,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer {
|
||||
final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(myProject);
|
||||
status.errorCount = new int[severityRegistrar.getSeveritiesCount()];
|
||||
status.rootsNumber = roots.length;
|
||||
fillDaemonCodeAnalyzerErrorsSatus(status, fillErrorsCount);
|
||||
fillDaemonCodeAnalyzerErrorsStatus(status, fillErrorsCount);
|
||||
List<TextEditorHighlightingPass> passes = myDaemonCodeAnalyzer.getPassesToShowProgressFor(myFile);
|
||||
ArrayList<DaemonCodeAnalyzerStatus.PassStatus> passStati = new ArrayList<DaemonCodeAnalyzerStatus.PassStatus>();
|
||||
for (TextEditorHighlightingPass tepass : passes) {
|
||||
@@ -127,7 +128,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer {
|
||||
return status;
|
||||
}
|
||||
|
||||
protected void fillDaemonCodeAnalyzerErrorsSatus(DaemonCodeAnalyzerStatus status, boolean fillErrorsCount) {
|
||||
protected void fillDaemonCodeAnalyzerErrorsStatus(DaemonCodeAnalyzerStatus status, boolean fillErrorsCount) {
|
||||
final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(myProject);
|
||||
List<HighlightInfo> highlights = DaemonCodeAnalyzerImpl.getHighlights(myDocument, myProject);
|
||||
if (highlights == null) highlights = Arrays.asList(HighlightInfo.EMPTY_ARRAY);
|
||||
@@ -185,6 +186,11 @@ public class TrafficLightRenderer implements ErrorStripeRenderer {
|
||||
|
||||
if (status == null) return null;
|
||||
@NonNls String text = HTML_HEADER;
|
||||
if (PowerSaveMode.isEnabled()) {
|
||||
text += "Code analysis is disabled in power save mode.";
|
||||
text += HTML_FOOTER;
|
||||
return text;
|
||||
}
|
||||
if (status.noHighlightingRoots != null && status.noHighlightingRoots.length == status.rootsNumber) {
|
||||
text += DaemonBundle.message("analysis.hasnot.been.run");
|
||||
text += HTML_FOOTER;
|
||||
|
||||
+8
-4
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.hint.HintManagerImpl;
|
||||
import com.intellij.codeInsight.hint.HintUtil;
|
||||
import com.intellij.ide.actions.ExternalJavaDocAction;
|
||||
import com.intellij.lang.documentation.DocumentationProvider;
|
||||
import com.intellij.lang.documentation.ExternalDocumentationHandler;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
@@ -405,10 +406,13 @@ public class DocumentationComponent extends JPanel implements Disposable {
|
||||
if (myElement != null) {
|
||||
final PsiElement element = myElement.getElement();
|
||||
final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element);
|
||||
final List<String> urls = provider.getUrlFor(element, DocumentationManager.getOriginalElement(element));
|
||||
assert urls != null;
|
||||
assert !urls.isEmpty();
|
||||
ExternalJavaDocAction.showExternalJavadoc(urls);
|
||||
final PsiElement originalElement = DocumentationManager.getOriginalElement(element);
|
||||
if (!(provider instanceof ExternalDocumentationHandler) || !((ExternalDocumentationHandler)provider).handleExternal(element, originalElement)) {
|
||||
final List<String> urls = provider.getUrlFor(element, originalElement);
|
||||
assert urls != null;
|
||||
assert !urls.isEmpty();
|
||||
ExternalJavaDocAction.showExternalJavadoc(urls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-21
@@ -33,6 +33,7 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageDocumentation;
|
||||
import com.intellij.lang.documentation.CompositeDocumentationProvider;
|
||||
import com.intellij.lang.documentation.DocumentationProvider;
|
||||
import com.intellij.lang.documentation.ExternalDocumentationHandler;
|
||||
import com.intellij.lang.documentation.ExternalDocumentationProvider;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
|
||||
@@ -816,38 +817,43 @@ public class DocumentationManager {
|
||||
}
|
||||
}
|
||||
else {
|
||||
final DocumentationProvider provider = getProviderFromElement(psiElement);
|
||||
if (!(provider instanceof ExternalDocumentationHandler) ||
|
||||
!((ExternalDocumentationHandler)provider).handleExternalLink(manager, url, psiElement)) {
|
||||
final String docUrl = url;
|
||||
|
||||
fetchDocInfo
|
||||
(new DocumentationCollector() {
|
||||
public String getDocumentation() throws Exception {
|
||||
if (docUrl.startsWith(DOC_ELEMENT_PROTOCOL)) {
|
||||
final List<String> urls = ApplicationManager.getApplication().runReadAction(
|
||||
fetchDocInfo
|
||||
(new DocumentationCollector() {
|
||||
public String getDocumentation() throws Exception {
|
||||
if (docUrl.startsWith(DOC_ELEMENT_PROTOCOL)) {
|
||||
final List<String> urls = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<List<String>>() {
|
||||
public List<String> compute() {
|
||||
final DocumentationProvider provider = getProviderFromElement(psiElement);
|
||||
return provider.getUrlFor(psiElement, getOriginalElement(psiElement));
|
||||
}
|
||||
}
|
||||
);
|
||||
BrowserUtil.launchBrowser(urls != null && !urls.isEmpty() ? urls.get(0) : docUrl);
|
||||
} else {
|
||||
BrowserUtil.launchBrowser(docUrl);
|
||||
);
|
||||
BrowserUtil.launchBrowser(urls != null && !urls.isEmpty() ? urls.get(0) : docUrl);
|
||||
}
|
||||
else {
|
||||
BrowserUtil.launchBrowser(docUrl);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public PsiElement getElement() {
|
||||
//String loc = getElementLocator(docUrl);
|
||||
//
|
||||
//if (loc != null) {
|
||||
// PsiElement context = component.getElement();
|
||||
// return JavaDocUtil.findReferenceTarget(context.getManager(), loc, context);
|
||||
//}
|
||||
public PsiElement getElement() {
|
||||
//String loc = getElementLocator(docUrl);
|
||||
//
|
||||
//if (loc != null) {
|
||||
// PsiElement context = component.getElement();
|
||||
// return JavaDocUtil.findReferenceTarget(context.getManager(), loc, context);
|
||||
//}
|
||||
|
||||
return psiElement;
|
||||
}
|
||||
}, component);
|
||||
return psiElement;
|
||||
}
|
||||
}, component);
|
||||
}
|
||||
}
|
||||
|
||||
component.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
|
||||
@@ -157,7 +157,7 @@ public class RunContentBuilder implements LogConsoleManager, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
final Content consoleContent = ui.createContent("Console", console.getComponent(), "Console",
|
||||
final Content consoleContent = ui.createContent(ExecutionConsole.CONSOLE_CONTENT_ID, console.getComponent(), "Console",
|
||||
IconLoader.getIcon("/debugger/console.png"),
|
||||
console.getPreferredFocusableComponent());
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.ide;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.messages.Topic;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PowerSaveMode {
|
||||
private boolean myEnabled = false;
|
||||
private final MessageBus myBus;
|
||||
|
||||
public PowerSaveMode(MessageBus bus) {
|
||||
myBus = bus;
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
return ServiceManager.getService(PowerSaveMode.class).myEnabled;
|
||||
}
|
||||
|
||||
public static void setEnabled(boolean value) {
|
||||
final PowerSaveMode instance = ServiceManager.getService(PowerSaveMode.class);
|
||||
if (instance.myEnabled != value) {
|
||||
instance.myEnabled = value;
|
||||
instance.myBus.syncPublisher(TOPIC).powerSaveStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void powerSaveStateChanged();
|
||||
}
|
||||
|
||||
public static Topic<Listener> TOPIC = Topic.create("PowerSaveMode.Listener", Listener.class);
|
||||
}
|
||||
@@ -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.ide.actions;
|
||||
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class TogglePowerSaveAction extends ToggleAction implements DumbAware {
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return PowerSaveMode.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
PowerSaveMode.setEnabled(state);
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,7 @@ public final class CustomFileTypeLexer extends AbstractCustomLexer {
|
||||
tokenParsers.add(multilineCommentParser);
|
||||
}
|
||||
tokenParsers.add(numberParser);
|
||||
tokenParsers.add(new PunctuationParser());
|
||||
if (hexNumberParser != null) {
|
||||
tokenParsers.add(hexNumberParser);
|
||||
}
|
||||
|
||||
+6
-2
@@ -42,8 +42,10 @@ class CustomFileTypeBraceMatcher implements BraceMatcher {
|
||||
}
|
||||
|
||||
public boolean isRBraceToken(HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
|
||||
final IElementType tokenType = iterator.getTokenType();
|
||||
return isRBraceToken(iterator.getTokenType());
|
||||
}
|
||||
|
||||
private static boolean isRBraceToken(IElementType tokenType) {
|
||||
return tokenType == CustomHighlighterTokenType.R_BRACKET ||
|
||||
tokenType == CustomHighlighterTokenType.R_PARENTH ||
|
||||
tokenType == CustomHighlighterTokenType.R_BRACE;
|
||||
@@ -80,7 +82,9 @@ class CustomFileTypeBraceMatcher implements BraceMatcher {
|
||||
}
|
||||
|
||||
public boolean isPairedBracesAllowedBeforeType(@NotNull final IElementType lbraceType, @Nullable final IElementType contextType) {
|
||||
return contextType == CustomHighlighterTokenType.WHITESPACE;
|
||||
return contextType == CustomHighlighterTokenType.PUNCTUATION ||
|
||||
contextType == CustomHighlighterTokenType.WHITESPACE ||
|
||||
isRBraceToken(contextType);
|
||||
}
|
||||
|
||||
public int getCodeConstructStart(final PsiFile file, final int openingBraceOffset) {
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.ide.highlighter.custom.tokens;
|
||||
|
||||
import com.intellij.psi.CustomHighlighterTokenType;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class PunctuationParser extends BaseTokenParser {
|
||||
@Override
|
||||
public boolean hasToken(int position) {
|
||||
final char c = myBuffer.charAt(position);
|
||||
if (".,:;".indexOf(c) >= 0) {
|
||||
myTokenInfo.updateData(position, position+1, CustomHighlighterTokenType.PUNCTUATION);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSmartUpdateShift() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+23
-6
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.impl.HectorComponent;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightLevelUtil;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.PowerSaveMode;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
@@ -38,6 +39,7 @@ import com.intellij.psi.PsiManager;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -57,7 +59,8 @@ public class TogglePopupHintsPanel implements StatusBarWidget, StatusBarWidget.I
|
||||
|
||||
public TogglePopupHintsPanel(@NotNull final Project project) {
|
||||
myCurrentIcon = EMPTY_ICON;
|
||||
project.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
|
||||
final MessageBusConnection connection = project.getMessageBus().connect();
|
||||
connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
|
||||
@Override
|
||||
public void selectionChanged(FileEditorManagerEvent event) {
|
||||
updateStatus();
|
||||
@@ -68,6 +71,12 @@ public class TogglePopupHintsPanel implements StatusBarWidget, StatusBarWidget.I
|
||||
updateStatus();
|
||||
}
|
||||
});
|
||||
connection.subscribe(PowerSaveMode.TOPIC, new PowerSaveMode.Listener() {
|
||||
@Override
|
||||
public void powerSaveStateChanged() {
|
||||
updateStatus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
@@ -130,13 +139,21 @@ public class TogglePopupHintsPanel implements StatusBarWidget, StatusBarWidget.I
|
||||
|
||||
private void updateStatus(PsiFile file) {
|
||||
if (isStateChangeable(file)) {
|
||||
if (HighlightLevelUtil.shouldInspect(file)) {
|
||||
if (PowerSaveMode.isEnabled()) {
|
||||
myCurrentIcon = EMPTY_ICON;
|
||||
myToolTipText = "Code analysis is disabled in power save mode. ";
|
||||
}
|
||||
else if (HighlightLevelUtil.shouldInspect(file)) {
|
||||
myCurrentIcon = INSPECTIONS_ICON;
|
||||
myToolTipText = "Current inspection profile: " + InspectionProjectProfileManager.getInstance(file.getProject()).getInspectionProfile().getName() + ". ";
|
||||
} else if (HighlightLevelUtil.shouldHighlight(file)) {
|
||||
myToolTipText = "Current inspection profile: " +
|
||||
InspectionProjectProfileManager.getInstance(file.getProject()).getInspectionProfile().getName() +
|
||||
". ";
|
||||
}
|
||||
else if (HighlightLevelUtil.shouldHighlight(file)) {
|
||||
myCurrentIcon = SYNTAX_ONLY_ICON;
|
||||
myToolTipText = "Highlighting level is: Syntax. ";
|
||||
} else {
|
||||
myToolTipText = "Highlighting level is: Syntax. ";
|
||||
}
|
||||
else {
|
||||
myCurrentIcon = INSPECTIONS_OFF_ICON;
|
||||
myToolTipText = "Inspections are off. ";
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -487,34 +488,62 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
myManager.getCacheManager().processFilesWithWord(processor, word, UsageSearchContext.IN_STRINGS, scope, true);
|
||||
}
|
||||
|
||||
public boolean processRequests(@NotNull SearchRequestCollector request, Processor<PsiReference> processor) {
|
||||
final MultiMap<Set<IdIndexEntry>, PsiSearchRequest> singles = new MultiMap<Set<IdIndexEntry>, PsiSearchRequest>();
|
||||
final List<Processor<Processor<PsiReference>>> customs = new ArrayList<Processor<Processor<PsiReference>>>();
|
||||
distributePrimitives(request, singles, customs);
|
||||
|
||||
if (!processRequestsOptimized(singles, processor)) {
|
||||
return false;
|
||||
private static class RequestWithProcessor extends Pair<PsiSearchRequest, Processor<PsiReference>> {
|
||||
private RequestWithProcessor(PsiSearchRequest first, Processor<PsiReference> second) {
|
||||
super(first, second);
|
||||
}
|
||||
|
||||
for (Processor<Processor<PsiReference>> custom : customs) {
|
||||
if (!custom.process(processor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private boolean processRequestsOptimized(MultiMap<Set<IdIndexEntry>, PsiSearchRequest> singles, final Processor<PsiReference> consumer) {
|
||||
public boolean processRequests(@NotNull SearchRequestCollector collector, Processor<PsiReference> processor) {
|
||||
Map<SearchRequestCollector, Processor<PsiReference>> collectors = new HashMap<SearchRequestCollector, Processor<PsiReference>>();
|
||||
collectors.put(collector, processor);
|
||||
|
||||
appendCollectorsFromQueryRequests(collectors);
|
||||
|
||||
do {
|
||||
final MultiMap<Set<IdIndexEntry>, RequestWithProcessor> singles = new MultiMap<Set<IdIndexEntry>, RequestWithProcessor>();
|
||||
final List<Computable<Boolean>> customs = new ArrayList<Computable<Boolean>>();
|
||||
distributePrimitives(collectors, singles, customs);
|
||||
|
||||
if (!processRequestsOptimized(singles)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Computable<Boolean> custom : customs) {
|
||||
if (!custom.compute()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while (appendCollectorsFromQueryRequests(collectors));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean appendCollectorsFromQueryRequests(Map<SearchRequestCollector, Processor<PsiReference>> collectors) {
|
||||
boolean changed = false;
|
||||
LinkedList<SearchRequestCollector> queue = new LinkedList<SearchRequestCollector>(collectors.keySet());
|
||||
while (!queue.isEmpty()) {
|
||||
final SearchRequestCollector each = queue.removeFirst();
|
||||
for (QuerySearchRequest request : each.takeQueryRequests()) {
|
||||
request.runQuery();
|
||||
collectors.put(request.collector, request.processor);
|
||||
queue.addLast(request.collector);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
private boolean processRequestsOptimized(MultiMap<Set<IdIndexEntry>, RequestWithProcessor> singles) {
|
||||
if (singles.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (singles.size() == 1) {
|
||||
final Collection<PsiSearchRequest> requests = singles.get(singles.keySet().iterator().next());
|
||||
final Collection<RequestWithProcessor> requests = singles.get(singles.keySet().iterator().next());
|
||||
if (requests.size() == 1) {
|
||||
return processSingleRequest(requests.iterator().next(), consumer);
|
||||
final RequestWithProcessor theOnly = requests.iterator().next();
|
||||
return processSingleRequest(theOnly.first, theOnly.second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,13 +553,17 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
progress.setText(PsiBundle.message("psi.scanning.files.progress"));
|
||||
}
|
||||
|
||||
final MultiMap<VirtualFile, PsiSearchRequest> candidateFiles = collectFiles(singles);
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> candidateFiles = collectFiles(singles);
|
||||
|
||||
final Map<PsiSearchRequest, StringSearcher> searchers = new HashMap<PsiSearchRequest, StringSearcher>();
|
||||
if (candidateFiles.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Map<RequestWithProcessor, StringSearcher> searchers = new HashMap<RequestWithProcessor, StringSearcher>();
|
||||
final Set<String> allWords = new TreeSet<String>();
|
||||
for (PsiSearchRequest singleRequest : candidateFiles.values()) {
|
||||
searchers.put(singleRequest, new StringSearcher(singleRequest.word, singleRequest.caseSensitive, true));
|
||||
allWords.add(singleRequest.word);
|
||||
for (RequestWithProcessor singleRequest : candidateFiles.values()) {
|
||||
searchers.put(singleRequest, new StringSearcher(singleRequest.first.word, singleRequest.first.caseSensitive, true));
|
||||
allWords.add(singleRequest.first.word);
|
||||
}
|
||||
|
||||
if (progress != null) {
|
||||
@@ -540,9 +573,9 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
return processPsiFileRoots(progress, new ArrayList<VirtualFile>(candidateFiles.keySet()), new Processor<PsiElement>() {
|
||||
public boolean process(PsiElement psiRoot) {
|
||||
final VirtualFile vfile = psiRoot.getContainingFile().getVirtualFile();
|
||||
for (final PsiSearchRequest singleRequest : candidateFiles.get(vfile)) {
|
||||
for (final RequestWithProcessor singleRequest : candidateFiles.get(vfile)) {
|
||||
StringSearcher searcher = searchers.get(singleRequest);
|
||||
if (!LowLevelSearchUtil.processElementsContainingWordInElement(adaptProcessor(singleRequest, consumer), psiRoot, searcher, false, progress)) {
|
||||
if (!LowLevelSearchUtil.processElementsContainingWordInElement(adaptProcessor(singleRequest.first, singleRequest.second), psiRoot, searcher, false, progress)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -565,18 +598,18 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
};
|
||||
}
|
||||
|
||||
private MultiMap<VirtualFile, PsiSearchRequest> collectFiles(MultiMap<Set<IdIndexEntry>, PsiSearchRequest> singles) {
|
||||
private MultiMap<VirtualFile, RequestWithProcessor> collectFiles(MultiMap<Set<IdIndexEntry>, RequestWithProcessor> singles) {
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex();
|
||||
final MultiMap<VirtualFile, PsiSearchRequest> result = new MultiMap<VirtualFile, PsiSearchRequest>();
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> result = new MultiMap<VirtualFile, RequestWithProcessor>();
|
||||
for (Set<IdIndexEntry> key : singles.keySet()) {
|
||||
final Collection<PsiSearchRequest> data = singles.get(key);
|
||||
final Collection<RequestWithProcessor> data = singles.get(key);
|
||||
GlobalSearchScope commonScope = uniteScopes(data);
|
||||
|
||||
MultiMap<VirtualFile, PsiSearchRequest> intersection = null;
|
||||
MultiMap<VirtualFile, RequestWithProcessor> intersection = null;
|
||||
|
||||
boolean first = true;
|
||||
for (IdIndexEntry entry : key) {
|
||||
final MultiMap<VirtualFile, PsiSearchRequest> local = findFilesWithIndexEntry(entry, index, data, commonScope);
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> local = findFilesWithIndexEntry(entry, index, data, commonScope);
|
||||
if (first) {
|
||||
intersection = local;
|
||||
first = false;
|
||||
@@ -593,31 +626,34 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GlobalSearchScope uniteScopes(Collection<PsiSearchRequest> requests) {
|
||||
private static GlobalSearchScope uniteScopes(Collection<RequestWithProcessor> requests) {
|
||||
GlobalSearchScope commonScope = null;
|
||||
for (PsiSearchRequest r : requests) {
|
||||
final GlobalSearchScope scope = (GlobalSearchScope)r.searchScope;
|
||||
for (RequestWithProcessor r : requests) {
|
||||
final GlobalSearchScope scope = (GlobalSearchScope)r.first.searchScope;
|
||||
commonScope = commonScope == null ? scope : commonScope.uniteWith(scope);
|
||||
}
|
||||
assert commonScope != null;
|
||||
return commonScope;
|
||||
}
|
||||
|
||||
private static MultiMap<VirtualFile, PsiSearchRequest> findFilesWithIndexEntry(final IdIndexEntry entry,
|
||||
private static MultiMap<VirtualFile, RequestWithProcessor> findFilesWithIndexEntry(final IdIndexEntry entry,
|
||||
final ProjectFileIndex index,
|
||||
final Collection<PsiSearchRequest> data,
|
||||
final Collection<RequestWithProcessor> data,
|
||||
final GlobalSearchScope commonScope) {
|
||||
final MultiMap<VirtualFile, PsiSearchRequest> local = new MultiMap<VirtualFile, PsiSearchRequest>();
|
||||
final MultiMap<VirtualFile, RequestWithProcessor> local = new MultiMap<VirtualFile, RequestWithProcessor>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
ProgressManager.checkCanceled();
|
||||
FileBasedIndex.getInstance().processValues(IdIndex.NAME, entry, null, new FileBasedIndex.ValueProcessor<Integer>() {
|
||||
public boolean process(VirtualFile file, Integer value) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!IndexCacheManagerImpl.shouldBeFound(file, index)) {
|
||||
return true;
|
||||
}
|
||||
int mask = value.intValue();
|
||||
for (PsiSearchRequest single : data) {
|
||||
if ((mask & single.searchContext) != 0 && ((GlobalSearchScope)single.searchScope).contains(file)) {
|
||||
for (RequestWithProcessor single : data) {
|
||||
final PsiSearchRequest request = single.first;
|
||||
if ((mask & request.searchContext) != 0 && ((GlobalSearchScope)request.searchScope).contains(file)) {
|
||||
local.putValue(file, single);
|
||||
}
|
||||
}
|
||||
@@ -630,27 +666,38 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
return local;
|
||||
}
|
||||
|
||||
private void distributePrimitives(SearchRequestCollector request,
|
||||
MultiMap<Set<IdIndexEntry>, PsiSearchRequest> singles,
|
||||
List<Processor<Processor<PsiReference>>> customs) {
|
||||
for (final PsiSearchRequest primitive : request.getSearchRequests()) {
|
||||
final SearchScope scope = primitive.searchScope;
|
||||
if (scope instanceof LocalSearchScope) {
|
||||
customs.add(new Processor<Processor<PsiReference>>() {
|
||||
public boolean process(Processor<PsiReference> processor) {
|
||||
return processSingleRequest(primitive, processor);
|
||||
private void distributePrimitives(final Map<SearchRequestCollector, Processor<PsiReference>> collectors,
|
||||
MultiMap<Set<IdIndexEntry>, RequestWithProcessor> singles,
|
||||
List<Computable<Boolean>> customs) {
|
||||
for (final SearchRequestCollector collector : collectors.keySet()) {
|
||||
final Processor<PsiReference> processor = collectors.get(collector);
|
||||
for (final PsiSearchRequest primitive : collector.takeSearchRequests()) {
|
||||
final SearchScope scope = primitive.searchScope;
|
||||
if (scope instanceof LocalSearchScope) {
|
||||
customs.add(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return processSingleRequest(primitive, processor);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final List<String> words = StringUtil.getWordsIn(primitive.word);
|
||||
final Set<IdIndexEntry> key = new HashSet<IdIndexEntry>(words.size() * 2);
|
||||
for (String word : words) {
|
||||
key.add(new IdIndexEntry(word, primitive.caseSensitive));
|
||||
}
|
||||
singles.putValue(key, new RequestWithProcessor(primitive, processor));
|
||||
}
|
||||
}
|
||||
for (final Processor<Processor<PsiReference>> customAction : collector.takeCustomSearchActions()) {
|
||||
customs.add(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return customAction.process(processor);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final List<String> words = StringUtil.getWordsIn(primitive.word);
|
||||
final Set<IdIndexEntry> key = new HashSet<IdIndexEntry>(words.size() * 2);
|
||||
for (String word : words) {
|
||||
key.add(new IdIndexEntry(word, primitive.caseSensitive));
|
||||
}
|
||||
singles.putValue(key, primitive);
|
||||
}
|
||||
}
|
||||
customs.addAll(request.getCustomSearchActions());
|
||||
}
|
||||
|
||||
private boolean processSingleRequest(PsiSearchRequest single, Processor<PsiReference> consumer) {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.util.proximity;
|
||||
|
||||
import com.intellij.openapi.util.NullableLazyKey;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.ProximityLocation;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* NOTE: This class is only registered in platform-based IDEs. In IDEA, SamePackageWeigher is used instead.
|
||||
*
|
||||
* @author yole
|
||||
*/
|
||||
public class SameDirectoryWeigher extends ProximityWeigher {
|
||||
private static final NullableLazyKey<PsiDirectory, ProximityLocation>
|
||||
PLACE_DIRECTORY = NullableLazyKey.create("placeDirectory", new NullableFunction<ProximityLocation, PsiDirectory>() {
|
||||
@Override
|
||||
public PsiDirectory fun(ProximityLocation location) {
|
||||
return PsiTreeUtil.getParentOfType(location.getPosition(), PsiDirectory.class, false);
|
||||
}
|
||||
});
|
||||
|
||||
public Comparable weigh(@NotNull final PsiElement element, final ProximityLocation location) {
|
||||
final PsiDirectory placeDirectory = PLACE_DIRECTORY.getValue(location);
|
||||
if (placeDirectory == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return placeDirectory.equals(PsiTreeUtil.getParentOfType(element, PsiDirectory.class, false));
|
||||
}
|
||||
}
|
||||
@@ -1662,10 +1662,20 @@ public class AbstractTreeUi {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (myResettingToReadyNow.get()) {
|
||||
getReady(this).notify(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
myResettingToReadyNow.set(true);
|
||||
|
||||
invokeLaterIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
if (!myResettingToReadyNow.get()) {
|
||||
result.setDone();
|
||||
return;
|
||||
}
|
||||
|
||||
Progressive[] progressives = myBatchIndicators.keySet().toArray(new Progressive[myBatchIndicators.size()]);
|
||||
for (Progressive each : progressives) {
|
||||
myBatchIndicators.remove(each).cancel();
|
||||
@@ -1790,6 +1800,10 @@ public class AbstractTreeUi {
|
||||
return isReady(false);
|
||||
}
|
||||
|
||||
public boolean isCancelledReady() {
|
||||
return isReady(false) && myCancelledBuild.size() > 0;
|
||||
}
|
||||
|
||||
public boolean isReady(boolean attempt) {
|
||||
Boolean ready = _isReady(attempt);
|
||||
return ready != null && ready.booleanValue();
|
||||
@@ -1864,6 +1878,11 @@ public class AbstractTreeUi {
|
||||
try {
|
||||
try {
|
||||
myYeildingPasses.remove(pass);
|
||||
|
||||
if (!canInitiateNewActivity()) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
|
||||
runnable.run();
|
||||
}
|
||||
finally {
|
||||
|
||||
+5
-5
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.hint;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.DocumentFragment;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.FoldingModelEx;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -51,7 +48,10 @@ public class DocumentFragmentTooltipRenderer implements TooltipRenderer {
|
||||
|
||||
JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane();
|
||||
|
||||
p = editor.logicalPositionToXY(new LogicalPosition(startLine, 0));
|
||||
// There is a possible case that collapsed folding region is soft wrapped, hence, we need to anchor
|
||||
// not logical but visual line start.
|
||||
VisualPosition visual = editor.offsetToVisualPosition(startOffset);
|
||||
p = editor.visualPositionToXY(visual);
|
||||
p = SwingUtilities.convertPoint(
|
||||
((EditorEx)editor).getGutterComponentEx(),
|
||||
p,
|
||||
|
||||
@@ -341,11 +341,10 @@ public class EditorUtil {
|
||||
for (int i = start; i < end; i++) {
|
||||
char c = text.charAt(i);
|
||||
prevX = x;
|
||||
if (c == '\t') {
|
||||
x = nextTabStop(x, editor);
|
||||
}
|
||||
else {
|
||||
x += charWidth(c, Font.PLAIN, editor);
|
||||
switch (c) {
|
||||
case '\t': x = nextTabStop(x, editor); break;
|
||||
case '\n': x = result = 0; break;
|
||||
default: x += charWidth(c, Font.PLAIN, editor);
|
||||
}
|
||||
result += columnsNumber(c, x, prevX, getSpaceWidth(Font.PLAIN, editor));
|
||||
}
|
||||
|
||||
@@ -1055,7 +1055,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
}
|
||||
|
||||
if (logLine == 0) {
|
||||
if (logLine <= 0) {
|
||||
lineStartOffset = 0;
|
||||
}
|
||||
else if (lineStartOffset < 0) {
|
||||
@@ -2700,6 +2700,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
|
||||
if (column < 0) column = 0;
|
||||
line = Math.min(line, myDocument.getLineCount() - 1);
|
||||
|
||||
LogicalPosition softWrapUnawareResult = new LogicalPosition(line, column);
|
||||
return mySoftWrapModel.adjustLogicalPosition(softWrapUnawareResult, visiblePos);
|
||||
@@ -4797,7 +4798,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
// I.e. we shouldn't use widths of the lines that are not shown for max width calculation because previous widths are calculated
|
||||
// for another visible area width.
|
||||
int startToUse = 0;
|
||||
int endToUse = lineCount;
|
||||
int endToUse = Math.min(lineCount, myLineWidths.size());
|
||||
if (getSoftWrapModel().isSoftWrappingEnabled()) {
|
||||
Rectangle visibleArea = getScrollingModel().getVisibleArea();
|
||||
startToUse = xyToLogicalPosition(visibleArea.getLocation()).line + 1;
|
||||
|
||||
+9
-1
@@ -583,10 +583,12 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
|
||||
|
||||
private class MyErrorPanel extends ButtonlessScrollBarUI implements MouseMotionListener, MouseListener {
|
||||
private PopupHandler myHandler;
|
||||
private ErrorStripeButton myErrorStripeButton;
|
||||
|
||||
@Override
|
||||
protected JButton createDecreaseButton(int orientation) {
|
||||
return new ErrorStripeButton();
|
||||
myErrorStripeButton = new ErrorStripeButton();
|
||||
return myErrorStripeButton;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -594,12 +596,16 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
|
||||
super.installListeners();
|
||||
scrollbar.addMouseMotionListener(this);
|
||||
scrollbar.addMouseListener(this);
|
||||
myErrorStripeButton.addMouseMotionListener(this);
|
||||
myErrorStripeButton.addMouseListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners() {
|
||||
scrollbar.removeMouseMotionListener(this);
|
||||
scrollbar.removeMouseListener(this);
|
||||
myErrorStripeButton.removeMouseMotionListener(this);
|
||||
myErrorStripeButton.removeMouseListener(this);
|
||||
super.uninstallListeners();
|
||||
}
|
||||
|
||||
@@ -735,10 +741,12 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
|
||||
public void setPopupHandler(final PopupHandler handler) {
|
||||
if (myHandler != null) {
|
||||
scrollbar.removeMouseListener(myHandler);
|
||||
myErrorStripeButton.removeMouseListener(myHandler);
|
||||
}
|
||||
|
||||
myHandler = handler;
|
||||
scrollbar.addMouseListener(handler);
|
||||
myErrorStripeButton.addMouseListener(myHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+289
-244
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper;
|
||||
import com.intellij.openapi.editor.impl.IterationState;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -36,6 +37,8 @@ import java.util.List;
|
||||
*/
|
||||
public class SoftWrapDataMapper {
|
||||
|
||||
private static final VisualPosition DUMMY_VISUAL = new VisualPosition(Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
|
||||
private final CharBuffer myCharBuffer = CharBuffer.allocate(1);
|
||||
|
||||
private final EditorTextRepresentationHelper myTextRepresentationHelper;
|
||||
@@ -67,6 +70,17 @@ public class SoftWrapDataMapper {
|
||||
|
||||
@NotNull
|
||||
public LogicalPosition adjustLogicalPosition(@NotNull LogicalPosition defaultLogical, @NotNull VisualPosition visual) {
|
||||
try {
|
||||
return doAdjustLogicalPosition(defaultLogical, visual);
|
||||
}
|
||||
finally {
|
||||
myFontTypeProvider.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"AssignmentToForLoopParameter"})
|
||||
@NotNull
|
||||
private LogicalPosition doAdjustLogicalPosition(@NotNull LogicalPosition defaultLogical, @NotNull VisualPosition visual) {
|
||||
Document document = myEditor.getDocument();
|
||||
int maxOffset = document.getLineEndOffset(Math.min(defaultLogical.line, document.getLineCount() - 1));
|
||||
|
||||
@@ -86,7 +100,7 @@ public class SoftWrapDataMapper {
|
||||
int max = Math.min(softWraps.size(), endIndex);
|
||||
for (; i < max; i++) {
|
||||
TextChange softWrap = softWraps.get(i);
|
||||
if (foldingModel.isOffsetCollapsed(softWrap.getStart())) {
|
||||
if (!isVisible(softWrap)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -97,10 +111,11 @@ public class SoftWrapDataMapper {
|
||||
if (visualLineBeforeSoftWrapAppliance > visual.line) {
|
||||
softWrapLinesBeforeCurrentLogicalLine += softWrapLinesOnCurrentLogicalLine;
|
||||
int logicalLine = defaultLogical.line - softWrapLinesBeforeCurrentLogicalLine;
|
||||
LogicalPosition foldingUnawarePosition = new LogicalPosition(
|
||||
logicalLine, defaultLogical.column, softWrapLinesBeforeCurrentLogicalLine, 0, 0, 0, 0
|
||||
return new LogicalPosition(
|
||||
logicalLine, defaultLogical.column, softWrapLinesBeforeCurrentLogicalLine, 0, 0,
|
||||
getFoldedLinesBefore(document.getLineStartOffset(logicalLine)),
|
||||
visual.column - defaultLogical.column
|
||||
);
|
||||
return adjustFoldingData(foldingModel, foldingUnawarePosition);
|
||||
}
|
||||
|
||||
if (lastSoftWrapLogicalLine >= 0 && lastSoftWrapLogicalLine != softWrapLine) {
|
||||
@@ -115,24 +130,29 @@ public class SoftWrapDataMapper {
|
||||
continue;
|
||||
}
|
||||
|
||||
int startLineOffset = document.getLineStartOffset(softWrapLine);
|
||||
int endLineOffset = document.getLineEndOffset(softWrapLine);
|
||||
FoldRegion region = foldingModel.getCollapsedRegionAtOffset(endLineOffset);
|
||||
while (region != null) {
|
||||
int line = document.getLineNumber(region.getEndOffset());
|
||||
endLineOffset = document.getLineEndOffset(line);
|
||||
region = foldingModel.getCollapsedRegionAtOffset(endLineOffset);
|
||||
}
|
||||
CharSequence documentText = document.getCharsSequence();
|
||||
|
||||
// If we're here that means that current soft wrap affects logical line that is matched to the given visual line.
|
||||
// We iterate from the logical line start then in order to calculate resulting logical position.
|
||||
Context context = new Context(
|
||||
defaultLogical, visual, softWrapLinesBeforeCurrentLogicalLine, softWrapLinesOnCurrentLogicalLine,
|
||||
visualLineBeforeSoftWrapAppliance, foldingModel
|
||||
visual, softWrapLine, softWrapLinesBeforeCurrentLogicalLine, softWrapLinesOnCurrentLogicalLine,
|
||||
visualLineBeforeSoftWrapAppliance, getFoldedLinesBefore(startLineOffset)
|
||||
);
|
||||
int startLineOffset = document.getLineStartOffset(softWrapLine);
|
||||
int endLineOffset = document.getLineEndOffset(softWrapLine);
|
||||
CharSequence documentText = document.getCharsSequence();
|
||||
|
||||
myFontTypeProvider.init(startLineOffset);
|
||||
context.fontType = myFontTypeProvider.getFontType(startLineOffset);
|
||||
|
||||
for (int j = startLineOffset; j < endLineOffset; j++) {
|
||||
|
||||
// Process soft wrap at the current offset if any.
|
||||
TextChange softWrapToProcess = myStorage.getSoftWrap(j);
|
||||
if (softWrapToProcess != null) {
|
||||
if (softWrapToProcess != null && isVisible(softWrapToProcess)) {
|
||||
context.beforeSoftWrap();
|
||||
if (j >= softWrap.getStart()) {
|
||||
CharSequence softWrapText = softWrapToProcess.getText();
|
||||
@@ -146,7 +166,16 @@ public class SoftWrapDataMapper {
|
||||
context.afterSoftWrap();
|
||||
}
|
||||
|
||||
context.fontType = myFontTypeProvider.getFontType(startLineOffset);
|
||||
context.fontType = myFontTypeProvider.getFontType(j);
|
||||
|
||||
FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(j);
|
||||
if (foldRegion != null) {
|
||||
LogicalPosition result = context.onCollapsedFolding(foldRegion);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
j = foldRegion.getEndOffset();
|
||||
}
|
||||
|
||||
// Process document symbol.
|
||||
LogicalPosition result = context.onNonSoftWrapSymbol(documentText.charAt(j));
|
||||
@@ -154,27 +183,25 @@ public class SoftWrapDataMapper {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
myFontTypeProvider.cleanup();
|
||||
|
||||
// If we are here that means that target visual position is located at virtual space after the line end.
|
||||
int logicalLine = defaultLogical.line - softWrapLinesBeforeCurrentLogicalLine
|
||||
- context.softWrapLinesOnCurrentLineBeforeTargetSoftWrap - context.targetSoftWrapLines;
|
||||
int logicalColumn = context.symbolsOnCurrentLogicalLine + visual.column - context.symbolsOnCurrentVisualLine;
|
||||
int softWrapColumnDiff = visual.column - logicalColumn;
|
||||
LogicalPosition foldingUnawarePosition = new LogicalPosition(
|
||||
logicalLine, logicalColumn, softWrapLinesBeforeCurrentLogicalLine,
|
||||
context.softWrapLinesOnCurrentLineBeforeTargetSoftWrap + context.targetSoftWrapLines, softWrapColumnDiff, 0, 0
|
||||
);
|
||||
return adjustFoldingData(foldingModel, foldingUnawarePosition);
|
||||
context.logicalColumn += visual.column - context.visualColumn;
|
||||
return context.build();
|
||||
}
|
||||
|
||||
// If we are here that means that there is no soft wrap on a logical line that corresponds to the target visual line.
|
||||
softWrapLinesBeforeCurrentLogicalLine += softWrapLinesOnCurrentLogicalLine;
|
||||
int logicalLine = defaultLogical.line - softWrapLinesBeforeCurrentLogicalLine;
|
||||
LogicalPosition foldingUnaware = new LogicalPosition(
|
||||
logicalLine, defaultLogical.column, softWrapLinesBeforeCurrentLogicalLine, 0, 0, 0, 0
|
||||
// There is a possible case that we can't count on given default logical position - e.g. if given visual position line
|
||||
// is more than total document lines count.
|
||||
if (logicalLine < 0) {
|
||||
logicalLine = Math.min(lastSoftWrapLogicalLine + 1, document.getLineCount() - 1);
|
||||
}
|
||||
int foldedLines = getFoldedLinesBefore(document.getLineStartOffset(logicalLine));
|
||||
int foldingColumnDiff = visual.column - defaultLogical.column;
|
||||
return new LogicalPosition(
|
||||
logicalLine, defaultLogical.column, softWrapLinesBeforeCurrentLogicalLine, 0, 0, foldedLines, foldingColumnDiff
|
||||
);
|
||||
return adjustFoldingData(foldingModel, foldingUnaware);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -202,7 +229,6 @@ public class SoftWrapDataMapper {
|
||||
int lineDiff = 0;
|
||||
int column = -1;
|
||||
|
||||
FoldingModel foldingModel = myEditor.getFoldingModel();
|
||||
int targetLogicalLineStartOffset = myEditor.logicalPositionToOffset(new LogicalPosition(logical.line, 0));
|
||||
for (int i = endIndex; i >= 0; i--) {
|
||||
TextChange softWrap = softWraps.get(i);
|
||||
@@ -211,7 +237,7 @@ public class SoftWrapDataMapper {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (foldingModel.isOffsetCollapsed(softWrap.getStart())) {
|
||||
if (!isVisible(softWrap)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -237,120 +263,161 @@ public class SoftWrapDataMapper {
|
||||
return new VisualPosition(visual.line + lineDiff, columnToUse);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"AssignmentToForLoopParameter"})
|
||||
public LogicalPosition offsetToLogicalPosition(int offset) {
|
||||
try {
|
||||
return doOffsetToLogicalPosition(offset);
|
||||
}
|
||||
finally {
|
||||
myFontTypeProvider.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"AssignmentToForLoopParameter"})
|
||||
private LogicalPosition doOffsetToLogicalPosition(int offset) {
|
||||
FoldingModel foldingModel = myEditor.getFoldingModel();
|
||||
Document document = myEditor.getDocument();
|
||||
CharSequence chars = document.getCharsSequence();
|
||||
CharSequence text = document.getCharsSequence();
|
||||
int line = document.getLineNumber(offset);
|
||||
int lineStartOffset = document.getLineStartOffset(line);
|
||||
FoldRegion region = foldingModel.getCollapsedRegionAtOffset(lineStartOffset);
|
||||
while (region != null && region.getStartOffset() != lineStartOffset) {
|
||||
line = document.getLineNumber(region.getStartOffset());
|
||||
lineStartOffset = document.getLineStartOffset(line);
|
||||
region = foldingModel.getCollapsedRegionAtOffset(lineStartOffset);
|
||||
}
|
||||
|
||||
int targetLine = document.getLineNumber(offset);
|
||||
int targetLineStartOffset = document.getLineStartOffset(targetLine);
|
||||
Context context = new Context(line, getSoftWrapIntroducedLinesBefore(lineStartOffset), getFoldedLinesBefore(lineStartOffset));
|
||||
myFontTypeProvider.init(lineStartOffset);
|
||||
context.fontType = myFontTypeProvider.getFontType(lineStartOffset);
|
||||
for (int i = lineStartOffset; i <= offset; i++) {
|
||||
TextChangeImpl softWrap = myStorage.getSoftWrap(i);
|
||||
if (softWrap != null) {
|
||||
context.beforeSoftWrap();
|
||||
CharSequence softWrapText = softWrap.getText();
|
||||
for (int k = 0; k < softWrapText.length(); k++) {
|
||||
context.onSoftWrapSymbol(softWrapText.charAt(k));
|
||||
}
|
||||
context.afterSoftWrap();
|
||||
}
|
||||
|
||||
int softWrapIntroducedLinesBefore = 0;
|
||||
int softWrapsOnCurrentLogicalLine = 0;
|
||||
int symbolsOnCurrentLogicalLine = 0;
|
||||
int symbolsOnCurrentVisibleLine = 0;
|
||||
List<TextChangeImpl> softWraps = myStorage.getSoftWraps();
|
||||
if (i == offset) {
|
||||
// We want to count soft wrap that is registered at target offset if any but not exceeding document symbols.
|
||||
break;
|
||||
}
|
||||
|
||||
// Retrieve information about logical position that is soft-wraps unaware.
|
||||
LogicalPosition rawLineStartLogicalPosition = myEditor.offsetToLogicalPosition(targetLineStartOffset);
|
||||
region = foldingModel.getCollapsedRegionAtOffset(i);
|
||||
if (region != null) {
|
||||
processFoldRegion(context, region, offset);
|
||||
if (offset <= region.getEndOffset()) {
|
||||
break;
|
||||
}
|
||||
i = region.getEndOffset();
|
||||
}
|
||||
context.fontType = myFontTypeProvider.getFontType(i);
|
||||
context.onNonSoftWrapSymbol(text.charAt(i));
|
||||
}
|
||||
return new LogicalPosition(
|
||||
context.logicalLine,
|
||||
context.logicalColumn,
|
||||
context.softWrapLinesBefore,
|
||||
context.targetSoftWrapLines,
|
||||
context.softWrapColumnDiff,
|
||||
getFoldedLinesBefore(offset),
|
||||
context.foldingColumnDiff
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes given collapsed fold region assuming that we need to stop at a target offset.
|
||||
* <p/>
|
||||
* Processing result is updated state of the given context object.
|
||||
*
|
||||
* @param context processing data holder
|
||||
* @param region collapsed fold region to process
|
||||
* @param offset target stop offset
|
||||
*/
|
||||
@SuppressWarnings({"AssignmentToForLoopParameter"})
|
||||
private void processFoldRegion(Context context, FoldRegion region, int offset) {
|
||||
CharSequence text = myEditor.getDocument().getCharsSequence();
|
||||
int max = Math.min(offset, region.getEndOffset());
|
||||
boolean multilineFolding = false;
|
||||
for (int i = region.getStartOffset(); i < max;) {
|
||||
int lineFeedOffset = CharArrayUtil.shiftForwardUntil(text, i, "\n");
|
||||
if (lineFeedOffset < max) {
|
||||
context.softWrapLinesBefore += context.targetSoftWrapLines;
|
||||
context.targetSoftWrapLines = 0;
|
||||
context.softWrapColumnDiff = 0;
|
||||
context.foldedLines++;
|
||||
context.logicalColumn = 0;
|
||||
context.foldingColumnDiff = context.visualColumn;
|
||||
context.logicalLine++;
|
||||
i = lineFeedOffset + 1;
|
||||
multilineFolding = true;
|
||||
}
|
||||
else {
|
||||
if (multilineFolding) {
|
||||
context.logicalColumn = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, i, max, 0);
|
||||
context.foldingColumnDiff = context.visualColumn - context.logicalColumn;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
int foldedColumns = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, region.getStartOffset(), max, context.x);
|
||||
context.logicalColumn += foldedColumns;
|
||||
context.foldingColumnDiff -= foldedColumns;
|
||||
if (offset >= region.getEndOffset()) {
|
||||
context.foldingColumnDiff += region.getPlaceholderText().length();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (offset >= region.getEndOffset()) {
|
||||
int foldPlaceholderColumns = region.getPlaceholderText().length();
|
||||
context.visualColumn += foldPlaceholderColumns;
|
||||
context.foldingColumnDiff += foldPlaceholderColumns;
|
||||
context.x += foldPlaceholderColumns * myTextRepresentationHelper.charWidth(' ', context.x, Font.PLAIN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to answer how many soft wrap-introduced visual lines are located before the given offset.
|
||||
*
|
||||
* @param offset target offset
|
||||
* @return number of soft wrap-introduced visual lines are located before the given offset
|
||||
*/
|
||||
private int getSoftWrapIntroducedLinesBefore(int offset) {
|
||||
int result = 0;
|
||||
List<? extends TextChange> softWraps = myStorage.getSoftWraps();
|
||||
|
||||
// Calculate number of soft wrap-introduced lines before the line that holds target offset.
|
||||
int index = myStorage.getSoftWrapIndex(targetLineStartOffset);
|
||||
int index = myStorage.getSoftWrapIndex(offset);
|
||||
if (index < 0) {
|
||||
index = -index - 1;
|
||||
}
|
||||
int max = Math.min(index, softWraps.size());
|
||||
for (int j = 0; j < max; j++) {
|
||||
softWrapIntroducedLinesBefore += StringUtil.countNewLines(softWraps.get(j).getText());
|
||||
}
|
||||
|
||||
FoldingModel foldingModel = myEditor.getFoldingModel();
|
||||
|
||||
// Return eagerly if there are no soft wraps before the target offset on a line that contains it.
|
||||
if (max >= softWraps.size() || softWraps.get(max).getStart() > offset) {
|
||||
int column = myTextRepresentationHelper.toVisualColumnSymbolsNumber(chars, targetLineStartOffset, offset, 0);
|
||||
LogicalPosition foldingUnawarePosition = new LogicalPosition(
|
||||
rawLineStartLogicalPosition.line, column, softWrapIntroducedLinesBefore, 0, 0, 0, 0
|
||||
);
|
||||
return adjustFoldingData(foldingModel, foldingUnawarePosition);
|
||||
}
|
||||
|
||||
// Calculate number of lines and columns introduced by soft wrap located at the line that holds target offset if any.
|
||||
|
||||
|
||||
// We add '1' here in order to correctly process situation when there is soft wrap at target offset (it impacts resulting logical
|
||||
// position but document symbol at that offset should not be count).
|
||||
max = Math.min(chars.length(), offset + 1);
|
||||
int x = 0;
|
||||
myFontTypeProvider.init(targetLineStartOffset);
|
||||
int fontType = myFontTypeProvider.getFontType(targetLineStartOffset);
|
||||
|
||||
for (int i = targetLineStartOffset; i < max; i++) {
|
||||
FoldRegion region = foldingModel.getCollapsedRegionAtOffset(i);
|
||||
if (region != null) {
|
||||
// Assuming that folded region placeholder doesn't contain line feed symbols.
|
||||
i = region.getEndOffset();
|
||||
symbolsOnCurrentVisibleLine += region.getPlaceholderText().length();
|
||||
continue;
|
||||
TextChange softWrap = softWraps.get(j);
|
||||
if (isVisible(softWrap)) {
|
||||
result += StringUtil.countNewLines(softWrap.getText());
|
||||
}
|
||||
|
||||
TextChange softWrap = myStorage.getSoftWrap(i);
|
||||
if (softWrap != null) {
|
||||
CharSequence softWrapText = softWrap.getText();
|
||||
for (int j = 0; j < softWrapText.length(); j++) {
|
||||
if (softWrapText.charAt(j) == '\n') {
|
||||
softWrapsOnCurrentLogicalLine++;
|
||||
symbolsOnCurrentVisibleLine = 0;
|
||||
x = 0;
|
||||
}
|
||||
else {
|
||||
symbolsOnCurrentVisibleLine++;
|
||||
x += myTextRepresentationHelper.charWidth(softWrapText.charAt(j), x, fontType);
|
||||
}
|
||||
}
|
||||
symbolsOnCurrentVisibleLine++; // For 'after soft wrap' sign.
|
||||
x += myPainter.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
}
|
||||
|
||||
// We don't want to count symbol at target offset.
|
||||
if (i == offset) {
|
||||
break;
|
||||
}
|
||||
|
||||
fontType = myFontTypeProvider.getFontType(targetLineStartOffset);
|
||||
|
||||
// Assuming that no line feed is contained before target offset on a line that holds it.
|
||||
int columnsForSymbol = toVisualColumnSymbolsNumber(chars.charAt(i), x);
|
||||
symbolsOnCurrentLogicalLine += columnsForSymbol;
|
||||
symbolsOnCurrentVisibleLine += columnsForSymbol;
|
||||
x += myTextRepresentationHelper.charWidth(chars.charAt(i), x, fontType);
|
||||
}
|
||||
myFontTypeProvider.cleanup();
|
||||
|
||||
LogicalPosition foldingUnawarePosition = new LogicalPosition(
|
||||
rawLineStartLogicalPosition.line, symbolsOnCurrentLogicalLine, softWrapIntroducedLinesBefore, softWrapsOnCurrentLogicalLine,
|
||||
symbolsOnCurrentVisibleLine - symbolsOnCurrentLogicalLine, 0, 0
|
||||
);
|
||||
return adjustFoldingData(foldingModel, foldingUnawarePosition);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds folding-aware logical position on the basis of the given folding-unaware position and folding model
|
||||
* Allows to answer how many folded lines are located before the logical line that contains given offset.
|
||||
*
|
||||
* @param foldingModel folding model to use for retrieving information about folding
|
||||
* @param position folding-unaware logical position
|
||||
* @return folding-aware logical position
|
||||
* @param offset target offset
|
||||
* @return number of folded lines are located before the logical line that contains given offset.
|
||||
*/
|
||||
private LogicalPosition adjustFoldingData(FoldingModel foldingModel, LogicalPosition position) {
|
||||
int offset = myEditor.logicalPositionToOffset(position);
|
||||
int foldedLines = 0;
|
||||
int foldColumnDiff = 0;
|
||||
int softWrapColumnDiff = position.softWrapColumnDiff;
|
||||
private int getFoldedLinesBefore(int offset) {
|
||||
Document document = myEditor.getDocument();
|
||||
int targetLine = document.getLineNumber(offset);
|
||||
int lastFoldEndLogicalLine = -1;
|
||||
for (FoldRegion foldRegion : foldingModel.getAllFoldRegions()) {
|
||||
if (foldRegion.getStartOffset() >= offset) {
|
||||
int line = document.getLineNumber(offset);
|
||||
int lineStartOffset = document.getLineStartOffset(line);
|
||||
int result = 0;
|
||||
for (FoldRegion foldRegion : myEditor.getFoldingModel().getAllFoldRegions()) {
|
||||
if (foldRegion.getStartOffset() >= lineStartOffset) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -360,99 +427,20 @@ public class SoftWrapDataMapper {
|
||||
|
||||
int foldingStartLine = document.getLineNumber(foldRegion.getStartOffset());
|
||||
int foldingEndLine = document.getLineNumber(foldRegion.getEndOffset());
|
||||
foldedLines += Math.min(targetLine, foldingEndLine) - foldingStartLine;
|
||||
|
||||
// Process situation when target offset is located inside the folded region.
|
||||
if (offset >= foldRegion.getStartOffset()) {
|
||||
if (offset < foldRegion.getEndOffset()) {
|
||||
// Our purpose is to define folding data in order to point to the visual folding start.
|
||||
int visualFoldingStartColumn = calculateVisualFoldingStartColumn(foldRegion);
|
||||
int diff = visualFoldingStartColumn - position.column - softWrapColumnDiff;
|
||||
if (lastFoldEndLogicalLine == foldingStartLine) {
|
||||
foldColumnDiff += diff;
|
||||
}
|
||||
else {
|
||||
foldColumnDiff = diff;
|
||||
}
|
||||
return new LogicalPosition(
|
||||
position.line, position.column, position.softWrapLinesBeforeCurrentLogicalLine, position.softWrapLinesOnCurrentLogicalLine,
|
||||
softWrapColumnDiff, foldedLines, foldColumnDiff
|
||||
);
|
||||
}
|
||||
|
||||
int diff = getFoldColumnDiff(foldRegion);
|
||||
if (lastFoldEndLogicalLine == foldingStartLine) {
|
||||
foldColumnDiff += diff;
|
||||
}
|
||||
else {
|
||||
foldColumnDiff = diff;
|
||||
}
|
||||
lastFoldEndLogicalLine = foldingEndLine;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastFoldEndLogicalLine != position.line) {
|
||||
foldColumnDiff = 0;
|
||||
}
|
||||
|
||||
return new LogicalPosition(
|
||||
position.line, position.column, position.softWrapLinesBeforeCurrentLogicalLine, position.softWrapLinesOnCurrentLogicalLine,
|
||||
softWrapColumnDiff, foldedLines, foldColumnDiff
|
||||
);
|
||||
}
|
||||
|
||||
private int getFoldColumnDiff(FoldRegion region) {
|
||||
int visualFoldingStartColumn = calculateVisualFoldingStartColumn(region);
|
||||
LogicalPosition foldEndLogical = myEditor.offsetToLogicalPosition(region.getEndOffset());
|
||||
// Assuming that there is no tabulations symbols at placeholder text.
|
||||
int foldingPlaceholderWidth = region.getPlaceholderText().length();
|
||||
return visualFoldingStartColumn + foldingPlaceholderWidth - foldEndLogical.column;
|
||||
}
|
||||
|
||||
private int calculateVisualFoldingStartColumn(FoldRegion region) {
|
||||
Document document = myEditor.getDocument();
|
||||
int foldingStartOffset = region.getStartOffset();
|
||||
int logicalLine = document.getLineNumber(foldingStartOffset);
|
||||
int logicalLineStartOffset = document.getLineStartOffset(logicalLine);
|
||||
|
||||
int softWrapIndex = myStorage.getSoftWrapIndex(logicalLineStartOffset);
|
||||
if (softWrapIndex < 0) {
|
||||
softWrapIndex = -softWrapIndex - 1;
|
||||
}
|
||||
|
||||
List<TextChangeImpl> softWraps = myStorage.getSoftWraps();
|
||||
int startOffsetOfVisualLineWithFoldingStart = logicalLineStartOffset;
|
||||
int softWrapOffsetInColumns = 0;
|
||||
for (; softWrapIndex < softWraps.size(); softWrapIndex++) {
|
||||
TextChange softWrap = softWraps.get(softWrapIndex);
|
||||
if (softWrap.getStart() >= foldingStartOffset) {
|
||||
break;
|
||||
}
|
||||
|
||||
startOffsetOfVisualLineWithFoldingStart = softWrap.getStart();
|
||||
softWrapOffsetInColumns = numberOfSymbolsOnLastVisualLine(softWrap);
|
||||
}
|
||||
|
||||
assert startOffsetOfVisualLineWithFoldingStart <= foldingStartOffset;
|
||||
int x = softWrapOffsetInColumns * myTextRepresentationHelper.charWidth(' ', 0, Font.PLAIN);
|
||||
return myTextRepresentationHelper.toVisualColumnSymbolsNumber(
|
||||
document.getCharsSequence(), startOffsetOfVisualLineWithFoldingStart, foldingStartOffset, x
|
||||
);
|
||||
}
|
||||
|
||||
private static int numberOfSymbolsOnLastVisualLine(TextChange textChange) {
|
||||
int result = 0;
|
||||
for (int i = textChange.getText().length() - 1; i >= 0; i--) {
|
||||
if (i == '\n') {
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
result++;
|
||||
}
|
||||
result += Math.min(line, foldingEndLine) - foldingStartLine;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isVisible(TextChange softWrap) {
|
||||
FoldingModel foldingModel = myEditor.getFoldingModel();
|
||||
int start = softWrap.getStart();
|
||||
|
||||
// There is a possible case that folding region starts just after soft wrap, i.e. soft wrap and folding region share the
|
||||
// same offset. However, soft wrap is shown, hence, we also check offset just before the target one.
|
||||
return !foldingModel.isOffsetCollapsed(start) || !foldingModel.isOffsetCollapsed(start - 1);
|
||||
}
|
||||
|
||||
private int toVisualColumnSymbolsNumber(char c, int x) {
|
||||
myCharBuffer.clear();
|
||||
myCharBuffer.put(c);
|
||||
@@ -462,28 +450,36 @@ public class SoftWrapDataMapper {
|
||||
|
||||
private class Context {
|
||||
|
||||
public final FoldingModel foldingModel;
|
||||
public final LogicalPosition softWrapUnawareLogicalPosition;
|
||||
public final VisualPosition targetVisualPosition;
|
||||
public final int softWrapLinesBefore;
|
||||
public final int visualLineBeforeSoftWrapAppliance;
|
||||
public final int softWrapLinesOnCurrentLineBeforeTargetSoftWrap;
|
||||
|
||||
public int logicalLine;
|
||||
public int visualLine;
|
||||
public int softWrapLinesBefore;
|
||||
public int targetSoftWrapLines;
|
||||
public int symbolsOnCurrentLogicalLine;
|
||||
public int symbolsOnCurrentVisualLine;
|
||||
public int softWrapColumnDiff;
|
||||
public int logicalColumn;
|
||||
public int visualColumn;
|
||||
public int foldedLines;
|
||||
public int foldingColumnDiff;
|
||||
public int x;
|
||||
public int fontType;
|
||||
|
||||
Context(LogicalPosition softWrapUnawareLogicalPosition, VisualPosition targetVisualPosition, int softWrapLinesBefore,
|
||||
int softWrapLinesOnCurrentLineBeforeTargetSoftWrap, int visualLineBeforeSoftWrapAppliance, FoldingModel foldingModel)
|
||||
Context(int logicalLine, int softWrapLinesBefore, int foldedLines) {
|
||||
this(DUMMY_VISUAL, logicalLine, softWrapLinesBefore, 0, 0, foldedLines);
|
||||
}
|
||||
|
||||
Context(VisualPosition targetVisualPosition, int logicalLine, int softWrapLinesBefore,
|
||||
int softWrapLinesOnCurrentLineBeforeTargetSoftWrap, int visualLineBeforeSoftWrapAppliance, int foldedLines)
|
||||
{
|
||||
this.softWrapUnawareLogicalPosition = softWrapUnawareLogicalPosition;
|
||||
this.targetVisualPosition = targetVisualPosition;
|
||||
this.softWrapLinesBefore = softWrapLinesBefore;
|
||||
this.softWrapLinesOnCurrentLineBeforeTargetSoftWrap = softWrapLinesOnCurrentLineBeforeTargetSoftWrap;
|
||||
this.visualLineBeforeSoftWrapAppliance = visualLineBeforeSoftWrapAppliance;
|
||||
this.foldingModel = foldingModel;
|
||||
this.foldedLines = foldedLines;
|
||||
this.logicalLine = logicalLine;
|
||||
visualLine = visualLineBeforeSoftWrapAppliance + targetSoftWrapLines;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -498,19 +494,24 @@ public class SoftWrapDataMapper {
|
||||
// Process line feed inside soft wrap.
|
||||
if (c == '\n') {
|
||||
if (targetVisualPosition.line == visualLineBeforeSoftWrapAppliance + targetSoftWrapLines) {
|
||||
return build(targetVisualPosition.column - symbolsOnCurrentLogicalLine);
|
||||
softWrapColumnDiff = targetVisualPosition.column - logicalColumn;
|
||||
return build();
|
||||
}
|
||||
else {
|
||||
x = 0;
|
||||
softWrapColumnDiff = -logicalColumn;
|
||||
targetSoftWrapLines++;
|
||||
symbolsOnCurrentVisualLine = 0;
|
||||
visualLine++;
|
||||
visualColumn = 0;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
softWrapColumnDiff++;
|
||||
|
||||
// Just update information about tracked symbols number if current visual line is too low.
|
||||
if (targetVisualPosition.line > visualLineBeforeSoftWrapAppliance + targetSoftWrapLines) {
|
||||
symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c, x);
|
||||
visualColumn += toVisualColumnSymbolsNumber(c, x);
|
||||
x += myTextRepresentationHelper.charWidth(c, x, fontType);
|
||||
return null;
|
||||
}
|
||||
@@ -518,15 +519,15 @@ public class SoftWrapDataMapper {
|
||||
// There is a possible case that, for example, target visual column is zero and it points to the soft-wrapped line,
|
||||
// i.e. soft wrap are. We shouldn't count symbols then. Hence, we perform this preliminary examination with eager
|
||||
// return if necessary.
|
||||
if (targetVisualPosition.column <= symbolsOnCurrentVisualLine) {
|
||||
if (targetVisualPosition.column <= visualColumn) {
|
||||
return build();
|
||||
}
|
||||
|
||||
// Process non-line feed inside soft wrap.
|
||||
symbolsOnCurrentVisualLine++; // Don't expect tabulation to be used inside soft wrap text.
|
||||
visualColumn++; // Don't expect tabulation to be used inside soft wrap text.
|
||||
x += myTextRepresentationHelper.charWidth(c, x, fontType);
|
||||
|
||||
if (targetVisualPosition.column <= symbolsOnCurrentVisualLine) {
|
||||
if (targetVisualPosition.column <= visualColumn) {
|
||||
return build();
|
||||
}
|
||||
else {
|
||||
@@ -540,7 +541,54 @@ public class SoftWrapDataMapper {
|
||||
|
||||
public void afterSoftWrap() {
|
||||
x += myPainter.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
symbolsOnCurrentVisualLine++;
|
||||
visualColumn++;
|
||||
softWrapColumnDiff++;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"AssignmentToForLoopParameter"})
|
||||
@Nullable
|
||||
public LogicalPosition onCollapsedFolding(FoldRegion region) {
|
||||
int visualFoldingPlaceholderWidth = region.getPlaceholderText().length(); // Assuming that no tabs are used as placeholder
|
||||
|
||||
// Process situation when target visual position points to collapsed folding placeholder.
|
||||
if (visualLine == targetVisualPosition.line && visualColumn + visualFoldingPlaceholderWidth > targetVisualPosition.column) {
|
||||
return build();
|
||||
}
|
||||
|
||||
// If control flow reaches this point that means that we should process whole folded region and update current object state.
|
||||
CharSequence text = myEditor.getDocument().getCharsSequence();
|
||||
boolean multiline = false;
|
||||
for (int i = region.getStartOffset(); i < region.getEndOffset();) {
|
||||
int lineFeedOffset = CharArrayUtil.shiftForwardUntil(text, i, "\n");
|
||||
// Process multiline folded text.
|
||||
if (lineFeedOffset < region.getEndOffset()) {
|
||||
logicalLine++;
|
||||
foldedLines++;
|
||||
logicalColumn = 0;
|
||||
softWrapLinesBefore += targetSoftWrapLines;
|
||||
targetSoftWrapLines = 0;
|
||||
softWrapColumnDiff = 0;
|
||||
i = lineFeedOffset + 1;
|
||||
multiline = true;
|
||||
}
|
||||
else {
|
||||
if (multiline) {
|
||||
logicalColumn = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, i, region.getEndOffset(), 0);
|
||||
}
|
||||
else {
|
||||
logicalColumn += myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, i, region.getEndOffset(), x);
|
||||
}
|
||||
foldingColumnDiff = visualColumn + visualFoldingPlaceholderWidth - logicalColumn - softWrapColumnDiff;
|
||||
i = region.getEndOffset();
|
||||
}
|
||||
}
|
||||
|
||||
visualColumn += visualFoldingPlaceholderWidth;
|
||||
x += visualFoldingPlaceholderWidth * myTextRepresentationHelper.charWidth(' ', x, Font.PLAIN);
|
||||
if (visualLine == targetVisualPosition.line && visualColumn == targetVisualPosition.column) {
|
||||
return build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,31 +608,31 @@ public class SoftWrapDataMapper {
|
||||
}
|
||||
|
||||
// Just update information about tracked symbols number if current visual line is too low.
|
||||
if (targetVisualPosition.line > visualLineBeforeSoftWrapAppliance + targetSoftWrapLines) {
|
||||
if (targetVisualPosition.line > visualLine) {
|
||||
int columnsForSymbol = toVisualColumnSymbolsNumber(c, x);
|
||||
symbolsOnCurrentVisualLine += columnsForSymbol;
|
||||
symbolsOnCurrentLogicalLine += columnsForSymbol;
|
||||
visualColumn += columnsForSymbol;
|
||||
logicalColumn += columnsForSymbol;
|
||||
x += myTextRepresentationHelper.charWidth(c, x, fontType);
|
||||
return null;
|
||||
}
|
||||
|
||||
// There is a possible case that, for example, target visual column is zero. We shouldn't count symbols then.
|
||||
// Hence, we perform this preliminary examination with eager return if necessary.
|
||||
if (targetVisualPosition.column <= symbolsOnCurrentVisualLine) {
|
||||
if (targetVisualPosition.column <= visualColumn) {
|
||||
return build();
|
||||
}
|
||||
|
||||
int columnsForSymbol = toVisualColumnSymbolsNumber(c, x);
|
||||
int diffInColumns = targetVisualPosition.column - symbolsOnCurrentVisualLine;
|
||||
int diffInColumns = targetVisualPosition.column - visualColumn;
|
||||
int incrementToUse = columnsForSymbol;
|
||||
if (columnsForSymbol >= diffInColumns) {
|
||||
incrementToUse = Math.min(columnsForSymbol, diffInColumns);
|
||||
}
|
||||
symbolsOnCurrentVisualLine += incrementToUse;
|
||||
symbolsOnCurrentLogicalLine += incrementToUse;
|
||||
visualColumn += incrementToUse;
|
||||
logicalColumn += incrementToUse;
|
||||
x += myTextRepresentationHelper.charWidth(c, x, fontType);
|
||||
|
||||
if (targetVisualPosition.column <= symbolsOnCurrentVisualLine) {
|
||||
if (targetVisualPosition.column <= visualColumn) {
|
||||
return build();
|
||||
}
|
||||
else {
|
||||
@@ -593,22 +641,19 @@ public class SoftWrapDataMapper {
|
||||
}
|
||||
|
||||
private LogicalPosition build() {
|
||||
return build(symbolsOnCurrentVisualLine - symbolsOnCurrentLogicalLine);
|
||||
return build(foldingColumnDiff);
|
||||
}
|
||||
|
||||
private LogicalPosition build(int softWrapColumnDiff) {
|
||||
int logicalLine = softWrapUnawareLogicalPosition.line - softWrapLinesBefore
|
||||
- softWrapLinesOnCurrentLineBeforeTargetSoftWrap - targetSoftWrapLines;
|
||||
LogicalPosition foldingUnawareResult = new LogicalPosition(
|
||||
private LogicalPosition build(int foldingColumnDiff) {
|
||||
return new LogicalPosition(
|
||||
logicalLine,
|
||||
symbolsOnCurrentLogicalLine,
|
||||
logicalColumn,
|
||||
softWrapLinesBefore,
|
||||
softWrapLinesOnCurrentLineBeforeTargetSoftWrap + targetSoftWrapLines,
|
||||
softWrapColumnDiff,
|
||||
0,
|
||||
0
|
||||
foldedLines,
|
||||
foldingColumnDiff
|
||||
);
|
||||
return adjustFoldingData(foldingModel, foldingUnawareResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -394,6 +394,10 @@ abstract class BaseTreeTestCase<StructureElement> extends FlyIdeaTestCase {
|
||||
}
|
||||
|
||||
void select(final Object[] elements, final boolean addToSelection) throws Exception {
|
||||
select(elements, addToSelection, false);
|
||||
}
|
||||
|
||||
void select(final Object[] elements, final boolean addToSelection, final boolean canBeInterrupted) throws Exception {
|
||||
final Ref<Boolean> done = new Ref<Boolean>(false);
|
||||
doAndWaitForBuilder(new Runnable() {
|
||||
public void run() {
|
||||
@@ -405,7 +409,7 @@ abstract class BaseTreeTestCase<StructureElement> extends FlyIdeaTestCase {
|
||||
}
|
||||
}, new Condition() {
|
||||
public boolean value(Object o) {
|
||||
return done.get();
|
||||
return done.get() || (canBeInterrupted && getBuilder().getUi().isCancelledReady());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -59,6 +59,43 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
|
||||
assertInterruption(Interruption.invokeCancel);
|
||||
}
|
||||
|
||||
public void testDoubleCancelUpdate() throws Exception {
|
||||
buildStructure(myRoot);
|
||||
|
||||
runAndInterrupt(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
select(new Object[] {new NodeElement("openapi")}, false, true);
|
||||
}
|
||||
catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}, "getChildren", new NodeElement("intellij"), Interruption.invokeCancel);
|
||||
|
||||
select(new NodeElement("fabrique"), false);
|
||||
|
||||
assertTree("-/\n"
|
||||
+ " -com\n"
|
||||
+ " intellij\n"
|
||||
+ " -jetbrains\n"
|
||||
+ " +[fabrique]\n"
|
||||
+ " +org\n"
|
||||
+ " +xunit\n");
|
||||
|
||||
updateFromRoot();
|
||||
|
||||
assertTree("-/\n"
|
||||
+ " -com\n"
|
||||
+ " +intellij\n"
|
||||
+ " -jetbrains\n"
|
||||
+ " +[fabrique]\n"
|
||||
+ " +org\n"
|
||||
+ " +xunit\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testBatchUpdate() throws Exception {
|
||||
buildStructure(myRoot);
|
||||
@@ -1987,6 +2024,12 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
|
||||
//todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testDoubleCancelUpdate() throws Exception {
|
||||
// doesn't make sense in pass-through mode
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void testSelectWhenUpdatesArePending() throws Exception {
|
||||
// doesn't make sense in pass-through mode
|
||||
|
||||
+72
-28
@@ -201,9 +201,9 @@ public class SoftWrapDataMapperTest {
|
||||
String document =
|
||||
"public class Test {\n" +
|
||||
" public void foo(int[] data) {\n" +
|
||||
" bar(data[0], data[1], data[2], data[3], <WRAP>\n" +
|
||||
" </WRAP>data[4], data[5], data[6], <WRAP> \n" +
|
||||
" </WRAP>data[7], data[8]); \n" +
|
||||
" bar(data[0], <WRAP>\n" +
|
||||
" </WRAP>data[1], <WRAP> \n" +
|
||||
" </WRAP>data[2]); \n" +
|
||||
" }\n" +
|
||||
" public void bar(int ... i) {\n" +
|
||||
" }\n" +
|
||||
@@ -230,22 +230,52 @@ public class SoftWrapDataMapperTest {
|
||||
test(document);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void softWrappedSingleLineFolding() {
|
||||
String document =
|
||||
"class Test {<WRAP>\n" +
|
||||
" </WRAP><FOLD>public void foo() {}</FOLD> \n" +
|
||||
" \n" +
|
||||
"}";
|
||||
test(document);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void softWrappedMultiLineLineFolding() {
|
||||
String document =
|
||||
"class Test {<WRAP>\n" +
|
||||
" </WRAP><FOLD>public void foo() {\n" +
|
||||
" }</FOLD> \n" +
|
||||
"}";
|
||||
test(document);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFoldRegionsAfterSingleSoftWrap() {
|
||||
String document =
|
||||
"class Test {<WRAP>\n" +
|
||||
" </WRAP><FOLD>public void foo() {\n" +
|
||||
" }</FOLD> <FOLD>// comment</FOLD> \n" +
|
||||
"}";
|
||||
test(document);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void softWrapAndFoldedLines() {
|
||||
String document =
|
||||
"public class Test {\n" +
|
||||
" public void foo(int[] data) {\n" +
|
||||
" bar(data[0], data[1], <WRAP>\n" +
|
||||
" </WRAP>data[2], data[3], <WRAP> \n" +
|
||||
" </WRAP>data[4], data[5], \n" +
|
||||
" data[6], data[7], \n" +
|
||||
" <FOLD>data[8], data[9], \n" +
|
||||
" data[10], data[11], \n" +
|
||||
" data[12], data[13], </FOLD>\n" +
|
||||
" data[14], data[15], \n" +
|
||||
" data[16], data[17], <WRAP> \n" +
|
||||
" </WRAP>data[18], data[19], <WRAP> \n" +
|
||||
" </WRAP>data[20], data[21]); \n" +
|
||||
" bar(data[0] <WRAP>\n" +
|
||||
" </WRAP>data[1], <WRAP> \n" +
|
||||
" </WRAP>data[2], \n" +
|
||||
" data[3], \n" +
|
||||
" <FOLD>data[4], \n" +
|
||||
" data[5], \n" +
|
||||
" data[6], </FOLD> \n" +
|
||||
" data[7], \n" +
|
||||
" data[8] <WRAP> \n" +
|
||||
" </WRAP>data[9], <WRAP> \n" +
|
||||
" </WRAP>data[10]); \n" +
|
||||
" }\n" +
|
||||
" public void bar(int ... i) {\n" +
|
||||
" }\n" +
|
||||
@@ -346,7 +376,7 @@ public class SoftWrapDataMapperTest {
|
||||
@Nullable
|
||||
private FoldRegion getCollapsedFoldRegion(int offset) {
|
||||
for (FoldRegion region : myFoldRegions) {
|
||||
if (region.getStartOffset() == offset) {
|
||||
if (region.getStartOffset() <= offset && region.getEndOffset() > offset) {
|
||||
return region;
|
||||
}
|
||||
}
|
||||
@@ -424,15 +454,15 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
|
||||
// Check visual by logical.
|
||||
VisualPosition actualVisual = myAdjuster.adjustVisualPosition(data.logical, toSoftWrapUnawareVisual(data));
|
||||
if (!actualVisual.equals(data.visual)) {
|
||||
myAdjuster.adjustVisualPosition(data.logical, toSoftWrapUnawareVisual(data));
|
||||
throw new AssertionError(
|
||||
String.format("Detected unmatched visual position by logical. Expected: '%s', actual: '%s'. Calculation was performed "
|
||||
+ "against logical position: '%s' and soft wrap-unaware visual: '%s'",
|
||||
data.visual, actualVisual, data.logical, toSoftWrapUnawareVisual(data))
|
||||
);
|
||||
}
|
||||
//VisualPosition actualVisual = myAdjuster.adjustVisualPosition(data.logical, toSoftWrapUnawareVisual(data));
|
||||
//if (!actualVisual.equals(data.visual)) {
|
||||
// myAdjuster.adjustVisualPosition(data.logical, toSoftWrapUnawareVisual(data));
|
||||
// throw new AssertionError(
|
||||
// String.format("Detected unmatched visual position by logical. Expected: '%s', actual: '%s'. Calculation was performed "
|
||||
// + "against logical position: '%s' and soft wrap-unaware visual: '%s'",
|
||||
// data.visual, actualVisual, data.logical, toSoftWrapUnawareVisual(data))
|
||||
// );
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,7 +501,8 @@ public class SoftWrapDataMapperTest {
|
||||
continue;
|
||||
}
|
||||
|
||||
context.onNewSymbol(documentText.charAt(i));
|
||||
char c = documentText.charAt(i);
|
||||
context.onNewSymbol(c);
|
||||
}
|
||||
|
||||
myLineRanges.add(new TextRange(context.logicalLineStartOffset, context.document.length()));
|
||||
@@ -549,6 +580,7 @@ public class SoftWrapDataMapperTest {
|
||||
int softWrapLinesBeforeCurrentLogical;
|
||||
int softWrapLinesOnCurrentLogical;
|
||||
int softWrapSymbolsOnCurrentVisualLine;
|
||||
int softWrapColumnDiff;
|
||||
int foldingStartOffset;
|
||||
int foldingStartLogicalColumn;
|
||||
int foldingStartVisualColumn;
|
||||
@@ -580,8 +612,9 @@ public class SoftWrapDataMapperTest {
|
||||
|
||||
public void onFoldingEnd() {
|
||||
visualColumn += 3; // For '...' folding
|
||||
foldingColumnDiff += 3;
|
||||
|
||||
x = foldingStartX + 3 * SPACE_SIZE;
|
||||
foldingColumnDiff = visualColumn - logicalColumn;
|
||||
insideFolding = false;
|
||||
myFoldRegions.add(new MockFoldRegion(foldingStartOffset, offset));
|
||||
}
|
||||
@@ -595,6 +628,10 @@ public class SoftWrapDataMapperTest {
|
||||
foldedLines++;
|
||||
offset++;
|
||||
x = 0;
|
||||
softWrapColumnDiff = 0;
|
||||
softWrapLinesBeforeCurrentLogical += softWrapLinesOnCurrentLogical;
|
||||
softWrapLinesOnCurrentLogical = 0;
|
||||
foldingColumnDiff = foldingStartVisualColumn;
|
||||
}
|
||||
else if (c == '\t') {
|
||||
int tabWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(c, x);
|
||||
@@ -611,12 +648,13 @@ public class SoftWrapDataMapperTest {
|
||||
|
||||
logicalColumn++;
|
||||
offset++;
|
||||
foldingColumnDiff -= tabWidthInColumns;
|
||||
} else {
|
||||
logicalColumn++;
|
||||
offset++;
|
||||
x += myRepresentationHelper.charWidth(c, x, Font.PLAIN);
|
||||
foldingColumnDiff--;
|
||||
}
|
||||
foldingColumnDiff = foldingStartVisualColumn - logicalColumn;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -627,20 +665,25 @@ public class SoftWrapDataMapperTest {
|
||||
// Emulate the situation when the user works with a virtual space after document line end (add such virtual
|
||||
// positions two symbols behind the end).
|
||||
visualColumn++;
|
||||
softWrapColumnDiff++;
|
||||
x += SPACE_SIZE;
|
||||
addData(true);
|
||||
|
||||
visualColumn++;
|
||||
softWrapColumnDiff++;
|
||||
x += SPACE_SIZE;
|
||||
addData(true);
|
||||
|
||||
visualLine++;
|
||||
x = 0;
|
||||
softWrapLinesOnCurrentLogical++;
|
||||
softWrapColumnDiff = -logicalColumn + 1;
|
||||
visualColumn = 1; // For the column reserved for soft wrap sign.
|
||||
softWrapSymbolsOnCurrentVisualLine = 0;
|
||||
}
|
||||
else {
|
||||
visualColumn++;
|
||||
softWrapColumnDiff++;
|
||||
softWrapSymbolsOnCurrentVisualLine++;
|
||||
x += myRepresentationHelper.charWidth(c, x, Font.PLAIN);
|
||||
}
|
||||
@@ -652,6 +695,8 @@ public class SoftWrapDataMapperTest {
|
||||
if (c == '\n') {
|
||||
visualLine++;
|
||||
visualColumn = 0;
|
||||
foldingColumnDiff = 0;
|
||||
softWrapColumnDiff = 0;
|
||||
x = 0;
|
||||
softWrapLinesBeforeCurrentLogical += softWrapLinesOnCurrentLogical;
|
||||
softWrapLinesOnCurrentLogical = 0;
|
||||
@@ -719,7 +764,6 @@ public class SoftWrapDataMapperTest {
|
||||
|
||||
private LogicalPosition buildLogicalPosition() {
|
||||
//int softWrapColumnDiff
|
||||
int softWrapColumnDiff = visualColumn - logicalColumn - foldingColumnDiff;
|
||||
return new LogicalPosition(
|
||||
logicalLine, logicalColumn, softWrapLinesBeforeCurrentLogical, softWrapLinesOnCurrentLogical, softWrapColumnDiff,
|
||||
foldedLines, foldingColumnDiff
|
||||
|
||||
@@ -1171,3 +1171,5 @@ group.ToolsBasicGroup.description=Tools Basic Group
|
||||
group.ToolbarNewElement.text=Toolbar New Element Group
|
||||
action.NewElementToolbarAction.text=Create New File
|
||||
action.ShowRegistry.text=Registry
|
||||
action.TogglePowerSave.text=Power Save Mode
|
||||
action.TogglePowerSave.description=Power save mode disables background code analysis and other background operations
|
||||
|
||||
@@ -128,6 +128,9 @@
|
||||
<applicationService serviceInterface="com.intellij.patterns.compiler.PatternCompilerFactory"
|
||||
serviceImplementation="com.intellij.patterns.compiler.PatternCompilerFactoryImpl"/>
|
||||
|
||||
<applicationService serviceInterface="com.intellij.ide.PowerSaveMode"
|
||||
serviceImplementation="com.intellij.ide.PowerSaveMode"/>
|
||||
|
||||
<projectService serviceInterface="com.intellij.psi.codeStyle.ProjectCodeStyleSettingsManager"
|
||||
serviceImplementation="com.intellij.psi.codeStyle.ProjectCodeStyleSettingsManager"/>
|
||||
|
||||
@@ -568,4 +571,6 @@
|
||||
<applicationService serviceInterface="com.intellij.ide.todo.TodoConfiguration"
|
||||
serviceImplementation="com.intellij.ide.todo.TodoConfiguration"/>
|
||||
<indexPatternProvider implementation="com.intellij.ide.todo.TodoIndexPatternProvider"/>
|
||||
|
||||
<hectorComponentProvider implementation="com.intellij.codeInsight.daemon.PowerSaveHectorProvider"/>
|
||||
</extensions>
|
||||
|
||||
@@ -80,6 +80,8 @@
|
||||
|
||||
<checkoutCompletedListener implementation="com.intellij.openapi.vcs.checkout.PlatformProjectCheckoutListener"/>
|
||||
|
||||
<weigher key="proximity" implementationClass="com.intellij.psi.util.proximity.SameDirectoryWeigher" id="sameDirectory"
|
||||
order="after openedInEditor"/>
|
||||
</extensions>
|
||||
|
||||
<xi:include href="xdebugger.xml" xpointer="xpointer(/root/*)"/>
|
||||
|
||||
@@ -70,6 +70,12 @@
|
||||
<add-to-group group-id="FileMenu" anchor="after" relative-to-action="ChangeFileEncodingGroup"/>
|
||||
</action>
|
||||
|
||||
<group id="PowerSaveGroup">
|
||||
<separator/>
|
||||
<action id="TogglePowerSave" class="com.intellij.ide.actions.TogglePowerSaveAction"/>
|
||||
<add-to-group group-id="FileMenu" anchor="after" relative-to-action="ToggleReadOnlyAttribute"/>
|
||||
</group>
|
||||
|
||||
<!-- Edit -->
|
||||
<action id="CopyReference" class="com.intellij.ide.actions.CopyReferenceAction">
|
||||
<add-to-group group-id="CutCopyPasteGroup" anchor="after" relative-to-action="CopyPaths"/>
|
||||
|
||||
@@ -38,15 +38,14 @@ public class MergeQuery<T> implements Query<T>{
|
||||
@NotNull
|
||||
public Collection<T> findAll() {
|
||||
List<T> results = new ArrayList<T>();
|
||||
results.addAll(myQuery1.findAll());
|
||||
results.addAll(myQuery2.findAll());
|
||||
forEach(new CommonProcessors.CollectProcessor<T>(results));
|
||||
return results;
|
||||
}
|
||||
|
||||
public T findFirst() {
|
||||
final T r1 = myQuery1.findFirst();
|
||||
if (r1 != null) return r1;
|
||||
return myQuery2.findFirst();
|
||||
final CommonProcessors.FindFirstProcessor<T> processor = new CommonProcessors.FindFirstProcessor<T>();
|
||||
forEach(processor);
|
||||
return processor.getFoundValue();
|
||||
}
|
||||
|
||||
public boolean forEach(@NotNull final Processor<T> consumer) {
|
||||
|
||||
@@ -221,7 +221,7 @@ public class TreeModelBuilder {
|
||||
final FilePath fp1 = ChangesUtil.getFilePath(o1);
|
||||
final FilePath fp2 = ChangesUtil.getFilePath(o2);
|
||||
|
||||
final int diff = fp1.getPath().length() - fp2.getPath().length();
|
||||
final int diff = fp1.getIOFile().getPath().length() - fp2.getIOFile().getPath().length();
|
||||
return diff == 0 ? 0 : (diff < 0 ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
package com.intellij.debugger.ui;
|
||||
|
||||
import com.intellij.execution.ui.ExecutionConsole;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
public interface DebuggerContentInfo {
|
||||
|
||||
@NonNls String CONSOLE_CONTENT = "ConsoleContent";
|
||||
@NonNls String CONSOLE_CONTENT = ExecutionConsole.CONSOLE_CONTENT_ID;
|
||||
@NonNls String THREADS_CONTENT = "ThreadsContent";
|
||||
@NonNls String VARIABLES_CONTENT = "VariablesContent";
|
||||
@NonNls String FRAME_CONTENT = "FrameContent";
|
||||
|
||||
+5
-4
@@ -21,6 +21,7 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyBundle;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
|
||||
@@ -94,10 +95,10 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
|
||||
if (expectedType == null || PsiType.VOID.equals(expectedType)) return;
|
||||
|
||||
ControlFlowUtils.visitAllExitPoints(block, new ControlFlowUtils.ExitPointVisitor() {
|
||||
public boolean visit(Instruction instruction) {
|
||||
final PsiElement psiElement = instruction.getElement();
|
||||
if (psiElement instanceof GrExpression) {
|
||||
checkAssignability(expectedType, (GrExpression)psiElement, (GrExpression)psiElement);
|
||||
@Override
|
||||
public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) {
|
||||
if (returnValue != null && !(returnValue.getParent() instanceof GrReturnStatement)) {
|
||||
checkAssignability(expectedType, returnValue, returnValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+5
-2
@@ -24,6 +24,7 @@ import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovySuppressableInspectionTool;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
|
||||
@@ -35,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrAssertStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.MaybeReturnInstruction;
|
||||
@@ -86,7 +88,8 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool {
|
||||
final Ref<Boolean> hasExplicitReturn = new Ref<Boolean>(false);
|
||||
final Ref<Boolean> sometimes = new Ref<Boolean>(false);
|
||||
ControlFlowUtils.visitAllExitPoints(block, new ControlFlowUtils.ExitPointVisitor() {
|
||||
public boolean visit(Instruction instruction) {
|
||||
@Override
|
||||
public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) {
|
||||
if (instruction instanceof MaybeReturnInstruction) {
|
||||
if (((MaybeReturnInstruction)instruction).mayReturnValue()) {
|
||||
sometimes.set(true);
|
||||
@@ -99,7 +102,7 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool {
|
||||
final PsiElement element = instruction.getElement();
|
||||
if (element instanceof GrReturnStatement) {
|
||||
sometimes.set(true);
|
||||
if (((GrReturnStatement)element).getReturnValue() != null) {
|
||||
if (returnValue != null) {
|
||||
hasExplicitReturn.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -543,7 +543,7 @@ public class ControlFlowUtils {
|
||||
|
||||
|
||||
public interface ExitPointVisitor {
|
||||
boolean visit(Instruction instruction);
|
||||
boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue);
|
||||
}
|
||||
|
||||
public static void visitAllExitPoints(@Nullable GrCodeBlock block, ExitPointVisitor visitor) {
|
||||
@@ -556,12 +556,16 @@ public class ControlFlowUtils {
|
||||
private static boolean visitAllExitPointsInner(Instruction last, Instruction first, boolean[] visited, ExitPointVisitor visitor) {
|
||||
if (first == last) return true;
|
||||
if (last instanceof MaybeReturnInstruction) {
|
||||
return visitor.visit(last);
|
||||
return visitor.visitExitPoint(last, (GrExpression)last.getElement());
|
||||
}
|
||||
|
||||
final PsiElement element = last.getElement();
|
||||
PsiElement element = last.getElement();
|
||||
if (element != null) {
|
||||
return visitor.visit(last);
|
||||
if (element instanceof GrReturnStatement) {
|
||||
element = ((GrReturnStatement)element).getReturnValue();
|
||||
}
|
||||
|
||||
return visitor.visitExitPoint(last, element instanceof GrExpression ? (GrExpression)element : null);
|
||||
}
|
||||
visited[last.num()] = true;
|
||||
for (Instruction pred : last.allPred()) {
|
||||
@@ -571,4 +575,5 @@ public class ControlFlowUtils {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+38
-18
@@ -21,25 +21,49 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
|
||||
import com.intellij.psi.stubs.StubIndex;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
|
||||
import org.jetbrains.plugins.groovy.lang.stubs.GroovyCacheUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnnotatedMemberIndex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class AnnotatedMembersSearcher implements QueryExecutor<PsiMember, AnnotatedElementsSearch.Parameters> {
|
||||
public class AnnotatedMembersSearcher implements QueryExecutor<PsiModifierListOwner, AnnotatedElementsSearch.Parameters> {
|
||||
|
||||
public boolean execute(final AnnotatedElementsSearch.Parameters p, final Processor<PsiMember> consumer) {
|
||||
@NotNull
|
||||
private static List<PsiModifierListOwner> getAnnotatedMemberCandidates(PsiClass clazz, GlobalSearchScope scope) {
|
||||
final String name = clazz.getName();
|
||||
if (name == null) return Collections.emptyList();
|
||||
final Collection<PsiElement> members = StubIndex.getInstance().get(GrAnnotatedMemberIndex.KEY, name, clazz.getProject(), scope);
|
||||
if (members.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final ArrayList<PsiModifierListOwner> result = new ArrayList<PsiModifierListOwner>();
|
||||
for (PsiElement element : members) {
|
||||
if (element instanceof GroovyFile) {
|
||||
element = ((GroovyFile)element).getPackageDefinition();
|
||||
}
|
||||
if (element instanceof PsiModifierListOwner) {
|
||||
result.add((PsiModifierListOwner)element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean execute(final AnnotatedElementsSearch.Parameters p, final Processor<PsiModifierListOwner> consumer) {
|
||||
final PsiClass annClass = p.getAnnotationClass();
|
||||
assert annClass.isAnnotationType() : "Annotation type should be passed to annotated members search";
|
||||
|
||||
@@ -48,29 +72,27 @@ public class AnnotatedMembersSearcher implements QueryExecutor<PsiMember, Annota
|
||||
|
||||
final SearchScope scope = p.getScope();
|
||||
|
||||
PsiMember[] candidates;
|
||||
final List<PsiModifierListOwner> candidates;
|
||||
if (scope instanceof GlobalSearchScope) {
|
||||
candidates = GroovyCacheUtil.getAnnotatedMemberCandidates(annClass, ((GlobalSearchScope)scope));
|
||||
candidates = getAnnotatedMemberCandidates(annClass, ((GlobalSearchScope)scope));
|
||||
} else {
|
||||
PsiElement[] elements = ((LocalSearchScope)scope).getScope();
|
||||
final List<GrMember> collector = new ArrayList<GrMember>();
|
||||
for (PsiElement element : elements) {
|
||||
candidates = new ArrayList<PsiModifierListOwner>();
|
||||
for (PsiElement element : ((LocalSearchScope)scope).getScope()) {
|
||||
if (element instanceof GroovyPsiElement) {
|
||||
((GroovyPsiElement)element).accept(new GroovyRecursiveElementVisitor() {
|
||||
public void visitMethod(GrMethod method) {
|
||||
collector.add(method);
|
||||
candidates.add(method);
|
||||
}
|
||||
|
||||
public void visitField(GrField field) {
|
||||
collector.add(field);
|
||||
candidates.add(field);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
candidates = collector.toArray(new PsiMember[collector.size()]);
|
||||
}
|
||||
|
||||
for (PsiMember candidate : candidates) {
|
||||
for (PsiModifierListOwner candidate : candidates) {
|
||||
if (!AnnotatedElementsSearcher.isInstanceof(candidate, p.getTypes())) {
|
||||
continue;
|
||||
}
|
||||
@@ -78,10 +100,8 @@ public class AnnotatedMembersSearcher implements QueryExecutor<PsiMember, Annota
|
||||
PsiModifierList list = candidate.getModifierList();
|
||||
if (list != null) {
|
||||
for (PsiAnnotation annotation : list.getAnnotations()) {
|
||||
if (annotationFQN.equals(annotation.getQualifiedName())) {
|
||||
PsiClass clazz = candidate.getContainingClass();
|
||||
if (clazz instanceof GroovyScriptClass) continue;
|
||||
if (!consumer.process(candidate)) return false;
|
||||
if (annotationFQN.equals(annotation.getQualifiedName()) && !consumer.process(candidate)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-5
@@ -15,26 +15,30 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.findUsages;
|
||||
|
||||
import com.intellij.openapi.application.QueryExecutorBase;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class ConstructorReferencesSearcher implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
public boolean execute(ReferencesSearch.SearchParameters queryParameters, final Processor<PsiReference> consumer) {
|
||||
public class ConstructorReferencesSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
protected ConstructorReferencesSearcher() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processQuery(ReferencesSearch.SearchParameters queryParameters, Processor<PsiReference> consumer) {
|
||||
final PsiElement element = queryParameters.getElementToSearch();
|
||||
if (element instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)element;
|
||||
if (method.isConstructor()) {
|
||||
return GroovyConstructorUsagesSearchHelper.execute(method, queryParameters.getScope(), consumer);
|
||||
GroovyConstructorUsagesSearcher.processConstructorUsages(method, queryParameters.getScope(), consumer, queryParameters.getOptimizer(), true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-199
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.groovy.findUsages;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightMemberReference;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
* Date: May 2, 2009 3:48:53 PM
|
||||
*/
|
||||
public class GroovyConstructorUsagesSearchHelper {
|
||||
private GroovyConstructorUsagesSearchHelper() {
|
||||
}
|
||||
|
||||
public static boolean execute(final PsiMethod constructor, SearchScope searchScope, final Processor<PsiReference> consumer) {
|
||||
if (!constructor.isConstructor()) return true;
|
||||
|
||||
if (searchScope instanceof GlobalSearchScope) {
|
||||
searchScope = GlobalSearchScope.getScopeRestrictedByFileTypes((GlobalSearchScope)searchScope, GroovyFileType.GROOVY_FILE_TYPE);
|
||||
}
|
||||
|
||||
final PsiClass clazz = ApplicationManager.getApplication().runReadAction(new NullableComputable<PsiClass>() {
|
||||
public PsiClass compute() {
|
||||
return constructor.getContainingClass();
|
||||
}
|
||||
});
|
||||
if (clazz == null) return true;
|
||||
|
||||
|
||||
//enum constants
|
||||
if (!ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
if (!clazz.isEnum()) return true;
|
||||
if (!(clazz instanceof GroovyPsiElement)) return true;
|
||||
final PsiField[] fields = clazz.getFields();
|
||||
for (PsiField field : fields) {
|
||||
if (field instanceof GrEnumConstant) {
|
||||
final PsiReference ref = field.getReference();
|
||||
if (ref.isReferenceTo(constructor)) {
|
||||
if (!consumer.process(ref)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ReferencesSearch.search(clazz, searchScope, true).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(PsiReference ref) {
|
||||
final PsiElement element = ref.getElement();
|
||||
if (element instanceof GrCodeReferenceElement) {
|
||||
GrNewExpression newExpression = null;
|
||||
if (element.getParent() instanceof GrNewExpression) {
|
||||
newExpression = (GrNewExpression)element.getParent();
|
||||
}
|
||||
else if (element.getParent() instanceof GrAnonymousClassDefinition) {
|
||||
newExpression = (GrNewExpression)element.getParent().getParent();
|
||||
}
|
||||
if (newExpression != null) {
|
||||
final PsiMethod resolvedConstructor = newExpression.resolveConstructor();
|
||||
final PsiManager manager = constructor.getManager();
|
||||
if (manager.areElementsEquivalent(resolvedConstructor, constructor) && !consumer.process(ref)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
//this()
|
||||
if (clazz instanceof GrTypeDefinition) {
|
||||
if (!processConstructors(constructor, consumer, clazz, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//super : does not work now, need to invent a way for it to work without repository
|
||||
if (!DirectClassInheritorsSearch.search(clazz, searchScope).forEach(new Processor<PsiClass>() {
|
||||
public boolean process(PsiClass inheritor) {
|
||||
if (inheritor instanceof GrTypeDefinition) {
|
||||
if (!processConstructors(constructor, consumer, inheritor, false)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processConstructors(final PsiMethod constructor, final Processor<PsiReference> consumer, final PsiClass clazz,
|
||||
final boolean processThisRefs) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
return processClassConstructors(clazz, constructor, consumer, processThisRefs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean processClassConstructors(PsiClass clazz,
|
||||
PsiMethod searchedConstructor,
|
||||
Processor<PsiReference> consumer,
|
||||
boolean processThisRefs) {
|
||||
final PsiMethod[] constructors = clazz.getConstructors();
|
||||
if (constructors.length == 0) {
|
||||
processImplicitConstructorCall(clazz, consumer, searchedConstructor);
|
||||
}
|
||||
for (PsiMethod constructor : constructors) {
|
||||
final GrOpenBlock block = ((GrMethod)constructor).getBlock();
|
||||
if (block != null) {
|
||||
final GrStatement[] statements = block.getStatements();
|
||||
if (statements.length > 0 && statements[0] instanceof GrConstructorInvocation) {
|
||||
final GrConstructorInvocation invocation = (GrConstructorInvocation)statements[0];
|
||||
if (invocation.isThisCall() == processThisRefs &&
|
||||
invocation.getManager().areElementsEquivalent(invocation.resolveConstructor(), searchedConstructor) &&
|
||||
!consumer.process(invocation)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
processImplicitConstructorCall(constructor, consumer, searchedConstructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void processImplicitConstructorCall(final PsiMember usage,
|
||||
final Processor<PsiReference> processor,
|
||||
final PsiMethod constructor) {
|
||||
if (constructor instanceof GrMethod) {
|
||||
GrParameter[] grParameters = (GrParameter[])constructor.getParameterList().getParameters();
|
||||
if (grParameters.length > 0 && !grParameters[0].isOptional()) return;
|
||||
}
|
||||
else if (constructor.getParameterList().getParameters().length > 0) return;
|
||||
|
||||
|
||||
PsiManager manager = constructor.getManager();
|
||||
if (manager.areElementsEquivalent(usage, constructor) || manager.areElementsEquivalent(constructor.getContainingClass(), usage.getContainingClass())) return;
|
||||
processor.process(new LightMemberReference(manager, usage, PsiSubstitutor.EMPTY) {
|
||||
public PsiElement getElement() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public TextRange getRangeInElement() {
|
||||
if (usage instanceof PsiClass) {
|
||||
PsiIdentifier identifier = ((PsiClass)usage).getNameIdentifier();
|
||||
if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength());
|
||||
}
|
||||
else if (usage instanceof PsiMethod) {
|
||||
PsiIdentifier identifier = ((PsiMethod)usage).getNameIdentifier();
|
||||
if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength());
|
||||
}
|
||||
return super.getRangeInElement();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
+387
-8
@@ -16,20 +16,399 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.findUsages;
|
||||
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.QueryExecutorBase;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightMemberReference;
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import com.intellij.util.containers.ConcurrentHashSet;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
|
||||
import org.jetbrains.plugins.groovy.gpp.GppTypeConverter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
public class GroovyConstructorUsagesSearcher implements QueryExecutor<PsiReference, MethodReferencesSearch.SearchParameters> {
|
||||
public boolean execute(MethodReferencesSearch.SearchParameters p, final Processor<PsiReference> consumer) {
|
||||
final PsiMethod method = p.getMethod();
|
||||
final SearchScope searchScope = p.getScope();
|
||||
return GroovyConstructorUsagesSearchHelper.execute(method, searchScope, consumer);
|
||||
public class GroovyConstructorUsagesSearcher extends QueryExecutorBase<PsiReference, MethodReferencesSearch.SearchParameters> {
|
||||
public GroovyConstructorUsagesSearcher() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processQuery(MethodReferencesSearch.SearchParameters p, Processor<PsiReference> consumer) {
|
||||
processConstructorUsages(p.getMethod(), p.getScope(), consumer, p.getOptimizer(), true);
|
||||
}
|
||||
|
||||
static void processConstructorUsages(final PsiMethod constructor, final SearchScope searchScope, final Processor<PsiReference> consumer, final SearchRequestCollector collector, final boolean searchGppCalls) {
|
||||
if (!constructor.isConstructor()) return;
|
||||
|
||||
SearchScope onlyGroovy = searchScope;
|
||||
if (onlyGroovy instanceof GlobalSearchScope) {
|
||||
onlyGroovy = GlobalSearchScope.getScopeRestrictedByFileTypes((GlobalSearchScope)onlyGroovy, GroovyFileType.GROOVY_FILE_TYPE);
|
||||
}
|
||||
|
||||
final PsiClass clazz = constructor.getContainingClass();
|
||||
if (clazz == null) return;
|
||||
|
||||
|
||||
if (clazz.isEnum() && clazz instanceof GroovyPsiElement) {
|
||||
for (PsiField field : clazz.getFields()) {
|
||||
if (field instanceof GrEnumConstant) {
|
||||
final PsiReference ref = field.getReference();
|
||||
if (ref != null && ref.isReferenceTo(constructor)) {
|
||||
if (!consumer.process(ref)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Set<PsiMethod> processedMethods = new ConcurrentHashSet<PsiMethod>();
|
||||
|
||||
ReferencesSearch.searchOptimized(clazz, searchScope, true, collector, true, new PairProcessor<PsiReference, SearchRequestCollector>() {
|
||||
@Override
|
||||
public boolean process(PsiReference ref, SearchRequestCollector collector) {
|
||||
final PsiElement element = ref.getElement();
|
||||
if (element instanceof GrCodeReferenceElement) {
|
||||
if (!processGroovyConstructorUsages((GrCodeReferenceElement)element, constructor, consumer, ref, !searchGppCalls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (searchGppCalls) {
|
||||
final PsiMethod method = getMethodToSearchForCallsWithLiteralArguments(element, clazz);
|
||||
if (method != null && processedMethods.add(method)) {
|
||||
processGppMethodCalls(clazz, constructor, consumer, searchScope, collector, method);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
//this()
|
||||
if (clazz instanceof GrTypeDefinition) {
|
||||
if (!processConstructors(constructor, consumer, clazz, true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
//super()
|
||||
DirectClassInheritorsSearch.search(clazz, onlyGroovy).forEach(new Processor<PsiClass>() {
|
||||
public boolean process(PsiClass inheritor) {
|
||||
if (inheritor instanceof GrTypeDefinition) {
|
||||
if (!processConstructors(constructor, consumer, inheritor, false)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PsiMethod getMethodToSearchForCallsWithLiteralArguments(PsiElement element, PsiClass targetClass) {
|
||||
final PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class);
|
||||
if (parameter != null) {
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(parameter, PsiMethod.class);
|
||||
if (method != null && Arrays.asList(method.getParameterList().getParameters()).contains(parameter)) {
|
||||
final PsiType parameterType = parameter.getType();
|
||||
if (parameterType instanceof PsiClassType) {
|
||||
if (method.getManager().areElementsEquivalent(targetClass, ((PsiClassType)parameterType).resolve())) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void processGppMethodCalls(final PsiClass targetClass,
|
||||
final PsiMethod originalTarget,
|
||||
final Processor<PsiReference> originalProcessor,
|
||||
SearchScope scope,
|
||||
SearchRequestCollector originalCollector, @NotNull PsiMethod currentTarget) {
|
||||
final SearchScope gppScope = getGppScope(targetClass.getProject()).intersectWith(scope);
|
||||
final ReadActionProcessor<PsiReference> gppCallProcessor = new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(PsiReference psiReference) {
|
||||
if (psiReference instanceof GrReferenceElement) {
|
||||
final PsiElement parent = ((GrReferenceElement)psiReference).getParent();
|
||||
if (parent instanceof GrCall) {
|
||||
final GrArgumentList argList = ((GrCall)parent).getArgumentList();
|
||||
if (argList != null) {
|
||||
boolean checkedTypedContext = false;
|
||||
|
||||
for (GrExpression argument : argList.getExpressionArguments()) {
|
||||
if (argument instanceof GrListOrMap && !((GrListOrMap)argument).isMap()) {
|
||||
if (!checkedTypedContext) {
|
||||
if (!GppTypeConverter.hasTypedContext(parent)) {
|
||||
return true;
|
||||
}
|
||||
checkedTypedContext = true;
|
||||
}
|
||||
|
||||
for (PsiType psiType : GroovyExpectedTypesProvider.getDefaultExpectedTypes(argument)) {
|
||||
if (psiType instanceof PsiClassType &&
|
||||
targetClass.getManager().areElementsEquivalent(targetClass, ((PsiClassType)psiType).resolve()) &&
|
||||
!checkListInstantiation(originalTarget, originalProcessor, (GrListOrMap)argument, (PsiClassType)psiType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
if (currentTarget.isConstructor()) {
|
||||
processConstructorUsages(currentTarget, gppScope, gppCallProcessor, originalCollector, false);
|
||||
}
|
||||
else {
|
||||
MethodReferencesSearch.searchOptimized(currentTarget, gppScope, true, originalCollector, gppCallProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
static GlobalSearchScope getGppScope(final Project project) {
|
||||
return CachedValuesManager.getManager(project).getCachedValue(project, new CachedValueProvider<GlobalSearchScope>() {
|
||||
@Override
|
||||
public Result<GlobalSearchScope> compute() {
|
||||
return Result.create(calcGppScope(project), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, ProjectRootManager.getInstance(project));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static boolean processGroovyConstructorUsages(GrCodeReferenceElement element,
|
||||
final PsiMethod constructor,
|
||||
final Processor<PsiReference> consumer,
|
||||
PsiReference ref, boolean usualCallsOnly) {
|
||||
PsiElement parent = element.getParent();
|
||||
|
||||
if (parent instanceof GrAnonymousClassDefinition) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof GrNewExpression) {
|
||||
final PsiMethod resolvedConstructor = ((GrNewExpression)parent).resolveConstructor();
|
||||
if (constructor.getManager().areElementsEquivalent(resolvedConstructor, constructor) && !consumer.process(ref)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!usualCallsOnly && parent instanceof GrTypeElement) {
|
||||
final GrTypeElement typeElement = (GrTypeElement)parent;
|
||||
|
||||
final PsiElement grandpa = typeElement.getParent();
|
||||
if (grandpa instanceof GrVariableDeclaration) {
|
||||
final GrVariable[] vars = ((GrVariableDeclaration)grandpa).getVariables();
|
||||
if (vars.length == 1) {
|
||||
final GrVariable variable = vars[0];
|
||||
if (!checkListInstantiation(constructor, consumer, variable.getInitializerGroovy(), typeElement)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (grandpa instanceof GrMethod) {
|
||||
final GrMethod method = (GrMethod)grandpa;
|
||||
if (typeElement == method.getReturnTypeElementGroovy()) {
|
||||
ControlFlowUtils.visitAllExitPoints(method.getBlock(), new ControlFlowUtils.ExitPointVisitor() {
|
||||
@Override
|
||||
public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) {
|
||||
if (!checkListInstantiation(constructor, consumer, returnValue, typeElement)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (grandpa instanceof GrTypeCastExpression) {
|
||||
final GrTypeCastExpression cast = (GrTypeCastExpression)grandpa;
|
||||
if (cast.getCastTypeElement() == typeElement &&
|
||||
!checkListInstantiation(constructor, consumer, cast.getOperand(), typeElement)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (grandpa instanceof GrSafeCastExpression) {
|
||||
final GrSafeCastExpression cast = (GrSafeCastExpression)grandpa;
|
||||
if (cast.getCastTypeElement() == typeElement &&
|
||||
!checkListInstantiation(constructor, consumer, cast.getOperand(), typeElement)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static GlobalSearchScope calcGppScope(Project project) {
|
||||
final GlobalSearchScope allScope = GlobalSearchScope.allScope(project);
|
||||
final GlobalSearchScope maximal = GlobalSearchScope.getScopeRestrictedByFileTypes(allScope, GroovyFileType.GROOVY_FILE_TYPE);
|
||||
GlobalSearchScope gppExtensions = new DelegatingGlobalSearchScope(maximal) {
|
||||
@Override
|
||||
public boolean contains(VirtualFile file) {
|
||||
return super.contains(file) && GppTypeConverter.isGppExtension(file.getExtension());
|
||||
}
|
||||
};
|
||||
final PsiClass typed = JavaPsiFacade.getInstance(project).findClass(GppTypeConverter.GROOVY_LANG_TYPED, allScope);
|
||||
if (typed != null) {
|
||||
final Set<VirtualFile> files = new HashSet<VirtualFile>();
|
||||
AnnotatedElementsSearch.searchElements(typed, maximal, PsiModifierListOwner.class).forEach(new Processor<PsiModifierListOwner>() {
|
||||
@Override
|
||||
public boolean process(PsiModifierListOwner occurrence) {
|
||||
ContainerUtil.addIfNotNull(occurrence.getContainingFile().getVirtualFile(), files);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
GlobalSearchScope withTypedAnno = GlobalSearchScope.filesScope(project, files);
|
||||
return withTypedAnno.union(gppExtensions);
|
||||
}
|
||||
|
||||
return gppExtensions;
|
||||
}
|
||||
|
||||
static boolean checkListInstantiation(PsiMethod constructor,
|
||||
Processor<PsiReference> consumer,
|
||||
GrExpression expression, final GrTypeElement typeElement) {
|
||||
if (expression instanceof GrListOrMap) {
|
||||
final GrListOrMap list = (GrListOrMap)expression;
|
||||
if (!list.isMap()) {
|
||||
final PsiType expectedType = typeElement.getType();
|
||||
if (expectedType instanceof PsiClassType) {
|
||||
return checkListInstantiation(constructor, consumer, list, (PsiClassType)expectedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean checkListInstantiation(PsiMethod constructor,
|
||||
Processor<PsiReference> consumer,
|
||||
GrListOrMap list,
|
||||
PsiClassType expectedType) {
|
||||
final PsiType listType = list.getType();
|
||||
if (listType instanceof GrTupleType) {
|
||||
for (GroovyResolveResult candidate : PsiUtil.getConstructorCandidates(expectedType, ((GrTupleType)listType).getComponentTypes(), list)) {
|
||||
if (constructor.getManager().areElementsEquivalent(candidate.getElement(), constructor)) {
|
||||
if (!consumer.process(PsiReferenceBase.createSelfReference(list, TextRange.from(0, list.getTextLength()), constructor))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean processConstructors(final PsiMethod constructor, final Processor<PsiReference> consumer, final PsiClass clazz,
|
||||
final boolean processThisRefs) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
return processClassConstructors(clazz, constructor, consumer, processThisRefs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static boolean processClassConstructors(PsiClass clazz,
|
||||
PsiMethod searchedConstructor,
|
||||
Processor<PsiReference> consumer,
|
||||
boolean processThisRefs) {
|
||||
final PsiMethod[] constructors = clazz.getConstructors();
|
||||
if (constructors.length == 0) {
|
||||
processImplicitConstructorCall(clazz, consumer, searchedConstructor);
|
||||
}
|
||||
for (PsiMethod constructor : constructors) {
|
||||
final GrOpenBlock block = ((GrMethod)constructor).getBlock();
|
||||
if (block != null) {
|
||||
final GrStatement[] statements = block.getStatements();
|
||||
if (statements.length > 0 && statements[0] instanceof GrConstructorInvocation) {
|
||||
final GrConstructorInvocation invocation = (GrConstructorInvocation)statements[0];
|
||||
if (invocation.isThisCall() == processThisRefs &&
|
||||
invocation.getManager().areElementsEquivalent(invocation.resolveConstructor(), searchedConstructor) &&
|
||||
!consumer.process(invocation)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
processImplicitConstructorCall(constructor, consumer, searchedConstructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void processImplicitConstructorCall(final PsiMember usage,
|
||||
final Processor<PsiReference> processor,
|
||||
final PsiMethod constructor) {
|
||||
if (constructor instanceof GrMethod) {
|
||||
GrParameter[] grParameters = (GrParameter[])constructor.getParameterList().getParameters();
|
||||
if (grParameters.length > 0 && !grParameters[0].isOptional()) return;
|
||||
}
|
||||
else if (constructor.getParameterList().getParameters().length > 0) return;
|
||||
|
||||
|
||||
PsiManager manager = constructor.getManager();
|
||||
if (manager.areElementsEquivalent(usage, constructor) || manager.areElementsEquivalent(constructor.getContainingClass(), usage.getContainingClass())) return;
|
||||
processor.process(new LightMemberReference(manager, usage, PsiSubstitutor.EMPTY) {
|
||||
public PsiElement getElement() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public TextRange getRangeInElement() {
|
||||
if (usage instanceof PsiClass) {
|
||||
PsiIdentifier identifier = ((PsiClass)usage).getNameIdentifier();
|
||||
if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength());
|
||||
}
|
||||
else if (usage instanceof PsiMethod) {
|
||||
PsiIdentifier identifier = ((PsiMethod)usage).getNameIdentifier();
|
||||
if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength());
|
||||
}
|
||||
return super.getRangeInElement();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -49,7 +50,7 @@ public class GppClosureParameterTypeProvider extends AbstractClosureParameterEnh
|
||||
if (listType instanceof GrTupleType) {
|
||||
for (PsiType type : GroovyExpectedTypesProvider.getDefaultExpectedTypes(list)) {
|
||||
if (type instanceof PsiClassType) {
|
||||
for (GroovyResolveResult resolveResult : GppTypeConverter
|
||||
for (GroovyResolveResult resolveResult : PsiUtil
|
||||
.getConstructorCandidates((PsiClassType)type, ((GrTupleType)listType).getComponentTypes(), closure)) {
|
||||
final PsiElement method = resolveResult.getElement();
|
||||
if (method instanceof PsiMethod && ((PsiMethod)method).isConstructor()) {
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesPr
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SubtypeConstraint;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -48,7 +49,7 @@ public class GppExpectedTypesContributor extends GroovyExpectedTypesContributor
|
||||
final ArrayList<TypeConstraint> result = new ArrayList<TypeConstraint>();
|
||||
for (PsiType type : GroovyExpectedTypesProvider.getDefaultExpectedTypes(expression)) {
|
||||
if (type instanceof PsiClassType) {
|
||||
for (GroovyResolveResult resolveResult : GppTypeConverter.getConstructorCandidates((PsiClassType)type, argTypes, expression)) {
|
||||
for (GroovyResolveResult resolveResult : PsiUtil.getConstructorCandidates((PsiClassType)type, argTypes, expression)) {
|
||||
final PsiElement method = resolveResult.getElement();
|
||||
if (method instanceof PsiMethod && ((PsiMethod)method).isConstructor()) {
|
||||
final PsiParameter[] constructorParameters = ((PsiMethod)method).getParameterList().getParameters();
|
||||
|
||||
@@ -7,12 +7,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.dsl.toplevel.AnnotatedContextFilter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
|
||||
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.impl.types.GrClosureSignatureUtil;
|
||||
|
||||
@@ -21,26 +19,29 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
|
||||
*/
|
||||
public class GppTypeConverter extends GrTypeConverter {
|
||||
|
||||
public static final String GROOVY_LANG_TYPED = "groovy.lang.Typed";
|
||||
|
||||
public static boolean hasTypedContext(PsiElement context) {
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AnnotatedContextFilter.hasAnnotatedContext(context, "groovy.lang.Typed")) {
|
||||
if (AnnotatedContextFilter.hasAnnotatedContext(context, GROOVY_LANG_TYPED)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final VirtualFile vfile = context.getContainingFile().getOriginalFile().getVirtualFile();
|
||||
if (vfile != null) {
|
||||
final String extension = vfile.getExtension();
|
||||
if ("gpp".equals(extension) || "grunit".equals(vfile.getExtension())) {
|
||||
return true;
|
||||
}
|
||||
if (vfile != null && isGppExtension(vfile.getExtension())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isGppExtension(String extension) {
|
||||
return "gpp".equals(extension) || "grunit".equals(extension);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
|
||||
if (rType instanceof GrTupleType) {
|
||||
@@ -93,21 +94,7 @@ public class GppTypeConverter extends GrTypeConverter {
|
||||
}
|
||||
|
||||
private static boolean hasConstructor(PsiClassType lType, PsiType[] argTypes, GroovyPsiElement context) {
|
||||
return getConstructorCandidates(lType, argTypes, context).length == 1;
|
||||
}
|
||||
|
||||
public static GroovyResolveResult[] getConstructorCandidates(PsiClassType classType, PsiType[] argTypes, GroovyPsiElement context) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
if (psiClass == null) {
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
final GroovyResolveResult grResult = resolveResult instanceof GroovyResolveResult
|
||||
? (GroovyResolveResult)resolveResult
|
||||
: new GroovyResolveResultImpl(psiClass, context, substitutor, true, true);
|
||||
return org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getConstructorCandidates(context, new GroovyResolveResult[]{grResult}, argTypes);
|
||||
return org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getConstructorCandidates(lType, argTypes, context).length == 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-6
@@ -16,10 +16,7 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging;
|
||||
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.UserDataHolderEx;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement;
|
||||
@@ -28,10 +25,11 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public interface GrPackageDefinition
|
||||
extends UserDataHolderEx, Cloneable, Iconable, PsiElement, NavigationItem, GrTopStatement {
|
||||
public interface GrPackageDefinition extends GrTopStatement, PsiModifierListOwner {
|
||||
@Nullable
|
||||
String getPackageName();
|
||||
|
||||
@Nullable
|
||||
GrCodeReferenceElement getPackageReference();
|
||||
|
||||
@Nullable
|
||||
|
||||
+11
-6
@@ -107,16 +107,19 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
|
||||
if (!(block.getParent() instanceof GrBlockStatement && block.getParent().getParent() instanceof GrLoopStatement)) {
|
||||
final GrStatement[] statements = block.getStatements();
|
||||
if (statements.length > 0) {
|
||||
final GrStatement last = statements[statements.length - 1];
|
||||
if (last instanceof GrExpression) {
|
||||
final MaybeReturnInstruction instruction = new MaybeReturnInstruction((GrExpression)last, myInstructionNumber++);
|
||||
checkPending(instruction);
|
||||
addNode(instruction);
|
||||
}
|
||||
handlePossibleReturn(statements[statements.length - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePossibleReturn(GrStatement last) {
|
||||
if (last instanceof GrExpression) {
|
||||
final MaybeReturnInstruction instruction = new MaybeReturnInstruction((GrExpression)last, myInstructionNumber++);
|
||||
checkPending(instruction);
|
||||
addNode(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
public Instruction[] buildControlFlow(GroovyPsiElement scope, GroovyPsiElement startInScope, GroovyPsiElement endInScope) {
|
||||
myInstructions = new ArrayList<InstructionImpl>();
|
||||
myProcessingStack = new Stack<InstructionImpl>();
|
||||
@@ -386,6 +389,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
|
||||
condition.accept(this);
|
||||
}
|
||||
thenBranch.accept(this);
|
||||
handlePossibleReturn(thenBranch);
|
||||
addPendingEdge(ifStatement, myHead);
|
||||
}
|
||||
|
||||
@@ -402,6 +406,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
|
||||
final GrStatement elseBranch = ifStatement.getElseBranch();
|
||||
if (elseBranch != null) {
|
||||
elseBranch.accept(this);
|
||||
handlePossibleReturn(elseBranch);
|
||||
addPendingEdge(ifStatement, myHead);
|
||||
}
|
||||
|
||||
|
||||
+33
-2
@@ -18,12 +18,23 @@ package org.jetbrains.plugins.groovy.lang.psi.impl;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||
import com.intellij.psi.stubs.StubIndex;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.plugins.groovy.lang.stubs.GroovyCacheUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnonymousClassIndex;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrDirectInheritorsIndex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -32,6 +43,26 @@ class GroovyDirectInheritorsSearcher implements QueryExecutor<PsiClass, DirectCl
|
||||
public GroovyDirectInheritorsSearcher() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiClass[] getDeriverCandidates(PsiClass clazz, GlobalSearchScope scope) {
|
||||
final String name = clazz.getName();
|
||||
if (name == null) return GrTypeDefinition.EMPTY_ARRAY;
|
||||
final ArrayList<PsiClass> inheritors = new ArrayList<PsiClass>();
|
||||
final Collection<GrReferenceList> refLists = StubIndex.getInstance().get(GrDirectInheritorsIndex.KEY, name, clazz.getProject(), scope);
|
||||
for (GrReferenceList list : refLists) {
|
||||
final PsiElement parent = list.getParent();
|
||||
if (parent instanceof GrTypeDefinition) {
|
||||
inheritors.add(GrClassSubstitutor.getSubstitutedClass(((GrTypeDefinition)parent)));
|
||||
}
|
||||
}
|
||||
final Collection<GrAnonymousClassDefinition> classes =
|
||||
StubIndex.getInstance().get(GrAnonymousClassIndex.KEY, name, clazz.getProject(), scope);
|
||||
for (GrAnonymousClassDefinition aClass : classes) {
|
||||
inheritors.add(aClass);
|
||||
}
|
||||
return inheritors.toArray(new PsiClass[inheritors.size()]);
|
||||
}
|
||||
|
||||
public boolean execute(DirectClassInheritorsSearch.SearchParameters queryParameters, final Processor<PsiClass> consumer) {
|
||||
final PsiClass clazz = queryParameters.getClassToProcess();
|
||||
final SearchScope scope = queryParameters.getScope();
|
||||
@@ -39,7 +70,7 @@ class GroovyDirectInheritorsSearcher implements QueryExecutor<PsiClass, DirectCl
|
||||
final PsiClass[] candidates = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
|
||||
public PsiClass[] compute() {
|
||||
if (!clazz.isValid()) return PsiClass.EMPTY_ARRAY;
|
||||
return GroovyCacheUtil.getDeriverCandidates(clazz, (GlobalSearchScope)scope);
|
||||
return getDeriverCandidates(clazz, (GlobalSearchScope)scope);
|
||||
}
|
||||
});
|
||||
for (final PsiClass candidate : candidates) {
|
||||
|
||||
+14
@@ -17,6 +17,9 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.toplevel.packaging;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.Modifier;
|
||||
import com.intellij.psi.PsiModifierList;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
@@ -56,4 +59,15 @@ public class GrPackageDefinitionImpl extends GroovyPsiElementImpl implements GrP
|
||||
public GrModifierList getAnnotationList() {
|
||||
return (GrModifierList)findChildByType(GroovyElementTypes.MODIFIERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiModifierList getModifierList() {
|
||||
return getAnnotationList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifierProperty(@Modifier @NonNls @NotNull String name) {
|
||||
final PsiModifierList list = getModifierList();
|
||||
return list != null && list.hasExplicitModifier(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,63 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.stubs;
|
||||
|
||||
import com.intellij.psi.stubs.PsiFileStub;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.stubs.PsiFileStubImpl;
|
||||
import com.intellij.psi.tree.IStubFileElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.io.StringRef;
|
||||
import org.jetbrains.plugins.groovy.lang.parser.GroovyParserDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.elements.GrTypeDefinitionElementType;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public interface GrFileStub extends PsiFileStub<GroovyFile> {
|
||||
StringRef getPackageName();
|
||||
public class GrFileStub extends PsiFileStubImpl<GroovyFile> {
|
||||
private final String[] myAnnotations;
|
||||
private final StringRef myPackageName;
|
||||
private final StringRef myName;
|
||||
private final boolean isScript;
|
||||
|
||||
StringRef getName();
|
||||
public GrFileStub(GroovyFile file) {
|
||||
super(file);
|
||||
myPackageName = StringRef.fromString(file.getPackageName());
|
||||
myName = StringRef.fromString(StringUtil.trimEnd(file.getName(), ".groovy"));
|
||||
isScript = file.isScript();
|
||||
final GrPackageDefinition definition = file.getPackageDefinition();
|
||||
if (definition != null) {
|
||||
myAnnotations = GrTypeDefinitionElementType.getAnnotationNames(definition);
|
||||
} else {
|
||||
myAnnotations = ArrayUtil.EMPTY_STRING_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isScript();
|
||||
public GrFileStub(StringRef packName, StringRef name, boolean isScript, String[] annotations) {
|
||||
super(null);
|
||||
myPackageName = packName;
|
||||
myName = name;
|
||||
this.isScript = isScript;
|
||||
myAnnotations = annotations;
|
||||
}
|
||||
|
||||
public IStubFileElementType getType() {
|
||||
return GroovyParserDefinition.GROOVY_FILE;
|
||||
}
|
||||
|
||||
public StringRef getPackageName() {
|
||||
return myPackageName;
|
||||
}
|
||||
|
||||
public StringRef getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public boolean isScript() {
|
||||
return isScript;
|
||||
}
|
||||
|
||||
public String[] getAnnotations() {
|
||||
return myAnnotations;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,5 +58,21 @@ public class GrStubUtils {
|
||||
dataStream.writeUTF(namepParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeStringArray(StubOutputStream dataStream, String[] array) throws IOException {
|
||||
dataStream.writeByte(array.length);
|
||||
for (String s : array) {
|
||||
dataStream.writeName(s);
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] readStringArray(StubInputStream dataStream) throws IOException {
|
||||
final byte b = dataStream.readByte();
|
||||
final String[] annNames = new String[b];
|
||||
for (int i = 0; i < b; i++) {
|
||||
annNames[i] = dataStream.readName().toString();
|
||||
}
|
||||
return annNames;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -19,7 +19,6 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.stubs.DefaultStubBuilder;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.impl.GrFileStubImpl;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -27,7 +26,7 @@ import org.jetbrains.plugins.groovy.lang.psi.stubs.impl.GrFileStubImpl;
|
||||
public class GroovyFileStubBuilder extends DefaultStubBuilder {
|
||||
protected StubElement createStubForFile(final PsiFile file) {
|
||||
if (file instanceof GroovyFile && ((GroovyFile) file).isScript()) {
|
||||
return new GrFileStubImpl((GroovyFile)file);
|
||||
return new GrFileStub((GroovyFile)file);
|
||||
}
|
||||
|
||||
return super.createStubForFile(file);
|
||||
|
||||
+1
-22
@@ -21,16 +21,10 @@ import com.intellij.psi.stubs.IndexSink;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.stubs.StubInputStream;
|
||||
import com.intellij.psi.stubs.StubOutputStream;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.StringRef;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrStubElementType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrFieldImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrFieldStub;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.impl.GrFieldStubImpl;
|
||||
@@ -64,22 +58,7 @@ public class GrFieldElementType extends GrStubElementType<GrFieldStub, GrField>
|
||||
}
|
||||
|
||||
public GrFieldStub createStub(GrField psi, StubElement parentStub) {
|
||||
final GrModifierList modifiers = psi.getModifierList();
|
||||
String[] annNames;
|
||||
if (modifiers == null) {
|
||||
annNames = ArrayUtil.EMPTY_STRING_ARRAY;
|
||||
}
|
||||
else {
|
||||
final GrAnnotation[] annotations = modifiers.getAnnotations();
|
||||
annNames = ContainerUtil.map(annotations, new Function<GrAnnotation, String>() {
|
||||
@Nullable
|
||||
public String fun(final GrAnnotation grAnnotation) {
|
||||
final GrCodeReferenceElement element = grAnnotation.getClassReference();
|
||||
if (element == null) return null;
|
||||
return element.getReferenceName();
|
||||
}
|
||||
}, new String[annotations.length]);
|
||||
}
|
||||
String[] annNames = GrTypeDefinitionElementType.getAnnotationNames(psi);
|
||||
|
||||
Set<String>[] namedParametersArray = new Set[0];
|
||||
if (psi instanceof GrFieldImpl){
|
||||
|
||||
+8
-32
@@ -20,15 +20,9 @@ import com.intellij.psi.stubs.IndexSink;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.stubs.StubInputStream;
|
||||
import com.intellij.psi.stubs.StubOutputStream;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.StringRef;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrStubElementType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrMethodImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrMethodStub;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrStubUtils;
|
||||
@@ -37,7 +31,9 @@ import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnnotatedMemberIndex;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrMethodNameIndex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -57,42 +53,22 @@ public class GrMethodElementType extends GrStubElementType<GrMethodStub, GrMetho
|
||||
}
|
||||
|
||||
public GrMethodStub createStub(GrMethod psi, StubElement parentStub) {
|
||||
final GrModifierList modifiers = psi.getModifierList();
|
||||
final GrAnnotation[] annotations = modifiers.getAnnotations();
|
||||
String[] annNames = ContainerUtil.map(annotations, new Function<GrAnnotation, String>() {
|
||||
@Nullable
|
||||
public String fun(final GrAnnotation grAnnotation) {
|
||||
final GrCodeReferenceElement element = grAnnotation.getClassReference();
|
||||
if (element == null) return null;
|
||||
return element.getReferenceName();
|
||||
}
|
||||
}, new String[annotations.length]);
|
||||
|
||||
Set<String>[] namedParametersArray;
|
||||
namedParametersArray = psi.getNamedParametersArray();
|
||||
|
||||
return new GrMethodStubImpl(parentStub, StringRef.fromString(psi.getName()), annNames, namedParametersArray);
|
||||
return new GrMethodStubImpl(parentStub, StringRef.fromString(psi.getName()), GrTypeDefinitionElementType.getAnnotationNames(psi),
|
||||
psi.getNamedParametersArray());
|
||||
}
|
||||
|
||||
public void serialize(GrMethodStub stub, StubOutputStream dataStream) throws IOException {
|
||||
dataStream.writeName(stub.getName());
|
||||
final String[] annotations = stub.getAnnotations();
|
||||
dataStream.writeByte(annotations.length);
|
||||
for (String s : annotations) {
|
||||
dataStream.writeName(s);
|
||||
}
|
||||
GrStubUtils.writeStringArray(dataStream, stub.getAnnotations());
|
||||
final Set<String>[] namedParameters = stub.getNamedParameters();
|
||||
|
||||
GrStubUtils.serializeCollectionsArray(dataStream, namedParameters);
|
||||
}
|
||||
|
||||
|
||||
public GrMethodStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException {
|
||||
StringRef ref = dataStream.readName();
|
||||
final byte b = dataStream.readByte();
|
||||
final String[] annNames = new String[b];
|
||||
for (int i = 0; i < b; i++) {
|
||||
annNames[i] = dataStream.readName().toString();
|
||||
}
|
||||
final String[] annNames = GrStubUtils.readStringArray(dataStream);
|
||||
final List<Set<String>> namedParametersSets = GrStubUtils.deserializeCollectionsArray(dataStream);
|
||||
|
||||
return new GrMethodStubImpl(parentStub, ref, annNames, namedParametersSets.toArray(new HashSet[0]));
|
||||
|
||||
+9
-3
@@ -21,8 +21,9 @@ import com.intellij.psi.stubs.*;
|
||||
import com.intellij.psi.tree.IStubFileElementType;
|
||||
import com.intellij.util.io.StringRef;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrFileStub;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrStubUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GroovyFileStubBuilder;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.impl.GrFileStubImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnnotatedMemberIndex;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrFullScriptNameIndex;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrScriptClassNameIndex;
|
||||
|
||||
@@ -43,7 +44,7 @@ public class GrStubFileElementType extends IStubFileElementType<GrFileStub> {
|
||||
|
||||
@Override
|
||||
public int getStubVersion() {
|
||||
return super.getStubVersion() + 5;
|
||||
return super.getStubVersion() + 6;
|
||||
}
|
||||
|
||||
public String getExternalId() {
|
||||
@@ -60,6 +61,7 @@ public class GrStubFileElementType extends IStubFileElementType<GrFileStub> {
|
||||
dataStream.writeName(stub.getPackageName().toString());
|
||||
dataStream.writeName(stub.getName().toString());
|
||||
dataStream.writeBoolean(stub.isScript());
|
||||
GrStubUtils.writeStringArray(dataStream, stub.getAnnotations());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,7 +69,7 @@ public class GrStubFileElementType extends IStubFileElementType<GrFileStub> {
|
||||
StringRef packName = dataStream.readName();
|
||||
StringRef name = dataStream.readName();
|
||||
boolean isScript = dataStream.readBoolean();
|
||||
return new GrFileStubImpl(packName, name, isScript);
|
||||
return new GrFileStub(packName, name, isScript, GrStubUtils.readStringArray(dataStream));
|
||||
}
|
||||
|
||||
public void indexStub(GrFileStub stub, IndexSink sink) {
|
||||
@@ -78,6 +80,10 @@ public class GrStubFileElementType extends IStubFileElementType<GrFileStub> {
|
||||
final String fqn = pName == null || pName.length() == 0 ? name : pName + "." + name;
|
||||
sink.occurrence(GrFullScriptNameIndex.KEY, fqn.hashCode());
|
||||
}
|
||||
|
||||
for (String anno : stub.getAnnotations()) {
|
||||
sink.occurrence(GrAnnotatedMemberIndex.KEY, anno);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.stubs.elements;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiModifierList;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.PsiNameHelper;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaShortClassNameIndex;
|
||||
@@ -59,7 +60,7 @@ public abstract class GrTypeDefinitionElementType<TypeDef extends GrTypeDefiniti
|
||||
flags);
|
||||
}
|
||||
|
||||
private static String[] getAnnotationNames(GrTypeDefinition psi) {
|
||||
public static String[] getAnnotationNames(PsiModifierListOwner psi) {
|
||||
List<String> annoNames = CollectionFactory.arrayList();
|
||||
final PsiModifierList modifierList = psi.getModifierList();
|
||||
if (modifierList instanceof GrModifierList) {
|
||||
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.stubs.impl;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.stubs.PsiFileStubImpl;
|
||||
import com.intellij.psi.tree.IStubFileElementType;
|
||||
import com.intellij.util.io.StringRef;
|
||||
import org.jetbrains.plugins.groovy.lang.parser.GroovyParserDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrFileStub;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GrFileStubImpl extends PsiFileStubImpl<GroovyFile> implements GrFileStub {
|
||||
private final StringRef myPackageName;
|
||||
private final StringRef myName;
|
||||
private final boolean isScript;
|
||||
|
||||
public GrFileStubImpl(GroovyFile file) {
|
||||
super(file);
|
||||
myPackageName = StringRef.fromString(file.getPackageName());
|
||||
myName = StringRef.fromString(StringUtil.trimEnd(file.getName(), ".groovy"));
|
||||
isScript = file.isScript();
|
||||
}
|
||||
|
||||
public GrFileStubImpl(StringRef packName, StringRef name, boolean isScript) {
|
||||
super(null);
|
||||
myPackageName = packName;
|
||||
myName = name;
|
||||
this.isScript = isScript;
|
||||
}
|
||||
|
||||
public IStubFileElementType getType() {
|
||||
return GroovyParserDefinition.GROOVY_FILE;
|
||||
}
|
||||
|
||||
public StringRef getPackageName() {
|
||||
return myPackageName;
|
||||
}
|
||||
|
||||
public StringRef getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public boolean isScript() {
|
||||
return isScript;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -15,17 +15,17 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.stubs.index;
|
||||
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension;
|
||||
import com.intellij.psi.stubs.StubIndexKey;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GrAnnotatedMemberIndex extends StringStubIndexExtension<PsiMember> {
|
||||
public static final StubIndexKey<String, PsiMember> KEY = StubIndexKey.createIndexKey("gr.annot.members");
|
||||
public class GrAnnotatedMemberIndex extends StringStubIndexExtension<PsiElement> {
|
||||
public static final StubIndexKey<String, PsiElement> KEY = StubIndexKey.createIndexKey("gr.annot.members");
|
||||
|
||||
public StubIndexKey<String, PsiMember> getKey() {
|
||||
public StubIndexKey<String, PsiElement> getKey() {
|
||||
return KEY;
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
|
||||
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.impl.synthetic.GroovyScriptClass;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.JavaIdentifier;
|
||||
@@ -939,4 +940,18 @@ public class PsiUtil {
|
||||
}
|
||||
return (GrReferenceExpression)replaced;
|
||||
}
|
||||
|
||||
public static GroovyResolveResult[] getConstructorCandidates(PsiClassType classType, PsiType[] argTypes, GroovyPsiElement context) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
if (psiClass == null) {
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
final GroovyResolveResult grResult = resolveResult instanceof GroovyResolveResult
|
||||
? (GroovyResolveResult)resolveResult
|
||||
: new GroovyResolveResultImpl(psiClass, context, substitutor, true, true);
|
||||
return getConstructorCandidates(context, new GroovyResolveResult[]{grResult}, argTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.stubs;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.stubs.StubIndex;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnnotatedMemberIndex;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnonymousClassIndex;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrDirectInheritorsIndex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public abstract class GroovyCacheUtil {
|
||||
|
||||
@NotNull
|
||||
public static PsiMember[] getAnnotatedMemberCandidates(PsiClass clazz, GlobalSearchScope scope) {
|
||||
final String name = clazz.getName();
|
||||
if (name == null) return GrMember.EMPTY_ARRAY;
|
||||
final Collection<PsiMember> members = StubIndex.getInstance().get(GrAnnotatedMemberIndex.KEY, name, clazz.getProject(), scope);
|
||||
return members.toArray(new PsiMember[members.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiClass[] getDeriverCandidates(PsiClass clazz, GlobalSearchScope scope) {
|
||||
final String name = clazz.getName();
|
||||
if (name == null) return GrTypeDefinition.EMPTY_ARRAY;
|
||||
final ArrayList<PsiClass> inheritors = new ArrayList<PsiClass>();
|
||||
final Collection<GrReferenceList> refLists = StubIndex.getInstance().get(GrDirectInheritorsIndex.KEY, name, clazz.getProject(), scope);
|
||||
for (GrReferenceList list : refLists) {
|
||||
final PsiElement parent = list.getParent();
|
||||
if (parent instanceof GrTypeDefinition) {
|
||||
inheritors.add(GrClassSubstitutor.getSubstitutedClass(((GrTypeDefinition)parent)));
|
||||
}
|
||||
}
|
||||
final Collection<GrAnonymousClassDefinition> classes =
|
||||
StubIndex.getInstance().get(GrAnonymousClassIndex.KEY, name, clazz.getProject(), scope);
|
||||
for (GrAnonymousClassDefinition aClass : classes) {
|
||||
inheritors.add(aClass);
|
||||
}
|
||||
return inheritors.toArray(new PsiClass[inheritors.size()]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
package org.jetbrains.plugins.groovy.lang
|
||||
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class LiteralConstructorUsagesTest extends LightCodeInsightFixtureTestCase {
|
||||
@Override protected void setUp() {
|
||||
super.setUp();
|
||||
myFixture.addClass("package groovy.lang; public @interface Typed {}");
|
||||
}
|
||||
|
||||
public void testList_Variable() throws Exception {
|
||||
def foo = myFixture.addClass("""class Foo {
|
||||
Foo() {}
|
||||
}
|
||||
""")
|
||||
myFixture.addFileToProject "a.groovy", "Foo x = []"
|
||||
assertOneElement(ReferencesSearch.search(foo.constructors[0]).findAll())
|
||||
}
|
||||
|
||||
public void testList_ReturnValue() throws Exception {
|
||||
def foo = myFixture.addClass("""class Foo {
|
||||
Foo() {}
|
||||
}
|
||||
""")
|
||||
myFixture.addFileToProject "a.groovy", "Foo foo() { if (true) [] else return [] }"
|
||||
assertEquals(2, ReferencesSearch.search(foo.constructors[0]).findAll().size())
|
||||
}
|
||||
|
||||
public void testList_Cast() throws Exception {
|
||||
def foo = myFixture.addClass("""class Foo {
|
||||
Foo() {}
|
||||
}
|
||||
""")
|
||||
myFixture.addFileToProject "a.groovy", "def x = (Foo) []"
|
||||
assertOneElement(ReferencesSearch.search(foo.constructors[0]).findAll())
|
||||
}
|
||||
|
||||
public void testList_AsCast() throws Exception {
|
||||
def foo = myFixture.addClass("""class Foo {
|
||||
Foo() {}
|
||||
}
|
||||
}""")
|
||||
myFixture.addFileToProject "a.groovy", "def x = [] as Foo"
|
||||
assertOneElement(ReferencesSearch.search(foo.constructors[0]).findAll())
|
||||
}
|
||||
|
||||
public void testList_GppMethodCall() throws Exception {
|
||||
//------------------------declarations
|
||||
def foo = myFixture.addClass("""
|
||||
package z;
|
||||
class Foo {
|
||||
public Foo() {}
|
||||
}
|
||||
""")
|
||||
|
||||
myFixture.addClass("""
|
||||
package z;
|
||||
public class Bar {
|
||||
public static void giveMeFoo(int a, Foo f) {}
|
||||
}
|
||||
""")
|
||||
myFixture.addFileToProject("Decl.groovy", "static def giveMeFooAsWell(z.Foo f) {}")
|
||||
|
||||
//----------------------usages
|
||||
myFixture.addFileToProject "a.gpp", "z.Bar.giveMeFoo(2, []) //usage"
|
||||
myFixture.addFileToProject "b.groovy", """
|
||||
@Typed package aa;
|
||||
z.Bar.giveMeFoo(3, []) //usage
|
||||
"""
|
||||
myFixture.addFileToProject "c.groovy", """
|
||||
@Typed def someMethod() {
|
||||
z.Bar.giveMeFoo 4, [] //usage
|
||||
Decl.giveMeFooAsWell([]) //usage
|
||||
}
|
||||
z.Bar.giveMeFoo 5, [] //non-typed context
|
||||
Decl.giveMeFooAsWell([])
|
||||
"""
|
||||
myFixture.addFileToProject "invalid.gpp", "z.Bar.giveMeFoo 42, 239, []"
|
||||
myFixture.addFileToProject "nonGpp.groovy", "z.Bar.giveMeFoo(6, [])"
|
||||
assertEquals(4, ReferencesSearch.search(foo.constructors[0]).findAll().size())
|
||||
}
|
||||
|
||||
public void testList_GppConstructorCallWithSeveralParameters() throws Exception {
|
||||
def foo = myFixture.addClass("""
|
||||
class Foo {
|
||||
Foo() {}
|
||||
}
|
||||
""")
|
||||
|
||||
myFixture.addClass("""
|
||||
class Bar {
|
||||
Bar(Foo f1, Foo f2, Foo f3) {}
|
||||
}
|
||||
""")
|
||||
myFixture.addFileToProject "a.gpp", "new Bar([],[],[])"
|
||||
assertEquals(3, ReferencesSearch.search(foo.constructors[0]).findAll().size())
|
||||
}
|
||||
|
||||
}
|
||||
+3
-2
@@ -7,6 +7,7 @@ if (true) {
|
||||
0(1) element: null
|
||||
1(2,4) element: IF statement
|
||||
2(3) WRITE a
|
||||
3(5) element: Assignment expression MAYBE_RETURN
|
||||
3(6) element: Assignment expression MAYBE_RETURN
|
||||
4(5) WRITE a
|
||||
5() element: null
|
||||
5(6) element: Assignment expression MAYBE_RETURN
|
||||
6() element: null
|
||||
@@ -3,17 +3,20 @@ else if (!(o instanceof Integer)) b = 2
|
||||
else b = 3
|
||||
-----
|
||||
0(1) element: null
|
||||
1(2,5) element: IF statement
|
||||
1(2,6) element: IF statement
|
||||
2(3) READ o
|
||||
3(4) assertion: o instanceof String
|
||||
4(14) WRITE b
|
||||
5(6) READ o
|
||||
6(7) assertion: ! o instanceof String
|
||||
7(8,11) element: IF statement
|
||||
8(9) READ o
|
||||
9(10) assertion: ! o instanceof Integer
|
||||
10(14) WRITE b
|
||||
11(12) READ o
|
||||
12(13) assertion: o instanceof Integer
|
||||
13(14) WRITE b
|
||||
14() element: null
|
||||
4(5) WRITE b
|
||||
5(17) element: Assignment expression MAYBE_RETURN
|
||||
6(7) READ o
|
||||
7(8) assertion: ! o instanceof String
|
||||
8(9,13) element: IF statement
|
||||
9(10) READ o
|
||||
10(11) assertion: ! o instanceof Integer
|
||||
11(12) WRITE b
|
||||
12(17) element: Assignment expression MAYBE_RETURN
|
||||
13(14) READ o
|
||||
14(15) assertion: o instanceof Integer
|
||||
15(16) WRITE b
|
||||
16(17) element: Assignment expression MAYBE_RETURN
|
||||
17() element: null
|
||||
@@ -616,11 +616,17 @@ public class SvnUtil {
|
||||
}
|
||||
|
||||
public static boolean doesRepositorySupportMergeinfo(final SvnVcs vcs, final SVNURL url) {
|
||||
SVNRepository repository = null;
|
||||
try {
|
||||
return vcs.createRepository(url).hasCapability(SVNCapability.MERGE_INFO);
|
||||
repository = vcs.createRepository(url);
|
||||
return repository.hasCapability(SVNCapability.MERGE_INFO);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return false;
|
||||
} finally {
|
||||
if (repository != null) {
|
||||
repository.closeSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,8 @@ public class CompareWithBranchAction extends AnAction implements DumbAware {
|
||||
|
||||
|
||||
SVNWCAccess wcAccess = vcs.createWCAccess();
|
||||
SVNRepository repository = null;
|
||||
SVNRepository repository2 = null;
|
||||
try {
|
||||
SVNAdminAreaInfo info = wcAccess.openAnchor(new File(myVirtualFile.getPath()), false, SVNWCAccess.INFINITE_DEPTH);
|
||||
File anchorPath = info.getAnchor().getRoot();
|
||||
@@ -150,18 +152,25 @@ public class CompareWithBranchAction extends AnAction implements DumbAware {
|
||||
}
|
||||
|
||||
SVNURL anchorURL = anchorEntry.getSVNURL();
|
||||
SVNRepository repository = vcs.createRepository(anchorURL.toString());
|
||||
repository = vcs.createRepository(anchorURL.toString());
|
||||
SVNReporter reporter = new SVNReporter(info, info.getAnchor().getFile(info.getTargetName()), false, true, SVNDepth.INFINITY,
|
||||
false, false, true, SVNDebugLog.getDefaultLog());
|
||||
long rev = repository.getLatestRevision();
|
||||
repository2 = vcs.createRepository((target == null) ? url.toString() : url.removePathTail().toString());
|
||||
SvnDiffEditor diffEditor = new SvnDiffEditor((target == null) ? myVirtualFile : myVirtualFile.getParent(),
|
||||
vcs.createRepository((target == null) ? url.toString() : url.removePathTail().toString()), rev, true);
|
||||
repository2, rev, true);
|
||||
repository.diff(url, rev, rev, target, true, true, false, reporter,
|
||||
SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null));
|
||||
changes.addAll(diffEditor.getChangesMap().values());
|
||||
}
|
||||
finally {
|
||||
wcAccess.close();
|
||||
if (repository != null) {
|
||||
repository.closeSession();
|
||||
}
|
||||
if (repository2 != null) {
|
||||
repository2.closeSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(SVNCancelException ex) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.idea.svn.SvnConfiguration;
|
||||
import org.jetbrains.idea.svn.SvnServerFileManager;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -137,10 +138,16 @@ public class SvnConfigureProxiesDialog extends DialogWrapper implements Validati
|
||||
if (pi != null) {
|
||||
pi.setText("Connecting to " + url);
|
||||
}
|
||||
SVNRepository repository = null;
|
||||
try {
|
||||
SvnVcs.getInstance(myProject).createRepository(url).testConnection();
|
||||
repository = SvnVcs.getInstance(myProject).createRepository(url);
|
||||
repository.testConnection();
|
||||
} catch (SVNException exc) {
|
||||
excRef.set(exc);
|
||||
} finally {
|
||||
if (repository != null) {
|
||||
repository.closeSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, "Test connection", true, myProject);
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.idea.svn.update.UpdateEventHandler;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||
import org.tmatesoft.svn.core.wc.SVNDiffClient;
|
||||
import org.tmatesoft.svn.core.wc.SVNDiffOptions;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
@@ -55,11 +56,17 @@ public class BranchMerger implements IMerger {
|
||||
myBranchName = branchName;
|
||||
mySourceCopyRevision = sourceCopyRevision;
|
||||
myAtStart = true;
|
||||
SVNRepository repository = null;
|
||||
try {
|
||||
mySourceLatestRevision = myVcs.createRepository(mySourceUrl).getLatestRevision();
|
||||
repository = myVcs.createRepository(mySourceUrl);
|
||||
mySourceLatestRevision = repository.getLatestRevision();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
mySourceLatestRevision = SVNRevision.HEAD.getNumber();
|
||||
} finally {
|
||||
if (repository != null) {
|
||||
repository.closeSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1099,10 +1099,13 @@ public class RepositoryBrowserDialog extends DialogWrapper {
|
||||
SVNRepository sourceRepository = myVCS.createRepository(sourceURL.toString());
|
||||
sourceRepository.setCanceller(new SvnProgressCanceller());
|
||||
SvnDiffEditor diffEditor;
|
||||
final long rev = sourceRepository.getLatestRevision();
|
||||
final long rev;
|
||||
SVNRepository targetRepository = null;
|
||||
try {
|
||||
rev = sourceRepository.getLatestRevision();
|
||||
// generate Map of path->Change
|
||||
diffEditor = new SvnDiffEditor(sourceRepository, myVCS.createRepository(targetURL.toString()), -1, false);
|
||||
targetRepository = myVCS.createRepository(targetURL.toString());
|
||||
diffEditor = new SvnDiffEditor(sourceRepository, targetRepository, -1, false);
|
||||
final ISVNEditor cancellableEditor = SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null);
|
||||
sourceRepository.diff(targetURL, rev, rev, null, true, true, false, new ISVNReporterBaton() {
|
||||
public void report(ISVNReporter reporter) throws SVNException {
|
||||
@@ -1113,6 +1116,9 @@ public class RepositoryBrowserDialog extends DialogWrapper {
|
||||
}
|
||||
finally {
|
||||
sourceRepository.closeSession();
|
||||
if (targetRepository != null) {
|
||||
targetRepository.closeSession();
|
||||
}
|
||||
}
|
||||
final String sourceTitle = SVNPathUtil.tail(sourceURL.toString());
|
||||
final String targetTitle = SVNPathUtil.tail(targetURL.toString());
|
||||
|
||||
@@ -120,12 +120,16 @@ public class SelectLocationDialog extends DialogWrapper {
|
||||
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
public void run() {
|
||||
SVNRepository repos = null;
|
||||
try {
|
||||
SVNRepository repos = SvnVcs.getInstance(project).createRepository(urlString);
|
||||
repos = SvnVcs.getInstance(project).createRepository(urlString);
|
||||
result.set(repos.getRepositoryRoot(true));
|
||||
repos.closeSession();
|
||||
} catch (SVNException e) {
|
||||
excRef.set(e);
|
||||
} finally {
|
||||
if (repos != null) {
|
||||
repos.closeSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, "Detecting repository root", true, project);
|
||||
|
||||
+29
-6
@@ -184,13 +184,17 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi
|
||||
}
|
||||
|
||||
final String repositoryRoot;
|
||||
SVNRepository repository = null;
|
||||
try {
|
||||
final SVNRepository repository = myVcs.createRepository(svnLocation.getURL());
|
||||
repository = myVcs.createRepository(svnLocation.getURL());
|
||||
repositoryRoot = repository.getRepositoryRoot(true).toString();
|
||||
repository.closeSession();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
} finally {
|
||||
if (repository != null) {
|
||||
repository.closeSession();
|
||||
}
|
||||
}
|
||||
|
||||
final ChangeBrowserSettings.Filter filter = settings.createFilter();
|
||||
@@ -219,13 +223,18 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi
|
||||
}
|
||||
|
||||
final String repositoryRoot;
|
||||
SVNRepository repository = null;
|
||||
try {
|
||||
final SVNRepository repository = myVcs.createRepository(svnLocation.getURL());
|
||||
repository = myVcs.createRepository(svnLocation.getURL());
|
||||
repositoryRoot = repository.getRepositoryRoot(true).toString();
|
||||
repository.closeSession();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
} finally {
|
||||
if (repository != null) {
|
||||
repository.closeSession();
|
||||
}
|
||||
}
|
||||
|
||||
getCommittedChangesImpl(settings, svnLocation.getURL(), new String[]{""}, maxCount, new Consumer<SVNLogEntry>() {
|
||||
@@ -249,13 +258,17 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi
|
||||
}
|
||||
|
||||
final String repositoryRoot;
|
||||
SVNRepository repository = null;
|
||||
try {
|
||||
final SVNRepository repository = myVcs.createRepository(svnLocation.getURL());
|
||||
repository = myVcs.createRepository(svnLocation.getURL());
|
||||
repositoryRoot = repository.getRepositoryRoot(true).toString();
|
||||
repository.closeSession();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
} finally {
|
||||
if (repository != null) {
|
||||
repository.closeSession();
|
||||
}
|
||||
}
|
||||
|
||||
final MergeTrackerProxy proxy = new MergeTrackerProxy(new Consumer<TreeStructureNode<SVNLogEntry>>() {
|
||||
@@ -356,7 +369,17 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi
|
||||
revisionBefore = SVNRevision.create(changeTo.longValue());
|
||||
}
|
||||
else {
|
||||
revisionBefore = SVNRevision.create(myVcs.createRepository(url).getLatestRevision());
|
||||
SVNRepository repository = null;
|
||||
final long revision;
|
||||
try {
|
||||
repository = myVcs.createRepository(url);
|
||||
revision = repository.getLatestRevision();
|
||||
} finally {
|
||||
if (repository != null) {
|
||||
repository.closeSession();
|
||||
}
|
||||
}
|
||||
revisionBefore = SVNRevision.create(revision);
|
||||
}
|
||||
final SVNRevision revisionAfter;
|
||||
if (dateFrom != null) {
|
||||
|
||||
@@ -20,10 +20,10 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
import org.jetbrains.idea.svn.SvnConfiguration;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||
@@ -131,14 +131,18 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme
|
||||
}
|
||||
else {
|
||||
|
||||
SVNRepository repos = null;
|
||||
try {
|
||||
SVNRepository repos = myVcs.createRepository(svnURL2.toString());
|
||||
repos = myVcs.createRepository(svnURL2.toString());
|
||||
final long latestRev = repos.getLatestRevision();
|
||||
repos.closeSession();
|
||||
return String.valueOf(latestRev);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (repos != null) {
|
||||
repos.closeSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ public class DomElementsErrorPanel extends JPanel implements CommittablePanel, H
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillDaemonCodeAnalyzerErrorsSatus(DaemonCodeAnalyzerStatus status, boolean fillErrorsCount) {
|
||||
protected void fillDaemonCodeAnalyzerErrorsStatus(DaemonCodeAnalyzerStatus status, boolean fillErrorsCount) {
|
||||
for (int i = 0; i < status.errorCount.length; i++) {
|
||||
final HighlightSeverity minSeverity = SeverityRegistrar.getInstance(myProject).getSeverityByIndex(i);
|
||||
if (minSeverity == null) {
|
||||
|
||||
Reference in New Issue
Block a user