mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -65,7 +65,7 @@ binding.setVariable("guessHome", {
|
||||
})
|
||||
|
||||
binding.setVariable("loadProject", {
|
||||
requireProperty("jdk", requireProperty("jdk15.home", guessJdk()))
|
||||
requireProperty("jdk", requireProperty("jdk16.home", guessJdk()))
|
||||
new IdeaProjectLoader().loadFromPath(project, "${home}")
|
||||
|
||||
binding.ant.patternset(id: "idea.compiler.resources") {
|
||||
|
||||
+3
-1
@@ -46,7 +46,6 @@ import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.newvfs.FileAttribute;
|
||||
import com.intellij.openapi.vfs.newvfs.ManagingFS;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
|
||||
import com.intellij.util.containers.SLRUCache;
|
||||
@@ -172,6 +171,9 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
while (scopeSrcIterator.hasNext()) {
|
||||
final VirtualFile file = scopeSrcIterator.next();
|
||||
if (!file.isValid()) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Skipping invalid file " + file.getPresentableUrl());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
final int fileId = getFileId(file);
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.intellij.execution.ExecutionResult;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.configurations.CommandLineState;
|
||||
import com.intellij.execution.configurations.RemoteConnection;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.configurations.RunProfileState;
|
||||
import com.intellij.execution.filters.ExceptionFilter;
|
||||
import com.intellij.execution.filters.TextConsoleBuilder;
|
||||
@@ -1738,11 +1739,14 @@ public abstract class DebugProcessImpl implements DebugProcess {
|
||||
// propagate exception only in case we succeded to obtain execution result,
|
||||
// otherwise it the error is induced by the fact that there is nothing to debug, and there is no need to show
|
||||
// this problem to the user
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
ExecutionUtil.handleExecutionError(myProject, state.getRunnerSettings().getRunProfile(), e);
|
||||
}
|
||||
});
|
||||
final RunProfile runProfile = state.getRunnerSettings().getRunProfile();
|
||||
if (runProfile != null) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
ExecutionUtil.handleExecutionError(myProject, runProfile, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+21
-34
@@ -99,44 +99,31 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread<DebuggerComma
|
||||
final DebuggerCommandImpl currentCommand = myEvents.getCurrentEvent();
|
||||
|
||||
invoke(command);
|
||||
final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
alarm.addRequest(new Runnable() {
|
||||
public void run() {
|
||||
if (currentCommand != null) {
|
||||
terminateCommand(currentCommand);
|
||||
|
||||
if (currentCommand != null) {
|
||||
final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
alarm.addRequest(new Runnable() {
|
||||
public void run() {
|
||||
if (currentCommand == myEvents.getCurrentEvent()) {
|
||||
// if current command is still in progress, cancel it
|
||||
getCurrentRequest().interrupt();
|
||||
try {
|
||||
getCurrentRequest().join();
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
startNewWorkerThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, terminateTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* interrupts command in old worker thread and closes old thread.
|
||||
* then starts new worker thread
|
||||
* <p/>
|
||||
* Note: if old thread is working and InterruptedException is not thrown
|
||||
* command will continue execution in old thread simulteniously with
|
||||
* commands in new thread
|
||||
* <p/>
|
||||
* use very carefully!
|
||||
*/
|
||||
|
||||
public void terminateCommand(final DebuggerCommandImpl command) {
|
||||
if (command == myEvents.getCurrentEvent()) {
|
||||
getCurrentRequest().interrupt();
|
||||
try {
|
||||
getCurrentRequest().join(RESTART_TIMEOUT);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
startNewWorkerThread();
|
||||
}, terminateTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
public DebuggerCommandImpl getCurrentCommand() {
|
||||
return myEvents.getCurrentEvent();
|
||||
}
|
||||
|
||||
|
||||
public void processEvent(@NotNull DebuggerCommandImpl managerCommand) {
|
||||
assertIsManagerThread();
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsListener;
|
||||
@@ -50,7 +51,6 @@ import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.Function;
|
||||
@@ -488,10 +488,10 @@ public class DebuggerManagerImpl extends DebuggerManagerEx {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
//if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
// need this in unit tests to avoid false alarms when comparing actual output with expected output
|
||||
return true;
|
||||
}
|
||||
//return true;
|
||||
//}
|
||||
|
||||
final String version = JdkUtil.getJdkMainAttribute(jdk, Attributes.Name.IMPLEMENTATION_VERSION);
|
||||
return version == null ||
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -132,18 +131,18 @@ public class HotSwapManager extends AbstractProjectComponent {
|
||||
|
||||
swapProgress.setCancelWorker(new Runnable() {
|
||||
public void run() {
|
||||
scanClassesCommand.terminate();
|
||||
scanClassesCommand.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
for (Iterator<DebuggerSession> iterator = sessions.iterator(); iterator.hasNext();) {
|
||||
final DebuggerSession debuggerSession = iterator.next();
|
||||
if(debuggerSession.isAttached()) {
|
||||
for (final DebuggerSession debuggerSession : sessions) {
|
||||
if (debuggerSession.isAttached()) {
|
||||
scanClassesCommand.addCommand(debuggerSession.getProcess(), new DebuggerCommandImpl() {
|
||||
protected void action() throws Exception {
|
||||
swapProgress.setDebuggerSession(debuggerSession);
|
||||
HashMap<String, HotSwapFile> sessionClasses = getInstance(swapProgress.getProject()).getModifiedClasses(debuggerSession, swapProgress);
|
||||
if(!sessionClasses.isEmpty()) {
|
||||
HashMap<String, HotSwapFile> sessionClasses =
|
||||
getInstance(swapProgress.getProject()).getModifiedClasses(debuggerSession, swapProgress);
|
||||
if (!sessionClasses.isEmpty()) {
|
||||
modifiedClasses.put(debuggerSession, sessionClasses);
|
||||
}
|
||||
}
|
||||
@@ -162,16 +161,17 @@ public class HotSwapManager extends AbstractProjectComponent {
|
||||
|
||||
reloadClassesProgress.setCancelWorker(new Runnable() {
|
||||
public void run() {
|
||||
reloadClassesCommand.terminate();
|
||||
reloadClassesCommand.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
for (Iterator<DebuggerSession> iterator = modifiedClasses.keySet().iterator(); iterator.hasNext();) {
|
||||
final DebuggerSession debuggerSession = iterator.next();
|
||||
for (final DebuggerSession debuggerSession : modifiedClasses.keySet()) {
|
||||
reloadClassesCommand.addCommand(debuggerSession.getProcess(), new DebuggerCommandImpl() {
|
||||
protected void action() throws Exception {
|
||||
reloadClassesProgress.setDebuggerSession(debuggerSession);
|
||||
getInstance(reloadClassesProgress.getProject()).reloadClasses(debuggerSession, modifiedClasses.get(debuggerSession), reloadClassesProgress);
|
||||
getInstance(reloadClassesProgress.getProject()).reloadClasses(
|
||||
debuggerSession, modifiedClasses.get(debuggerSession), reloadClassesProgress
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -121,15 +121,19 @@ public abstract class InvokeThread<E extends PrioritizedTask> {
|
||||
workerRequest.setRequestFuture( ApplicationManager.getApplication().executeOnPooledThread(workerRequest) );
|
||||
}
|
||||
|
||||
public void run(WorkerThreadRequest current) {
|
||||
public void run(WorkerThreadRequest threadRequest) {
|
||||
while(true) {
|
||||
try {
|
||||
if(current.isInterrupted()) {
|
||||
if(threadRequest.isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(getCurrentRequest() != current) {
|
||||
LOG.error("Expected " + current + " instead of " + getCurrentRequest());
|
||||
final WorkerThreadRequest currentRequest = getCurrentRequest();
|
||||
if(currentRequest != threadRequest) {
|
||||
LOG.error("Expected " + threadRequest + " instead of " + currentRequest);
|
||||
if (currentRequest != null && !currentRequest.isDone()) {
|
||||
continue; // ensure events are processed by one thread at a time
|
||||
}
|
||||
}
|
||||
|
||||
processEvent(myEvents.get());
|
||||
|
||||
@@ -15,44 +15,31 @@
|
||||
*/
|
||||
package com.intellij.debugger.impl;
|
||||
|
||||
import com.intellij.debugger.engine.DebugProcess;
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
|
||||
import com.intellij.debugger.engine.managerThread.DebuggerCommand;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class MultiProcessCommand implements Runnable{
|
||||
private final List<Pair<DebugProcessImpl, DebuggerCommandImpl>> myCommands = new ArrayList<Pair<DebugProcessImpl, DebuggerCommandImpl>>();
|
||||
|
||||
public void run() {
|
||||
for(;;) {
|
||||
while(true) {
|
||||
Pair<DebugProcessImpl, DebuggerCommandImpl> pair;
|
||||
|
||||
synchronized(myCommands) {
|
||||
if(myCommands.isEmpty()) break;
|
||||
|
||||
pair = myCommands.get(0);
|
||||
if(myCommands.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
pair = myCommands.remove(0);
|
||||
}
|
||||
|
||||
pair.getFirst().getManagerThread().invokeAndWait(pair.getSecond());
|
||||
|
||||
synchronized(myCommands) {
|
||||
if(myCommands.isEmpty()) break;
|
||||
|
||||
myCommands.remove(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
public void cancel() {
|
||||
synchronized(myCommands) {
|
||||
if(myCommands.isEmpty()) return;
|
||||
Pair<DebugProcessImpl, DebuggerCommandImpl> pair = myCommands.get(0);
|
||||
pair.getFirst().getManagerThread().terminateCommand(pair.getSecond());
|
||||
myCommands.clear();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -103,8 +103,8 @@ public class AppletConfigurationProducer extends JavaRuntimeConfigurationProduce
|
||||
|
||||
@Override
|
||||
protected RunnerAndConfigurationSettings findExistingByElement(Location location,
|
||||
@NotNull RunnerAndConfigurationSettings[] existingConfigurations
|
||||
) {
|
||||
@NotNull RunnerAndConfigurationSettings[] existingConfigurations,
|
||||
ConfigurationContext context) {
|
||||
final PsiClass aClass = getAppletClass(location.getPsiElement(), PsiManager.getInstance(location.getProject()));
|
||||
if (aClass != null) {
|
||||
for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) {
|
||||
|
||||
+2
-2
@@ -89,8 +89,8 @@ public class ApplicationConfigurationProducer extends JavaRuntimeConfigurationPr
|
||||
|
||||
@Override
|
||||
protected RunnerAndConfigurationSettings findExistingByElement(Location location,
|
||||
@NotNull RunnerAndConfigurationSettings[] existingConfigurations
|
||||
) {
|
||||
@NotNull RunnerAndConfigurationSettings[] existingConfigurations,
|
||||
ConfigurationContext context) {
|
||||
final PsiClass aClass = ApplicationConfigurationType.getMainClass(location.getPsiElement());
|
||||
if (aClass == null) {
|
||||
return null;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -71,10 +72,11 @@ public class CodeInsightUtil {
|
||||
|
||||
@NotNull
|
||||
public static PsiElement[] findStatementsInRange(@NotNull PsiFile file, int startOffset, int endOffset) {
|
||||
Language language = findJavaOrLikeLanguage(file);
|
||||
if (language == null) return PsiElement.EMPTY_ARRAY;
|
||||
FileViewProvider viewProvider = file.getViewProvider();
|
||||
if (!viewProvider.getLanguages().contains(StdLanguages.JAVA)) return PsiElement.EMPTY_ARRAY;
|
||||
PsiElement element1 = viewProvider.findElementAt(startOffset, StdLanguages.JAVA);
|
||||
PsiElement element2 = viewProvider.findElementAt(endOffset - 1, StdLanguages.JAVA);
|
||||
PsiElement element1 = viewProvider.findElementAt(startOffset, language);
|
||||
PsiElement element2 = viewProvider.findElementAt(endOffset - 1, language);
|
||||
if (element1 instanceof PsiWhiteSpace) {
|
||||
startOffset = element1.getTextRange().getEndOffset();
|
||||
element1 = file.findElementAt(startOffset);
|
||||
@@ -148,6 +150,18 @@ public class CodeInsightUtil {
|
||||
return array.toArray(new PsiElement[array.size()]);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Language findJavaOrLikeLanguage(@NotNull final PsiFile file) {
|
||||
final Set<Language> languages = file.getViewProvider().getLanguages();
|
||||
for (final Language language : languages) {
|
||||
if (language == StdLanguages.JAVA) return language;
|
||||
}
|
||||
for (final Language language : languages) {
|
||||
if (language.isKindOf(StdLanguages.JAVA)) return language;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void sortIdenticalShortNameClasses(PsiClass[] classes, @NotNull PsiElement context) {
|
||||
if (classes.length <= 1) return;
|
||||
|
||||
|
||||
@@ -146,6 +146,17 @@ public class AllClassesGetter {
|
||||
public void getClasses(final PsiElement context, final CompletionResultSet set, final int offset, final boolean filterByScope) {
|
||||
if (context == null || !context.isValid()) return;
|
||||
|
||||
final boolean lookingForAnnotations = PsiJavaPatterns.psiElement().afterLeaf("@").accepts(context);
|
||||
getClasses(context, set, offset, filterByScope, lookingForAnnotations);
|
||||
}
|
||||
|
||||
public void getClasses(final PsiElement context,
|
||||
final CompletionResultSet set,
|
||||
final int offset,
|
||||
final boolean filterByScope,
|
||||
final boolean lookingForAnnotations) {
|
||||
if (context == null || !context.isValid()) return;
|
||||
|
||||
final String packagePrefix = getPackagePrefix(context, offset);
|
||||
|
||||
final Set<String> qnames = new THashSet<String>();
|
||||
@@ -157,8 +168,6 @@ public class AllClassesGetter {
|
||||
});
|
||||
final PrefixMatcher prefixMatcher = set.getPrefixMatcher();
|
||||
|
||||
final boolean lookingForAnnotations = PsiJavaPatterns.psiElement().afterLeaf("@").accepts(context);
|
||||
|
||||
AllClassesSearch.search(scope, context.getProject(), new Condition<String>() {
|
||||
public boolean value(String s) {
|
||||
return prefixMatcher.prefixMatches(s);
|
||||
|
||||
@@ -439,7 +439,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{
|
||||
}
|
||||
final PsiClass methodClass = method.getContainingClass();
|
||||
if (methodClass != null && manager.areElementsEquivalent(methodClass, aClass)){
|
||||
addMethodUsages(methods[i], results, options, options.searchScope);
|
||||
addElementUsages(methods[i], results, options);
|
||||
}
|
||||
else{
|
||||
boolean strictSignatureSearch = !options.isIncludeOverloadUsages;
|
||||
@@ -453,9 +453,8 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiMethod[] methods = aClass.getMethods();
|
||||
for (PsiMethod method : methods) {
|
||||
addMethodUsages(method, results, options, options.searchScope);
|
||||
for (PsiMethod method : aClass.getMethods()) {
|
||||
addElementUsages(method, results, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -580,21 +579,10 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{
|
||||
}
|
||||
}
|
||||
|
||||
public static void addElementUsages(final PsiElement element, final Processor<UsageInfo> results, final FindUsagesOptions options) {
|
||||
if (element instanceof PsiMethod){
|
||||
addMethodUsages((PsiMethod)element, results, options, options.searchScope);
|
||||
}
|
||||
else {
|
||||
ReferencesSearch.search(element, options.searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
return addResult(results, ref, options, element);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void addMethodUsages(final PsiMethod method, final Processor<UsageInfo> result, final FindUsagesOptions options, SearchScope searchScope) {
|
||||
if (method.isConstructor()) {
|
||||
public static void addElementUsages(final PsiElement element, final Processor<UsageInfo> result, final FindUsagesOptions options) {
|
||||
final SearchScope searchScope = options.searchScope;
|
||||
if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()){
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
if (options.isIncludeOverloadUsages) {
|
||||
for (PsiMethod constructor : method.getContainingClass().getConstructors()) {
|
||||
addConstructorUsages(constructor, searchScope, result, options);
|
||||
@@ -603,14 +591,24 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{
|
||||
else {
|
||||
addConstructorUsages(method, searchScope, result, options);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
boolean strictSignatureSearch = !options.isIncludeOverloadUsages;
|
||||
MethodReferencesSearch.search(method, searchScope, strictSignatureSearch).forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() {
|
||||
public boolean execute(PsiReference ref) {
|
||||
return addResult(result, ref, options, method);
|
||||
}
|
||||
}));
|
||||
|
||||
final ReadActionProcessor<PsiReference> consumer = new ReadActionProcessor<PsiReference>() {
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
return addResult(result, ref, options, element);
|
||||
}
|
||||
};
|
||||
|
||||
if (options.fastTrack != null) {
|
||||
SearchRequestor.collectRequests(element, options, options.fastTrack);
|
||||
return;
|
||||
}
|
||||
|
||||
if (element instanceof PsiMethod) {
|
||||
MethodReferencesSearch.search((PsiMethod)element, searchScope, !options.isIncludeOverloadUsages).forEach(consumer);
|
||||
} else {
|
||||
ReferencesSearch.search(element, searchScope, false).forEach(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
|
||||
List<PsiClass> result = new ArrayList<PsiClass>();
|
||||
for (final VirtualFile classRoot : classRoots) {
|
||||
if (scope.contains(classRoot)) {
|
||||
final String pkgName = psiPackage.getName();
|
||||
final VirtualFile dir = pkgName != null ? classRoot.findFileByRelativePath(pkgName.replace('.', '/')) : classRoot;
|
||||
final String pkgName = psiPackage.getQualifiedName();
|
||||
final VirtualFile dir = classRoot.findFileByRelativePath(pkgName.replace('.', '/'));
|
||||
if (dir != null && dir.isDirectory()) {
|
||||
for (final VirtualFile file : dir.getChildren()) {
|
||||
if (!file.isDirectory()) {
|
||||
@@ -121,8 +121,8 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
|
||||
List<PsiPackage> result = new ArrayList<PsiPackage>();
|
||||
for (final VirtualFile classRoot : classRoots) {
|
||||
if (scope.contains(classRoot)) {
|
||||
final String pkgName = psiPackage.getName();
|
||||
final VirtualFile dir = pkgName != null ? classRoot.findFileByRelativePath(pkgName.replace('.', '/')) : classRoot;
|
||||
final String pkgName = psiPackage.getQualifiedName();
|
||||
final VirtualFile dir = classRoot.findFileByRelativePath(pkgName.replace('.', '/'));
|
||||
if (dir != null && dir.isDirectory()) {
|
||||
for (final VirtualFile file : dir.getChildren()) {
|
||||
if (file.isDirectory()) {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.TextOccurenceProcessor;
|
||||
import com.intellij.psi.search.RequestResultProcessor;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
@@ -26,62 +26,53 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class MethodTextOccurenceProcessor implements TextOccurenceProcessor {
|
||||
public class MethodTextOccurenceProcessor extends RequestResultProcessor {
|
||||
private final PsiMethod[] myMethods;
|
||||
private final Processor<PsiReference> myConsumer;
|
||||
private final PsiClass myContainingClass;
|
||||
private final boolean myStrictSignatureSearch;
|
||||
|
||||
public MethodTextOccurenceProcessor(final Processor<PsiReference> consumer,
|
||||
@NotNull final PsiClass aClass,
|
||||
final boolean strictSignatureSearch,
|
||||
final PsiMethod... methods) {
|
||||
public MethodTextOccurenceProcessor(@NotNull final PsiClass aClass, final boolean strictSignatureSearch, final PsiMethod... methods) {
|
||||
myMethods = methods;
|
||||
myConsumer = consumer;
|
||||
myContainingClass = aClass;
|
||||
myStrictSignatureSearch = strictSignatureSearch;
|
||||
}
|
||||
|
||||
public boolean execute(PsiElement element, int offsetInElement) {
|
||||
final PsiReference[] refs = element.getReferences();
|
||||
for (PsiReference ref : refs) {
|
||||
if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
|
||||
for (PsiMethod method : myMethods) {
|
||||
if (!method.isValid()) {
|
||||
continue;
|
||||
}
|
||||
@Override
|
||||
protected boolean processReference(Processor<PsiReference> consumer, PsiReference ref) {
|
||||
for (PsiMethod method : myMethods) {
|
||||
if (!method.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ref instanceof ResolvingHint && !((ResolvingHint)ref).canResolveTo(method)) {
|
||||
return true;
|
||||
}
|
||||
if (ref.isReferenceTo(method)) {
|
||||
return myConsumer.process(ref);
|
||||
}
|
||||
PsiElement refElement = ref.resolve();
|
||||
if (ref instanceof ResolvingHint && !((ResolvingHint)ref).canResolveTo(method)) {
|
||||
return true;
|
||||
}
|
||||
if (ref.isReferenceTo(method)) {
|
||||
return consumer.process(ref);
|
||||
}
|
||||
PsiElement refElement = ref.resolve();
|
||||
|
||||
if (refElement instanceof PsiMethod) {
|
||||
PsiMethod refMethod = (PsiMethod)refElement;
|
||||
PsiClass refMethodClass = refMethod.getContainingClass();
|
||||
if (refMethodClass == null) continue;
|
||||
if (refElement instanceof PsiMethod) {
|
||||
PsiMethod refMethod = (PsiMethod)refElement;
|
||||
PsiClass refMethodClass = refMethod.getContainingClass();
|
||||
if (refMethodClass == null) continue;
|
||||
|
||||
if (!refMethod.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(myContainingClass, refMethodClass, PsiSubstitutor.EMPTY);
|
||||
if (substitutor != null) {
|
||||
MethodSignature superSignature = method.getSignature(substitutor);
|
||||
MethodSignature refSignature = refMethod.getSignature(PsiSubstitutor.EMPTY);
|
||||
if (!refMethod.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(myContainingClass, refMethodClass, PsiSubstitutor.EMPTY);
|
||||
if (substitutor != null) {
|
||||
MethodSignature superSignature = method.getSignature(substitutor);
|
||||
MethodSignature refSignature = refMethod.getSignature(PsiSubstitutor.EMPTY);
|
||||
|
||||
if (MethodSignatureUtil.isSubsignature(superSignature, refSignature)) {
|
||||
if (!myConsumer.process(ref)) return false;
|
||||
}
|
||||
}
|
||||
if (MethodSignatureUtil.isSubsignature(superSignature, refSignature)) {
|
||||
if (!consumer.process(ref)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!myStrictSignatureSearch) {
|
||||
PsiManager manager = method.getManager();
|
||||
if (manager.areElementsEquivalent(refMethodClass, myContainingClass)) {
|
||||
if (!myConsumer.process(ref)) return false;
|
||||
}
|
||||
}
|
||||
if (!myStrictSignatureSearch) {
|
||||
PsiManager manager = method.getManager();
|
||||
if (manager.areElementsEquivalent(refMethodClass, myContainingClass)) {
|
||||
if (!consumer.process(ref)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,11 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -21,103 +15,102 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class MethodUsagesSearcher implements QueryExecutor<PsiReference, MethodReferencesSearch.SearchParameters> {
|
||||
public class MethodUsagesSearcher extends SearchRequestor implements QueryExecutor<PsiReference, MethodReferencesSearch.SearchParameters> {
|
||||
|
||||
public boolean execute(final MethodReferencesSearch.SearchParameters p, final Processor<PsiReference> consumer) {
|
||||
final PsiMethod method = p.getMethod();
|
||||
final SearchScope searchScope = p.getScope();
|
||||
final PsiManager psiManager = PsiManager.getInstance(method.getProject());
|
||||
final boolean isStrictSignatureSearch = p.isStrictSignatureSearch();
|
||||
|
||||
final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
public PsiClass compute() {
|
||||
return method.getContainingClass();
|
||||
}
|
||||
});
|
||||
if (aClass == null) return true;
|
||||
|
||||
if (method.isConstructor()) {
|
||||
final ConstructorReferencesSearchHelper helper = new ConstructorReferencesSearchHelper(psiManager);
|
||||
if (!helper.processConstructorReferences(consumer, method, searchScope, !isStrictSignatureSearch, isStrictSignatureSearch)) {
|
||||
return false;
|
||||
}
|
||||
if (p instanceof MySearchParameters) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean needStrictSignatureSearch = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
return method.isValid() && isStrictSignatureSearch && (aClass instanceof PsiAnonymousClass
|
||||
|| aClass.hasModifierProperty(PsiModifier.FINAL)
|
||||
|| method.hasModifierProperty(PsiModifier.STATIC)
|
||||
|| method.hasModifierProperty(PsiModifier.FINAL)
|
||||
|| method.hasModifierProperty(PsiModifier.PRIVATE));
|
||||
final PsiMethod method = p.getMethod();
|
||||
final SearchRequestCollector collector = new SearchRequestCollector();
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final FindUsagesOptions options = new MyFindUsagesOptions(p);
|
||||
options.isUsages = true;
|
||||
contributeSearchTargets(method, options, collector, p.isStrictSignatureSearch());
|
||||
SearchRequestor.collectRequests(method, options, collector);
|
||||
}
|
||||
}).booleanValue();
|
||||
if (needStrictSignatureSearch) {
|
||||
return ReferencesSearch.search(method, searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
public boolean processInReadAction(final PsiReference psiReference) {
|
||||
return consumer.process(psiReference);
|
||||
});
|
||||
|
||||
return method.getManager().getSearchHelper().processRequests(collector, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeRequests(@NotNull PsiElement target,
|
||||
@NotNull final FindUsagesOptions options,
|
||||
@NotNull SearchRequestCollector collector) {
|
||||
if (options instanceof MyFindUsagesOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target instanceof PsiMethod) {
|
||||
final boolean strictSignatureSearch = !options.isIncludeOverloadUsages;
|
||||
final PsiMethod method = (PsiMethod)target;
|
||||
contributeSearchTargets(method, options, collector, strictSignatureSearch);
|
||||
collector.searchCustom(new Processor<Processor<PsiReference>>() {
|
||||
public boolean process(Processor<PsiReference> processor) {
|
||||
return MethodReferencesSearch.search(new MySearchParameters(method, options, strictSignatureSearch)).forEach(processor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void contributeSearchTargets(@NotNull final PsiMethod method,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull SearchRequestCollector collector,
|
||||
final boolean strictSignatureSearch) {
|
||||
final SearchScope searchScope = options.searchScope;
|
||||
|
||||
final PsiManager psiManager = PsiManager.getInstance(method.getProject());
|
||||
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return;
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean needStrictSignatureSearch = method.isValid() && strictSignatureSearch && (aClass instanceof PsiAnonymousClass
|
||||
|| aClass.hasModifierProperty(PsiModifier.FINAL)
|
||||
|| method.hasModifierProperty(PsiModifier.STATIC)
|
||||
|| method.hasModifierProperty(PsiModifier.FINAL)
|
||||
|| method.hasModifierProperty(PsiModifier.PRIVATE));
|
||||
if (needStrictSignatureSearch) {
|
||||
// CacheBasedRefSearcher deals with that
|
||||
return;
|
||||
}
|
||||
|
||||
final String textToSearch = method.getName();
|
||||
final PsiMethod[] methods = isStrictSignatureSearch ? new PsiMethod[]{method} : getOverloads(method);
|
||||
final PsiMethod[] methods = strictSignatureSearch ? new PsiMethod[]{method} : aClass.findMethodsByName(textToSearch, false);
|
||||
|
||||
SearchScope accessScope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
|
||||
public SearchScope compute() {
|
||||
if (!method.isValid()) return searchScope;
|
||||
SearchScope accessScope = methods[0].getUseScope();
|
||||
for (int i = 1; i < methods.length; i++) {
|
||||
PsiMethod method1 = methods[i];
|
||||
accessScope = accessScope.union(method1.getUseScope());
|
||||
}
|
||||
return accessScope;
|
||||
}
|
||||
});
|
||||
|
||||
final TextOccurenceProcessor processor1 = new MethodTextOccurenceProcessor(consumer, aClass, isStrictSignatureSearch, methods);
|
||||
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);
|
||||
|
||||
short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_COMMENTS | UsageSearchContext.IN_FOREIGN_LANGUAGES;
|
||||
PsiSearchHelper helper = psiManager.getSearchHelper();
|
||||
if (!helper.processElementsWithWord(processor1, restrictedByAccess, textToSearch, searchContext, true)) return false;
|
||||
collector.searchWord(textToSearch, restrictedByAccess, searchContext, true, new MethodTextOccurenceProcessor(aClass, strictSignatureSearch, methods));
|
||||
}
|
||||
|
||||
final String propertyName = ApplicationManager.getApplication().runReadAction(new Computable<String>(){
|
||||
public String compute() {
|
||||
if (!method.isValid()) return null;
|
||||
return PropertyUtil.getPropertyName(method);
|
||||
}
|
||||
});
|
||||
if (StringUtil.isEmpty(propertyName)) {
|
||||
return true;
|
||||
private static class MySearchParameters extends MethodReferencesSearch.SearchParameters {
|
||||
public MySearchParameters(PsiMethod method, FindUsagesOptions options, boolean strictSignatureSearch) {
|
||||
super(method, options.searchScope, strictSignatureSearch);
|
||||
}
|
||||
final SearchScope scope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
|
||||
public SearchScope compute() {
|
||||
SearchScope additional = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(psiManager.getProject()),
|
||||
StdFileTypes.JSP, StdFileTypes.JSPX,
|
||||
StdFileTypes.XML, StdFileTypes.XHTML);
|
||||
|
||||
for (CustomPropertyScopeProvider provider : Extensions.getExtensions(CustomPropertyScopeProvider.EP_NAME)) {
|
||||
SearchScope s = provider.getScope(psiManager.getProject());
|
||||
additional = additional.union(s);
|
||||
}
|
||||
|
||||
return restrictedByAccess.intersectWith(additional);
|
||||
}
|
||||
});
|
||||
return helper.processElementsWithWord(processor1, scope, propertyName, UsageSearchContext.IN_FOREIGN_LANGUAGES, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiMethod[] getOverloads(final PsiMethod method) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() {
|
||||
public PsiMethod[] compute() {
|
||||
if (!method.isValid()) return PsiMethod.EMPTY_ARRAY;
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return new PsiMethod[]{method};
|
||||
return aClass.findMethodsByName(method.getName(), false);
|
||||
}
|
||||
});
|
||||
private static class MyFindUsagesOptions extends FindUsagesOptions {
|
||||
public MyFindUsagesOptions(MethodReferencesSearch.SearchParameters p) {
|
||||
super(p.getScope());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+25
-46
@@ -15,63 +15,42 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class SimpleAccessorReferenceSearcher implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
public boolean execute(final ReferencesSearch.SearchParameters queryParameters, final Processor<PsiReference> consumer) {
|
||||
final PsiElement refElement = queryParameters.getElementToSearch();
|
||||
if (!(refElement instanceof PsiMethod)) return true;
|
||||
public class SimpleAccessorReferenceSearcher extends SearchRequestor {
|
||||
|
||||
@Override
|
||||
public void contributeRequests(@NotNull final PsiElement refElement,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull SearchRequestCollector collector) {
|
||||
if (!(refElement instanceof PsiMethod)) return;
|
||||
|
||||
final PsiMethod method = (PsiMethod)refElement;
|
||||
final String propertyName = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
public String compute() {
|
||||
if (!method.isValid()) return null;
|
||||
return PropertyUtil.getPropertyName(method);
|
||||
|
||||
final String propertyName = PropertyUtil.getPropertyName(method);
|
||||
if (StringUtil.isNotEmpty(propertyName)) {
|
||||
SearchScope additional = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(method.getProject()),
|
||||
StdFileTypes.JSP, StdFileTypes.JSPX,
|
||||
StdFileTypes.XML, StdFileTypes.XHTML);
|
||||
|
||||
for (CustomPropertyScopeProvider provider : Extensions.getExtensions(CustomPropertyScopeProvider.EP_NAME)) {
|
||||
additional = additional.union(provider.getScope(method.getProject()));
|
||||
}
|
||||
});
|
||||
if (StringUtil.isEmptyOrSpaces(propertyName)) {
|
||||
return true;
|
||||
assert propertyName != null;
|
||||
final SearchScope propScope = options.searchScope.intersectWith(method.getUseScope()).intersectWith(additional);
|
||||
collector.searchWord(propertyName, propScope, UsageSearchContext.IN_FOREIGN_LANGUAGES, true, refElement);
|
||||
}
|
||||
SearchScope searchScope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
|
||||
public SearchScope compute() {
|
||||
SearchScope searchScope = queryParameters.getEffectiveSearchScope();
|
||||
if (searchScope instanceof GlobalSearchScope) {
|
||||
searchScope = GlobalSearchScope.getScopeRestrictedByFileTypes((GlobalSearchScope)searchScope,
|
||||
StdFileTypes.JSP,
|
||||
StdFileTypes.JSPX,
|
||||
StdFileTypes.XML,
|
||||
StdFileTypes.XHTML);
|
||||
}
|
||||
return searchScope;
|
||||
}
|
||||
});
|
||||
|
||||
final PsiSearchHelper helper = PsiManager.getInstance(refElement.getProject()).getSearchHelper();
|
||||
final TextOccurenceProcessor processor = new TextOccurenceProcessor() {
|
||||
public boolean execute(PsiElement element, int offsetInElement) {
|
||||
final PsiReference[] refs = element.getReferences();
|
||||
for (PsiReference ref : refs) {
|
||||
if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
|
||||
if (ref.isReferenceTo(refElement)) {
|
||||
return consumer.process(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return helper.processElementsWithWord(processor, searchScope, propertyName, UsageSearchContext.IN_FOREIGN_LANGUAGES, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.refactoring.rename;
|
||||
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -133,7 +134,7 @@ public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor {
|
||||
}
|
||||
|
||||
public void prepareRenaming(final PsiElement element, final String newName, final Map<PsiElement, String> allRenames) {
|
||||
if (element instanceof PsiField) {
|
||||
if (element instanceof PsiField && StdLanguages.JAVA.equals(element.getLanguage())) {
|
||||
prepareFieldRenaming((PsiField)element, newName, allRenames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,6 +289,9 @@ public class InlineUtil {
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
if (resolved instanceof PsiTypeParameter) {
|
||||
PsiType newType = resolveResult.getSubstitutor().putAll(substitutor).substitute((PsiTypeParameter)resolved);
|
||||
if (newType == null) {
|
||||
newType = PsiType.getJavaLangObject(resolved.getManager(), resolved.getResolveScope());
|
||||
}
|
||||
try {
|
||||
typeElement.replace(factory.createTypeElement(newType));
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
public class NotRaw<T> {
|
||||
T g<caret>et(T t){
|
||||
T tt = t;
|
||||
if ( t == null) {
|
||||
return null;
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Raw extends NotRaw {
|
||||
void foo() {
|
||||
Object o = get(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
public class NotRaw<T> {
|
||||
|
||||
}
|
||||
|
||||
class Raw extends NotRaw {
|
||||
void foo() {
|
||||
Object result;
|
||||
Object tt = null;
|
||||
if ( null == null) {
|
||||
result = null;
|
||||
} else
|
||||
result = null;
|
||||
Object o = result;
|
||||
}
|
||||
}
|
||||
@@ -153,6 +153,10 @@ public class InlineMethodTest extends LightCodeInsightTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testRawSubstitution() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return JavaSdkImpl.getMockJdk15("java 1.5");
|
||||
|
||||
@@ -18,8 +18,11 @@ package com.intellij.patterns;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -55,10 +58,15 @@ public class PsiJavaPatterns extends StandardPatterns{
|
||||
}
|
||||
|
||||
public static PsiJavaElementPattern.Capture<PsiLiteral> psiLiteral(final ElementPattern value) {
|
||||
return new PsiJavaElementPattern.Capture<PsiLiteral>(new InitialPatternCondition<PsiLiteral>(PsiLiteral.class) {
|
||||
return new PsiJavaElementPattern.Capture<PsiLiteral>(new InitialPatternConditionPlus<PsiLiteral>(PsiLiteral.class) {
|
||||
public boolean accepts(@Nullable final Object o, final ProcessingContext context) {
|
||||
return o instanceof PsiLiteral && (value == null || value.accepts(((PsiLiteral)o).getValue(), context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ElementPattern<?>> getPatterns() {
|
||||
return Collections.<ElementPattern<?>>singletonList(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -78,11 +86,16 @@ public class PsiJavaPatterns extends StandardPatterns{
|
||||
|
||||
|
||||
public static PsiJavaElementPattern.Capture<PsiLiteralExpression> literalExpression(final ElementPattern value) {
|
||||
return new PsiJavaElementPattern.Capture<PsiLiteralExpression>(new InitialPatternCondition<PsiLiteralExpression>(PsiLiteralExpression.class) {
|
||||
return new PsiJavaElementPattern.Capture<PsiLiteralExpression>(new InitialPatternConditionPlus<PsiLiteralExpression>(PsiLiteralExpression.class) {
|
||||
public boolean accepts(@Nullable final Object o, final ProcessingContext context) {
|
||||
return o instanceof PsiLiteralExpression
|
||||
&& (value == null || value.accepts(((PsiLiteralExpression)o).getValue(), context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ElementPattern<?>> getPatterns() {
|
||||
return Collections.<ElementPattern<?>>singletonList(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.util.Query;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -54,7 +55,12 @@ public class MethodReferencesSearch extends ExtensibleQueryFactory<PsiReference,
|
||||
private MethodReferencesSearch() {}
|
||||
|
||||
public static Query<PsiReference> search(final PsiMethod method, SearchScope scope, final boolean strictSignatureSearch) {
|
||||
return INSTANCE.createUniqueResultsQuery(new SearchParameters(method, scope, strictSignatureSearch));
|
||||
return search(new SearchParameters(method, scope, strictSignatureSearch));
|
||||
}
|
||||
|
||||
public static Query<PsiReference> search(final SearchParameters parameters) {
|
||||
//noinspection unchecked
|
||||
return INSTANCE.createUniqueResultsQuery(parameters, TObjectHashingStrategy.CANONICAL, ReferenceDescriptor.MAPPER);
|
||||
}
|
||||
|
||||
public static Query<PsiReference> search(final PsiMethod method, final boolean strictSignatureSearch) {
|
||||
|
||||
+3
@@ -29,4 +29,7 @@ public interface JavaCodeInsightTestFixture extends CodeInsightTestFixture {
|
||||
JavaPsiFacade getJavaFacade();
|
||||
|
||||
PsiClass addClass(@NotNull @NonNls final String classText) throws IOException;
|
||||
|
||||
@NotNull
|
||||
PsiClass findClass(@NotNull @NonNls String name);
|
||||
}
|
||||
|
||||
+8
-1
@@ -17,6 +17,7 @@ package com.intellij.testFramework.fixtures.impl;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
|
||||
import com.intellij.testFramework.fixtures.TempDirTestFixture;
|
||||
@@ -54,5 +55,11 @@ public class JavaCodeInsightTestFixtureImpl extends CodeInsightTestFixtureImpl i
|
||||
final PsiFile psiFile = addFileToProject(rootPath, qName.replace('.', '/') + ".java", classText);
|
||||
return ((PsiJavaFile)psiFile).getClasses()[0];
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiClass findClass(@NotNull @NonNls final String name) {
|
||||
final PsiClass aClass = getJavaFacade().findClass(name, ProjectScope.getProjectScope(getProject()));
|
||||
assertNotNull("Class " + name + " not found", aClass);
|
||||
return aClass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,12 +106,12 @@ public class ConfigurationContext {
|
||||
if (producers == null) return null;
|
||||
if (myRuntimeConfiguration != null) {
|
||||
for (RuntimeConfigurationProducer producer : producers) {
|
||||
final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation);
|
||||
final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation, this);
|
||||
if (configuration != null && configuration.getConfiguration() == myRuntimeConfiguration) return configuration;
|
||||
}
|
||||
}
|
||||
for (RuntimeConfigurationProducer producer : producers) {
|
||||
final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation);
|
||||
final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation, this);
|
||||
if (configuration != null) return configuration;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -116,7 +116,8 @@ class PreferedProducerFind {
|
||||
|
||||
@Override
|
||||
protected RunnerAndConfigurationSettings findExistingByElement(Location location,
|
||||
@NotNull RunnerAndConfigurationSettings[] existingConfigurations) {
|
||||
@NotNull RunnerAndConfigurationSettings[] existingConfigurations,
|
||||
ConfigurationContext context) {
|
||||
if (existingConfigurations.length > 0) {
|
||||
ConfigurationType type = existingConfigurations[0].getType();
|
||||
if (type instanceof LocatableConfigurationType) {
|
||||
|
||||
+5
-4
@@ -61,7 +61,7 @@ public abstract class RuntimeConfigurationProducer implements Comparable, Clonea
|
||||
final RunManager runManager = RunManager.getInstance(context.getProject());
|
||||
final ConfigurationType type = result.myConfiguration.getType();
|
||||
final RunnerAndConfigurationSettings[] configurations = runManager.getConfigurationSettings(type);
|
||||
final RunnerAndConfigurationSettings configuration = findExistingByElement(_location, configurations);
|
||||
final RunnerAndConfigurationSettings configuration = findExistingByElement(_location, configurations, context);
|
||||
if (configuration != null) {
|
||||
result.myConfiguration = configuration;
|
||||
}
|
||||
@@ -72,10 +72,10 @@ public abstract class RuntimeConfigurationProducer implements Comparable, Clonea
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RunnerAndConfigurationSettings findExistingConfiguration(@NotNull Location location) {
|
||||
public RunnerAndConfigurationSettings findExistingConfiguration(@NotNull Location location, ConfigurationContext context) {
|
||||
final RunManager runManager = RunManager.getInstance(location.getProject());
|
||||
final RunnerAndConfigurationSettings[] configurations = runManager.getConfigurationSettings(getConfigurationType());
|
||||
return findExistingByElement(location, configurations);
|
||||
return findExistingByElement(location, configurations, context);
|
||||
}
|
||||
|
||||
public abstract PsiElement getSourceElement();
|
||||
@@ -89,7 +89,8 @@ public abstract class RuntimeConfigurationProducer implements Comparable, Clonea
|
||||
|
||||
@Nullable
|
||||
protected RunnerAndConfigurationSettings findExistingByElement(final Location location,
|
||||
@NotNull final RunnerAndConfigurationSettings[] existingConfigurations) {
|
||||
@NotNull final RunnerAndConfigurationSettings[] existingConfigurations,
|
||||
ConfigurationContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,19 +18,21 @@ package com.intellij.patterns;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
import static com.intellij.patterns.StandardPatterns.collection;
|
||||
import static com.intellij.patterns.StandardPatterns.not;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.meta.PsiMetaData;
|
||||
import com.intellij.psi.meta.PsiMetaOwner;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.ReflectionCache;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
import static com.intellij.patterns.StandardPatterns.collection;
|
||||
import static com.intellij.patterns.StandardPatterns.not;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
@@ -206,11 +208,13 @@ public abstract class PsiElementPattern<T extends PsiElement,Self extends PsiEle
|
||||
}
|
||||
|
||||
private PatternCondition<T> _withText(final ElementPattern pattern) {
|
||||
return new PatternCondition<T>("_withText") {
|
||||
public boolean accepts(@NotNull final T t, final ProcessingContext context) {
|
||||
return pattern.getCondition().accepts(t.getText(), context);
|
||||
return new PatternConditionPlus<T, String>("_withText", pattern) {
|
||||
@Override
|
||||
public boolean processValues(T t,
|
||||
ProcessingContext context,
|
||||
PairProcessor<String, ProcessingContext> processor) {
|
||||
return processor.process(t.getText(), context);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.psi.search;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -175,6 +176,8 @@ public interface PsiSearchHelper {
|
||||
*/
|
||||
void processAllFilesWithWordInLiterals(@NotNull String word, @NotNull GlobalSearchScope scope, @NotNull Processor<PsiFile> processor);
|
||||
|
||||
boolean processRequests(@NotNull SearchRequestCollector request, Processor<PsiReference> processor);
|
||||
|
||||
boolean processElementsWithWord(@NotNull TextOccurenceProcessor processor,
|
||||
@NotNull SearchScope searchScope,
|
||||
@NotNull String text,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.intellij.psi.search;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class PsiSearchRequest {
|
||||
public final SearchScope searchScope;
|
||||
public final String word;
|
||||
public final short searchContext;
|
||||
public final boolean caseSensitive;
|
||||
public final RequestResultProcessor processor;
|
||||
|
||||
public PsiSearchRequest(@NotNull SearchScope searchScope,
|
||||
@NotNull String word,
|
||||
short searchContext,
|
||||
boolean caseSensitive,
|
||||
@NotNull RequestResultProcessor processor) {
|
||||
|
||||
this.searchScope = searchScope;
|
||||
this.word = word;
|
||||
this.searchContext = searchContext;
|
||||
this.caseSensitive = caseSensitive;
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.intellij.psi.search;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.ReferenceRange;
|
||||
import com.intellij.util.Processor;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class RequestResultProcessor {
|
||||
|
||||
public boolean execute(PsiElement element, int offsetInElement, final Processor<PsiReference> consumer) {
|
||||
for (PsiReference ref : element.getReferences()) {
|
||||
if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
|
||||
if (!processReference(consumer, ref)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract boolean processReference(Processor<PsiReference> consumer, PsiReference ref);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.intellij.psi.search;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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>>>();
|
||||
|
||||
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;
|
||||
searchWord(word, searchScope, searchContext, caseSensitive, searchTarget);
|
||||
}
|
||||
|
||||
public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, short searchContext, boolean caseSensitive, @NotNull PsiElement searchTarget) {
|
||||
searchWord(word, searchScope, searchContext, caseSensitive, new SingleTargetRequestResultProcessor(searchTarget));
|
||||
}
|
||||
|
||||
public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, short searchContext, boolean caseSensitive, @NotNull RequestResultProcessor processor) {
|
||||
myRequests.add(new PsiSearchRequest(searchScope, word, searchContext, caseSensitive, processor));
|
||||
}
|
||||
|
||||
public void searchCustom(Processor<Processor<PsiReference>> searchAction) {
|
||||
myCustomSearchActions.add(searchAction);
|
||||
}
|
||||
|
||||
public List<PsiSearchRequest> getSearchRequests() {
|
||||
return myRequests;
|
||||
}
|
||||
|
||||
public List<Processor<Processor<PsiReference>>> getCustomSearchActions() {
|
||||
return myCustomSearchActions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.intellij.psi.search;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class SingleTargetRequestResultProcessor extends RequestResultProcessor {
|
||||
private final PsiElement myTarget;
|
||||
|
||||
public SingleTargetRequestResultProcessor(@NotNull PsiElement target) {
|
||||
myTarget = target;
|
||||
}
|
||||
|
||||
protected boolean processReference(Processor<PsiReference> consumer, PsiReference ref) {
|
||||
if (ref.isReferenceTo(myTarget)) {
|
||||
return consumer.process(ref);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.intellij.psi.search.searches;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.Function;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class ReferenceDescriptor {
|
||||
public static final Function<PsiReference, ReferenceDescriptor> MAPPER = new Function<PsiReference, ReferenceDescriptor>() {
|
||||
public ReferenceDescriptor fun(PsiReference psiReference) {
|
||||
final PsiElement element = psiReference.getElement();
|
||||
final PsiFile file = element.getContainingFile();
|
||||
return new ReferenceDescriptor(file, element.getTextRange().getStartOffset() + psiReference.getRangeInElement().getStartOffset());
|
||||
}
|
||||
};
|
||||
private final PsiFile file;
|
||||
private final int offset;
|
||||
|
||||
ReferenceDescriptor(PsiFile file, int offset) {
|
||||
this.file = file;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ReferenceDescriptor)) return false;
|
||||
|
||||
ReferenceDescriptor that = (ReferenceDescriptor)o;
|
||||
|
||||
if (offset != that.offset) return false;
|
||||
return file.equals(that.file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * file.hashCode() + offset;
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,9 @@
|
||||
package com.intellij.psi.search.searches;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.Query;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -31,40 +29,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class ReferencesSearch extends ExtensibleQueryFactory<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
private static final ReferencesSearch INSTANCE = new ReferencesSearch();
|
||||
|
||||
private static class ReferenceDescriptor {
|
||||
private final PsiFile file;
|
||||
private final int offset;
|
||||
|
||||
private ReferenceDescriptor(PsiFile file, int offset) {
|
||||
this.file = file;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ReferenceDescriptor)) return false;
|
||||
|
||||
ReferenceDescriptor that = (ReferenceDescriptor)o;
|
||||
|
||||
if (offset != that.offset) return false;
|
||||
return file.equals(that.file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * file.hashCode() + offset;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Function<PsiReference, ReferenceDescriptor> MAPPER = new Function<PsiReference, ReferenceDescriptor>() {
|
||||
public ReferenceDescriptor fun(PsiReference psiReference) {
|
||||
final PsiElement element = psiReference.getElement();
|
||||
final PsiFile file = element.getContainingFile();
|
||||
return new ReferenceDescriptor(file, element.getTextRange().getStartOffset() + psiReference.getRangeInElement().getStartOffset());
|
||||
}
|
||||
};
|
||||
|
||||
private ReferencesSearch() {
|
||||
}
|
||||
|
||||
@@ -116,6 +80,6 @@ public class ReferencesSearch extends ExtensibleQueryFactory<PsiReference, Refer
|
||||
|
||||
public static Query<PsiReference> search(@NotNull SearchParameters parameters) {
|
||||
//noinspection unchecked
|
||||
return INSTANCE.createUniqueResultsQuery(parameters, TObjectHashingStrategy.CANONICAL, MAPPER);
|
||||
return INSTANCE.createUniqueResultsQuery(parameters, TObjectHashingStrategy.CANONICAL, ReferenceDescriptor.MAPPER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.stubs.StubBase;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -251,6 +252,19 @@ public class PsiTreeUtil {
|
||||
return getParentOfType(element, aClass, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <E extends PsiElement> E getStubOrPsiParentOfType(@Nullable PsiElement element, final Class<E> parentClass) {
|
||||
if (element instanceof StubBasedPsiElement) {
|
||||
StubBase stub = (StubBase)((StubBasedPsiElement) element).getStub();
|
||||
if (stub != null) {
|
||||
//noinspection unchecked
|
||||
return (E)stub.getParentStubOfType(parentClass);
|
||||
}
|
||||
|
||||
}
|
||||
return getParentOfType(element, parentClass);
|
||||
}
|
||||
|
||||
@Nullable public static <T extends PsiElement> T getContextOfType(@Nullable PsiElement element, @NotNull Class<T> aClass, boolean strict) {
|
||||
if (element == null) return null;
|
||||
if (strict) {
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* {@linkplain RefactoringElementListenerProvider} recieves a notifictaion of what happened
|
||||
* {@linkplain RefactoringElementListenerProvider} receives a notification of what happened
|
||||
* to element it have been observing during a refactoring.
|
||||
* @author dsl
|
||||
*/
|
||||
|
||||
+4
-7
@@ -30,7 +30,7 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CodeStyleMainPanel extends JPanel {
|
||||
public class CodeStyleMainPanel extends JPanel implements LanguageSelectorListener {
|
||||
private final CardLayout myLayout = new CardLayout();
|
||||
private final JPanel mySettingsPanel = new JPanel(myLayout);
|
||||
|
||||
@@ -78,11 +78,7 @@ public class CodeStyleMainPanel extends JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
myLangSelector.addListener(new LanguageSelectorListener(){
|
||||
public void languageChanged(Language lang) {
|
||||
onLanguageChange(lang);
|
||||
}
|
||||
});
|
||||
myLangSelector.addListener(this);
|
||||
|
||||
addWaitCard();
|
||||
|
||||
@@ -206,6 +202,7 @@ public class CodeStyleMainPanel extends JPanel {
|
||||
public void disposeUIResources() {
|
||||
myAlarm.cancelAllRequests();
|
||||
clearPanels();
|
||||
myLangSelector.removeListener(this);
|
||||
}
|
||||
|
||||
public boolean isModified(final CodeStyleScheme scheme) {
|
||||
@@ -216,7 +213,7 @@ public class CodeStyleMainPanel extends JPanel {
|
||||
return mySettingsPanels.get(scheme.getName()).isModified();
|
||||
}
|
||||
|
||||
private void onLanguageChange(Language lang) {
|
||||
public void languageChanged(Language lang) {
|
||||
for (NewCodeStyleSettingsPanel panel : mySettingsPanels.values()) {
|
||||
panel.setLanguage(lang);
|
||||
}
|
||||
|
||||
+8
-7
@@ -16,17 +16,16 @@
|
||||
package com.intellij.application.options.codeStyle;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Maintains programming language selection for code style panels.
|
||||
*/
|
||||
public class LanguageSelector {
|
||||
|
||||
private Language myLanguage;
|
||||
private ArrayList<LanguageSelectorListener> listeners = new ArrayList<LanguageSelectorListener>();
|
||||
private final EventDispatcher<LanguageSelectorListener> myDispatcher = EventDispatcher.create(LanguageSelectorListener.class);
|
||||
private Language[] myLanguages = LanguageCodeStyleSettingsProvider.getLanguagesWithCodeStyleSettings();
|
||||
|
||||
/**
|
||||
@@ -54,12 +53,14 @@ public class LanguageSelector {
|
||||
* @param l The listener to add.
|
||||
*/
|
||||
public void addListener(LanguageSelectorListener l) {
|
||||
listeners.add(l);
|
||||
myDispatcher.addListener(l);
|
||||
}
|
||||
|
||||
public void removeListener(LanguageSelectorListener l) {
|
||||
myDispatcher.removeListener(l);
|
||||
}
|
||||
|
||||
private void notifyListeners(Language lang) {
|
||||
for (LanguageSelectorListener l : listeners) {
|
||||
l.languageChanged(lang);
|
||||
}
|
||||
myDispatcher.getMulticaster().languageChanged(lang);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -17,11 +17,13 @@ package com.intellij.application.options.codeStyle;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* Must be implemented by components willing to be notified on current code style language
|
||||
* change.
|
||||
*/
|
||||
public interface LanguageSelectorListener {
|
||||
public interface LanguageSelectorListener extends EventListener {
|
||||
|
||||
void languageChanged(Language lang);
|
||||
|
||||
|
||||
+3
-3
@@ -37,8 +37,8 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class SurroundWithHandler implements CodeInsightActionHandler{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler");
|
||||
@@ -77,7 +77,7 @@ public class SurroundWithHandler implements CodeInsightActionHandler{
|
||||
|
||||
final Language baseLanguage = file.getViewProvider().getBaseLanguage();
|
||||
final Language l = element1.getParent().getLanguage();
|
||||
List<SurroundDescriptor> surroundDescriptors = new ArrayList<SurroundDescriptor>();
|
||||
final Set<SurroundDescriptor> surroundDescriptors = new HashSet<SurroundDescriptor>();
|
||||
|
||||
surroundDescriptors.addAll(LanguageSurrounders.INSTANCE.allForLanguage(l));
|
||||
if (l != baseLanguage) surroundDescriptors.addAll(LanguageSurrounders.INSTANCE.allForLanguage(baseLanguage));
|
||||
|
||||
+9
-1
@@ -128,7 +128,15 @@ public class ImplementationViewComponent extends JPanel {
|
||||
myEditor = factory.createEditor(doc, project);
|
||||
PsiFile psiFile = getContainingFile(myElements[myIndex]);
|
||||
|
||||
EditorHighlighter highlighter = HighlighterFactory.createHighlighter(project, psiFile.getVirtualFile());
|
||||
VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
EditorHighlighter highlighter;
|
||||
if (virtualFile != null)
|
||||
highlighter = HighlighterFactory.createHighlighter(project, virtualFile);
|
||||
else {
|
||||
String fileName = psiFile.getName(); // some artificial psi file, lets do best we can
|
||||
highlighter = HighlighterFactory.createHighlighter(project, fileName);
|
||||
}
|
||||
|
||||
((EditorEx)myEditor).setHighlighter(highlighter);
|
||||
((EditorEx)myEditor).setBackgroundColor(EditorFragmentComponent.getBackgroundColor(myEditor));
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ public abstract class ASTDelegatePsiElement extends PsiElementBase {
|
||||
getParent().deleteChildRange(this, this);
|
||||
}
|
||||
else {
|
||||
super.delete();
|
||||
throw new UnsupportedOperationException(getClass().getName() + " under " + (getParent() == null ? "null" : getParent().getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,9 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.refactoring.util.TextOccurrencesUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -90,18 +89,39 @@ public abstract class FindUsagesHandler {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void processElementUsages(@NotNull final PsiElement element, @NotNull final Processor<UsageInfo> processor, @NotNull FindUsagesOptions options) {
|
||||
if (options.isUsages) {
|
||||
ReferencesSearch.search(element, options.searchScope, false).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
TextRange rangeInElement = ref.getRangeInElement();
|
||||
return processor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
|
||||
}
|
||||
});
|
||||
public void processElementUsages(@NotNull final PsiElement element, @NotNull final Processor<UsageInfo> processor, @NotNull final FindUsagesOptions options) {
|
||||
final ReadActionProcessor<PsiReference> refProcessor = new ReadActionProcessor<PsiReference>() {
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
TextRange rangeInElement = ref.getRangeInElement();
|
||||
return processor
|
||||
.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
|
||||
}
|
||||
};
|
||||
|
||||
final SearchScope scope = options.searchScope;
|
||||
|
||||
final boolean searchText = options.isSearchForTextOccurences && scope instanceof GlobalSearchScope;
|
||||
if (options.fastTrack != null) {
|
||||
SearchRequestor.collectRequests(element, options, options.fastTrack);
|
||||
|
||||
if (searchText) {
|
||||
options.fastTrack.searchCustom(new Processor<Processor<PsiReference>>() {
|
||||
public boolean process(Processor<PsiReference> consumer) {
|
||||
processUsagesInText(element, processor, (GlobalSearchScope)scope);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.isSearchForTextOccurences && options.searchScope instanceof GlobalSearchScope) {
|
||||
processUsagesInText(element, processor, (GlobalSearchScope)options.searchScope);
|
||||
if (options.isUsages) {
|
||||
ReferencesSearch.search(element, scope, false).forEach(refProcessor);
|
||||
}
|
||||
|
||||
if (searchText) {
|
||||
processUsagesInText(element, processor, (GlobalSearchScope)scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -44,6 +45,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import com.intellij.ui.content.Content;
|
||||
@@ -52,6 +54,7 @@ import com.intellij.usageView.UsageViewManager;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
import com.intellij.usages.*;
|
||||
import com.intellij.usages.impl.UsageViewManagerImpl;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jdom.Element;
|
||||
@@ -338,29 +341,40 @@ public class FindUsagesManager implements JDOMExternalizable {
|
||||
if (scopeFile != null) {
|
||||
options.searchScope = new LocalSearchScope(scopeFile);
|
||||
}
|
||||
final Processor<UsageInfo> usageInfoProcessorToUsageProcessorAdapter = new Processor<UsageInfo>() {
|
||||
final Processor<UsageInfo> usageInfoProcessor = new CommonProcessors.UniqueProcessor<UsageInfo>(new Processor<UsageInfo>() {
|
||||
public boolean process(UsageInfo usageInfo) {
|
||||
return processor.process(UsageInfoToUsageConverter.convert(descriptor, usageInfo));
|
||||
}
|
||||
};
|
||||
});
|
||||
List<? extends PsiElement> elements =
|
||||
ApplicationManager.getApplication().runReadAction(new Computable<List<? extends PsiElement>>() {
|
||||
public List<? extends PsiElement> compute() {
|
||||
return descriptor.getAllElements();
|
||||
}
|
||||
});
|
||||
|
||||
options.fastTrack = new SearchRequestCollector();
|
||||
|
||||
for (final PsiElement element : elements) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
LOG.assertTrue(element.isValid());
|
||||
}
|
||||
});
|
||||
handler.processElementUsages(element, usageInfoProcessorToUsageProcessorAdapter, options);
|
||||
handler.processElementUsages(element, usageInfoProcessor, options);
|
||||
}
|
||||
|
||||
PsiManager.getInstance(handler.getProject()).getSearchHelper().processRequests(options.fastTrack, new ReadActionProcessor<PsiReference>() {
|
||||
public boolean processInReadAction(final PsiReference ref) {
|
||||
TextRange rangeInElement = ref.getRangeInElement();
|
||||
return usageInfoProcessor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static PsiElement2UsageTargetAdapter[] convertToUsageTargets(final List<? extends PsiElement> elementsToSearch) {
|
||||
final ArrayList<PsiElement2UsageTargetAdapter> targets = new ArrayList<PsiElement2UsageTargetAdapter>(elementsToSearch.size());
|
||||
for (PsiElement element : elementsToSearch) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -55,6 +56,7 @@ public class FindUsagesOptions extends UserDataHolderBase implements Cloneable {
|
||||
public boolean isWriteAccess = false;
|
||||
public boolean isIncludeOverloadUsages = false;
|
||||
public boolean isThrowUsages = false;
|
||||
public SearchRequestCollector fastTrack = null;
|
||||
|
||||
public FindUsagesOptions(@NotNull Project project, @Nullable final DataContext dataContext) {
|
||||
String defaultScopeName = FindSettings.getInstance().getDefaultScopeName();
|
||||
@@ -70,6 +72,10 @@ public class FindUsagesOptions extends UserDataHolderBase implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
public FindUsagesOptions(SearchScope searchScope) {
|
||||
this.searchScope = searchScope;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
+13
-14
@@ -19,12 +19,12 @@ package com.intellij.psi.impl.cache.impl;
|
||||
import com.intellij.ide.caches.CacheUpdater;
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
@@ -78,6 +78,10 @@ public class IndexCacheManagerImpl implements CacheManager{
|
||||
return processor.getResults().isEmpty() ? PsiFile.EMPTY_ARRAY : processor.toArray(PsiFile.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
public static boolean shouldBeFound(VirtualFile virtualFile, ProjectFileIndex index) {
|
||||
return (index.isInContent(virtualFile) || index.isInLibrarySource(virtualFile)) && !virtualFile.getFileType().isBinary();
|
||||
}
|
||||
|
||||
public boolean processFilesWithWord(@NotNull final Processor<PsiFile> psiFileProcessor, @NotNull final String word, final short occurrenceMask, @NotNull final GlobalSearchScope scope, final boolean caseSensitively) {
|
||||
final Set<VirtualFile> vFiles = new THashSet<VirtualFile>();
|
||||
final GlobalSearchScope projectScope = GlobalSearchScope.allScope(myProject);
|
||||
@@ -100,20 +104,15 @@ public class IndexCacheManagerImpl implements CacheManager{
|
||||
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
|
||||
final Processor<VirtualFile> virtualFileProcessor = new Processor<VirtualFile>() {
|
||||
public boolean process(final VirtualFile virtualFile) {
|
||||
final Processor<VirtualFile> virtualFileProcessor = new ReadActionProcessor<VirtualFile>() {
|
||||
@Override
|
||||
public boolean processInReadAction(VirtualFile virtualFile) {
|
||||
LOG.assertTrue(virtualFile.isValid());
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
if (virtualFile.isValid() && scope.contains(virtualFile) && (index.isInContent(virtualFile) || index.isInLibrarySource(virtualFile))) {
|
||||
if (virtualFile.getFileType().isBinary()) return Boolean.TRUE;
|
||||
|
||||
final PsiFile psiFile = myPsiManager.findFile(virtualFile);
|
||||
return psiFile == null || psiFileProcessor.process(psiFile);
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}).booleanValue();
|
||||
if (virtualFile.isValid() && scope.contains(virtualFile) && shouldBeFound(virtualFile, index)) {
|
||||
final PsiFile psiFile = myPsiManager.findFile(virtualFile);
|
||||
return psiFile == null || psiFileProcessor.process(psiFile);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,94 +3,110 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.meta.PsiMetaData;
|
||||
import com.intellij.psi.meta.PsiMetaOwner;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchRequestor;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class CachesBasedRefSearcher implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
public static boolean DEBUG = false;
|
||||
public class CachesBasedRefSearcher extends SearchRequestor implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
|
||||
public boolean execute(final ReferencesSearch.SearchParameters p, final Processor<PsiReference> consumer) {
|
||||
if (p instanceof MySearchParameters) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final PsiElement refElement = p.getElementToSearch();
|
||||
final SearchRequestCollector collector = new SearchRequestCollector();
|
||||
|
||||
String text = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
public String compute() {
|
||||
String text = null;
|
||||
if (refElement instanceof PsiFile) {
|
||||
final VirtualFile vFile = ((PsiFile)refElement).getVirtualFile();
|
||||
if (vFile != null) {
|
||||
text = vFile.getNameWithoutExtension();
|
||||
}
|
||||
}
|
||||
else if (refElement instanceof PsiNamedElement) {
|
||||
text = ((PsiNamedElement)refElement).getName();
|
||||
if (refElement instanceof PsiMetaOwner) {
|
||||
final PsiMetaData metaData = ((PsiMetaOwner)refElement).getMetaData();
|
||||
if (metaData != null) text = metaData.getName();
|
||||
}
|
||||
}
|
||||
|
||||
if (text == null && refElement instanceof PsiMetaOwner) {
|
||||
final PsiMetaData metaData = ((PsiMetaOwner)refElement).getMetaData();
|
||||
if (metaData != null) text = metaData.getName();
|
||||
}
|
||||
return text;
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final FindUsagesOptions options = new MyFindUsagesOptions(p);
|
||||
options.isUsages = true;
|
||||
contributeSearchTargets(refElement, options, collector, p.isIgnoreAccessScope(), options.searchScope);
|
||||
SearchRequestor.collectRequests(refElement, options, collector);
|
||||
}
|
||||
});
|
||||
if (StringUtil.isEmpty(text)) return true;
|
||||
if (DEBUG) System.out.println("Searching for :" + text);
|
||||
return refElement.getManager().getSearchHelper().processRequests(collector, consumer);
|
||||
}
|
||||
|
||||
SearchScope searchScope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
|
||||
public SearchScope compute() {
|
||||
return p.getEffectiveSearchScope();
|
||||
@Override
|
||||
public void contributeRequests(@NotNull final PsiElement refElement,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull SearchRequestCollector collector) {
|
||||
if (options instanceof MyFindUsagesOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean ignoreAccessScope = false;
|
||||
final SearchScope scope = options.searchScope;
|
||||
contributeSearchTargets(refElement, options, collector, ignoreAccessScope, scope);
|
||||
collector.searchCustom(new Processor<Processor<PsiReference>>() {
|
||||
public boolean process(Processor<PsiReference> consumer) {
|
||||
return ReferencesSearch.search(new MySearchParameters(refElement, scope, ignoreAccessScope)).forEach(consumer);
|
||||
}
|
||||
});
|
||||
final boolean ignoreInjectedPsi = searchScope instanceof LocalSearchScope && ((LocalSearchScope)searchScope).isIgnoreInjectedPsi();
|
||||
}
|
||||
|
||||
final TextOccurenceProcessor processor = new TextOccurenceProcessor() {
|
||||
public boolean execute(PsiElement element, int offsetInElement) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (DEBUG) {
|
||||
System.out.println("!!! About to check " + element);
|
||||
}
|
||||
if (ignoreInjectedPsi && element instanceof PsiLanguageInjectionHost) return true;
|
||||
final PsiReference[] refs = element.getReferences();
|
||||
for (PsiReference ref : refs) {
|
||||
if (DEBUG) {
|
||||
System.out.println("!!!!!!!!!!!!!! Ref " + ref);
|
||||
}
|
||||
if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
|
||||
if (DEBUG) {
|
||||
System.out.println("!!!!!!!!!!!!!!!!!!!!! Ref " + ref + " contains");
|
||||
}
|
||||
if (ref.isReferenceTo(refElement)) {
|
||||
if (DEBUG) {
|
||||
System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Found ref " + ref);
|
||||
}
|
||||
return consumer.process(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
private static void contributeSearchTargets(@NotNull final PsiElement refElement,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull SearchRequestCollector collector,
|
||||
final boolean ignoreAccessScope,
|
||||
final SearchScope scope) {
|
||||
if (!options.isUsages) {
|
||||
return;
|
||||
}
|
||||
|
||||
String text = null;
|
||||
if (refElement instanceof PsiFile) {
|
||||
final VirtualFile vFile = ((PsiFile)refElement).getVirtualFile();
|
||||
if (vFile != null) {
|
||||
text = vFile.getNameWithoutExtension();
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (refElement instanceof PsiNamedElement) {
|
||||
text = ((PsiNamedElement)refElement).getName();
|
||||
if (refElement instanceof PsiMetaOwner) {
|
||||
final PsiMetaData metaData = ((PsiMetaOwner)refElement).getMetaData();
|
||||
if (metaData != null) text = metaData.getName();
|
||||
}
|
||||
}
|
||||
|
||||
short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_FOREIGN_LANGUAGES | UsageSearchContext.IN_COMMENTS;
|
||||
if (text == null && refElement instanceof PsiMetaOwner) {
|
||||
final PsiMetaData metaData = ((PsiMetaOwner)refElement).getMetaData();
|
||||
if (metaData != null) text = metaData.getName();
|
||||
}
|
||||
if (StringUtil.isNotEmpty(text)) {
|
||||
final SearchScope searchScope = ignoreAccessScope ? scope : refElement.getUseScope().intersectWith(scope);
|
||||
assert text != null;
|
||||
collector.searchWord(text, searchScope, refElement.getLanguage().isCaseSensitive(), refElement);
|
||||
}
|
||||
}
|
||||
|
||||
final PsiSearchHelper helper = PsiManager.getInstance(refElement.getProject()).getSearchHelper();
|
||||
return helper.processElementsWithWord(processor, searchScope, text, searchContext,
|
||||
refElement.getLanguage().isCaseSensitive());
|
||||
private static class MySearchParameters extends ReferencesSearch.SearchParameters {
|
||||
public MySearchParameters(PsiElement refElement, SearchScope scope, boolean ignoreAccessScope) {
|
||||
super(refElement, scope, ignoreAccessScope);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyFindUsagesOptions extends FindUsagesOptions {
|
||||
public MyFindUsagesOptions(ReferencesSearch.SearchParameters p) {
|
||||
super(p.getScope());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,9 +108,14 @@ public class LowLevelSearchUtil {
|
||||
if (contains) {
|
||||
if (!ignoreInjectedPsi) {
|
||||
Boolean result = processInjectedFile(run, processor, searcher, progress);
|
||||
if (result != null) return result.booleanValue();
|
||||
if (result != null) {
|
||||
return result.booleanValue();
|
||||
}
|
||||
}
|
||||
if (!processor.execute(run, start)) {
|
||||
processor.execute(run, start);
|
||||
return false;
|
||||
}
|
||||
if (!processor.execute(run, start)) return false;
|
||||
}
|
||||
if (useTree) {
|
||||
leafNode = leafNode.getTreeParent();
|
||||
|
||||
@@ -25,16 +25,22 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.cache.impl.IndexCacheManagerImpl;
|
||||
import com.intellij.psi.impl.cache.impl.id.IdIndex;
|
||||
import com.intellij.psi.impl.cache.impl.id.IdIndexEntry;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.searches.IndexPatternSearch;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.text.StringSearcher;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -213,24 +219,39 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
progress.pushState();
|
||||
progress.setText(PsiBundle.message("psi.scanning.files.progress"));
|
||||
}
|
||||
myManager.startBatchFilesProcessingMode();
|
||||
|
||||
try {
|
||||
String text = searcher.getPattern();
|
||||
List<PsiFile> fileSet = getFilesWithText(scope, searchContext, caseSensitively, text, progress);
|
||||
String text = searcher.getPattern();
|
||||
List<VirtualFile> fileSet = getFilesWithText(scope, searchContext, caseSensitively, text, progress);
|
||||
|
||||
if (progress != null) {
|
||||
progress.setText(PsiBundle.message("psi.search.for.word.progress", text));
|
||||
if (progress != null) {
|
||||
progress.setText(PsiBundle.message("psi.search.for.word.progress", text));
|
||||
}
|
||||
|
||||
return processPsiFileRoots(progress, fileSet, new Processor<PsiElement>() {
|
||||
public boolean process(PsiElement psiRoot) {
|
||||
return LowLevelSearchUtil.processElementsContainingWordInElement(processor, psiRoot, searcher, false, progress);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean processPsiFileRoots(final ProgressIndicator progress,
|
||||
List<VirtualFile> files,
|
||||
final Processor<PsiElement> psiRootProcessor) {
|
||||
myManager.startBatchFilesProcessingMode();
|
||||
try {
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final AtomicBoolean canceled = new AtomicBoolean(false);
|
||||
final AtomicBoolean pceThrown = new AtomicBoolean(false);
|
||||
|
||||
final int size = fileSet.size();
|
||||
boolean completed = JobUtil.invokeConcurrentlyUnderMyProgress(fileSet, new Processor<PsiFile>() {
|
||||
public boolean process(final PsiFile file) {
|
||||
if (!(file instanceof PsiBinaryFile)) {
|
||||
final int size = files.size();
|
||||
boolean completed = JobUtil.invokeConcurrentlyUnderMyProgress(files, new Processor<VirtualFile>() {
|
||||
public boolean process(final VirtualFile vfile) {
|
||||
final PsiFile file = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
|
||||
public PsiFile compute() {
|
||||
return myManager.findFile(vfile);
|
||||
}
|
||||
});
|
||||
if (file != null && !(file instanceof PsiBinaryFile)) {
|
||||
file.getViewProvider().getContents(); // load contents outside readaction
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
@@ -240,7 +261,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
for (PsiElement psiRoot : psiRoots) {
|
||||
if (progress != null) progress.checkCanceled();
|
||||
if (!processed.add(psiRoot)) continue;
|
||||
if (!LowLevelSearchUtil.processElementsContainingWordInElement(processor, psiRoot, searcher, false, progress)) {
|
||||
if (!psiRootProcessor.process(psiRoot)) {
|
||||
canceled.set(true);
|
||||
return;
|
||||
}
|
||||
@@ -276,16 +297,27 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private List<PsiFile> getFilesWithText(@NotNull GlobalSearchScope scope,
|
||||
private List<VirtualFile> getFilesWithText(@NotNull GlobalSearchScope scope,
|
||||
final short searchContext,
|
||||
final boolean caseSensitively,
|
||||
@NotNull String text,
|
||||
ProgressIndicator progress) {
|
||||
List<PsiFile> result = new ArrayList<PsiFile>();
|
||||
if (!processFilesWithText(scope, searchContext, caseSensitively, text, new CommonProcessors.CollectProcessor<PsiFile>(result), progress)) {
|
||||
return Collections.emptyList();
|
||||
myManager.startBatchFilesProcessingMode();
|
||||
try {
|
||||
final List<VirtualFile> result = new ArrayList<VirtualFile>();
|
||||
if (!processFilesWithText(scope, searchContext, caseSensitively, text, new Processor<PsiFile>() {
|
||||
public boolean process(PsiFile file) {
|
||||
result.add(file.getViewProvider().getVirtualFile());
|
||||
return true;
|
||||
}
|
||||
}, progress)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
finally {
|
||||
myManager.finishBatchFilesProcessingMode();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean processFilesWithText(@NotNull final GlobalSearchScope scope,
|
||||
@@ -447,6 +479,170 @@ 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (singles.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (singles.size() == 1) {
|
||||
final Collection<PsiSearchRequest> requests = singles.get(singles.keySet().iterator().next());
|
||||
if (requests.size() == 1) {
|
||||
return processSingleRequest(requests.iterator().next(), consumer);
|
||||
}
|
||||
}
|
||||
|
||||
final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (progress != null) {
|
||||
progress.pushState();
|
||||
progress.setText(PsiBundle.message("psi.scanning.files.progress"));
|
||||
}
|
||||
|
||||
final MultiMap<VirtualFile, PsiSearchRequest> candidateFiles = collectFiles(singles);
|
||||
|
||||
final Map<PsiSearchRequest, StringSearcher> searchers = new HashMap<PsiSearchRequest, 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);
|
||||
}
|
||||
|
||||
if (progress != null) {
|
||||
progress.setText(PsiBundle.message("psi.search.for.word.progress", StringUtil.join(allWords, ", ")));
|
||||
}
|
||||
|
||||
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)) {
|
||||
StringSearcher searcher = searchers.get(singleRequest);
|
||||
if (!LowLevelSearchUtil.processElementsContainingWordInElement(adaptProcessor(singleRequest, consumer), psiRoot, searcher, false, progress)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static TextOccurenceProcessor adaptProcessor(final PsiSearchRequest singleRequest,
|
||||
final Processor<PsiReference> consumer) {
|
||||
final SearchScope searchScope = singleRequest.searchScope;
|
||||
final boolean ignoreInjectedPsi = searchScope instanceof LocalSearchScope && ((LocalSearchScope)searchScope).isIgnoreInjectedPsi();
|
||||
return new TextOccurenceProcessor() {
|
||||
public boolean execute(PsiElement element, int offsetInElement) {
|
||||
if (ignoreInjectedPsi && element instanceof PsiLanguageInjectionHost) return true;
|
||||
|
||||
return singleRequest.processor.execute(element, offsetInElement, consumer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private MultiMap<VirtualFile, PsiSearchRequest> collectFiles(MultiMap<Set<IdIndexEntry>, PsiSearchRequest> singles) {
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex();
|
||||
final MultiMap<VirtualFile, PsiSearchRequest> result = new MultiMap<VirtualFile, PsiSearchRequest>();
|
||||
for (Set<IdIndexEntry> key : singles.keySet()) {
|
||||
final Collection<PsiSearchRequest> data = singles.get(key);
|
||||
GlobalSearchScope commonScope = uniteScopes(data);
|
||||
|
||||
MultiMap<VirtualFile, PsiSearchRequest> intersection = null;
|
||||
|
||||
boolean first = true;
|
||||
for (IdIndexEntry entry : key) {
|
||||
final MultiMap<VirtualFile, PsiSearchRequest> local = findFilesWithIndexEntry(entry, index, data, commonScope);
|
||||
if (first) {
|
||||
intersection = local;
|
||||
first = false;
|
||||
} else {
|
||||
for (VirtualFile file : local.keySet()) {
|
||||
if (intersection.containsKey(file)) {
|
||||
intersection.putValues(file, local.get(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.putAllValues(intersection);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GlobalSearchScope uniteScopes(Collection<PsiSearchRequest> requests) {
|
||||
GlobalSearchScope commonScope = null;
|
||||
for (PsiSearchRequest r : requests) {
|
||||
final GlobalSearchScope scope = (GlobalSearchScope)r.searchScope;
|
||||
commonScope = commonScope == null ? scope : commonScope.uniteWith(scope);
|
||||
}
|
||||
assert commonScope != null;
|
||||
return commonScope;
|
||||
}
|
||||
|
||||
private static MultiMap<VirtualFile, PsiSearchRequest> findFilesWithIndexEntry(IdIndexEntry entry,
|
||||
final ProjectFileIndex index,
|
||||
final Collection<PsiSearchRequest> data,
|
||||
GlobalSearchScope commonScope) {
|
||||
final MultiMap<VirtualFile, PsiSearchRequest> local = new MultiMap<VirtualFile, PsiSearchRequest>();
|
||||
FileBasedIndex.getInstance().processValues(IdIndex.NAME, entry, null, new FileBasedIndex.ValueProcessor<Integer>() {
|
||||
public boolean process(VirtualFile file, Integer value) {
|
||||
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)) {
|
||||
local.putValue(file, single);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, commonScope);
|
||||
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);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final List<String> words = StringUtil.getWordsIn(primitive.word);
|
||||
final Set<IdIndexEntry> key = new HashSet<IdIndexEntry>(words.size());
|
||||
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) {
|
||||
return processElementsWithWord(adaptProcessor(single, consumer), single.searchScope, single.word, single.searchContext, single.caseSensitive);
|
||||
}
|
||||
|
||||
public SearchCostResult isCheapEnoughToSearch(@NotNull String name,
|
||||
@NotNull GlobalSearchScope scope,
|
||||
@Nullable final PsiFile fileToIgnoreOccurencesIn,
|
||||
|
||||
+6
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.source.resolve.reference.impl.providers;
|
||||
|
||||
import com.intellij.openapi.paths.PsiDynaReference;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
@@ -52,7 +53,11 @@ public class FileReferenceUtil {
|
||||
@Nullable
|
||||
public static PsiFile findFile(PsiReference...references) {
|
||||
for (int i = references.length - 1; i >= 0; i--) {
|
||||
if (references[i] instanceof FileReference) {
|
||||
PsiReference ref = references[i];
|
||||
if (ref instanceof PsiDynaReference) {
|
||||
ref = ((PsiDynaReference)ref).getLastFileReference();
|
||||
}
|
||||
if (ref instanceof FileReference) {
|
||||
final PsiElement file = references[i].resolve();
|
||||
return file instanceof PsiFile ? (PsiFile)file : null;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.extapi.psi.ASTDelegatePsiElement;
|
||||
import com.intellij.lang.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.pom.tree.events.ChangeInfo;
|
||||
import com.intellij.pom.tree.events.TreeChangeEvent;
|
||||
import com.intellij.pom.tree.events.impl.ChangeInfoImpl;
|
||||
@@ -502,7 +503,9 @@ public class CompositeElement extends TreeElement {
|
||||
}
|
||||
}
|
||||
|
||||
public PsiElement getPsi() {
|
||||
public final PsiElement getPsi() {
|
||||
ProgressManager.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
|
||||
|
||||
PsiElement wrapper = myWrapper;
|
||||
if (wrapper != null) return wrapper;
|
||||
|
||||
@@ -510,18 +513,21 @@ public class CompositeElement extends TreeElement {
|
||||
wrapper = myWrapper;
|
||||
if (wrapper != null) return wrapper;
|
||||
|
||||
final Language lang = getElementType().getLanguage();
|
||||
final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(lang);
|
||||
if (parserDefinition != null) {
|
||||
myWrapper = wrapper = parserDefinition.createElement(this);
|
||||
//noinspection ConstantConditions
|
||||
LOG.assertTrue(wrapper != null, "ParserDefinition.createElement() may not return null");
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
return myWrapper = createPsiNoLock();
|
||||
}
|
||||
}
|
||||
|
||||
protected PsiElement createPsiNoLock() {
|
||||
final Language lang = getElementType().getLanguage();
|
||||
final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(lang);
|
||||
if (parserDefinition != null) {
|
||||
return parserDefinition.createElement(this);
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setPsi(@NotNull PsiElement psi) {
|
||||
myWrapper = psi;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.FileStatusManager;
|
||||
@@ -278,8 +277,8 @@ public abstract class CompositePsiElement extends CompositeElement implements Ps
|
||||
return this;
|
||||
}
|
||||
|
||||
public PsiElement getPsi() {
|
||||
ProgressManager.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
|
||||
@Override
|
||||
protected PsiElement createPsiNoLock() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -21,7 +21,6 @@ package com.intellij.psi.impl.source.tree;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiLock;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.ILazyParseableElementType;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
@@ -30,10 +29,17 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class LazyParseableElement extends CompositeElement {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.LazyParseableElement");
|
||||
private static final RecursiveTreeElementWalkingVisitor CREATE_PSI = new RecursiveTreeElementWalkingVisitor(false) {
|
||||
|
||||
@Override
|
||||
protected void visitNode(TreeElement element) {
|
||||
element.getPsi();
|
||||
public void visitLeaf(LeafElement leaf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitComposite(CompositeElement composite) {
|
||||
composite.createPsiNoLock();
|
||||
super.visitComposite(composite);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private static class ChameleonLock {
|
||||
@@ -169,14 +175,8 @@ public class LazyParseableElement extends CompositeElement {
|
||||
rawAddChildren((TreeElement)parsedNode);
|
||||
|
||||
//ensure PSI is created all at once, to reduce contention of PsiLock in CompositeElement.getPsi()
|
||||
/*
|
||||
synchronized (PsiLock.LOCK) {
|
||||
while (parsedNode != null) {
|
||||
((TreeElement)parsedNode).acceptTree(CREATE_PSI);
|
||||
parsedNode = parsedNode.getTreeNext();
|
||||
}
|
||||
}
|
||||
*/
|
||||
((TreeElement)parsedNode).acceptTree(CREATE_PSI);
|
||||
parsedNode = parsedNode.getTreeNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -25,7 +25,6 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.FileStatusManager;
|
||||
@@ -282,8 +281,8 @@ public class LazyParseablePsiElement extends LazyParseableElement implements Psi
|
||||
return this;
|
||||
}
|
||||
|
||||
public PsiElement getPsi() {
|
||||
ProgressManager.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
|
||||
@Override
|
||||
protected PsiElement createPsiNoLock() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.intellij.psi.search;
|
||||
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class SearchRequestor {
|
||||
public static final ExtensionPointName<SearchRequestor> EP_NAME = ExtensionPointName.create("com.intellij.searchRequestor");
|
||||
|
||||
public static void collectRequests(final PsiElement element, final FindUsagesOptions options, final SearchRequestCollector collector) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
for (SearchRequestor searcher : EP_NAME.getExtensions()) {
|
||||
searcher.contributeRequests(element, options, collector);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public abstract void contributeRequests(@NotNull PsiElement target, @NotNull FindUsagesOptions options, @NotNull SearchRequestCollector collector);
|
||||
|
||||
}
|
||||
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.patterns.PatternCondition;
|
||||
import com.intellij.patterns.PatternConditionPlus;
|
||||
import com.intellij.patterns.ValuePatternCondition;
|
||||
import com.intellij.patterns.*;
|
||||
import gnu.trove.THashSet;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -51,7 +48,12 @@ public class PatternValuesIndex {
|
||||
stack.add(next);
|
||||
while (!stack.isEmpty()) {
|
||||
final ElementPattern<?> pattern = stack.removeFirst();
|
||||
for (PatternCondition<?> condition : pattern.getCondition().getConditions()) {
|
||||
final ElementPatternCondition<?> patternCondition = pattern.getCondition();
|
||||
final InitialPatternCondition<?> initialCondition = patternCondition.getInitialCondition();
|
||||
if (initialCondition instanceof InitialPatternConditionPlus) {
|
||||
stack.addAll(((InitialPatternConditionPlus<?>)initialCondition).getPatterns());
|
||||
}
|
||||
for (PatternCondition<?> condition : patternCondition.getConditions()) {
|
||||
if (condition instanceof PatternConditionPlus) {
|
||||
stack.add(((PatternConditionPlus)condition).getValuePattern());
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.openapi.progress;
|
||||
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -33,6 +34,7 @@ public class BackgroundTaskQueue {
|
||||
private final Queue<Task> myQueue = new LinkedList<Task>();
|
||||
private boolean myHasActiveTask = false;
|
||||
private Task.Backgroundable myRunnerTask;
|
||||
private Boolean myForcedTestMode = null;
|
||||
|
||||
public BackgroundTaskQueue(String title) {
|
||||
this(null, title);
|
||||
@@ -74,7 +76,7 @@ public class BackgroundTaskQueue {
|
||||
}
|
||||
|
||||
public void run(Task.Backgroundable task) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (isInTestMode()) {
|
||||
task.run(new EmptyProgressIndicator());
|
||||
task.onSuccess();
|
||||
}
|
||||
@@ -88,20 +90,43 @@ public class BackgroundTaskQueue {
|
||||
myQueue.offer(task);
|
||||
myHasActiveTask = true;
|
||||
}
|
||||
if (!hadActiveTask) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
ProgressManager.getInstance().run(myRunnerTask);
|
||||
}
|
||||
else {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (myProject == null || !myProject.isDisposed()) {
|
||||
ProgressManager.getInstance().run(myRunnerTask);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (! hadActiveTask) {
|
||||
runRunner();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void runRunner() {
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
if (application.isUnitTestMode()) {
|
||||
application.executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
myRunnerTask.run(new EmptyProgressIndicator());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (application.isDispatchThread()) {
|
||||
ProgressManager.getInstance().run(myRunnerTask);
|
||||
}
|
||||
else {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (myProject == null || !myProject.isDisposed()) {
|
||||
ProgressManager.getInstance().run(myRunnerTask);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInTestMode() {
|
||||
if (myForcedTestMode != null) return myForcedTestMode.booleanValue();
|
||||
return ApplicationManager.getApplication().isUnitTestMode();
|
||||
}
|
||||
|
||||
public void setTestMode(boolean forcedTestMode) {
|
||||
myForcedTestMode = forcedTestMode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.LineBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.ArrayList;
|
||||
@@ -427,7 +426,7 @@ public abstract class DialogWrapper {
|
||||
}
|
||||
setMargin(button);
|
||||
if (action.getValue(DEFAULT_ACTION) != null) {
|
||||
if (!myPeer.isHeadless()) {
|
||||
if (myPeer != null && !myPeer.isHeadless()) {
|
||||
getRootPane().setDefaultButton(button);
|
||||
}
|
||||
}
|
||||
@@ -1340,4 +1339,4 @@ public abstract class DialogWrapper {
|
||||
|
||||
String getDoNotShowMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.patterns;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class InitialPatternConditionPlus<T> extends InitialPatternCondition<T> {
|
||||
|
||||
protected InitialPatternConditionPlus(final Class<T> aAcceptedClass) {
|
||||
super(aAcceptedClass);
|
||||
}
|
||||
|
||||
public abstract List<ElementPattern<?>> getPatterns();
|
||||
}
|
||||
@@ -22,6 +22,10 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
@@ -83,7 +87,7 @@ public class StandardPatterns {
|
||||
}
|
||||
|
||||
public static <E> ElementPattern<E> or(final ElementPattern<? extends E>... patterns) {
|
||||
return new ObjectPattern.Capture<E>(new InitialPatternCondition(Object.class) {
|
||||
return new ObjectPattern.Capture<E>(new InitialPatternConditionPlus(Object.class) {
|
||||
public boolean accepts(@Nullable final Object o, final ProcessingContext context) {
|
||||
for (final ElementPattern pattern : patterns) {
|
||||
if (pattern.getCondition().accepts(o, context)) return true;
|
||||
@@ -102,11 +106,15 @@ public class StandardPatterns {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ElementPattern<?>> getPatterns() {
|
||||
return Arrays.<ElementPattern<?>>asList(patterns);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <E> ElementPattern<E> and(final ElementPattern<? extends E>... patterns) {
|
||||
return new ObjectPattern.Capture<E>(new InitialPatternCondition(Object.class) {
|
||||
return new ObjectPattern.Capture<E>(new InitialPatternConditionPlus(Object.class) {
|
||||
public boolean accepts(@Nullable final Object o, final ProcessingContext context) {
|
||||
for (final ElementPattern pattern : patterns) {
|
||||
if (!pattern.getCondition().accepts(o, context)) return false;
|
||||
@@ -124,11 +132,16 @@ public class StandardPatterns {
|
||||
pattern.getCondition().append(builder, indent + " ");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ElementPattern<?>> getPatterns() {
|
||||
return Arrays.<ElementPattern<?>>asList(patterns);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <E> ObjectPattern.Capture<E> not(final ElementPattern<E> pattern) {
|
||||
return new ObjectPattern.Capture<E>(new InitialPatternCondition(Object.class) {
|
||||
return new ObjectPattern.Capture<E>(new InitialPatternConditionPlus(Object.class) {
|
||||
public boolean accepts(@Nullable final Object o, final ProcessingContext context) {
|
||||
return !pattern.getCondition().accepts(o, context);
|
||||
}
|
||||
@@ -137,6 +150,11 @@ public class StandardPatterns {
|
||||
pattern.getCondition().append(builder.append("not("), indent + " ");
|
||||
builder.append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ElementPattern<?>> getPatterns() {
|
||||
return Collections.<ElementPattern<?>>singletonList(pattern);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@ public class Alarm implements Disposable {
|
||||
private final List<Request> myRequests = new ArrayList<Request>();
|
||||
private final List<Request> myPendingRequests = new ArrayList<Request>();
|
||||
|
||||
private final ThreadPoolExecutor myExecutorService;
|
||||
|
||||
private static final ThreadPoolExecutor ourSharedExecutorService = ConcurrencyUtil.newSingleThreadExecutor("Alarm pool(shared)", Thread.NORM_PRIORITY - 2);
|
||||
|
||||
private final Object LOCK = new Object();
|
||||
@@ -55,10 +53,6 @@ public class Alarm implements Disposable {
|
||||
public void dispose() {
|
||||
myDisposed = true;
|
||||
cancelAllRequests();
|
||||
if (myThreadToUse == ThreadToUse.OWN_THREAD) {
|
||||
myExecutorService.getQueue().clear();
|
||||
myExecutorService.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ThreadToUse {
|
||||
@@ -84,7 +78,6 @@ public class Alarm implements Disposable {
|
||||
}
|
||||
public Alarm(@NotNull ThreadToUse threadToUse, Disposable parentDisposable) {
|
||||
myThreadToUse = threadToUse;
|
||||
myExecutorService = threadToUse == ThreadToUse.OWN_THREAD ? ConcurrencyUtil.newSingleThreadExecutor("Alarm pool(own)", Thread.NORM_PRIORITY - 2) : ourSharedExecutorService;
|
||||
|
||||
if (parentDisposable != null) {
|
||||
Disposer.register(parentDisposable, this);
|
||||
@@ -243,7 +236,9 @@ public class Alarm implements Disposable {
|
||||
}
|
||||
}
|
||||
else {
|
||||
myFuture = myExecutorService.submit(scheduledTask);
|
||||
myFuture = (myThreadToUse == ThreadToUse.SHARED_THREAD)
|
||||
? ourSharedExecutorService.submit(scheduledTask)
|
||||
: ApplicationManager.getApplication().executeOnPooledThread(scheduledTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application
|
||||
private final ExecutorService ourThreadExecutorsService = new ThreadPoolExecutor(
|
||||
3,
|
||||
Integer.MAX_VALUE,
|
||||
30 * 60L,
|
||||
5 * 60L,
|
||||
TimeUnit.SECONDS,
|
||||
new SynchronousQueue<Runnable>(),
|
||||
new ThreadFactory() {
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
<extensionPoint name="referencesSearch" interface="com.intellij.util.QueryExecutor"/>
|
||||
<extensionPoint name="definitionsSearch" interface="com.intellij.util.QueryExecutor"/>
|
||||
|
||||
<extensionPoint name="searchRequestor" interface="com.intellij.psi.search.SearchRequestor"/>
|
||||
|
||||
<extensionPoint name="gotoClassContributor"
|
||||
interface="com.intellij.navigation.ChooseByNameContributor"/>
|
||||
<extensionPoint name="gotoSymbolContributor"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<appStarter implementation="com.intellij.ide.ui.search.TraverseUIStarter"/>
|
||||
|
||||
<referencesSearch implementation="com.intellij.psi.impl.search.CachesBasedRefSearcher"/>
|
||||
<searchRequestor implementation="com.intellij.psi.impl.search.CachesBasedRefSearcher"/>
|
||||
|
||||
<applicationService serviceInterface="com.intellij.codeInsight.completion.CompletionService"
|
||||
serviceImplementation="com.intellij.codeInsight.completion.impl.CompletionServiceImpl"/>
|
||||
|
||||
@@ -43,6 +43,22 @@ public class MultiMap<K, V> {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public void putAllValues(MultiMap<? extends K, ? extends V> from) {
|
||||
for (K k : from.keySet()) {
|
||||
//noinspection unchecked
|
||||
putValues(k, ((MultiMap)from).get(k));
|
||||
}
|
||||
}
|
||||
|
||||
public void putValues(K key, Collection<? extends V> values) {
|
||||
Collection<V> list = myMap.get(key);
|
||||
if (list == null) {
|
||||
list = createCollection();
|
||||
myMap.put(key, list);
|
||||
}
|
||||
list.addAll(values);
|
||||
}
|
||||
|
||||
public void putValue(K key, V value) {
|
||||
Collection<V> list = myMap.get(key);
|
||||
if (list == null) {
|
||||
|
||||
@@ -294,6 +294,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
final boolean wasEverythingDirty = invalidated.isEverythingDirty();
|
||||
final List<VcsDirtyScope> scopes = invalidated.getScopes();
|
||||
|
||||
boolean somethingChangedInView = false;
|
||||
try {
|
||||
checkIfDisposed();
|
||||
|
||||
@@ -314,7 +315,6 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
if (wasEverythingDirty) {
|
||||
changeListWorker.notifyStartProcessingChanges(null);
|
||||
}
|
||||
myChangesViewManager.scheduleRefresh();
|
||||
|
||||
final ChangeListManagerGate gate = changeListWorker.createSelfGate();
|
||||
|
||||
@@ -380,11 +380,12 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
myModifier.clearQueue();
|
||||
// update member from copy
|
||||
if (takeChanges) {
|
||||
myWorker.takeData(changeListWorker);
|
||||
somethingChangedInView |= myWorker.takeData(changeListWorker);
|
||||
}
|
||||
|
||||
if (takeChanges && updateUnversionedFiles) {
|
||||
boolean statusChanged = !myComposite.equals(composite);
|
||||
somethingChangedInView |= statusChanged;
|
||||
myComposite = composite;
|
||||
if (statusChanged) {
|
||||
myDelayedNotificator.getProxyDispatcher().unchangedFileStatusChanged();
|
||||
@@ -396,7 +397,6 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
}
|
||||
myShowLocalChangesInvalidated = false;
|
||||
}
|
||||
myChangesViewManager.scheduleRefresh();
|
||||
}
|
||||
catch (DisposedException e) {
|
||||
// OK, we're finishing all the stuff now.
|
||||
@@ -415,6 +415,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
|
||||
synchronized (myDataLock) {
|
||||
myDelayedNotificator.getProxyDispatcher().changeListUpdateDone();
|
||||
}
|
||||
if (somethingChangedInView) {
|
||||
myChangesViewManager.scheduleRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,20 +94,22 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
myDefault = defaultList;
|
||||
}
|
||||
|
||||
public void takeData(@NotNull final ChangeListWorker worker) {
|
||||
public boolean takeData(@NotNull final ChangeListWorker worker) {
|
||||
myMap.clear();
|
||||
myMap.putAll(worker.myMap);
|
||||
myDefault = worker.myDefault;
|
||||
|
||||
myListsToDisappear.clear();
|
||||
myListsToDisappear.addAll(worker.myListsToDisappear);
|
||||
|
||||
myDelta.step(myIdx, worker.myIdx);
|
||||
|
||||
final boolean somethingChanged = myDelta.step(myIdx, worker.myIdx);
|
||||
myIdx = new ChangeListsIndexes(worker.myIdx);
|
||||
checkForMultipleCopiesNotMove();
|
||||
// todo +-
|
||||
|
||||
myLocallyDeleted.takeFrom(worker.myLocallyDeleted);
|
||||
mySwitchedHolder.takeFrom(worker.mySwitchedHolder);
|
||||
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
private void checkForMultipleCopiesNotMove() {
|
||||
|
||||
@@ -36,12 +36,13 @@ public class ChangesDelta {
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
}
|
||||
|
||||
public void step(final ChangeListsIndexes was, final ChangeListsIndexes became) {
|
||||
// true -> something changed
|
||||
public boolean step(final ChangeListsIndexes was, final ChangeListsIndexes became) {
|
||||
List<Pair<String, VcsKey>> wasAffected = was.getAffectedFilesUnderVcs();
|
||||
if (! myInitialized) {
|
||||
sendPlus(wasAffected);
|
||||
myInitialized = true;
|
||||
return;
|
||||
return true; //+-
|
||||
}
|
||||
final List<Pair<String, VcsKey>> becameAffected = became.getAffectedFilesUnderVcs();
|
||||
|
||||
@@ -54,6 +55,7 @@ public class ChangesDelta {
|
||||
}
|
||||
}
|
||||
sendPlus(toAdd);
|
||||
return toRemove != null || toAdd != null;
|
||||
}
|
||||
|
||||
private void sendPlus(final Collection<Pair<String, VcsKey>> toAdd) {
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
package org.intellij.plugins.intelliLang;
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.ide.plugins.cl.PluginClassLoader;
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.command.undo.DocumentReference;
|
||||
@@ -199,14 +201,25 @@ public final class Configuration implements PersistentStateComponent<Element>, M
|
||||
}
|
||||
}
|
||||
}
|
||||
final THashSet<String> visitedUrls = new THashSet<String>();
|
||||
final THashSet<Object> visited = new THashSet<Object>();
|
||||
for (IdeaPluginDescriptor pluginDescriptor : PluginManager.getPlugins()) {
|
||||
if (pluginDescriptor instanceof IdeaPluginDescriptorImpl && !((IdeaPluginDescriptorImpl)pluginDescriptor).isEnabled()) continue;
|
||||
final ClassLoader loader = pluginDescriptor.getPluginClassLoader();
|
||||
final URL url = loader != null ? loader.getResource("META-INF/languageInjections.xml") : null;
|
||||
if (url == null) continue;
|
||||
if (!visitedUrls.add(url.getFile())) continue; // for DEBUG mode
|
||||
if (!visited.add(loader)) continue;
|
||||
if (loader instanceof PluginClassLoader && ((PluginClassLoader)loader).getUrls().isEmpty()) continue;
|
||||
try {
|
||||
cfgList.add(load(url.openStream()));
|
||||
final Enumeration<URL> enumeration = loader.getResources("META-INF/languageInjections.xml");
|
||||
if (enumeration == null) continue;
|
||||
while (enumeration.hasMoreElements()) {
|
||||
URL url = enumeration.nextElement();
|
||||
if (!visited.add(url.getFile())) continue; // for DEBUG mode
|
||||
try {
|
||||
cfgList.add(load(url.openStream()));
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn(e);
|
||||
|
||||
+22
-7
@@ -54,13 +54,9 @@ public class PatternBasedInjectionHelper {
|
||||
final String[] parts = text.split("[,|\\s]+");
|
||||
boolean useMatches = false;
|
||||
for (String part : parts) {
|
||||
if (!StringUtil.escapeToRegexp(part).equals(part)) {
|
||||
try {
|
||||
final URL url = new URL(part);
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
useMatches = true;
|
||||
}
|
||||
if (isRegexp(part)) {
|
||||
useMatches = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (useMatches) {
|
||||
@@ -83,6 +79,25 @@ public class PatternBasedInjectionHelper {
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static boolean isRegexp(final String s) {
|
||||
boolean hasReChars = false;
|
||||
for (int i = 0, len = s.length(); i < len; i++) {
|
||||
final char c = s.charAt(i);
|
||||
if (c == ' ' || c == '_' || c == '-' || Character.isLetterOrDigit(c)) continue;
|
||||
hasReChars = true;
|
||||
break;
|
||||
}
|
||||
if (hasReChars) {
|
||||
try {
|
||||
new URL(s);
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Set<Method> getStaticMethods() {
|
||||
if (myStaticMethods == null) {
|
||||
myStaticMethods = getStaticMethods(mySupportId);
|
||||
|
||||
-4
@@ -19,7 +19,6 @@ package org.intellij.plugins.intelliLang.inject;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
@@ -73,7 +72,6 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection
|
||||
}
|
||||
|
||||
public AnAction[] createAddActions(final Project project, final Consumer<BaseInjection> consumer) {
|
||||
if (!ApplicationManagerEx.getApplicationEx().isInternal()) return AnAction.EMPTY_ARRAY;
|
||||
return new AnAction[] { createDefaultAddAction(project, consumer, this) };
|
||||
}
|
||||
|
||||
@@ -85,7 +83,6 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection
|
||||
return new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
if (!ApplicationManagerEx.getApplicationEx().isInternal()) return;
|
||||
final BaseInjection originalInjection = producer.create();
|
||||
final BaseInjection newInjection = showDefaultInjectionUI(project, originalInjection.copy());
|
||||
if (newInjection != null) {
|
||||
@@ -114,7 +111,6 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection
|
||||
|
||||
@Nullable
|
||||
protected static BaseInjection showDefaultInjectionUI(Project project, BaseInjection injection) {
|
||||
if (!ApplicationManagerEx.getApplicationEx().isInternal()) return null;
|
||||
final BaseInjectionPanel panel = new BaseInjectionPanel(injection, project);
|
||||
panel.reset();
|
||||
final DialogBuilder builder = new DialogBuilder(project);
|
||||
|
||||
+2
-1
@@ -147,7 +147,8 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
|
||||
public boolean acceptsPsiElement(final PsiElement element) {
|
||||
ProgressManager.checkCanceled();
|
||||
for (InjectionPlace place : myPlaces) {
|
||||
for (int i = 0, myPlacesSize = myPlaces.size(); i < myPlacesSize; i++) {
|
||||
final InjectionPlace place = myPlaces.get(i);
|
||||
if (place.isEnabled() && place.getElementPattern() != null && place.getElementPattern().accepts(element)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+48
-8
@@ -20,6 +20,7 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.lang.injection.MultiHostInjector;
|
||||
import com.intellij.lang.injection.MultiHostRegistrar;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
@@ -37,6 +38,7 @@ import com.intellij.util.PairProcessor;
|
||||
import com.intellij.util.PatternValuesIndex;
|
||||
import gnu.trove.THashMap;
|
||||
import org.intellij.plugins.intelliLang.Configuration;
|
||||
import org.intellij.plugins.intelliLang.PatternBasedInjectionHelper;
|
||||
import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
|
||||
import org.intellij.plugins.intelliLang.inject.InjectorUtils;
|
||||
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
|
||||
@@ -46,6 +48,7 @@ import org.intellij.plugins.intelliLang.inject.config.InjectionPlace;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* This is the main part of the injection code. The component registers a language injector, the reference provider that
|
||||
@@ -60,7 +63,7 @@ public final class XmlLanguageInjector implements MultiHostInjector {
|
||||
|
||||
private final Configuration myConfiguration;
|
||||
private final Project myProject;
|
||||
private CachedValue<Collection<String>> myXmlIndex;
|
||||
private CachedValue<Pair<Pattern, Collection<String>>> myXmlIndex;
|
||||
|
||||
public XmlLanguageInjector(Configuration configuration, Project project) {
|
||||
myConfiguration = configuration;
|
||||
@@ -73,9 +76,11 @@ public final class XmlLanguageInjector implements MultiHostInjector {
|
||||
}
|
||||
|
||||
public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull PsiElement host) {
|
||||
final XmlElement xmlElement = (XmlElement) host;
|
||||
if (notInIndex(xmlElement)) return;
|
||||
final TreeSet<TextRange> ranges = new TreeSet<TextRange>(InjectorUtils.RANGE_COMPARATOR);
|
||||
final PsiFile containingFile = host.getContainingFile();
|
||||
getInjectedLanguage(host, new PairProcessor<Language, List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>>>() {
|
||||
final PsiFile containingFile = xmlElement.getContainingFile();
|
||||
getInjectedLanguage(xmlElement, new PairProcessor<Language, List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>>>() {
|
||||
public boolean process(final Language language, List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> list) {
|
||||
for (Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange> trinity : list) {
|
||||
if (ranges.contains(trinity.third.shiftRight(trinity.first.getTextRange().getStartOffset()))) return true;
|
||||
@@ -92,7 +97,6 @@ public final class XmlLanguageInjector implements MultiHostInjector {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void getInjectedLanguage(final PsiElement place, final PairProcessor<Language, List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>>> processor) {
|
||||
if (place instanceof XmlTag) {
|
||||
final XmlTag xmlTag = (XmlTag)place;
|
||||
@@ -189,10 +193,35 @@ public final class XmlLanguageInjector implements MultiHostInjector {
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<String> getXmlAnnotatedElementsValue() {
|
||||
// NOTE: local name of an xml entity or attribute value should match at least one string in the index
|
||||
private boolean notInIndex(XmlElement xmlElement) {
|
||||
final Pair<Pattern, Collection<String>> index = getXmlAnnotatedElementsValue();
|
||||
final XmlTag tag;
|
||||
if (xmlElement instanceof XmlAttribute) {
|
||||
final XmlAttribute attribute = (XmlAttribute)xmlElement;
|
||||
if (areThereInjectionsWithText(attribute.getLocalName(), index)) return false;
|
||||
if (areThereInjectionsWithText(attribute.getValue(), index)) return false;
|
||||
//if (areThereInjectionsWithText(attribute.getNamespace(), index)) return false;
|
||||
tag = attribute.getParent();
|
||||
}
|
||||
else tag = (XmlTag)xmlElement;
|
||||
if (areThereInjectionsWithText(tag.getLocalName(), index)) return false;
|
||||
//if (areThereInjectionsWithText(tag.getNamespace(), index)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static boolean areThereInjectionsWithText(final String text, Pair<Pattern, Collection<String>> index) {
|
||||
if (text == null) return false;
|
||||
if (index.second.contains(text)) return true;
|
||||
if (index.first.matcher(text).matches()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private Pair<Pattern, Collection<String>> getXmlAnnotatedElementsValue() {
|
||||
if (myXmlIndex == null) {
|
||||
myXmlIndex = CachedValuesManager.getManager(myProject).createCachedValue(new CachedValueProvider<Collection<String>>() {
|
||||
public Result<Collection<String>> compute() {
|
||||
myXmlIndex = CachedValuesManager.getManager(myProject).createCachedValue(new CachedValueProvider<Pair<Pattern, Collection<String>>>() {
|
||||
public Result<Pair<Pattern, Collection<String>>> compute() {
|
||||
final Map<ElementPattern<?>, BaseInjection> map = new THashMap<ElementPattern<?>, BaseInjection>();
|
||||
for (BaseInjection injection : myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID)) {
|
||||
for (InjectionPlace place : injection.getInjectionPlaces()) {
|
||||
@@ -201,7 +230,8 @@ public final class XmlLanguageInjector implements MultiHostInjector {
|
||||
}
|
||||
}
|
||||
final Set<String> stringSet = PatternValuesIndex.buildStringIndex(map.keySet());
|
||||
final Result<Collection<String>> r = new Result<Collection<String>>(stringSet, myConfiguration);
|
||||
final Result<Pair<Pattern, Collection<String>>> r = new Result<Pair<Pattern, Collection<String>>>(
|
||||
Pair.<Pattern, Collection<String>>create(buildPattern(stringSet), stringSet), myConfiguration);
|
||||
r.setLockValue(true);
|
||||
return r;
|
||||
}
|
||||
@@ -210,4 +240,14 @@ public final class XmlLanguageInjector implements MultiHostInjector {
|
||||
return myXmlIndex.getValue();
|
||||
}
|
||||
|
||||
private static Pattern buildPattern(Set<String> stringSet) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (String s : stringSet) {
|
||||
if (!PatternBasedInjectionHelper.isRegexp(s)) continue;
|
||||
if (sb.length() > 0) sb.append('|');
|
||||
sb.append("(?:").append(s).append(")");
|
||||
}
|
||||
return Pattern.compile(sb.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,11 +76,4 @@
|
||||
<place><![CDATA[xmlTag().withLocalName(string().equalTo("style")).withNamespace(string().equalTo("http://www.w3.org/1999/xhtml"))]]></place>
|
||||
<xpath-condition>lower-case(@type)='text/css'</xpath-condition>
|
||||
</injection>
|
||||
<injection language="TEL" injector-id="xml">
|
||||
<display-name>Bare Tapestry EL in attribute value</display-name>
|
||||
<prefix>${</prefix>
|
||||
<suffix>}</suffix>
|
||||
<place><![CDATA[xmlAttribute().withLocalName(not(string().oneOf("id", "type"))).withText(string().matches("[^${}/\\]+")).inside(xmlTag().withNamespace(string().oneOf("http://tapestry.apache.org/schema/tapestry_5_1_0.xsd", "http://tapestry.apache.org/schema/tapestry_5_0_0.xsd")))]]></place>
|
||||
<place><![CDATA[xmlAttribute().withLocalName(not(string().oneOf("id", "type"))).withText(string().matches("[^${}/\\]+")).withNamespace(string().oneOf("http://tapestry.apache.org/schema/tapestry_5_1_0.xsd", "http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"))]]></place>
|
||||
</injection>
|
||||
</component>
|
||||
|
||||
@@ -32,7 +32,7 @@ public class GitCommitAndPushExecutor implements CommitExecutor {
|
||||
|
||||
@Nls
|
||||
public String getActionText() {
|
||||
return "Commit and &Push";
|
||||
return "Commit and &Push...";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -65,6 +65,7 @@ public class GitUsersComponent implements ProjectComponent {
|
||||
private VcsListener myVcsListener;
|
||||
private final GitVcs myVcs;
|
||||
private final ProjectLevelVcsManager myManager;
|
||||
private final File myFile;
|
||||
|
||||
public GitUsersComponent(final ProjectLevelVcsManager manager) {
|
||||
myVcs = (GitVcs) manager.findVcsByName(GitVcs.getKey().getName());
|
||||
@@ -74,14 +75,8 @@ public class GitUsersComponent implements ProjectComponent {
|
||||
final File vcsFile = new File(PathManager.getSystemPath(), "vcs");
|
||||
File file = new File(vcsFile, "git_users");
|
||||
file.mkdirs();
|
||||
file = new File(file, myVcs.getProject().getLocationHash());
|
||||
myFile = new File(file, myVcs.getProject().getLocationHash());
|
||||
|
||||
try {
|
||||
myState = new PersistentHashMap<String, UsersData>(file, new EnumeratorStringDescriptor(), createExternalizer());
|
||||
}
|
||||
catch (IOException e) {
|
||||
myState = null;
|
||||
}
|
||||
myAccessMap = new HashMap<VirtualFile, Pair<String, LowLevelAccess>>();
|
||||
|
||||
// every 10 seconds is ok to check
|
||||
@@ -157,12 +152,27 @@ public class GitUsersComponent implements ProjectComponent {
|
||||
}
|
||||
|
||||
public void activate() {
|
||||
try {
|
||||
myState = new PersistentHashMap<String, UsersData>(myFile, new EnumeratorStringDescriptor(), createExternalizer());
|
||||
}
|
||||
catch (IOException e) {
|
||||
myState = null;
|
||||
}
|
||||
|
||||
myIsActive = true;
|
||||
myManager.addVcsListener(myVcsListener);
|
||||
myControlledCycle.start();
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
if (myState != null) try {
|
||||
myState.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
myState = null;
|
||||
|
||||
synchronized (myLock) {
|
||||
myAccessMap.clear();
|
||||
}
|
||||
|
||||
@@ -178,8 +178,8 @@
|
||||
<extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyGStringSelectioner" order="before wordSelectioner"/>
|
||||
<extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyParameterListSelectioner"/>
|
||||
|
||||
<methodReferencesSearch implementation="org.jetbrains.plugins.groovy.findUsages.AccessorReferencesSearcher"/>
|
||||
<methodReferencesSearch implementation="org.jetbrains.plugins.groovy.findUsages.MethodLateBoundReferencesSearcher"/>
|
||||
<searchRequestor implementation="org.jetbrains.plugins.groovy.findUsages.AccessorReferencesSearcher"/>
|
||||
<searchRequestor implementation="org.jetbrains.plugins.groovy.findUsages.MethodLateBoundReferencesSearcher"/>
|
||||
<methodReferencesSearch implementation="org.jetbrains.plugins.groovy.findUsages.GroovyConstructorUsagesSearcher"/>
|
||||
<annotatedElementsSearch implementation="org.jetbrains.plugins.groovy.findUsages.AnnotatedMembersSearcher"/>
|
||||
<superMethodsSearch implementation="org.jetbrains.plugins.groovy.findUsages.GDKSuperMethodSearcher"/>
|
||||
@@ -209,6 +209,8 @@
|
||||
<stubIndex implementation="org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnonymousClassIndex"/>
|
||||
|
||||
<referencesSearch implementation="org.jetbrains.plugins.groovy.findUsages.ConstructorReferencesSearcher"/>
|
||||
<referencesSearch implementation="org.jetbrains.plugins.groovy.findUsages.GrAliasedImportedElementSearcher"/>
|
||||
|
||||
<antCustomCompiler implementation="org.jetbrains.plugins.groovy.ant.GroovyAntCustomCompilerProvider"/>
|
||||
|
||||
<project.converterProvider implementation="org.jetbrains.plugins.groovy.config.GroovyModuleConverterProvider"/>
|
||||
|
||||
@@ -201,6 +201,8 @@ strictfp.visibility.presentation=strictfp
|
||||
transient.visibility.presentation=transient
|
||||
# suppress inspection "UnusedProperty"
|
||||
volatile.visibility.presentation=volatile
|
||||
# suppress inspection "UnusedProperty"
|
||||
def.visibility.presentation=def
|
||||
|
||||
|
||||
|
||||
|
||||
+4
-7
@@ -22,7 +22,7 @@ import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrDynamicImplicitProperty;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.LightModifierList;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* User: Dmitry.Krasilschikov
|
||||
@@ -48,17 +48,14 @@ public class DPropertyElement extends DItemElement {
|
||||
public PsiVariable getPsi(PsiManager manager, final String containingClassName) {
|
||||
if (myPsi != null) return myPsi;
|
||||
|
||||
LinkedHashSet<String> hashSet = new LinkedHashSet<String>();
|
||||
|
||||
Boolean isStatic = isStatic();
|
||||
if (isStatic != null && isStatic.booleanValue()) {
|
||||
hashSet.add(PsiModifier.STATIC);
|
||||
}
|
||||
int modifiers = (isStatic != null && isStatic.booleanValue()) ? Modifier.STATIC : 0;
|
||||
|
||||
String type = getType();
|
||||
if (type == null) {
|
||||
type = CommonClassNames.JAVA_LANG_OBJECT;
|
||||
}
|
||||
myPsi = new GrDynamicImplicitProperty(manager, getName(), type, containingClassName, new LightModifierList(manager, hashSet), null) {
|
||||
myPsi = new GrDynamicImplicitProperty(manager, getName(), type, containingClassName, new LightModifierList(manager, modifiers), null) {
|
||||
@Override
|
||||
public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
|
||||
DynamicManager.getInstance(getProject()).replaceDynamicPropertyName(containingClassName, getName(), name);
|
||||
|
||||
+21
-39
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.findUsages;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
@@ -26,52 +27,33 @@ import com.intellij.psi.search.UsageSearchContext;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.SearchRequestCollector;
|
||||
import com.intellij.psi.search.SearchRequestor;
|
||||
import com.intellij.psi.search.UsageSearchContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
/**
|
||||
* author ven
|
||||
*/
|
||||
public class AccessorReferencesSearcher implements QueryExecutor<PsiReference, MethodReferencesSearch.SearchParameters> {
|
||||
public class AccessorReferencesSearcher extends SearchRequestor {
|
||||
@Override
|
||||
public void contributeRequests(@NotNull PsiElement target,
|
||||
@NotNull final FindUsagesOptions options,
|
||||
@NotNull SearchRequestCollector collector) {
|
||||
if (!(target instanceof PsiMethod)) {
|
||||
return;
|
||||
}
|
||||
|
||||
public boolean execute(final MethodReferencesSearch.SearchParameters searchParameters, final Processor<PsiReference> consumer) {
|
||||
final PsiMethod method = searchParameters.getMethod();
|
||||
final String propertyName = getPropertyName(method);
|
||||
if (propertyName == null) return true;
|
||||
|
||||
SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable<SearchScope>() {
|
||||
public SearchScope compute() {
|
||||
return searchParameters.getScope();
|
||||
}
|
||||
});
|
||||
|
||||
final PsiSearchHelper helper = PsiManager.getInstance(method.getProject()).getSearchHelper();
|
||||
final TextOccurenceProcessor processor = new TextOccurenceProcessor() {
|
||||
public boolean execute(PsiElement element, int offsetInElement) {
|
||||
final PsiReference[] refs = element.getReferences();
|
||||
for (PsiReference ref : refs) {
|
||||
if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
|
||||
if (ref.isReferenceTo(method)) {
|
||||
return consumer.process(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return helper.processElementsWithWord(processor,
|
||||
searchScope,
|
||||
propertyName,
|
||||
UsageSearchContext.IN_CODE,
|
||||
false);
|
||||
final String propertyName = GroovyPropertyUtils.getPropertyName((PsiMethod)target);
|
||||
if (propertyName != null) {
|
||||
collector.searchWord(propertyName, PsiUtil.restrictScopeToGroovyFiles(options.searchScope), UsageSearchContext.IN_CODE, true, target);
|
||||
}
|
||||
}
|
||||
|
||||
private String getPropertyName(final PsiMethod method) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
public String compute() {
|
||||
return GroovyPropertyUtils.getPropertyName(method);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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 org.jetbrains.plugins.groovy.findUsages;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.TextOccurenceProcessor;
|
||||
import com.intellij.psi.search.UsageSearchContext;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
public class GrAliasedImportedElementSearcher implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
|
||||
private static final ThreadLocal<Object> I_WAS_HERE = new ThreadLocal<Object>();
|
||||
|
||||
public boolean execute(final ReferencesSearch.SearchParameters parameters, final Processor<PsiReference> consumer) {
|
||||
final PsiElement elementToSearch = parameters.getElementToSearch();
|
||||
if (!(elementToSearch instanceof PsiMember)) return true;
|
||||
if (I_WAS_HERE.get() != null) return true;
|
||||
|
||||
try {
|
||||
I_WAS_HERE.set(Boolean.TRUE);
|
||||
final TextOccurenceProcessor processor = new MyTextOccurenceProcessor(elementToSearch, consumer);
|
||||
|
||||
final SearchScope groovySearchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable<SearchScope>() {
|
||||
public SearchScope compute() {
|
||||
return parameters.getEffectiveSearchScope();
|
||||
}
|
||||
});
|
||||
|
||||
if (!ReferencesSearch.search(elementToSearch, groovySearchScope).forEach(new MyProcessor(null, processor))) return false;
|
||||
|
||||
if (elementToSearch instanceof PsiMethod && isAccessor(elementToSearch)) {
|
||||
final PsiField field = ApplicationManager.getApplication().runReadAction(new Computable<PsiField>() {
|
||||
public PsiField compute() {
|
||||
return GroovyPropertyUtils.findFieldForAccessor((PsiMethod)elementToSearch, true);
|
||||
}
|
||||
});
|
||||
if (field != null) {
|
||||
final String prefix = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
public String compute() {
|
||||
return GroovyPropertyUtils.getAccessorPrefix((PsiMethod)elementToSearch);
|
||||
}
|
||||
});
|
||||
if (prefix == null) return true;
|
||||
if (!ReferencesSearch.search(field, groovySearchScope).forEach(new MyProcessor(prefix, processor))) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
finally {
|
||||
I_WAS_HERE.set(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Boolean isAccessor(final PsiElement elementToSearch) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
return GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)elementToSearch);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static class MyProcessor implements Processor<PsiReference> {
|
||||
private final String prefix;
|
||||
private final TextOccurenceProcessor processor;
|
||||
|
||||
MyProcessor(@Nullable String prefix, TextOccurenceProcessor processor) {
|
||||
this.prefix = prefix;
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
public boolean process(PsiReference psiReference) {
|
||||
final PsiElement element = psiReference.getElement();
|
||||
if (element == null) return true;
|
||||
|
||||
String alias = getAlias(element);
|
||||
if (alias == null) return true;
|
||||
|
||||
final PsiFile containingFile = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
|
||||
public PsiFile compute() {
|
||||
return element.getContainingFile();
|
||||
}
|
||||
});
|
||||
|
||||
if (prefix != null) {
|
||||
if (!PsiManager.getInstance(element.getProject()).getSearchHelper()
|
||||
.processElementsWithWord(processor, GlobalSearchScope.fileScope(containingFile), prefix + GroovyPropertyUtils.capitalize(alias),
|
||||
UsageSearchContext.IN_CODE,
|
||||
false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return PsiManager.getInstance(element.getProject()).getSearchHelper()
|
||||
.processElementsWithWord(processor, GlobalSearchScope.fileScope(containingFile), alias, UsageSearchContext.IN_CODE, false);
|
||||
}
|
||||
|
||||
private static String getAlias(final PsiElement element) {
|
||||
return ApplicationManager.getApplication().runReadAction(new NullableComputable<String>() {
|
||||
public String compute() {
|
||||
if (!(element.getParent() instanceof GrImportStatement)) return null;
|
||||
final GrImportStatement importStatement = (GrImportStatement)element.getParent();
|
||||
if (!importStatement.isAliasedImport()) return null;
|
||||
return importStatement.getImportedName();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyTextOccurenceProcessor implements TextOccurenceProcessor {
|
||||
private final PsiElement elementToSearch;
|
||||
private final Processor<PsiReference> consumer;
|
||||
|
||||
public MyTextOccurenceProcessor(PsiElement elementToSearch, Processor<PsiReference> consumer) {
|
||||
this.elementToSearch = elementToSearch;
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
public boolean execute(PsiElement element, int offsetInElement) {
|
||||
final PsiReference[] refs = element.getParent().getReferences();
|
||||
for (PsiReference ref : refs) {
|
||||
if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
|
||||
if (ref.isReferenceTo(elementToSearch)) {
|
||||
return consumer.process(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
-39
@@ -16,21 +16,18 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.findUsages;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.TextOccurenceProcessor;
|
||||
import com.intellij.psi.search.UsageSearchContext;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.search.GrSourceFilterScope;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
@@ -38,25 +35,24 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class MethodLateBoundReferencesSearcher implements QueryExecutor<PsiReference, MethodReferencesSearch.SearchParameters> {
|
||||
public boolean execute(final MethodReferencesSearch.SearchParameters params, final Processor<PsiReference> consumer) {
|
||||
final PsiMethod method = params.getMethod();
|
||||
SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable<SearchScope>() {
|
||||
public SearchScope compute() {
|
||||
return params.getScope().intersectWith(getUseScope(method));
|
||||
}
|
||||
});
|
||||
public class MethodLateBoundReferencesSearcher extends SearchRequestor {
|
||||
@Override
|
||||
public void contributeRequests(@NotNull PsiElement target,
|
||||
@NotNull FindUsagesOptions options,
|
||||
@NotNull SearchRequestCollector collector) {
|
||||
if (!(target instanceof PsiMethod)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String name = method.getName();
|
||||
final PsiMethod method = (PsiMethod)target;
|
||||
SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(options.searchScope.intersectWith(getUseScope(method)));
|
||||
|
||||
final Project project = method.getProject();
|
||||
if (!processTextOccurrences(searchScope, name, consumer, project)) return false;
|
||||
orderSearching(searchScope, method.getName(), collector, method);
|
||||
|
||||
final String propName = getPropertyName(method);
|
||||
final String propName = PropertyUtil.getPropertyName(method);
|
||||
if (propName != null) {
|
||||
if (!processTextOccurrences(searchScope, propName, consumer, project)) return false;
|
||||
orderSearching(searchScope, propName, collector, method);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static SearchScope getUseScope(final PsiMethod method) {
|
||||
@@ -72,18 +68,13 @@ public class MethodLateBoundReferencesSearcher implements QueryExecutor<PsiRefer
|
||||
return scope;
|
||||
}
|
||||
|
||||
private static String getPropertyName(final PsiMethod method) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<String>(){
|
||||
@Nullable
|
||||
public String compute() {
|
||||
return PropertyUtil.getPropertyName(method);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean processTextOccurrences(SearchScope searchScope, final String name, final Processor<PsiReference> consumer, Project project) {
|
||||
final TextOccurenceProcessor processor = new TextOccurenceProcessor() {
|
||||
public boolean execute(PsiElement element, int offsetInElement) {
|
||||
private static void orderSearching(SearchScope searchScope,
|
||||
final String name,
|
||||
@NotNull SearchRequestCollector collector, PsiMethod method) {
|
||||
collector.searchWord(name, searchScope, UsageSearchContext.IN_CODE, true, new SingleTargetRequestResultProcessor(method) {
|
||||
@Override
|
||||
public boolean execute(PsiElement element, int offsetInElement, Processor<PsiReference> consumer) {
|
||||
if (!(element instanceof GrReferenceExpression)) {
|
||||
return true;
|
||||
}
|
||||
@@ -95,10 +86,7 @@ public class MethodLateBoundReferencesSearcher implements QueryExecutor<PsiRefer
|
||||
|
||||
return consumer.process((PsiReference)element);
|
||||
}
|
||||
};
|
||||
|
||||
return PsiManager.getInstance(project).getSearchHelper().processElementsWithWord(processor,
|
||||
searchScope, name, UsageSearchContext.IN_CODE, true);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
+76
-58
@@ -22,10 +22,9 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -45,6 +44,7 @@ import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
@@ -53,15 +53,18 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlo
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrMethodImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyValidationUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.intentions.style.parameterToEntry.ConvertParameterToMapEntryIntention.FIRST_PARAMETER_KIND.*;
|
||||
|
||||
@@ -139,7 +142,7 @@ public class ConvertParameterToMapEntryIntention extends Intention {
|
||||
else {
|
||||
//todo add statictics manager
|
||||
performRefactoring(element, owner, occurrences, true,
|
||||
(new GroovyValidationUtil.ParameterNameSuggester("attrs", firstParam)).generateName(), false);
|
||||
(new GroovyValidationUtil.ParameterNameSuggester("attrs", firstParam)).generateName(), true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -170,14 +173,60 @@ public class ConvertParameterToMapEntryIntention extends Intention {
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
|
||||
|
||||
final GrParameterList list = owner.getParameterList();
|
||||
assert list != null;
|
||||
final int index = list.getParameterNumber(param);
|
||||
final int newIndex = createNewFirstParam ? index : index - 1;
|
||||
if (!createNewFirstParam && index <= 0) { // bad undo
|
||||
return;
|
||||
}
|
||||
|
||||
//Remove old arguments from occurrences
|
||||
//final List<GrCall> calls = getCallOccurrences(occurrences);
|
||||
try {
|
||||
for (PsiElement occurrence : occurrences) {
|
||||
if (occurrence instanceof GrReferenceExpression && occurrence.getParent() instanceof GrCall) {
|
||||
final GrReferenceExpression refExpr = (GrReferenceExpression)occurrence;
|
||||
final GrClosureSignature signature = generateSignature(owner, refExpr);
|
||||
if (signature == null) continue;
|
||||
final GrCall call = (GrCall)refExpr.getParent();
|
||||
final GrArgumentList argumentList = call.getArgumentList();
|
||||
final GrClosableBlock[] closureArguments =
|
||||
call instanceof GrCallExpression ? ((GrCallExpression)call).getClosureArguments() : GrClosableBlock.EMPTY_ARRAY;
|
||||
|
||||
final GrClosureSignatureUtil.ArgInfo[] argInfos =
|
||||
GrClosureSignatureUtil.mapParametersToArguments(signature, argumentList, closureArguments, occurrence.getManager(), owner.getResolveScope());
|
||||
if (argInfos == null) continue;
|
||||
final GrClosureSignatureUtil.ArgInfo argInfo = argInfos[index];
|
||||
|
||||
final GrNamedArgument namedArg;
|
||||
if (argInfo.isMultiArg) {
|
||||
if (argInfo.args.size() == 0) continue;
|
||||
String arg = "[" + StringUtil.join(ContainerUtil.map(argInfo.args, new Function<PsiElement, String>() {
|
||||
public String fun(PsiElement element) {
|
||||
return element.getText();
|
||||
}
|
||||
}), ", ") + "]";
|
||||
for (PsiElement psiElement : argInfo.args) {
|
||||
psiElement.delete();
|
||||
}
|
||||
namedArg = factory.createNamedArgument(paramName, factory.createExpressionFromText(arg));
|
||||
}
|
||||
else {
|
||||
if (argInfo.args.size() == 0) continue;
|
||||
final PsiElement argument = argInfo.args.iterator().next();
|
||||
assert argument instanceof GrExpression;
|
||||
namedArg = factory.createNamedArgument(paramName, (GrExpression)argument);
|
||||
argument.delete();
|
||||
}
|
||||
((GrCall)refExpr.getParent()).addNamedArgument(namedArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
//Replace of occurrences of old parameter in closure/method
|
||||
final Collection<PsiReference> references = ReferencesSearch.search(param).findAll();
|
||||
for (PsiReference ref : references) {
|
||||
@@ -202,35 +251,6 @@ public class ConvertParameterToMapEntryIntention extends Intention {
|
||||
|
||||
//Eliminate obsolete parameter from parameter list
|
||||
param.delete();
|
||||
|
||||
|
||||
//Remove old arguments from occurrences
|
||||
final List<GrCall> calls = getCallOccurrences(occurrences);
|
||||
try {
|
||||
for (final GrCall call : calls) {
|
||||
GrExpression expr = call.removeArgument(newIndex);
|
||||
if (expr != null) {
|
||||
GrNamedArgument argument = factory.createNamedArgument(paramName, expr);
|
||||
call.addNamedArgument(argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
//reformat code
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
try {
|
||||
for (GrCall call : calls) {
|
||||
reformatOwner(call.getArgumentList());
|
||||
}
|
||||
reformatOwner(owner.getParameterList());
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
//owner.putUserData(hasFirstMapParameter, true);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -242,20 +262,6 @@ public class ConvertParameterToMapEntryIntention extends Intention {
|
||||
}
|
||||
|
||||
|
||||
private static List<GrCall> getCallOccurrences(final Collection<PsiElement> occurrences) {
|
||||
final List<PsiElement> elementList = ContainerUtil.findAll(occurrences, new Condition<PsiElement>() {
|
||||
public boolean value(final PsiElement psiElement) {
|
||||
return psiElement instanceof GrReferenceExpression && psiElement.getParent() instanceof GrCall;
|
||||
}
|
||||
});
|
||||
return ContainerUtil.map(elementList, new Function<PsiElement, GrCall>() {
|
||||
public GrCall fun(final PsiElement psiElement) {
|
||||
return ((GrCall)psiElement.getParent());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static GrParameter getAppropriateParameter(final PsiElement element) {
|
||||
if (element instanceof GrParameter) {
|
||||
@@ -271,6 +277,18 @@ public class ConvertParameterToMapEntryIntention extends Intention {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GrClosureSignature generateSignature(GrParametersOwner owner, GrReferenceExpression refExpr) {
|
||||
if (owner instanceof PsiMethod) {
|
||||
final GroovyResolveResult resolveResult = refExpr.advancedResolve();
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
return GrClosureSignatureUtil.createSignature((PsiMethod)owner, substitutor);
|
||||
}
|
||||
else if (owner instanceof GrClosableBlock) {
|
||||
return GrClosureSignatureUtil.createSignature((GrClosableBlock)owner);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param owner Method or closure
|
||||
@@ -388,18 +406,23 @@ public class ConvertParameterToMapEntryIntention extends Intention {
|
||||
|
||||
private static class MyPsiElementPredicate implements PsiElementPredicate {
|
||||
public boolean satisfiedBy(final PsiElement element) {
|
||||
GrParametersOwner owner = null;
|
||||
GrParameter parameter = null;
|
||||
if (element instanceof GrParameter) {
|
||||
owner = PsiTreeUtil.getParentOfType(element, GrParametersOwner.class);
|
||||
parameter = (GrParameter)element;
|
||||
}
|
||||
else if (element instanceof GrReferenceExpression) {
|
||||
GrReferenceExpression expr = (GrReferenceExpression)element;
|
||||
if (expr.getQualifierExpression() != null) return false;
|
||||
final PsiElement resolved = expr.resolve();
|
||||
if (!(resolved instanceof GrParameter)) return false;
|
||||
owner = PsiTreeUtil.getParentOfType(resolved, GrParametersOwner.class);
|
||||
if (resolved instanceof GrParameter) {
|
||||
parameter = (GrParameter)resolved;
|
||||
}
|
||||
}
|
||||
if (!(owner instanceof GrClosableBlock || owner instanceof GrMethodImpl)) return false;
|
||||
if (parameter == null) return false;
|
||||
if (parameter.isOptional()) return false;
|
||||
|
||||
GrParametersOwner owner = PsiTreeUtil.getParentOfType(element, GrParametersOwner.class);
|
||||
if (!(owner instanceof GrClosableBlock || owner instanceof GrMethod)) return false;
|
||||
return checkForMapParameters(owner);
|
||||
}
|
||||
}
|
||||
@@ -420,11 +443,6 @@ public class ConvertParameterToMapEntryIntention extends Intention {
|
||||
CommonRefactoringUtil.showErrorMessage(REFACTORING_NAME, message, null, project);
|
||||
}
|
||||
|
||||
private static void reformatOwner(PsiElement owner) throws IncorrectOperationException {
|
||||
if (owner == null) return;
|
||||
CodeStyleManager.getInstance(owner.getProject()).reformat(owner);
|
||||
}
|
||||
|
||||
private static boolean reportConflicts(final MultiMap<PsiElement, String> conflicts, final Project project) {
|
||||
if (conflicts.size() == 0) return true;
|
||||
ConflictsDialog conflictsDialog = new ConflictsDialog(project, conflicts);
|
||||
|
||||
+10
-7
@@ -16,7 +16,10 @@
|
||||
package org.jetbrains.plugins.groovy.lang.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
|
||||
@@ -109,11 +112,14 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
public void consume(Object element) {
|
||||
if (element instanceof PsiClass) {
|
||||
final PsiClass clazz = (PsiClass)element;
|
||||
final MutableLookupElement<PsiClass> lookupElement = LookupElementFactory.getInstance().createLookupElement(clazz);
|
||||
final LookupElement lookupElement = GroovyCompletionUtil.getLookupElement(clazz);
|
||||
result.addElement(GroovyCompletionUtil.setTailTypeForConstructor(clazz, lookupElement));
|
||||
} else if (element instanceof LookupElement && ((LookupElement)element).getObject() instanceof PsiClass) {
|
||||
result.addElement(GroovyCompletionUtil
|
||||
.setTailTypeForConstructor(((PsiClass)((LookupElement)element).getObject()), ((LookupElement)element)));
|
||||
}
|
||||
else {
|
||||
result.addElement(LookupItemUtil.objectToLookupItem(element));
|
||||
result.addElement(GroovyCompletionUtil.getLookupElement(element));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -123,11 +129,8 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
// final boolean addGDKMethods = parameters.getInvocationCount() > 1;
|
||||
((GrReferenceElement)reference).processVariants(new Consumer<Object>() {
|
||||
public void consume(Object element) {
|
||||
LookupElement lookupElement = LookupItemUtil.objectToLookupItem(element);
|
||||
LookupElement lookupElement = GroovyCompletionUtil.getLookupElement(element);
|
||||
// if (lookupElement.getObject() instanceof GrGdkMethod && !addGDKMethods) return;
|
||||
if (lookupElement instanceof LookupItem) {
|
||||
lookupElement = ((LookupItem)lookupElement).setInsertHandler(new GroovyInsertHandlerAdapter());
|
||||
}
|
||||
result.addElement(lookupElement);
|
||||
}
|
||||
});
|
||||
|
||||
+123
-59
@@ -20,13 +20,18 @@ import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
|
||||
@@ -44,10 +49,15 @@ 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.impl.PsiImplUtil;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public abstract class GroovyCompletionUtil {
|
||||
public class GroovyCompletionUtil {
|
||||
|
||||
private GroovyCompletionUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if last element of curren statement is expression
|
||||
@@ -57,7 +67,7 @@ public abstract class GroovyCompletionUtil {
|
||||
*/
|
||||
public static boolean endsWithExpression(PsiElement statement) {
|
||||
while (statement != null &&
|
||||
!(statement instanceof GrExpression)) {
|
||||
!(statement instanceof GrExpression)) {
|
||||
statement = statement.getLastChild();
|
||||
}
|
||||
return statement != null;
|
||||
@@ -67,7 +77,7 @@ public abstract class GroovyCompletionUtil {
|
||||
public static PsiElement nearestLeftSibling(PsiElement elem) {
|
||||
elem = elem.getPrevSibling();
|
||||
while (elem != null &&
|
||||
(elem instanceof PsiWhiteSpace ||
|
||||
(elem instanceof PsiWhiteSpace ||
|
||||
elem instanceof PsiComment ||
|
||||
GroovyTokenTypes.mNLS.equals(elem.getNode().getElementType()))) {
|
||||
elem = elem.getPrevSibling();
|
||||
@@ -75,15 +85,6 @@ public abstract class GroovyCompletionUtil {
|
||||
return elem;
|
||||
}
|
||||
|
||||
public static boolean isIncomplete(PsiElement element) {
|
||||
while (element != null) {
|
||||
final PsiElement child = element.getLastChild();
|
||||
if (child instanceof PsiErrorElement) return true;
|
||||
element = child;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows wether keyword may be placed asas a new statement beginning
|
||||
*
|
||||
@@ -100,6 +101,7 @@ public abstract class GroovyCompletionUtil {
|
||||
return (previousLeaf == null || SEPARATORS.contains(previousLeaf.getNode().getElementType()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getLeafByOffset(int offset, PsiElement element) {
|
||||
if (offset < 0) {
|
||||
return null;
|
||||
@@ -131,40 +133,25 @@ public abstract class GroovyCompletionUtil {
|
||||
return variableDeclaration.getVariables()[0] == parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks next element after modifier candidate to be appropriate
|
||||
*
|
||||
* @param element
|
||||
* @return
|
||||
*/
|
||||
public static boolean canBeModifier(PsiElement element) {
|
||||
PsiElement next = element.getNextSibling();
|
||||
while (next != null && (next instanceof PsiWhiteSpace ||
|
||||
next instanceof PsiComment)) {
|
||||
next = next.getNextSibling();
|
||||
}
|
||||
return (next == null || SEPARATORS.contains(next.getNode().getElementType()));
|
||||
}
|
||||
|
||||
private static final TokenSet SEPARATORS = TokenSet.create(GroovyElementTypes.mNLS,
|
||||
GroovyElementTypes.mSEMI);
|
||||
GroovyElementTypes.mSEMI);
|
||||
|
||||
public static boolean asSimpleVariable(PsiElement context) {
|
||||
return isInTypeDefinitionBody(context) &&
|
||||
isNewStatement(context, true);
|
||||
isNewStatement(context, true);
|
||||
}
|
||||
|
||||
public static boolean isInTypeDefinitionBody(PsiElement context) {
|
||||
return (context.getParent() instanceof GrCodeReferenceElement &&
|
||||
context.getParent().getParent() instanceof GrClassTypeElement &&
|
||||
context.getParent().getParent().getParent() instanceof GrTypeDefinitionBody) ||
|
||||
context.getParent() instanceof GrTypeDefinitionBody;
|
||||
context.getParent().getParent() instanceof GrClassTypeElement &&
|
||||
context.getParent().getParent().getParent() instanceof GrTypeDefinitionBody) ||
|
||||
context.getParent() instanceof GrTypeDefinitionBody;
|
||||
}
|
||||
|
||||
public static boolean asVariableInBlock(PsiElement context) {
|
||||
if (context.getParent() instanceof GrReferenceExpression &&
|
||||
(context.getParent().getParent() instanceof GrOpenBlock ||
|
||||
context.getParent().getParent() instanceof GrClosableBlock) &&
|
||||
context.getParent().getParent() instanceof GrClosableBlock) &&
|
||||
isNewStatement(context, true)) {
|
||||
return true;
|
||||
}
|
||||
@@ -172,46 +159,54 @@ public abstract class GroovyCompletionUtil {
|
||||
if (context.getParent() instanceof GrReferenceExpression &&
|
||||
context.getParent().getParent() instanceof GrApplicationStatement &&
|
||||
(context.getParent().getParent().getParent() instanceof GrOpenBlock ||
|
||||
context.getParent().getParent().getParent() instanceof GrClosableBlock) &&
|
||||
context.getParent().getParent().getParent() instanceof GrClosableBlock) &&
|
||||
isNewStatement(context, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return context.getParent() instanceof GrTypeDefinitionBody &&
|
||||
isNewStatement(context, true);
|
||||
}
|
||||
|
||||
public static boolean inMemberDeclaration(PsiElement context) {
|
||||
if (context.getParent() instanceof GrReferenceElement &&
|
||||
context.getParent().getParent() instanceof GrTypeElement) {
|
||||
PsiElement parent = context.getParent().getParent().getParent();
|
||||
if (parent instanceof GrMethod || parent instanceof GrVariableDeclaration) {
|
||||
return parent.getParent() instanceof GrTypeDefinitionBody || parent.getParent() instanceof GroovyFile;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
isNewStatement(context, true);
|
||||
}
|
||||
|
||||
public static boolean asTypedMethod(PsiElement context) {
|
||||
return context.getParent() instanceof GrReferenceElement &&
|
||||
context.getParent().getParent() instanceof GrTypeElement &&
|
||||
context.getParent().getParent().getParent() instanceof GrMethod &&
|
||||
context.getParent().getParent().getParent().getParent() instanceof GrTypeDefinitionBody &&
|
||||
context.getTextRange().getStartOffset() == context.getParent().getParent().getParent().getParent().getTextRange().getStartOffset();
|
||||
context.getParent().getParent() instanceof GrTypeElement &&
|
||||
context.getParent().getParent().getParent() instanceof GrMethod &&
|
||||
context.getParent().getParent().getParent().getParent() instanceof GrTypeDefinitionBody &&
|
||||
context.getTextRange().getStartOffset() ==
|
||||
context.getParent().getParent().getParent().getParent().getTextRange().getStartOffset();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static Object[] getCompletionVariants(GroovyResolveResult[] candidates) {
|
||||
Object[] result = new Object[candidates.length];
|
||||
Outer:
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
final PsiElement element = candidates[i].getElement();
|
||||
final PsiElement context = candidates[i].getCurrentFileResolveContext();
|
||||
if (context instanceof GrImportStatement) {
|
||||
final String importedName = ((GrImportStatement) context).getImportedName();
|
||||
if (importedName != null && element != null) {
|
||||
result[i] = LookupElementBuilder.create(element, importedName).setPresentableText(importedName);
|
||||
continue;
|
||||
if (context instanceof GrImportStatement && element != null) {
|
||||
final String importedName = ((GrImportStatement)context).getImportedName();
|
||||
if (importedName != null) {
|
||||
final GrCodeReferenceElement importReference = ((GrImportStatement)context).getImportReference();
|
||||
if (importReference != null) {
|
||||
final GroovyResolveResult[] results = importReference.multiResolve(false);
|
||||
for (GroovyResolveResult r : results) {
|
||||
final PsiElement resolved = r.getElement();
|
||||
if (PsiManager.getInstance(context.getProject()).areElementsEquivalent(resolved, element)) {
|
||||
result[i] = generateLookupForImportedElement(candidates[i], importedName);
|
||||
continue Outer;
|
||||
}
|
||||
else {
|
||||
if (resolved instanceof PsiField && element instanceof PsiMethod && isAccessorFor((PsiMethod)element, (PsiField)resolved)) {
|
||||
result[i] =
|
||||
generateLookupForImportedElement(candidates[i], getAccessorPrefix((PsiMethod)element) + capitalize(importedName));
|
||||
continue Outer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result[i] = element;
|
||||
@@ -220,8 +215,75 @@ public abstract class GroovyCompletionUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static LookupElement setTailTypeForConstructor(PsiClass clazz, LookupElement lookupElement) {
|
||||
return LookupElementDecorator.withInsertHandler(lookupElement, ParenthesesInsertHandler.getInstance(hasConstructorParameters(clazz)));
|
||||
private static LookupElementBuilder generateLookupForImportedElement(GroovyResolveResult resolveResult, String importedName) {
|
||||
final PsiElement element = resolveResult.getElement();
|
||||
assert element != null;
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
LookupElementBuilder builder = LookupElementBuilder.create(element, importedName).setPresentableText(importedName);
|
||||
return setupLookupBuilder(element, substitutor, builder);
|
||||
}
|
||||
|
||||
public static LookupElement getLookupElement(Object o) {
|
||||
if (o instanceof LookupElement) return (LookupElement)o;
|
||||
if (o instanceof PsiNamedElement) return generateLookupElement((PsiNamedElement)o);
|
||||
if (o instanceof PsiElement) return setupLookupBuilder((PsiElement)o, PsiSubstitutor.EMPTY, LookupElementBuilder.create(o, ((PsiElement)o).getText()));
|
||||
return LookupElementBuilder.create(o, o.toString());
|
||||
}
|
||||
public static LookupElementBuilder generateLookupElement(PsiNamedElement element) {
|
||||
LookupElementBuilder builder = LookupElementBuilder.create(element);
|
||||
return setupLookupBuilder(element, PsiSubstitutor.EMPTY, builder);
|
||||
}
|
||||
|
||||
public static LookupElementBuilder setupLookupBuilder(PsiElement element, PsiSubstitutor substitutor, LookupElementBuilder builder) {
|
||||
builder = builder.setIcon(element.getIcon(Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS))
|
||||
.setInsertHandler(new GroovyInsertHandler());
|
||||
builder = setTailText(element, builder, substitutor);
|
||||
builder = setTypeText(element, builder, substitutor);
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static LookupElementBuilder setTailText(PsiElement element, LookupElementBuilder builder, PsiSubstitutor substitutor) {
|
||||
if (element instanceof PsiMethod) {
|
||||
builder = builder.setTailText(PsiFormatUtil.formatMethod((PsiMethod)element, substitutor, PsiFormatUtil.SHOW_PARAMETERS,
|
||||
PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE));
|
||||
}
|
||||
else if (element instanceof PsiClass) {
|
||||
String tailText = getPackageText((PsiClass)element);
|
||||
final PsiClass psiClass = (PsiClass)element;
|
||||
if ((substitutor == null || substitutor.getSubstitutionMap().size() == 0) && psiClass.getTypeParameters().length > 0) {
|
||||
tailText = "<" + StringUtil.join(psiClass.getTypeParameters(), new Function<PsiTypeParameter, String>() {
|
||||
public String fun(PsiTypeParameter psiTypeParameter) {
|
||||
return psiTypeParameter.getName();
|
||||
}
|
||||
}, "," + (showSpaceAfterComma(psiClass) ? " " : "")) + ">" + tailText;
|
||||
}
|
||||
builder = builder.setTailText(tailText, true);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static String getPackageText(PsiClass psiClass) {
|
||||
@NonNls String packageName = PsiFormatUtil.getPackageDisplayName(psiClass);
|
||||
return " (" + packageName + ")";
|
||||
}
|
||||
|
||||
|
||||
private static boolean showSpaceAfterComma(PsiClass element) {
|
||||
return CodeStyleSettingsManager.getSettings(element.getProject()).SPACE_AFTER_COMMA;
|
||||
}
|
||||
|
||||
|
||||
private static LookupElementBuilder setTypeText(PsiElement element, LookupElementBuilder builder, PsiSubstitutor substitutor) {
|
||||
if (element instanceof PsiVariable) {
|
||||
builder = builder.setTypeText(substitutor.substitute(((PsiVariable)element).getType()).getPresentableText());
|
||||
}
|
||||
else if (element instanceof PsiMethod) {
|
||||
final PsiType type = substitutor.substitute(((PsiMethod)element).getReturnType());
|
||||
if (type != null) {
|
||||
builder = builder.setTypeText(type.getPresentableText());
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static boolean hasConstructorParameters(PsiClass clazz) {
|
||||
@@ -233,5 +295,7 @@ public abstract class GroovyCompletionUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static LookupElement setTailTypeForConstructor(PsiClass clazz, LookupElement lookupElement) {
|
||||
return LookupElementDecorator.withInsertHandler(lookupElement, ParenthesesInsertHandler.getInstance(hasConstructorParameters(clazz)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,8 @@ public abstract class TokenSets implements GroovyTokenTypes {
|
||||
kSYNCHRONIZED,
|
||||
kSTRICTFP,
|
||||
kVOLATILE,
|
||||
kSTRICTFP
|
||||
kSTRICTFP,
|
||||
kDEF
|
||||
);
|
||||
|
||||
public static TokenSet STRING_LITERALS = TokenSet.create(
|
||||
|
||||
+1
-1
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.modifiers;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
|
||||
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
|
||||
|
||||
@@ -38,6 +37,7 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
|
||||
* | synchronized
|
||||
* | volatile
|
||||
* | srtictfp
|
||||
* | def
|
||||
*/
|
||||
|
||||
public class Modifier implements GroovyElementTypes {
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ public class Modifiers implements GroovyElementTypes {
|
||||
boolean endsWithNewLine;
|
||||
PsiBuilder.Marker modifiersMarker = builder.mark();
|
||||
|
||||
if (!Annotation.parse(builder, parser) && !Modifier.parse(builder) && !ParserUtils.getToken(builder, kDEF)) {
|
||||
if (!Annotation.parse(builder, parser) && !Modifier.parse(builder)) {
|
||||
modifiersMarker.done(MODIFIERS);
|
||||
return false;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class Modifiers implements GroovyElementTypes {
|
||||
newLineMarker = builder.mark();
|
||||
endsWithNewLine = ParserUtils.getToken(builder, mNLS);
|
||||
|
||||
if (!Annotation.parse(builder, parser) && !Modifier.parse(builder) && !ParserUtils.getToken(builder, kDEF)) break;
|
||||
if (!Annotation.parse(builder, parser) && !Modifier.parse(builder)) break;
|
||||
}
|
||||
|
||||
// Do not include last newline
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ public class ConstructorDefinition implements GroovyElementTypes {
|
||||
return false;
|
||||
}
|
||||
ParserUtils.getToken(builder, mNLS);
|
||||
} while(Annotation.parse(builder, parser) || Modifier.parse(builder) || ParserUtils.getToken(builder, kDEF));
|
||||
} while(Annotation.parse(builder, parser) || Modifier.parse(builder));
|
||||
|
||||
modifiersMarker.done(MODIFIERS);
|
||||
return true;
|
||||
|
||||
+4
-3
@@ -4,12 +4,11 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.lang.psi.api.statements;
|
||||
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMembersDeclaration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
|
||||
/**
|
||||
* @author: Dmitry.Krasilschikov
|
||||
@@ -20,4 +19,6 @@ public interface GrVariableDeclaration extends GrStatement, GrMembersDeclaration
|
||||
GrTypeElement getTypeElementGroovy();
|
||||
|
||||
GrVariable[] getVariables();
|
||||
|
||||
void setType(@Nullable PsiType type);
|
||||
}
|
||||
|
||||
+2
@@ -28,6 +28,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterLi
|
||||
* @author ilyas
|
||||
*/
|
||||
public interface GrClosableBlock extends GrExpression, GrCodeBlock, GrParametersOwner {
|
||||
GrClosableBlock[] EMPTY_ARRAY = new GrClosableBlock[0];
|
||||
|
||||
String GROOVY_LANG_CLOSURE = "groovy.lang.Closure";
|
||||
String OWNER_NAME = "owner";
|
||||
String IT_PARAMETER_NAME = "it";
|
||||
|
||||
+17
-23
@@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTag;
|
||||
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
@@ -59,7 +60,6 @@ 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.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrConstructorImpl;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -136,28 +136,16 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
|
||||
return (GrExpression) ((GroovyFileBase) file).getTopStatements()[0];
|
||||
}
|
||||
|
||||
public GrVariableDeclaration createVariableDeclaration(String[] modifiers, GrExpression initializer, PsiType type, String... identifiers) {
|
||||
public GrVariableDeclaration createVariableDeclaration(String[] modifiers,
|
||||
GrExpression initializer,
|
||||
PsiType type,
|
||||
String... identifiers) {
|
||||
StringBuffer text = writeModifiers(modifiers);
|
||||
|
||||
text.append("def ");
|
||||
if (type != null) {
|
||||
type = TypesUtil.unboxPrimitiveTypeWrapper(type);
|
||||
final String typeText = getTypeText(type);
|
||||
int lastDot = typeText.lastIndexOf('.');
|
||||
int idx = 0 < lastDot && lastDot < typeText.length() - 1 ? lastDot + 1 : 0;
|
||||
if (typeText.length() == 0) {
|
||||
text.append("def ");
|
||||
}
|
||||
else {
|
||||
char c = typeText.charAt(idx);
|
||||
if (!Character.isLetter(c) || Character.isLowerCase(c) && !GroovyNamesUtil.isKeyword(typeText)) { //primitive type
|
||||
text.append("def ");
|
||||
}
|
||||
else {
|
||||
text.append(typeText).append(" ");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
text.append("def ");
|
||||
text.append(typeText).append(" ");
|
||||
}
|
||||
|
||||
for (int i = 0; i < identifiers.length; i++) {
|
||||
@@ -169,19 +157,25 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
|
||||
|
||||
if (initializer != null) {
|
||||
if (initializer instanceof GrApplicationStatement) {
|
||||
expr = createMethodCallByAppCall(((GrApplicationStatement) initializer));
|
||||
} else {
|
||||
expr = createMethodCallByAppCall(((GrApplicationStatement)initializer));
|
||||
}
|
||||
else {
|
||||
expr = initializer;
|
||||
}
|
||||
text.append(" = ").append(expr.getText());
|
||||
}
|
||||
|
||||
PsiFile file = createGroovyFile(text.toString());
|
||||
GrTopStatement[] topStatements = ((GroovyFileBase) file).getTopStatements();
|
||||
GrTopStatement[] topStatements = ((GroovyFileBase)file).getTopStatements();
|
||||
if (topStatements.length == 0 || !(topStatements[0] instanceof GrVariableDeclaration)) {
|
||||
throw new RuntimeException("Invalid arguments, text = " + text.toString());
|
||||
}
|
||||
return (GrVariableDeclaration) topStatements[0];
|
||||
|
||||
final GrVariableDeclaration declaration = (GrVariableDeclaration)topStatements[0];
|
||||
if (declaration.getTypeElementGroovy() != null) {
|
||||
declaration.getModifierList().setModifierProperty(GrModifier.DEF, false);
|
||||
}
|
||||
return declaration;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-3
@@ -92,14 +92,11 @@ public class GrModifierListImpl extends GroovyBaseElementImpl<GrModifierListStub
|
||||
List<PsiElement> modifiers = new ArrayList<PsiElement>();
|
||||
PsiElement[] modifiersKeywords = findChildrenByType(TokenSets.MODIFIERS, PsiElement.class);
|
||||
GrAnnotation[] modifiersAnnotations = findChildrenByClass(GrAnnotation.class);
|
||||
PsiElement defKeyword = findChildByType(GroovyTokenTypes.kDEF);
|
||||
|
||||
if (modifiersKeywords.length != 0) modifiers.addAll(Arrays.asList(modifiersKeywords));
|
||||
|
||||
if (modifiersAnnotations.length != 0) modifiers.addAll(Arrays.asList(modifiersAnnotations));
|
||||
|
||||
if (defKeyword != null) modifiers.add(defKeyword);
|
||||
|
||||
return modifiers.toArray(new PsiElement[modifiers.size()]);
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -48,7 +48,10 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* User: Dmitry.Krasilschikov
|
||||
@@ -121,7 +124,6 @@ public class GrFieldImpl extends GrVariableBaseImpl<GrFieldStub> implements GrFi
|
||||
return ((GroovyFileBase)file).getScriptClass();
|
||||
}
|
||||
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+16
-46
@@ -32,9 +32,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyIcons;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTupleDeclaration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
@@ -186,44 +184,8 @@ public abstract class GrVariableBaseImpl<T extends StubElement> extends GroovyBa
|
||||
}
|
||||
|
||||
public void setType(@Nullable PsiType type) {
|
||||
final GrTypeElement typeElement = getTypeElementGroovy();
|
||||
if (type == null) {
|
||||
if (typeElement == null) return;
|
||||
final ASTNode typeElementNode = typeElement.getNode();
|
||||
final ASTNode parent = typeElementNode.getTreeParent();
|
||||
parent.addLeaf(GroovyTokenTypes.kDEF, GrModifier.DEF, typeElementNode);
|
||||
parent.removeChild(typeElementNode);
|
||||
} else {
|
||||
type = TypesUtil.unboxPrimitiveTypeWrapper(type);
|
||||
GrTypeElement newTypeElement;
|
||||
try {
|
||||
newTypeElement = GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(type);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
final ASTNode newTypeElementNode = newTypeElement.getNode();
|
||||
if (typeElement == null) {
|
||||
final PsiElement defKeyword = findChildByType(GroovyTokenTypes.kDEF);
|
||||
if (defKeyword != null) {
|
||||
final ASTNode defKeywordNode = defKeyword.getNode();
|
||||
assert defKeywordNode != null;
|
||||
defKeywordNode.getTreeParent().removeChild(defKeywordNode);
|
||||
}
|
||||
final PsiElement nameID = getNameIdentifierGroovy();
|
||||
final ASTNode nameIdNode = nameID.getNode();
|
||||
assert nameIdNode != null;
|
||||
nameIdNode.getTreeParent().addChild(newTypeElementNode);
|
||||
} else {
|
||||
final ASTNode typeElementNode = typeElement.getNode();
|
||||
final ASTNode parent = typeElementNode.getTreeParent();
|
||||
parent.replaceChild(typeElementNode, newTypeElementNode);
|
||||
}
|
||||
|
||||
PsiUtil.shortenReferences(newTypeElement);
|
||||
}
|
||||
final GrVariableDeclaration variableDeclaration = getDeclaration();
|
||||
if (variableDeclaration != null) variableDeclaration.setType(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -281,12 +243,8 @@ public abstract class GrVariableBaseImpl<T extends StubElement> extends GroovyBa
|
||||
|
||||
@Nullable
|
||||
public GrModifierList getModifierList() {
|
||||
PsiElement parent = getParent();
|
||||
if (parent instanceof GrVariableDeclaration) {
|
||||
return ((GrVariableDeclaration)parent).getModifierList();
|
||||
} else if (parent instanceof GrTupleDeclaration) {
|
||||
return ((GrVariableDeclaration)parent.getParent()).getModifierList();
|
||||
}
|
||||
final GrVariableDeclaration variableDeclaration = getDeclaration();
|
||||
if (variableDeclaration!=null) return variableDeclaration.getModifierList();
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -299,4 +257,16 @@ public abstract class GrVariableBaseImpl<T extends StubElement> extends GroovyBa
|
||||
return getType();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private GrVariableDeclaration getDeclaration() {
|
||||
PsiElement parent = getParent();
|
||||
if (parent instanceof GrTupleDeclaration) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof GrVariableDeclaration) {
|
||||
return (GrVariableDeclaration)parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+40
-1
@@ -5,14 +5,19 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.statements;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
@@ -22,15 +27,17 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
|
||||
/**
|
||||
* @author: Dmitry.Krasilschikov
|
||||
* @date: 27.03.2007
|
||||
*/
|
||||
public class GrVariableDeclarationImpl extends GroovyPsiElementImpl implements GrVariableDeclaration {
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrVariableDeclarationImpl");
|
||||
|
||||
public GrVariableDeclarationImpl(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
@@ -64,6 +71,38 @@ public class GrVariableDeclarationImpl extends GroovyPsiElementImpl implements G
|
||||
return findChildrenByClass(GrVariable.class);
|
||||
}
|
||||
|
||||
public void setType(@Nullable PsiType type) {
|
||||
final GrTypeElement typeElement = getTypeElementGroovy();
|
||||
if (type == null) {
|
||||
if (typeElement == null) return;
|
||||
getModifierList().setModifierProperty(GrModifier.DEF, true);
|
||||
typeElement.delete();
|
||||
return;
|
||||
}
|
||||
|
||||
type = TypesUtil.unboxPrimitiveTypeWrapper(type);
|
||||
GrTypeElement newTypeElement;
|
||||
try {
|
||||
newTypeElement = GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(type);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeElement == null) {
|
||||
getModifierList().setModifierProperty(GrModifier.DEF, false);
|
||||
final GrVariable[] variables = getVariables();
|
||||
if (variables.length == 0) return;
|
||||
newTypeElement = (GrTypeElement)addBefore(newTypeElement, variables[0]);
|
||||
}
|
||||
else {
|
||||
newTypeElement = (GrTypeElement)typeElement.replace(newTypeElement);
|
||||
}
|
||||
|
||||
PsiUtil.shortenReferences(newTypeElement);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GrTypeElement getTypeElementGroovy() {
|
||||
return findChildByClass(GrTypeElement.class);
|
||||
|
||||
+3
-14
@@ -115,7 +115,6 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume
|
||||
public GrNamedArgument addNamedArgument(final GrNamedArgument namedArgument) {
|
||||
final GrNamedArgument[] namedArguments = getNamedArguments();
|
||||
final GrExpression[] args = getExpressionArguments();
|
||||
final ASTNode newNode = namedArgument.getNode();
|
||||
PsiElement anchor = null;
|
||||
final int namedCount = namedArguments.length;
|
||||
final int exprCount = args.length;
|
||||
@@ -133,24 +132,14 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume
|
||||
anchor = getRightParen();
|
||||
}
|
||||
|
||||
if (anchor != null) {
|
||||
final ASTNode astNode = anchor.getNode();
|
||||
getNode().addChild(newNode, astNode);
|
||||
}
|
||||
else {
|
||||
getNode().addChild(newNode);
|
||||
}
|
||||
|
||||
if (namedCount + exprCount > 0) {
|
||||
getNode().addLeaf(mCOMMA, ",", newNode);
|
||||
}
|
||||
addBefore(namedArgument, anchor);
|
||||
return namedArgument;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException {
|
||||
if (element instanceof GrNamedArgument || element instanceof GrExpression) {
|
||||
if (anchor == null) anchor=getLastChild();
|
||||
if (anchor == null) anchor = getLastChild();
|
||||
if (anchor == null) {
|
||||
return super.addBefore(element, anchor);
|
||||
}
|
||||
@@ -182,9 +171,9 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume
|
||||
else {
|
||||
astNode.addLeaf(mCOMMA, ",", result.getNode());
|
||||
}
|
||||
CodeStyleManager.getInstance(getManager().getProject()).reformat(this);
|
||||
}
|
||||
|
||||
CodeStyleManager.getInstance(getManager().getProject()).reformat(this);
|
||||
return result;
|
||||
}
|
||||
return super.addAfter(element, anchor);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user