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

This commit is contained in:
Kirill Kalishev
2010-06-16 15:05:49 +04:00
172 changed files with 3213 additions and 1446 deletions
+1 -1
View File
@@ -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") {
@@ -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;
}
@@ -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();
}
}
@@ -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) {
@@ -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());
}
}
}
@@ -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) {
@@ -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);
}
@@ -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) {
@@ -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) {
@@ -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
*/
@@ -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);
}
@@ -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);
}
}
@@ -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);
@@ -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));
@@ -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();
}
@@ -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,
@@ -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;
}
@@ -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();
}
}
@@ -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);
}
}
}
@@ -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);
@@ -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);
@@ -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);
@@ -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;
}
@@ -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();
}
+4 -2
View File
@@ -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
@@ -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);
@@ -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);
}
});
}
}
@@ -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;
}
}
}
@@ -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);
});
}
}
@@ -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);
@@ -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);
}
});
@@ -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(
@@ -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 {
@@ -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
@@ -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,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);
}
@@ -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";
@@ -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
@@ -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()]);
}
@@ -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;
}
@@ -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;
}
}
@@ -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);
@@ -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