Snapshot aea001abfc1b38fec3a821bcd5174cc77dc75787 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: Icdea2a2bd7ad43b4d05967b1f0479db3bda1c93c
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
index be2b1d2..f384d72 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
@@ -27,12 +27,17 @@
import com.intellij.compiler.make.CacheUtils;
import com.intellij.compiler.make.ChangedConstantsDependencyProcessor;
import com.intellij.compiler.make.DependencyCache;
+import com.intellij.compiler.options.CompilerConfigurable;
import com.intellij.compiler.progress.CompilerTask;
import com.intellij.compiler.server.BuildManager;
import com.intellij.compiler.server.CustomBuilderMessageHandler;
import com.intellij.compiler.server.DefaultMessageHandler;
import com.intellij.diagnostic.IdeErrorsDialog;
import com.intellij.diagnostic.PluginException;
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationListener;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
import com.intellij.openapi.application.*;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.Compiler;
@@ -48,6 +53,7 @@
import com.intellij.openapi.module.LanguageLevelUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
@@ -102,6 +108,7 @@
import org.jetbrains.jps.api.RequestFuture;
import javax.swing.*;
+import javax.swing.event.HyperlinkEvent;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -639,14 +646,14 @@
final String contentName =
forceCompile ? CompilerBundle.message("compiler.content.name.compile") : CompilerBundle.message("compiler.content.name.make");
- final CompilerTask compileTask = new CompilerTask(myProject, contentName, ApplicationManager.getApplication().isUnitTestMode(), true, true,
- isCompilationStartedAutomatically(scope));
+ final boolean isUnitTestMode = ApplicationManager.getApplication().isUnitTestMode();
+ final CompilerTask compileTask = new CompilerTask(myProject, contentName, isUnitTestMode, true, true, isCompilationStartedAutomatically(scope));
StatusBar.Info.set("", myProject, "Compiler");
if (useExtProcessBuild) {
// ensure the project model seen by build process is up-to-date
myProject.save();
- if (!ApplicationManager.getApplication().isUnitTestMode()) {
+ if (!isUnitTestMode) {
ApplicationManager.getApplication().saveSettings();
}
}
@@ -743,6 +750,12 @@
if (message != null) {
compileContext.addMessage(message);
}
+ else {
+ if (!isUnitTestMode) {
+ notifyDeprecatedImplementation();
+ }
+ }
+
TranslatingCompilerFilesMonitor.getInstance().ensureInitializationCompleted(myProject, compileContext.getProgressIndicator());
doCompile(compileContext, isRebuild, forceCompile, callback, checkCachesVersion);
}
@@ -770,6 +783,25 @@
});
}
+ private void notifyDeprecatedImplementation() {
+ final NotificationListener hyperlinkHandler = new NotificationListener.Adapter() {
+ @Override
+ protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
+ notification.expire();
+ if (!myProject.isDisposed()) {
+ ShowSettingsUtil.getInstance().editConfigurable(myProject, new CompilerConfigurable(myProject));
+ }
+ }
+ };
+ final Notification notification = new Notification(
+ "Compile", "Deprecated make implementation",
+ "Old implementation of \"Make\" feature is enabled for this project.<br>It has been deprecated and will be removed soon.<br>Please enable newer 'external build' feature in <a href=\"#\">Settings | Compiler</a>.",
+ NotificationType.WARNING,
+ hyperlinkHandler
+ );
+ Notifications.Bus.notify(notification, myProject);
+ }
+
@Nullable @TestOnly
public static ExitStatus getExternalBuildExitStatus(CompileContext context) {
return context.getUserData(COMPILE_SERVER_BUILD_STATUS);
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java b/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java
index 320898a..e625dc1 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java
@@ -70,7 +70,7 @@
if (project.isDisposed()) {
return;
}
- final ToolWindow tw = wm.registerToolWindow(PROBLEMS_TOOLWINDOW_ID, false, ToolWindowAnchor.BOTTOM, project);
+ final ToolWindow tw = wm.registerToolWindow(PROBLEMS_TOOLWINDOW_ID, false, ToolWindowAnchor.BOTTOM, project, true);
tw.setIcon(AllIcons.Toolwindows.Problems);
final Content content = ContentFactory.SERVICE.getInstance().createContent(myPanel, "", false);
// todo: setup content?
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
index a9ad726..b0a4969 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
@@ -69,11 +69,13 @@
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.openapi.vfs.newvfs.impl.FileNameCache;
import com.intellij.util.Alarm;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.concurrency.SequentialTaskExecutor;
+import com.intellij.util.containers.IntArrayList;
import com.intellij.util.io.storage.HeavyProcessLatch;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.net.NetUtils;
@@ -391,12 +393,20 @@
synchronized (myProjectDataMap) {
ProjectData data = myProjectDataMap.get(projectPath);
if (data != null && !data.myNeedRescan) {
- return new ArrayList<String>(data.myChanged);
+ return convertToStringPaths(data.myChanged);
}
return null;
}
}
+ private static List<String> convertToStringPaths(final Collection<InternedPath> interned) {
+ final ArrayList<String> list = new ArrayList<String>(interned.size());
+ for (InternedPath path : interned) {
+ list.add(path.getValue());
+ }
+ return list;
+ }
+
@Nullable
private static String getProjectPath(final Project project) {
final String url = project.getPresentableUrl();
@@ -419,7 +429,7 @@
}
private void runAutoMake() {
- final List<RequestFuture> futures = new ArrayList<RequestFuture>();
+ final List<RequestFuture> futures = new SmartList<RequestFuture>();
for (final Project project : getActiveProjects()) {
if (!canStartAutoMake(project)) {
continue;
@@ -472,7 +482,7 @@
}
public Collection<RequestFuture> cancelAutoMakeTasks(Project project) {
- final Collection<RequestFuture> futures = new ArrayList<RequestFuture>();
+ final Collection<RequestFuture> futures = new SmartList<RequestFuture>();
synchronized (myAutomakeFutures) {
for (Map.Entry<RequestFuture, Project> entry : myAutomakeFutures.entrySet()) {
if (entry.getValue().equals(project)) {
@@ -490,11 +500,38 @@
final Project project, final boolean isRebuild, final boolean isMake,
final boolean onlyCheckUpToDate, final List<TargetTypeBuildScope> scopes,
final Collection<String> paths,
- final Map<String, String> userData, final DefaultMessageHandler handler) {
+ final Map<String, String> userData, final DefaultMessageHandler messageHandler) {
final String projectPath = getProjectPath(project);
final UUID sessionId = UUID.randomUUID();
+ final boolean isAutomake = messageHandler instanceof AutoMakeMessageHandler;
+ final BuilderMessageHandler handler = new MessageHandlerWrapper(messageHandler) {
+ @Override
+ public void buildStarted(UUID sessionId) {
+ super.buildStarted(sessionId);
+ try {
+ ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildStarted(project, sessionId, isAutomake);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ }
+ @Override
+ public void sessionTerminated(UUID sessionId) {
+ try {
+ super.sessionTerminated(sessionId);
+ }
+ finally {
+ try {
+ ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildFinished(project, sessionId, isAutomake);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ }
+ }
+ };
// ensure server is listening
if (myListenPort < 0) {
try {
@@ -548,9 +585,9 @@
LOG.info("Scheduling build for " +
projectPath +
"; CHANGED: " +
- new HashSet<String>(data.myChanged) +
+ new HashSet<String>(convertToStringPaths(data.myChanged)) +
"; DELETED: " +
- new HashSet<String>(data.myDeleted));
+ new HashSet<String>(convertToStringPaths(data.myDeleted)));
}
currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent();
projectTaskQueue = data.taskQueue;
@@ -568,7 +605,7 @@
userData, globals, currentFSChanges);
}
- myMessageDispatcher.registerBuildMessageHandler(sessionId, new BuilderMessageHandlerWrapper(handler) {
+ myMessageDispatcher.registerBuildMessageHandler(sessionId, new MessageHandlerWrapper(handler) {
@Override
public void sessionTerminated(UUID sessionId) {
try {
@@ -815,8 +852,8 @@
cmdLine.addParameter("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + debugPort);
}
- if (Registry.is("compiler.process.use.memory.temp.cache")) {
- cmdLine.addParameter("-D"+ GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION);
+ if (!Registry.is("compiler.process.use.memory.temp.cache")) {
+ cmdLine.addParameter("-D"+ GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION + "=false");
}
if (Registry.is("compiler.process.use.external.javac")) {
cmdLine.addParameter("-D"+ GlobalOptions.USE_EXTERNAL_JAVAC_OPTION);
@@ -851,7 +888,7 @@
cp.addAll(myClasspathManager.getBuildProcessPluginsClasspath(project));
if (isProfilingMode) {
cp.add(new File(workDirectory, "yjp-controller-api-redist.jar").getPath());
- cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,sessionname=ExternalBuild");
+ cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,delay=10000,sessionname=ExternalBuild");
}
cmdLine.addParameter("-classpath");
@@ -971,34 +1008,6 @@
return builder.toString();
}
- private static class BuilderMessageHandlerWrapper implements BuilderMessageHandler {
- private final DefaultMessageHandler myHandler;
-
- public BuilderMessageHandlerWrapper(DefaultMessageHandler handler) {
- myHandler = handler;
- }
-
- @Override
- public void buildStarted(UUID sessionId) {
- myHandler.buildStarted(sessionId);
- }
-
- @Override
- public void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg) {
- myHandler.handleBuildMessage(channel, sessionId, msg);
- }
-
- @Override
- public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
- myHandler.handleFailure(sessionId, failure);
- }
-
- @Override
- public void sessionTerminated(UUID sessionId) {
- myHandler.sessionTerminated(sessionId);
- }
- }
-
private static abstract class BuildManagerPeriodicTask implements Runnable {
private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
private final AtomicBoolean myInProgress = new AtomicBoolean(false);
@@ -1107,8 +1116,8 @@
private static class ProjectData {
final SequentialTaskExecutor taskQueue;
- private final Set<String> myChanged = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
- private final Set<String> myDeleted = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
+ private final Set<InternedPath> myChanged = new THashSet<InternedPath>();
+ private final Set<InternedPath> myDeleted = new THashSet<InternedPath>();
private long myNextEventOrdinal = 0L;
private boolean myNeedRescan = true;
@@ -1118,15 +1127,21 @@
public void addChanged(Collection<String> paths) {
if (!myNeedRescan) {
- myDeleted.removeAll(paths);
- myChanged.addAll(paths);
+ for (String path : paths) {
+ final InternedPath _path = InternedPath.create(path);
+ myDeleted.remove(_path);
+ myChanged.add(_path);
+ }
}
}
public void addDeleted(Collection<String> paths) {
if (!myNeedRescan) {
- myChanged.removeAll(paths);
- myDeleted.addAll(paths);
+ for (String path : paths) {
+ final InternedPath _path = InternedPath.create(path);
+ myChanged.remove(_path);
+ myDeleted.add(_path);
+ }
}
}
@@ -1134,10 +1149,17 @@
final CmdlineRemoteProto.Message.ControllerMessage.FSEvent.Builder builder =
CmdlineRemoteProto.Message.ControllerMessage.FSEvent.newBuilder();
builder.setOrdinal(++myNextEventOrdinal);
- builder.addAllChangedPaths(myChanged);
+
+ for (InternedPath path : myChanged) {
+ builder.addChangedPaths(path.getValue());
+ }
myChanged.clear();
- builder.addAllDeletedPaths(myDeleted);
+
+ for (InternedPath path : myDeleted) {
+ builder.addDeletedPaths(path.getValue());
+ }
myDeleted.clear();
+
return builder.build();
}
@@ -1155,4 +1177,84 @@
}
}
+ private static abstract class InternedPath {
+ protected final int[] myPath;
+
+ /**
+ * @param path assuming system-independent path with forward slashes
+ */
+ protected InternedPath(String path) {
+ final IntArrayList list = new IntArrayList();
+ final StringTokenizer tokenizer = new StringTokenizer(path, "/", false);
+ while(tokenizer.hasMoreTokens()) {
+ final String element = tokenizer.nextToken();
+ list.add(FileNameCache.storeName(element));
+ }
+ myPath = list.toArray();
+ }
+
+ public abstract String getValue();
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ InternedPath path = (InternedPath)o;
+
+ if (!Arrays.equals(myPath, path.myPath)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(myPath);
+ }
+
+ public static InternedPath create(String path) {
+ return path.startsWith("/")? new XInternedPath(path) : new WinInternedPath(path);
+ }
+ }
+
+ private static class WinInternedPath extends InternedPath {
+ private WinInternedPath(String path) {
+ super(path);
+ }
+
+ public String getValue() {
+ if (myPath.length == 1) {
+ final String name = FileNameCache.getVFileName(myPath[0]);
+ // handle case of windows drive letter
+ return name.length() == 2 && name.endsWith(":")? name + "/" : name;
+ }
+
+ final StringBuilder buf = new StringBuilder();
+ for (int element : myPath) {
+ if (buf.length() > 0) {
+ buf.append("/");
+ }
+ buf.append(FileNameCache.getVFileName(element));
+ }
+ return buf.toString();
+ }
+ }
+
+ private static class XInternedPath extends InternedPath {
+ private XInternedPath(String path) {
+ super(path);
+ }
+
+ public String getValue() {
+ if (myPath.length > 0) {
+ final StringBuilder buf = new StringBuilder();
+ for (int element : myPath) {
+ buf.append("/").append(FileNameCache.getVFileName(element));
+ }
+ return buf.toString();
+ }
+ return "/";
+ }
+ }
+
}
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManagerListener.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManagerListener.java
new file mode 100644
index 0000000..292e6bd
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManagerListener.java
@@ -0,0 +1,18 @@
+package com.intellij.compiler.server;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.util.messages.Topic;
+
+import java.util.UUID;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 7/3/13
+ */
+public interface BuildManagerListener {
+ Topic<BuildManagerListener> TOPIC = Topic.create("Build Manager", BuildManagerListener.class);
+
+ void buildStarted(Project project, UUID sessionId, boolean isAutomake);
+
+ void buildFinished(Project project, UUID sessionId, boolean isAutomake);
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/MessageHandlerWrapper.java b/java/compiler/impl/src/com/intellij/compiler/server/MessageHandlerWrapper.java
new file mode 100644
index 0000000..a90ff9b
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/server/MessageHandlerWrapper.java
@@ -0,0 +1,38 @@
+package com.intellij.compiler.server;
+
+import org.jboss.netty.channel.Channel;
+import org.jetbrains.jps.api.CmdlineRemoteProto;
+
+import java.util.UUID;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 7/3/13
+*/
+class MessageHandlerWrapper implements BuilderMessageHandler {
+ private final BuilderMessageHandler myHandler;
+
+ public MessageHandlerWrapper(BuilderMessageHandler handler) {
+ myHandler = handler;
+ }
+
+ @Override
+ public void buildStarted(UUID sessionId) {
+ myHandler.buildStarted(sessionId);
+ }
+
+ @Override
+ public void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg) {
+ myHandler.handleBuildMessage(channel, sessionId, msg);
+ }
+
+ @Override
+ public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
+ myHandler.handleFailure(sessionId, failure);
+ }
+
+ @Override
+ public void sessionTerminated(UUID sessionId) {
+ myHandler.sessionTerminated(sessionId);
+ }
+}
diff --git a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java
index 77a13ad..3716f4d 100644
--- a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java
+++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java
@@ -101,7 +101,7 @@
return aClass;
}
- final InputStream is = aClass == null? getClassBytesAsStream(internalName) : null;
+ final InputStream is = aClass == null? getClassBytesStream(internalName) : null;
if (is == null) {
if (aClass == null) {
@@ -132,6 +132,23 @@
public InputStream getClassBytesAsStream(String className) throws IOException {
final String internalName = className.replace('.', '/'); // normalize
+ final PseudoClass aClass = myLoaded.get(internalName);
+ if (aClass == PseudoClass.NULL_OBJ) {
+ return null;
+ }
+ InputStream bytes = null;
+ try {
+ bytes = getClassBytesStream(internalName);
+ }
+ finally {
+ if (aClass == null && bytes == null) {
+ myLoaded.put(internalName, PseudoClass.NULL_OBJ);
+ }
+ }
+ return bytes;
+ }
+
+ private InputStream getClassBytesStream(String internalName) throws IOException {
InputStream is = null;
// first look into platformCp
final String resourceName = internalName + CLASS_RESOURCE_EXTENSION;
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java
index 76f1b79..9ca1bd1 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java
@@ -36,6 +36,7 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -44,12 +45,16 @@
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex;
import com.intellij.psi.jsp.JspFile;
+import com.intellij.psi.search.EverythingGlobalScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.classFilter.ClassFilter;
+import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.StringBuilderSpinAllocator;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.XDebuggerUtil;
import com.sun.jdi.*;
import com.sun.jdi.event.LocatableEvent;
@@ -203,6 +208,37 @@
return true;
}
}
+ if (LOG.isDebugEnabled()) {
+ final GlobalSearchScope scope = debugProcess.getSearchScope();
+ final boolean contains = scope.contains(breakpointFile);
+ final Project project = getProject();
+ final List<VirtualFile> files = ContainerUtil.map(
+ JavaFullClassNameIndex.getInstance().get(className.hashCode(), project, scope), new Function<PsiClass, VirtualFile>() {
+ @Override
+ public VirtualFile fun(PsiClass aClass) {
+ return aClass.getContainingFile().getVirtualFile();
+ }
+ });
+ final List<VirtualFile> allFiles = ContainerUtil.map(
+ JavaFullClassNameIndex.getInstance().get(className.hashCode(), project, new EverythingGlobalScope(project)), new Function<PsiClass, VirtualFile>() {
+ @Override
+ public VirtualFile fun(PsiClass aClass) {
+ return aClass.getContainingFile().getVirtualFile();
+ }
+ });
+ final VirtualFile contentRoot = fileIndex.getContentRootForFile(breakpointFile);
+ final Module module = fileIndex.getModuleForFile(breakpointFile);
+
+ LOG.debug("Did not find '" +
+ className + "' in " + scope +
+ "; contains=" + contains +
+ "; contentRoot=" + contentRoot +
+ "; module = " + module +
+ "; all files in index are: " + files+
+ "; all possible files are: " + allFiles
+ );
+ }
+
return false;
}
}
@@ -218,7 +254,7 @@
public Collection<VirtualFile> compute() {
final PsiClass[] classes = JavaPsiFacade.getInstance(myProject).findClasses(topLevelClassName, scope);
if (LOG.isDebugEnabled()) {
- LOG.debug("Found "+ classes.length + " classes " + topLevelClassName + " in scope");
+ LOG.debug("Found "+ classes.length + " classes " + topLevelClassName + " in scope "+scope);
}
if (classes.length == 0) {
return null;
@@ -241,12 +277,14 @@
LOG.debug(msg.toString());
}
- if (psiFile != null) {
- final VirtualFile vFile = psiFile.getVirtualFile();
- if (vFile != null && fileIndex.isInSourceContent(vFile)) {
- list.add(vFile);
- }
+ if (psiFile == null) {
+ return null;
}
+ final VirtualFile vFile = psiFile.getVirtualFile();
+ if (vFile == null || !fileIndex.isInSourceContent(vFile)) {
+ return null; // this will switch off the check if at least one class is from libraries
+ }
+ list.add(vFile);
}
return list;
}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
index 1dc0610..9fcc7d7 100644
--- a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
@@ -130,7 +130,7 @@
}
}
- public static final int MAX_DISPLAY_LABEL_LENGTH = 1024/*kb*/ *1024 /*bytes*/ / 2; // 1 Mb string
+ public static final int MAX_DISPLAY_LABEL_LENGTH = 1024 * 5;
public static String convertToPresentationString(String str) {
if (str.length() > MAX_DISPLAY_LABEL_LENGTH) {
diff --git a/java/execution/openapi/src/com/intellij/execution/configurations/PatchedRunnableState.java b/java/execution/openapi/src/com/intellij/execution/configurations/PatchedRunnableState.java
index 05d11b7..e09a206 100644
--- a/java/execution/openapi/src/com/intellij/execution/configurations/PatchedRunnableState.java
+++ b/java/execution/openapi/src/com/intellij/execution/configurations/PatchedRunnableState.java
@@ -15,6 +15,6 @@
*/
package com.intellij.execution.configurations;
-public interface PatchedRunnableState extends RunnableState{
+public interface PatchedRunnableState extends RunProfileState {
RunnerSettings getPatcher();
}
\ No newline at end of file
diff --git a/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java b/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java
index d588951..bd92290 100644
--- a/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java
+++ b/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java
@@ -35,6 +35,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.projectImport.ProjectImportProvider;
import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -106,6 +107,15 @@
String description = getFileChooserDescription(project);
descriptor.setDescription(description);
+ return selectFileAndCreateWizard(project, dialogParent, descriptor, providers);
+ }
+
+ @Nullable
+ public static AddModuleWizard selectFileAndCreateWizard(final Project project,
+ @Nullable Component dialogParent,
+ @NotNull FileChooserDescriptor descriptor,
+ ProjectImportProvider[] providers)
+ {
FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, project, dialogParent);
VirtualFile toSelect = null;
String lastLocation = PropertiesComponent.getInstance().getValue(LAST_IMPORTED_LOCATION);
@@ -151,7 +161,7 @@
}
public static AddModuleWizard createImportWizard(final Project project,
- Component dialogParent,
+ @Nullable Component dialogParent,
final VirtualFile file,
ProjectImportProvider... providers) {
List<ProjectImportProvider> available = ContainerUtil.filter(providers, new Condition<ProjectImportProvider>() {
diff --git a/java/idea-ui/src/com/intellij/ide/actions/ShowStructureSettingsAction.java b/java/idea-ui/src/com/intellij/ide/actions/ShowStructureSettingsAction.java
index 81e4729..777105f 100644
--- a/java/idea-ui/src/com/intellij/ide/actions/ShowStructureSettingsAction.java
+++ b/java/idea-ui/src/com/intellij/ide/actions/ShowStructureSettingsAction.java
@@ -15,20 +15,15 @@
*/
package com.intellij.ide.actions;
-import com.intellij.facet.Facet;
-import com.intellij.facet.FacetManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.options.newEditor.OptionsEditorDialog;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
-import com.intellij.openapi.ui.Messages;
public class ShowStructureSettingsAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
@@ -37,37 +32,6 @@
project = ProjectManager.getInstance().getDefaultProject();
}
- // TEMPORARY HACK! DO NOT MERGE INTO INTELLIJ. This just works around a lot
- // of confusion caused by the fact that the structure dialog lets you edit
- // project state which is ignored by gradle, so temporarily disable this
- // dialog for Android-Gradle-based projects.
- if (isGradleProject(project)) {
- showDisabledProjectStructureDialogMessage();
- }
-
ShowSettingsUtil.getInstance().editConfigurable(project, OptionsEditorDialog.DIMENSION_KEY, ProjectStructureConfigurable.getInstance(project));
}
-
- public static void showDisabledProjectStructureDialogMessage() {
- Messages.showWarningDialog(
- "We will provide a UI to configure project settings later. " +
- "Until then, please manually edit your build.gradle file to " +
- "configure source folders, libraries and dependencies.\n\n" +
- "NOTE THAT EDITS MADE IN THE FOLLOWING DIALOG DO NOT AFFECT THE GRADLE BUILD.\n" +
- "The dialog can be used for temporary adjustments to SDKs etc.",
- "Project Structure");
- }
-
- public static boolean isGradleProject(Project project) {
- ModuleManager moduleManager = ModuleManager.getInstance(project);
- for (Module module : moduleManager.getModules()) {
- FacetManager facetManager = FacetManager.getInstance(module);
- for (Facet facet : facetManager.getAllFacets()) {
- if ("android-gradle".equals(facet.getType().getStringId())) {
- return true;
- }
- }
- }
- return false;
- }
}
\ No newline at end of file
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddModuleWizard.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddModuleWizard.java
index 167b861..2cb74deb 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddModuleWizard.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddModuleWizard.java
@@ -89,7 +89,7 @@
}
/** Import mode */
- public AddModuleWizard(Project project, String filePath, ProjectImportProvider... importProviders) {
+ public AddModuleWizard(@Nullable Project project, String filePath, ProjectImportProvider... importProviders) {
super(getImportWizardTitle(project, importProviders), project);
myCurrentProject = project;
myImportProviders = importProviders;
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
index cfdcf81..13b4fcd 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
@@ -156,7 +156,16 @@
@Override
public String getHelpId() {
- return myWizardContext.isCreatingNewProject() ? "New_Project_Main_Settings" : "Add_Module_Main_Settings";
+ String helpId = myWizardContext.isCreatingNewProject() ? "New_Project_Main_Settings" : "Add_Module_Main_Settings";
+ ProjectTemplate projectTemplate = getSelectedTemplate();
+ if (projectTemplate instanceof WebProjectTemplate) {
+ WebProjectTemplate webProjectTemplate = (WebProjectTemplate) projectTemplate;
+ String subHelpId = webProjectTemplate.getHelpId();
+ if (subHelpId != null) {
+ helpId = helpId + ":" + subHelpId;
+ }
+ }
+ return helpId;
}
private static NamePathComponent initNamePathComponent(WizardContext context) {
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/IdeaProjectSettingsService.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/IdeaProjectSettingsService.java
index 612399a..e654eab 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/IdeaProjectSettingsService.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/IdeaProjectSettingsService.java
@@ -16,7 +16,6 @@
package com.intellij.openapi.roots.ui.configuration;
import com.intellij.compiler.actions.ArtifactAwareProjectSettingsService;
-import com.intellij.ide.actions.ShowStructureSettingsAction;
import com.intellij.ide.projectView.impl.ModuleGroup;
import com.intellij.ide.util.projectWizard.JdkChooserPanel;
import com.intellij.openapi.module.Module;
@@ -66,7 +65,6 @@
@Override
public void openLibrary(@NotNull final Library library) {
- warnIfGradleProject();
final ProjectStructureConfigurable config = ProjectStructureConfigurable.getInstance(myProject);
ShowSettingsUtil.getInstance().editConfigurable(myProject, config, new Runnable() {
@Override
@@ -83,7 +81,6 @@
@Override
public void openModuleSettings(final Module module) {
- warnIfGradleProject();
ModulesConfigurator.showDialog(myProject, module.getName(), null);
}
@@ -94,7 +91,6 @@
@Override
public void openModuleLibrarySettings(final Module module) {
- warnIfGradleProject();
ModulesConfigurator.showDialog(myProject, module.getName(), ClasspathEditor.NAME);
}
@@ -105,7 +101,6 @@
@Override
public void openContentEntriesSettings(final Module module) {
- warnIfGradleProject();
ModulesConfigurator.showDialog(myProject, module.getName(), ContentEntriesEditor.NAME);
}
@@ -116,7 +111,6 @@
@Override
public void openModuleDependenciesSettings(@NotNull final Module module, @Nullable final OrderEntry orderEntry) {
- warnIfGradleProject();
ShowSettingsUtil.getInstance().editConfigurable(myProject, ProjectStructureConfigurable.getInstance(myProject), new Runnable() {
@Override
public void run() {
@@ -132,7 +126,6 @@
@Override
public void openLibraryOrSdkSettings(@NotNull final OrderEntry orderEntry) {
- warnIfGradleProject();
final ProjectStructureConfigurable config = ProjectStructureConfigurable.getInstance(myProject);
ShowSettingsUtil.getInstance().editConfigurable(myProject, config, new Runnable() {
@Override
@@ -173,14 +166,6 @@
@Override
public void openArtifactSettings(@Nullable Artifact artifact) {
- warnIfGradleProject();
ModulesConfigurator.showArtifactSettings(myProject, artifact);
}
-
- // TEMPORARY HACK!! REMOVE ME ASAP!
- private void warnIfGradleProject() {
- if (ShowStructureSettingsAction.isGradleProject(myProject)) {
- ShowStructureSettingsAction.showDisabledProjectStructureDialogMessage();
- }
- }
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
index 356eddb..d78731b 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
@@ -172,7 +172,7 @@
}
});
actions.add(new MyActionGroupWrapper(group));
- actions.add(new MyDeleteAction(forAll(Conditions.alwaysTrue())));
+ actions.add(new MyDeleteAction(Conditions.<Object[]>alwaysTrue()));
return actions;
}
diff --git a/java/idea-ui/src/com/intellij/platform/templates/LocalArchivedTemplate.java b/java/idea-ui/src/com/intellij/platform/templates/LocalArchivedTemplate.java
index 1b9f3c2..f671335 100644
--- a/java/idea-ui/src/com/intellij/platform/templates/LocalArchivedTemplate.java
+++ b/java/idea-ui/src/com/intellij/platform/templates/LocalArchivedTemplate.java
@@ -19,6 +19,7 @@
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleTypeManager;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.JDOMUtil;
@@ -43,8 +44,8 @@
*/
public class LocalArchivedTemplate extends ArchivedProjectTemplate {
- public static final String DESCRIPTION_PATH = ".idea/description.html";
- static final String IDEA_INPUT_FIELDS_XML = ".idea/project-template.xml";
+ public static final String DESCRIPTION_PATH = Project.DIRECTORY_STORE_FOLDER + "/description.html";
+ static final String IDEA_INPUT_FIELDS_XML = Project.DIRECTORY_STORE_FOLDER + "/project-template.xml";
private final URL myArchivePath;
private final ModuleType myModuleType;
diff --git a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java
index e6cb2a3..54c0b7c 100644
--- a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java
+++ b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java
@@ -162,7 +162,7 @@
if (relativePath == null) {
throw new RuntimeException("Can't find relative path for " + virtualFile);
}
- final boolean system = ".idea".equals(virtualFile.getParent().getName());
+ final boolean system = Project.DIRECTORY_STORE_FOLDER.equals(virtualFile.getParent().getName());
if (system) {
if (!fileName.equals("description.html") &&
!fileName.equals(PROJECT_TEMPLATE_XML) &&
diff --git a/java/idea-ui/src/com/intellij/platform/templates/SystemFileProcessor.java b/java/idea-ui/src/com/intellij/platform/templates/SystemFileProcessor.java
index f57c954..29f21b4 100644
--- a/java/idea-ui/src/com/intellij/platform/templates/SystemFileProcessor.java
+++ b/java/idea-ui/src/com/intellij/platform/templates/SystemFileProcessor.java
@@ -53,7 +53,7 @@
@Override
protected String encodeFileText(String content, VirtualFile file, Project project) throws IOException {
final String fileName = file.getName();
- if (file.getParent().getName().equals(".idea") && fileName.equals("workspace.xml")) {
+ if (file.getParent().getName().equals(Project.DIRECTORY_STORE_FOLDER) && fileName.equals("workspace.xml")) {
List<Object> componentList = new ArrayList<Object>();
for (String componentName : COMPONENT_NAMES) {
diff --git a/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java b/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java
index 61bf78f..4b0727a 100644
--- a/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java
+++ b/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java
@@ -205,7 +205,7 @@
@Nullable
@Override
public String fun(String path) {
- if (moduleMode && path.contains(".idea")) return null;
+ if (moduleMode && path.contains(Project.DIRECTORY_STORE_FOLDER)) return null;
if (basePackage != null) {
return path.replace(getPathFragment(basePackage.getDefaultValue()), getPathFragment(basePackage.getValue()));
}
@@ -218,7 +218,7 @@
FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(FileUtilRt.getExtension(file.getName()));
return fileType.isBinary() ? content : processTemplates(projectName, new String(content), file);
}
- });
+ }, true);
String iml = ContainerUtil.find(dir.list(), new Condition<String>() {
@Override
public boolean value(String s) {
diff --git a/java/idea-ui/src/com/intellij/projectImport/ProjectFormatPanel.java b/java/idea-ui/src/com/intellij/projectImport/ProjectFormatPanel.java
index e367ce7..9b7795d 100644
--- a/java/idea-ui/src/com/intellij/projectImport/ProjectFormatPanel.java
+++ b/java/idea-ui/src/com/intellij/projectImport/ProjectFormatPanel.java
@@ -23,13 +23,14 @@
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.components.StorageScheme;
+import com.intellij.openapi.project.Project;
import javax.swing.*;
public class ProjectFormatPanel {
private static final String STORAGE_FORMAT_PROPERTY = "default.storage.format";
- public static final String DIR_BASED = ".idea (directory based)";
+ public static final String DIR_BASED = Project.DIRECTORY_STORE_FOLDER + " (directory based)";
private static final String FILE_BASED = ".ipr (file based)";
private JComboBox myStorageFormatCombo;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableUtil.java
index 4515cc8..dd32cd0 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableUtil.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PropertyUtil;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import gnu.trove.THashSet;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java
index e4c583d..08bb341 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java
@@ -19,8 +19,10 @@
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
+import com.intellij.psi.impl.source.tree.ChildRole;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -67,8 +69,11 @@
LOG.assertTrue(classReference != null);
final PsiReferenceParameterList parameterList = classReference.getParameterList();
LOG.assertTrue(parameterList != null);
- holder.registerProblem(parameterList, "Explicit type argument #ref #loc can be replaced with <>",
- ProblemHighlightType.LIKE_UNUSED_SYMBOL, new ReplaceWithDiamondFix());
+ final PsiElement firstChild = parameterList.getFirstChild();
+ final PsiElement lastChild = parameterList.getLastChild();
+ final TextRange range = new TextRange(firstChild != null && firstChild.getNode().getElementType() == JavaTokenType.LT ? 1 : 0,
+ parameterList.getTextLength() - (lastChild != null && lastChild.getNode().getElementType() == JavaTokenType.GT ? 1 : 0));
+ holder.registerProblem(parameterList, "Explicit type argument #ref #loc can be replaced with <>", ProblemHighlightType.LIKE_UNUSED_SYMBOL, range, new ReplaceWithDiamondFix());
}
}
};
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
index 369f6ec..2dd724f 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
@@ -29,6 +29,7 @@
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -38,6 +39,7 @@
class ControlFlowAnalyzer extends JavaElementVisitor {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer");
private static final int NOT_FOUND = -10;
+ private boolean myIgnoreAssertions;
private static class CannotAnalyzeException extends RuntimeException { }
@@ -54,9 +56,8 @@
myFactory = valueFactory;
}
- public ControlFlow buildControlFlow(PsiElement codeFragment) {
- if (codeFragment == null) return null;
-
+ public ControlFlow buildControlFlow(@NotNull PsiElement codeFragment, boolean ignoreAssertions) {
+ myIgnoreAssertions = ignoreAssertions;
PsiManager manager = codeFragment.getManager();
GlobalSearchScope scope = codeFragment.getResolveScope();
myRuntimeException = myFactory.getNotNullFactory().create(PsiType.getJavaLangRuntimeException(manager, scope));
@@ -203,6 +204,10 @@
}
@Override public void visitAssertStatement(PsiAssertStatement statement) {
+ if (myIgnoreAssertions) {
+ return;
+ }
+
startElement(statement);
final PsiExpression condition = statement.getAssertCondition();
final PsiExpression description = statement.getAssertDescription();
@@ -654,7 +659,6 @@
PsiType type = cd.getLubType();
if (type instanceof PsiClassType && ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType)type)) {
addConditionalRuntimeThrow(cd, true);
- break;
}
}
}
@@ -1595,15 +1599,16 @@
return null;
}
- PsiVariable var = resolveToVariable(refExpr);
+ PsiElement target = refExpr.resolve();
+ PsiVariable var = getAccessedVariable(target);
if (var == null) {
return null;
}
- boolean isCall = expression instanceof PsiMethodCallExpression;
+ PsiMethod accessMethod = target instanceof PsiMethod ? (PsiMethod)target : null;
PsiExpression qualifier = refExpr.getQualifierExpression();
if (qualifier == null) {
- DfaVariableValue result = myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, null, isCall);
+ DfaVariableValue result = myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, null, accessMethod);
if (var instanceof PsiField) {
myFields.add(result);
}
@@ -1613,15 +1618,14 @@
if (DfaPsiUtil.isFinalField(var) || DfaPsiUtil.isPlainMutableField(var)) {
DfaVariableValue qualifierValue = createChainedVariableValue(qualifier);
if (qualifierValue != null) {
- return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, qualifierValue, isCall || qualifierValue.isViaMethods());
+ return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, qualifierValue, accessMethod);
}
}
return null;
}
@Nullable
- private static PsiVariable resolveToVariable(PsiReferenceExpression refExpr) {
- PsiElement target = refExpr.resolve();
+ private static PsiVariable getAccessedVariable(final PsiElement target) {
if (target instanceof PsiVariable) {
return (PsiVariable)target;
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
index 391fa1b..a5028fc 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
@@ -35,6 +35,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.WriteExternalException;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -42,6 +43,7 @@
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SmartList;
+import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,6 +56,7 @@
@NonNls private static final String SHORT_NAME = "ConstantConditions";
public boolean SUGGEST_NULLABLE_ANNOTATIONS = false;
public boolean DONT_REPORT_TRUE_ASSERT_STATEMENTS = false;
+ public boolean IGNORE_ASSERT_STATEMENTS = false;
@Override
public JComponent createOptionsPanel() {
@@ -61,6 +64,15 @@
}
@Override
+ public void writeSettings(@NotNull Element node) throws WriteExternalException {
+ node.addContent(new Element("option").setAttribute("name", "SUGGEST_NULLABLE_ANNOTATIONS").setAttribute("value", String.valueOf(SUGGEST_NULLABLE_ANNOTATIONS)));
+ node.addContent(new Element("option").setAttribute("name", "DONT_REPORT_TRUE_ASSERT_STATEMENTS").setAttribute("value", String.valueOf(DONT_REPORT_TRUE_ASSERT_STATEMENTS)));
+ if (IGNORE_ASSERT_STATEMENTS) {
+ node.addContent(new Element("option").setAttribute("name", "IGNORE_ASSERT_STATEMENTS").setAttribute("value", "true"));
+ }
+ }
+
+ @Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new JavaElementVisitor() {
@@ -85,7 +97,7 @@
if (scope == null) return;
final StandardDataFlowRunner dfaRunner = new StandardDataFlowRunner(SUGGEST_NULLABLE_ANNOTATIONS);
final StandardInstructionVisitor visitor = new DataFlowInstructionVisitor(dfaRunner);
- final RunnerResult rc = dfaRunner.analyzeMethod(scope, visitor);
+ final RunnerResult rc = dfaRunner.analyzeMethod(scope, visitor, IGNORE_ASSERT_STATEMENTS);
if (rc == RunnerResult.OK) {
if (dfaRunner.problemsDetected(visitor)) {
createDescription(dfaRunner, holder, visitor);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
index 4e30cdd..a01901c 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
@@ -91,11 +91,15 @@
}
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, InstructionVisitor visitor) {
+ return analyzeMethod(psiBlock, visitor, false);
+ }
+
+ public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, InstructionVisitor visitor, boolean ignoreAssertions) {
try {
final Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor);
if (initialStates == null) return RunnerResult.NOT_APPLICABLE;
- final ControlFlow flow = createControlFlowAnalyzer().buildControlFlow(psiBlock);
+ final ControlFlow flow = createControlFlowAnalyzer().buildControlFlow(psiBlock, ignoreAssertions);
if (flow == null) return RunnerResult.NOT_APPLICABLE;
int endOffset = flow.getInstructionCount();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
index dcc4a3f..1ea146e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
@@ -136,7 +136,7 @@
}
if (!variable.hasModifierProperty(PsiModifier.VOLATILE) && isEffectivelyUnqualified(referenceExpression)) {
- return getVarFactory().createVariableValue(variable, referenceExpression.getType(), false, null, false);
+ return getVarFactory().createVariableValue(variable, referenceExpression.getType(), false, null, null);
}
return null;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
index 39541bf..695c0e6 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
@@ -49,15 +49,15 @@
}
public DfaVariableValue createVariableValue(PsiVariable myVariable, boolean isNegated) {
- return createVariableValue(myVariable, myVariable.getType(), isNegated, null, false);
+ return createVariableValue(myVariable, myVariable.getType(), isNegated, null, null);
}
@NotNull
public DfaVariableValue createVariableValue(PsiVariable myVariable,
- @Nullable PsiType varType, boolean isNegated, @Nullable DfaVariableValue qualifier, boolean viaMethods) {
+ @Nullable PsiType varType, boolean isNegated, @Nullable DfaVariableValue qualifier, @Nullable PsiMethod accessMethod) {
mySharedInstance.myVariable = myVariable;
mySharedInstance.myIsNegated = isNegated;
mySharedInstance.myQualifier = qualifier;
- mySharedInstance.myViaMethods = viaMethods;
+ mySharedInstance.myAccessMethod = accessMethod;
String id = mySharedInstance.toString();
ArrayList<DfaVariableValue> conditions = myStringToObject.get(id);
@@ -71,7 +71,7 @@
}
}
- DfaVariableValue result = new DfaVariableValue(myVariable, varType, isNegated, myFactory, qualifier, viaMethods);
+ DfaVariableValue result = new DfaVariableValue(myVariable, varType, isNegated, myFactory, qualifier, accessMethod);
if (qualifier != null) {
myQualifiersToChainedVariables.putValue(qualifier, result);
}
@@ -92,18 +92,18 @@
private PsiVariable myVariable;
private PsiType myVarType;
+ private PsiMethod myAccessMethod;
@Nullable private DfaVariableValue myQualifier;
private boolean myIsNegated;
- private boolean myViaMethods;
private Nullness myInherentNullability;
- private DfaVariableValue(PsiVariable variable, PsiType varType, boolean isNegated, DfaValueFactory factory, @Nullable DfaVariableValue qualifier, boolean viaMethods) {
+ private DfaVariableValue(PsiVariable variable, PsiType varType, boolean isNegated, DfaValueFactory factory, @Nullable DfaVariableValue qualifier, PsiMethod accessMethod) {
super(factory);
myVariable = variable;
myIsNegated = isNegated;
myQualifier = qualifier;
- myViaMethods = viaMethods;
myVarType = varType;
+ myAccessMethod = accessMethod;
}
private DfaVariableValue(DfaValueFactory factory) {
@@ -128,7 +128,7 @@
@Override
public DfaVariableValue createNegated() {
- return myFactory.getVarFactory().createVariableValue(myVariable, myVarType, !myIsNegated, myQualifier, myViaMethods);
+ return myFactory.getVarFactory().createVariableValue(myVariable, myVarType, !myIsNegated, myQualifier, myAccessMethod);
}
@SuppressWarnings({"HardCodedStringLiteral"})
@@ -140,7 +140,7 @@
private boolean hardEquals(DfaVariableValue aVar) {
return aVar.myVariable == myVariable &&
aVar.myIsNegated == myIsNegated &&
- aVar.myViaMethods == myViaMethods &&
+ aVar.myAccessMethod == myAccessMethod &&
(myQualifier == null ? aVar.myQualifier == null : myQualifier.hardEquals(aVar.myQualifier));
}
@@ -150,7 +150,7 @@
}
public boolean isViaMethods() {
- return myViaMethods;
+ return myAccessMethod != null || myQualifier != null && myQualifier.isViaMethods();
}
public Nullness getInherentNullability() {
@@ -158,19 +158,32 @@
return myInherentNullability;
}
+ return myInherentNullability = calcInherentNullability();
+ }
+
+ private Nullness calcInherentNullability() {
+ PsiMethod accessMethod = myAccessMethod;
+ Nullness nullability = DfaPsiUtil.getElementNullability(getVariableType(), accessMethod);
+ if (nullability != Nullness.UNKNOWN) {
+ return nullability;
+ }
+
PsiVariable var = getPsiVariable();
- Nullness nullability = DfaPsiUtil.getElementNullability(getVariableType(), var);
- if (nullability == Nullness.UNKNOWN && var != null) {
+ nullability = DfaPsiUtil.getElementNullability(getVariableType(), var);
+ if (nullability != Nullness.UNKNOWN) {
+ return nullability;
+ }
+
+ if (var != null) {
if (DfaPsiUtil.isNullableInitialized(var, true)) {
- nullability = Nullness.NULLABLE;
- } else if (DfaPsiUtil.isNullableInitialized(var, false)) {
- nullability = Nullness.NOT_NULL;
+ return Nullness.NULLABLE;
+ }
+ if (DfaPsiUtil.isNullableInitialized(var, false)) {
+ return Nullness.NOT_NULL;
}
}
- myInherentNullability = nullability;
-
- return nullability;
+ return Nullness.UNKNOWN;
}
public boolean isLocalVariable() {
diff --git a/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.java b/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.java
index 44ccf49..aebfb44 100644
--- a/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.java
+++ b/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.java
@@ -18,8 +18,10 @@
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ToolbarDecorator;
@@ -230,18 +232,18 @@
reset(mySettings);
}
- public void apply(CodeStyleSettings settings) {
+ public void apply(CodeStyleSettings settings) throws ConfigurationException {
settings.PREFER_LONGER_NAMES = myCbPreferLongerNames.isSelected();
- settings.FIELD_NAME_PREFIX = myFieldPrefixField.getText().trim();
- settings.STATIC_FIELD_NAME_PREFIX = myStaticFieldPrefixField.getText().trim();
- settings.PARAMETER_NAME_PREFIX = myParameterPrefixField.getText().trim();
- settings.LOCAL_VARIABLE_NAME_PREFIX = myLocalVariablePrefixField.getText().trim();
+ settings.FIELD_NAME_PREFIX = setPrefixSuffix(myFieldPrefixField.getText(), true);
+ settings.STATIC_FIELD_NAME_PREFIX = setPrefixSuffix(myStaticFieldPrefixField.getText(), true);
+ settings.PARAMETER_NAME_PREFIX = setPrefixSuffix(myParameterPrefixField.getText(), true);
+ settings.LOCAL_VARIABLE_NAME_PREFIX = setPrefixSuffix(myLocalVariablePrefixField.getText(), true);
- settings.FIELD_NAME_SUFFIX = myFieldSuffixField.getText().trim();
- settings.STATIC_FIELD_NAME_SUFFIX = myStaticFieldSuffixField.getText().trim();
- settings.PARAMETER_NAME_SUFFIX = myParameterSuffixField.getText().trim();
- settings.LOCAL_VARIABLE_NAME_SUFFIX = myLocalVariableSuffixField.getText().trim();
+ settings.FIELD_NAME_SUFFIX = setPrefixSuffix(myFieldSuffixField.getText(), false);
+ settings.STATIC_FIELD_NAME_SUFFIX = setPrefixSuffix(myStaticFieldSuffixField.getText(), false);
+ settings.PARAMETER_NAME_SUFFIX = setPrefixSuffix(myParameterSuffixField.getText(), false);
+ settings.LOCAL_VARIABLE_NAME_SUFFIX = setPrefixSuffix(myLocalVariableSuffixField.getText(), false);
settings.LINE_COMMENT_AT_FIRST_COLUMN = myCbLineCommentAtFirstColumn.isSelected();
settings.BLOCK_COMMENT_AT_FIRST_COLUMN = myCbBlockCommentAtFirstColumn.isSelected();
@@ -260,7 +262,16 @@
}
}
- public void apply() {
+ private static String setPrefixSuffix(String text, boolean prefix) throws ConfigurationException {
+ text = text.trim();
+ if (text.isEmpty()) return text;
+ if (!StringUtil.isJavaIdentifier(text)) {
+ throw new ConfigurationException("Not a valid java identifier part in " + (prefix ? "prefix" : "suffix") + " \'" + text + "\'");
+ }
+ return text;
+ }
+
+ public void apply() throws ConfigurationException {
apply(mySettings);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypeInfo.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypeInfo.java
index 650a6b0..7fe0abc 100644
--- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypeInfo.java
+++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypeInfo.java
@@ -44,9 +44,5 @@
ExpectedTypeInfo[] intersect(ExpectedTypeInfo info);
- boolean isArrayTypeInfo();
-
TailType getTailType();
-
- boolean isInsertExplicitTypeParams();
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypeInfoImpl.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypeInfoImpl.java
index 0751887..619b647 100644
--- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypeInfoImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypeInfoImpl.java
@@ -28,13 +28,6 @@
private final PsiType type;
private final PsiType defaultType;
- private boolean myInsertExplicitTypeParams;
-
- int getDimCount() {
- return dimCount;
- }
-
- private final int dimCount;
@Override
public int getKind() {
@@ -59,29 +52,11 @@
private PsiMethod myCalledMethod;
- public ExpectedTypeInfoImpl(@NotNull PsiType type, int kind, int dimCount, @NotNull PsiType defaultType, @NotNull TailType myTailType) {
+ public ExpectedTypeInfoImpl(@NotNull PsiType type, int kind, @NotNull PsiType defaultType, @NotNull TailType myTailType) {
this.type = type;
this.kind = kind;
this.myTailType = myTailType;
- this.dimCount = dimCount;
-
- if (type == defaultType && type instanceof PsiClassType) {
- final PsiClassType psiClassType = (PsiClassType)type;
- final PsiClass psiClass = psiClassType.resolve();
- if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
- final PsiType[] parameters = psiClassType.getParameters();
- PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
- if (parameters.length == 1 && parameters[0] instanceof PsiWildcardType && typeParameters.length == 1) {
- final PsiType bound = ((PsiWildcardType)parameters[0]).getExtendsBound();
- if (bound instanceof PsiClassType) {
- defaultType = JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory()
- .createType(psiClass, PsiSubstitutor.EMPTY.put(typeParameters[0], bound));
- }
- }
- }
- }
-
this.defaultType = defaultType;
PsiUtil.ensureValidType(type);
@@ -100,30 +75,13 @@
@Override
@NotNull
public PsiType getType () {
- PsiType t = type;
- int dims = dimCount;
-
- while (dims-- > 0) t = t.createArrayType();
- return t;
+ return type;
}
@Override
@NotNull
public PsiType getDefaultType () {
- PsiType t = defaultType;
- int dims = dimCount;
-
- while (dims-- > 0) t = t.createArrayType();
- return t;
- }
-
- @Override
- public boolean isInsertExplicitTypeParams() {
- return myInsertExplicitTypeParams;
- }
-
- public void setInsertExplicitTypeParams(final boolean insertExplicitTypeParams) {
- this.myInsertExplicitTypeParams = insertExplicitTypeParams;
+ return defaultType;
}
public boolean equals(final Object o) {
@@ -132,20 +90,18 @@
final ExpectedTypeInfoImpl that = (ExpectedTypeInfoImpl)o;
- if (dimCount != that.dimCount) return false;
if (kind != that.kind) return false;
- if (defaultType != null ? !defaultType.equals(that.defaultType) : that.defaultType != null) return false;
+ if (!defaultType.equals(that.defaultType)) return false;
if (myTailType != null ? !myTailType.equals(that.myTailType) : that.myTailType != null) return false;
- if (type != null ? !type.equals(that.type) : that.type != null) return false;
+ if (!type.equals(that.type)) return false;
return true;
}
public int hashCode() {
int result;
- result = (type != null ? type.hashCode() : 0);
- result = 31 * result + (defaultType != null ? defaultType.hashCode() : 0);
- result = 31 * result + dimCount;
+ result = (type.hashCode());
+ result = 31 * result + (defaultType.hashCode());
result = 31 * result + kind;
result = 31 * result + (myTailType != null ? myTailType.hashCode() : 0);
return result;
@@ -158,17 +114,15 @@
@SuppressWarnings({"HardCodedStringLiteral"})
public String toString() {
- return "ExpectedTypeInfo[type='" + type + "' kind='" + kind + "' dims='" + dimCount+ "']";
+ return "ExpectedTypeInfo[type='" + type + "' kind='" + kind + "']";
}
@Override
public ExpectedTypeInfo[] intersect(ExpectedTypeInfo info) {
ExpectedTypeInfoImpl info1 = (ExpectedTypeInfoImpl)info;
- LOG.assertTrue(!(type instanceof PsiArrayType) && !(info1.type instanceof PsiArrayType));
if (kind == TYPE_STRICTLY) {
if (info1.kind == TYPE_STRICTLY) {
- if (dimCount != info1.dimCount) return ExpectedTypeInfo.EMPTY_ARRAY;
if (info1.type.equals(type)) return new ExpectedTypeInfoImpl[] {this};
}
else {
@@ -177,12 +131,10 @@
}
else if (kind == TYPE_OR_SUBTYPE) {
if (info1.kind == TYPE_STRICTLY) {
- if (dimCount != info1.dimCount) return ExpectedTypeInfo.EMPTY_ARRAY;
if (type.isAssignableFrom(info1.type)) return new ExpectedTypeInfoImpl[] {info1};
}
else if (info1.kind == TYPE_OR_SUBTYPE) {
- PsiType type = dimCount == info1.dimCount ? this.type : getType();
- PsiType otherType = dimCount == info1.dimCount ? info1.type : info1.getType();
+ PsiType otherType = info1.type;
if (type.isAssignableFrom(otherType)) return new ExpectedTypeInfoImpl[] {info1};
else if (otherType.isAssignableFrom(type)) return new ExpectedTypeInfoImpl[] {this};
}
@@ -192,17 +144,14 @@
}
else if (kind == TYPE_OR_SUPERTYPE) {
if (info1.kind == TYPE_STRICTLY) {
- if (dimCount != info1.dimCount) return ExpectedTypeInfo.EMPTY_ARRAY;
if (info1.type.isAssignableFrom(type)) return new ExpectedTypeInfoImpl[] {info1};
}
else if (info1.kind == TYPE_OR_SUBTYPE) {
- PsiType type = dimCount == info1.dimCount ? this.type : getType();
- PsiType otherType = dimCount == info1.dimCount ? info1.type : info1.getType();
+ PsiType otherType = info1.type;
if (otherType.isAssignableFrom(type)) return new ExpectedTypeInfoImpl[] {this};
}
else if (info1.kind == TYPE_OR_SUPERTYPE) {
- PsiType type = dimCount == info1.dimCount ? this.type : getType();
- PsiType otherType = dimCount == info1.dimCount ? info1.type : info1.getType();
+ PsiType otherType = info1.type;
if (type.isAssignableFrom(otherType)) return new ExpectedTypeInfoImpl[] {this};
else if (otherType.isAssignableFrom(type)) return new ExpectedTypeInfoImpl[] {info1};
}
@@ -216,10 +165,4 @@
return ExpectedTypeInfo.EMPTY_ARRAY;
}
-
- @Override
- public boolean isArrayTypeInfo () {
- return dimCount > 0;
- }
-
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
index ebc4714..6a3d3f6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
@@ -52,7 +52,7 @@
* @author ven
*/
public class ExpectedTypesProvider {
- private static final ExpectedTypeInfo VOID_EXPECTED = new ExpectedTypeInfoImpl(PsiType.VOID, ExpectedTypeInfo.TYPE_OR_SUBTYPE, 0, PsiType.VOID,
+ private static final ExpectedTypeInfo VOID_EXPECTED = new ExpectedTypeInfoImpl(PsiType.VOID, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.VOID,
TailType.SEMICOLON);
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.ExpectedTypesProvider");
@@ -91,13 +91,7 @@
@NotNull
private static ExpectedTypeInfoImpl createInfoImpl(@NotNull PsiType type, int kind, PsiType defaultType, @NotNull TailType tailType) {
- int dims = 0;
- while (type instanceof PsiArrayType && defaultType instanceof PsiArrayType) {
- type = ((PsiArrayType) type).getComponentType();
- defaultType = ((PsiArrayType) defaultType).getComponentType();
- dims++;
- }
- return new ExpectedTypeInfoImpl(type, kind, dims, defaultType, tailType);
+ return new ExpectedTypeInfoImpl(type, kind, defaultType, tailType);
}
@NotNull
@@ -139,7 +133,7 @@
for (ExpectedTypeInfo info : infos) {
ExpectedTypeInfoImpl infoImpl = (ExpectedTypeInfoImpl)info;
- if (infoImpl.getDefaultType() instanceof PsiClassType && infoImpl.getDimCount() == 0) {
+ if (infoImpl.getDefaultType() instanceof PsiClassType) {
JavaResolveResult result = ((PsiClassType)infoImpl.getDefaultType()).resolveGenerics();
PsiClass aClass = (PsiClass)result.getElement();
if (aClass instanceof PsiAnonymousClass) {
@@ -155,10 +149,10 @@
}
if (infoImpl.kind == ExpectedTypeInfo.TYPE_OR_SUPERTYPE) {
- processAllSuperTypes(infoImpl.getType(), infoImpl.getDimCount(), visitor, project, set);
+ processAllSuperTypes(infoImpl.getType(), visitor, project, set);
}
else if (infoImpl.getKind() == ExpectedTypeInfo.TYPE_OR_SUBTYPE) {
- if (infoImpl.getType() instanceof PsiPrimitiveType && infoImpl.getDimCount() == 0) {
+ if (infoImpl.getType() instanceof PsiPrimitiveType) {
processPrimitiveTypeAndSubtypes((PsiPrimitiveType)infoImpl.getType(), visitor, set);
}
//else too expensive to search
@@ -183,7 +177,7 @@
}
}
- public static void processAllSuperTypes(@NotNull PsiType type, int dimCount, @NotNull PsiTypeVisitor<PsiType> visitor, @NotNull Project project, @NotNull Set<PsiType> set) {
+ public static void processAllSuperTypes(@NotNull PsiType type, @NotNull PsiTypeVisitor<PsiType> visitor, @NotNull Project project, @NotNull Set<PsiType> set) {
if (type instanceof PsiPrimitiveType) {
if (type.equals(PsiType.BOOLEAN) || type.equals(PsiType.VOID) || type.equals(PsiType.NULL)) return;
@@ -205,12 +199,8 @@
if (type instanceof PsiClassType) {
PsiType[] superTypes = type.getSuperTypes();
for (PsiType superType : superTypes) {
- PsiType wrappedType = superType;
- for (int j = 0; j < dimCount; j++) {
- wrappedType = wrappedType.createArrayType();
- }
- processType(wrappedType, visitor, set);
- processAllSuperTypes(superType, dimCount, visitor, project, set);
+ processType(superType, visitor, set);
+ processAllSuperTypes(superType, visitor, project, set);
}
}
}
@@ -864,7 +854,6 @@
ExpectedTypeInfo[] types = getExpectedTypes(expr, myForCompletion);
for (ExpectedTypeInfo info : types) {
ExpectedTypeInfoImpl infoImpl = (ExpectedTypeInfoImpl)info;
- infoImpl.setInsertExplicitTypeParams(true);
infoImpl.myTailType = TailType.COND_EXPR_COLON;
}
myResult = types;
@@ -874,9 +863,6 @@
LOG.error(Arrays.asList(expr.getChildren()) + "; " + myExpr);
}
myResult = getExpectedTypes(expr, myForCompletion);
- for (ExpectedTypeInfo info : myResult) {
- ((ExpectedTypeInfoImpl)info).setInsertExplicitTypeParams(true);
- }
}
}
@@ -1038,7 +1024,6 @@
PsiType defaultType = getDefaultType(method, substitutor, parameterType, argument, args, index);
ExpectedTypeInfoImpl info = createInfoImpl(parameterType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, defaultType, tailType);
- info.setInsertExplicitTypeParams(true);
info.setCalledMethod(method);
NullableComputable<String> propertyName = getPropertyName(parameter);
info.expectedName = propertyName;
@@ -1048,7 +1033,6 @@
//Then we may still want to call with array argument
final PsiArrayType arrayType = parameterType.createArrayType();
ExpectedTypeInfoImpl info1 = createInfoImpl(arrayType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, arrayType, tailType);
- info1.setInsertExplicitTypeParams(true);
info1.setCalledMethod(method);
info1.expectedName = propertyName;
array.add(info1);
diff --git a/java/java-impl/src/com/intellij/codeInsight/TargetElementUtil.java b/java/java-impl/src/com/intellij/codeInsight/TargetElementUtil.java
index 7ed0085..f9efd10 100644
--- a/java/java-impl/src/com/intellij/codeInsight/TargetElementUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/TargetElementUtil.java
@@ -21,6 +21,7 @@
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.xml.XmlAttribute;
@@ -299,7 +300,7 @@
return super.acceptImplementationForReference(reference, element);
}
- private static class PsiElementFindProcessor<T extends PsiElement> implements Processor<T> {
+ private static class PsiElementFindProcessor<T extends PsiClass> implements Processor<T> {
private final T myElement;
public PsiElementFindProcessor(T t) {
@@ -308,6 +309,7 @@
@Override
public boolean process(T t) {
+ if (InheritanceUtil.isInheritorOrSelf(t, myElement, true)) return false;
return !myElement.getManager().areElementsEquivalent(myElement, t);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java
index ba8486b..a9167f2 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java
@@ -21,6 +21,7 @@
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupItem;
+import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.codeInsight.lookup.TailTypeDecorator;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiJavaElementPattern;
@@ -612,6 +613,17 @@
return;
}
+ boolean afterNew = psiElement().afterLeaf(
+ psiElement().withText(PsiKeyword.NEW).andNot(psiElement().afterLeaf(PsiKeyword.THROW, "."))).accepts(position);
+ if (afterNew) {
+ PsiElementFactory factory = JavaPsiFacade.getElementFactory(position.getProject());
+ for (String primitiveType : PRIMITIVE_TYPES) {
+ result.addElement(PsiTypeLookupItem.createLookupItem(factory.createTypeFromText(primitiveType + "[]", null), null));
+ }
+ result.addElement(PsiTypeLookupItem.createLookupItem(factory.createTypeFromText("void[]", null), null));
+ return;
+ }
+
boolean inCast = psiElement()
.afterLeaf(psiElement().withText("(").withParent(psiElement(PsiParenthesizedExpression.class, PsiTypeCastExpression.class)))
.accepts(position);
@@ -619,8 +631,6 @@
boolean typeFragment = position.getContainingFile() instanceof PsiTypeCodeFragment && PsiTreeUtil.prevVisibleLeaf(position) == null;
boolean declaration = DECLARATION_START.accepts(position);
boolean expressionPosition = isExpressionPosition(position);
- boolean afterNew = psiElement().afterLeaf(
- psiElement().withText(PsiKeyword.NEW).andNot(psiElement().afterLeaf(PsiKeyword.THROW, "."))).accepts(position);
boolean inGenerics = PsiTreeUtil.getParentOfType(position, PsiReferenceParameterList.class) != null;
if (START_FOR.accepts(position) ||
isInsideParameterList(position) ||
@@ -629,7 +639,6 @@
inCast ||
declaration ||
typeFragment ||
- afterNew ||
expressionPosition ||
isStatementPosition(position)) {
for (String primitiveType : PRIMITIVE_TYPES) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
index ee6de05..1de9f59 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
@@ -34,6 +34,7 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -260,7 +261,17 @@
public PreferDefaultTypeWeigher(ExpectedTypeInfo[] expectedTypes, CompletionParameters parameters) {
super("defaultType");
- myExpectedTypes = expectedTypes;
+ myExpectedTypes = expectedTypes == null ? null : ContainerUtil.map2Array(expectedTypes, ExpectedTypeInfo.class, new Function<ExpectedTypeInfo, ExpectedTypeInfo>() {
+ @Override
+ public ExpectedTypeInfo fun(ExpectedTypeInfo info) {
+ PsiType type = removeClassWildcard(info.getType());
+ PsiType defaultType = removeClassWildcard(info.getDefaultType());
+ if (type == info.getType() && defaultType == info.getDefaultType()) {
+ return info;
+ }
+ return new ExpectedTypeInfoImpl(type, info.getKind(), defaultType, info.getTailType());
+ }
+ });
myParameters = parameters;
final Pair<PsiClass,Integer> pair = TypeArgumentCompletionProvider.getTypeParameterInfo(parameters.getPosition());
@@ -293,7 +304,7 @@
}
for (final ExpectedTypeInfo expectedInfo : myExpectedTypes) {
- final PsiType defaultType = expectedInfo.getDefaultType();
+ final PsiType defaultType = expectedInfo.getDefaultType();
final PsiType expectedType = expectedInfo.getType();
if (!expectedType.isValid()) {
return MyResult.normal;
@@ -316,6 +327,16 @@
return MyResult.normal;
}
+ private static PsiType removeClassWildcard(PsiType type) {
+ if (type instanceof PsiClassType) {
+ final PsiClass psiClass = ((PsiClassType)type).resolve();
+ if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
+ return GenericsUtil.eliminateWildcards(type);
+ }
+ }
+ return type;
+ }
+
private enum MyResult {
expectedNoSelect,
exactlyDefault,
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
index 75dc090..9e18f7b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
@@ -29,6 +29,7 @@
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
@@ -38,10 +39,13 @@
import com.intellij.psi.filters.TrueFilter;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
import com.intellij.psi.javadoc.*;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ProcessingContext;
+import com.intellij.util.Processor;
+import com.intellij.util.SystemProperties;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -120,18 +124,19 @@
@Override
protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
- List<String> ret = new ArrayList<String>();
+ final List<String> ret = new ArrayList<String>();
final PsiElement position = parameters.getPosition();
final PsiDocComment comment = PsiTreeUtil.getParentOfType(position, PsiDocComment.class);
+ assert comment != null;
final PsiElement parent = comment.getContext();
final boolean isInline = position.getContext() instanceof PsiInlineDocTag;
- final JavadocManager manager = JavadocManager.SERVICE.getInstance(position.getProject());
- final JavadocTagInfo[] infos = manager.getTagInfos(parent);
- for (JavadocTagInfo info : infos) {
- if (info.getName().equals(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME)) continue;
- if (isInline != (info.isInline())) continue;
- ret.add(info.getName());
+ for (JavadocTagInfo info : JavadocManager.SERVICE.getInstance(position.getProject()).getTagInfos(parent)) {
+ String tagName = info.getName();
+ if (tagName.equals(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME)) continue;
+ if (isInline != info.isInline()) continue;
+ ret.add(tagName);
+ addSpecialTags(ret, comment, tagName);
}
InspectionProfile inspectionProfile =
@@ -149,11 +154,43 @@
result.addElement(TailTypeDecorator.withTail(LookupElementBuilder.create(s), TailType.INSERT_SPACE));
}
}
+ result.stopHere(); // no word completions at this point
}
- @SuppressWarnings({"HardCodedStringLiteral"})
- public String toString() {
- return "javadoc-tag-chooser";
+ private static void addSpecialTags(final List<String> result, PsiDocComment comment, String tagName) {
+ if ("author".equals(tagName)) {
+ result.add(tagName + " " + SystemProperties.getUserName());
+ return;
+ }
+
+ if ("param".equals(tagName)) {
+ PsiMethod psiMethod = PsiTreeUtil.getParentOfType(comment, PsiMethod.class);
+ if (psiMethod != null) {
+ PsiDocTag[] tags = comment.getTags();
+ for (PsiParameter param : psiMethod.getParameterList().getParameters()) {
+ if (!JavaDocLocalInspection.isFound(tags, param)) {
+ result.add(tagName + " " + param.getName());
+ }
+ }
+ }
+ return;
+ }
+
+ if ("see".equals(tagName)) {
+ PsiMember member = PsiTreeUtil.getParentOfType(comment, PsiMember.class);
+ if (member instanceof PsiClass) {
+ InheritanceUtil.processSupers((PsiClass)member, false, new Processor<PsiClass>() {
+ @Override
+ public boolean process(PsiClass psiClass) {
+ String name = psiClass.getQualifiedName();
+ if (StringUtil.isNotEmpty(name) && !CommonClassNames.JAVA_LANG_OBJECT.equals(name)) {
+ result.add("see " + name);
+ }
+ return true;
+ }
+ });
+ }
+ }
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
index ac70993..5e7af80 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
@@ -378,11 +378,11 @@
final PsiClassType classType = factory
.createTypeByFQClassName(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, position.getResolveScope());
final List<ExpectedTypeInfo> result = new SmartList<ExpectedTypeInfo>();
- result.add(new ExpectedTypeInfoImpl(classType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, 0, classType, TailType.SEMICOLON));
+ result.add(new ExpectedTypeInfoImpl(classType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, classType, TailType.SEMICOLON));
final PsiMethod method = PsiTreeUtil.getContextOfType(position, PsiMethod.class, true);
if (method != null) {
for (final PsiClassType type : method.getThrowsList().getReferencedTypes()) {
- result.add(new ExpectedTypeInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, 0, type, TailType.SEMICOLON));
+ result.add(new ExpectedTypeInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.SEMICOLON));
}
}
return result.toArray(new ExpectedTypeInfo[result.size()]);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java b/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java
index e79fdbe..5caad61 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java
@@ -20,9 +20,8 @@
*/
package com.intellij.codeInsight.daemon;
-import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.ModifiableModel;
-import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import org.jdom.Element;
@@ -53,8 +52,8 @@
super.fillErrorLevels(profile);
//javadoc attributes
- final InspectionProfileEntry inspectionTool = profile.getInspectionTool(JavaDocLocalInspection.SHORT_NAME, null);
- JavaDocLocalInspection inspection = (JavaDocLocalInspection)((LocalInspectionToolWrapper)inspectionTool).getTool();
+ final InspectionToolWrapper toolWrapper = profile.getInspectionTool(JavaDocLocalInspection.SHORT_NAME, null);
+ JavaDocLocalInspection inspection = (JavaDocLocalInspection)toolWrapper.getTool();
inspection.myAdditionalJavadocTags = myAdditionalJavadocTags;
}
}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
index a36521f..43a7037 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
@@ -139,7 +139,7 @@
VirtualFile virtualFile = viewProvider.getVirtualFile();
myInLibrary = fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile);
- myRefCountHolder = RefCountHolder.endUsing(myFile);
+ myRefCountHolder = RefCountHolder.endUsing(myFile, progress);
if (myRefCountHolder == null || !myRefCountHolder.retrieveUnusedReferencesInfo(progress, new Runnable() {
@Override
public void run() {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java
index 0fd2685..892eec1 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java
@@ -63,7 +63,7 @@
public static boolean isRecursiveMethodCall(@NotNull PsiMethodCallExpression methodCall) {
final PsiMethod method = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class);
- if (method == null) {
+ if (method == null || !method.getName().equals(methodCall.getMethodExpression().getReferenceName())) {
return false;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
index 6fd6ba5..175c133 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
@@ -18,7 +18,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.psi.*;
@@ -34,11 +33,7 @@
import org.jetbrains.annotations.Nullable;
import java.lang.ref.SoftReference;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
public class RefCountHolder {
@@ -55,34 +50,35 @@
private volatile ProgressIndicator analyzedUnder;
private static class HolderReference extends SoftReference<RefCountHolder> {
- @SuppressWarnings("UnusedDeclaration")
- private volatile RefCountHolder myHardRef; // to prevent gc
- // number of live references to RefCountHolder. Once it reaches zero, hard ref is cleared
- // the counter is used instead of a flag because multiple passes can be running simultaneously (one actual and several canceled winding down)
- // and there is a chance they overlap the usage of RCH
- private final AtomicInteger myRefCount = new AtomicInteger();
+ // Map holding hard references to RefCountHolder for each highlighting pass (identified by its progress indicator)
+ // there can be multiple passes running simultaneously (one actual and several passes just canceled and winding down but still alive)
+ // so there is a chance they overlap the usage of RCH
+ // As soon as everybody finished using RCH, map become empty and the RefCountHolder is eligible for gc
+ private final Map<ProgressIndicator, RefCountHolder> map = new ConcurrentHashMap<ProgressIndicator, RefCountHolder>();
public HolderReference(@NotNull RefCountHolder holder) {
super(holder);
- myHardRef = holder;
}
- private void changeLivenessBy(int delta) {
- if (myRefCount.addAndGet(delta) == 0) {
- myHardRef = null;
- }
- else if (myHardRef == null) {
- myHardRef = get();
- }
+ private void acquire(@NotNull ProgressIndicator indicator) {
+ RefCountHolder holder = get();
+ assert holder != null: "no way";
+ map.put(indicator, holder);
+ holder = get();
+ assert holder != null: "can't be!";
+ }
+
+ private RefCountHolder release(@NotNull ProgressIndicator indicator) {
+ return map.remove(indicator);
}
}
private static final Key<HolderReference> REF_COUNT_HOLDER_IN_FILE_KEY = Key.create("REF_COUNT_HOLDER_IN_FILE_KEY");
- @NotNull
- private static Pair<RefCountHolder, HolderReference> getInstance(@NotNull PsiFile file, boolean create) {
+
+ private static RefCountHolder getInstance(@NotNull PsiFile file, @NotNull ProgressIndicator indicator, boolean acquire) {
HolderReference ref = file.getUserData(REF_COUNT_HOLDER_IN_FILE_KEY);
RefCountHolder holder = ref == null ? null : ref.get();
- if (holder == null && create) {
+ if (holder == null && acquire) {
holder = new RefCountHolder(file);
HolderReference newRef = new HolderReference(holder);
while (true) {
@@ -99,31 +95,30 @@
}
}
}
- return Pair.create(holder, ref);
+ if (ref != null) {
+ if (acquire) {
+ ref.acquire(indicator);
+ }
+ else {
+ ref.release(indicator);
+ }
+ }
+ return holder;
}
@NotNull
- public static RefCountHolder startUsing(@NotNull PsiFile file) {
- Pair<RefCountHolder, HolderReference> pair = getInstance(file, true);
- HolderReference reference = pair.second;
- reference.changeLivenessBy(1); // make sure RefCountHolder won't be gced during highlighting
- log("startUsing: " + pair.first.myState+" for "+file);
- return pair.first;
+ public static RefCountHolder startUsing(@NotNull PsiFile file, @NotNull ProgressIndicator indicator) {
+ return getInstance(file, indicator, true);
}
@Nullable("might be gced")
- public static RefCountHolder endUsing(@NotNull PsiFile file) {
- Pair<RefCountHolder, HolderReference> pair = getInstance(file, false);
- HolderReference reference = pair.second;
- reference.changeLivenessBy(-1); // no longer needed, can be cleared
- RefCountHolder holder = pair.first;
- log("endUsing: " + (holder == null ? null : holder.myState)+" for "+file);
- return holder;
+ public static RefCountHolder endUsing(@NotNull PsiFile file, @NotNull ProgressIndicator indicator) {
+ return getInstance(file, indicator, false);
}
private RefCountHolder(@NotNull PsiFile file) {
myFile = file;
- log("c: created: " + myState.get()+" for "+file);
+ log("c: created: ", myState.get(), " for ", file);
}
private void clear() {
@@ -284,10 +279,10 @@
ProgressIndicator old = myState.get();
if (old != VIRGIN && old != READY) return false;
if (!myState.compareAndSet(old, indicator)) {
- log("a: failed to change " + old + "->" + indicator);
+ log("a: failed to change ", old, "->", indicator);
return false;
}
- log("a: changed " + old + "->" + indicator);
+ log("a: changed ", old, "->", indicator);
analyzedUnder = null;
boolean completed = false;
try {
@@ -308,22 +303,22 @@
ProgressIndicator resultState = completed ? READY : VIRGIN;
boolean set = myState.compareAndSet(indicator, resultState);
assert set : myState.get();
- log("a: changed after analyze" + indicator + "->" + resultState);
+ log("a: changed after analyze", indicator, "->", resultState);
}
return true;
}
- private static void log(@NonNls String s) {
- //System.err.println("RFC: "+s);
+ private static void log(@NonNls Object... s) {
+ //System.err.println("RFC: "+ Arrays.asList(s));
}
public boolean retrieveUnusedReferencesInfo(@NotNull ProgressIndicator indicator, @NotNull Runnable analyze) {
ProgressIndicator old = myState.get();
if (!myState.compareAndSet(READY, indicator)) {
- log("r: failed to change " + old + "->" + indicator);
+ log("r: failed to change ", old, "->", indicator);
return false;
}
- log("r: changed " + old + "->" + indicator);
+ log("r: changed ", old, "->", indicator);
try {
if (analyzedUnder != indicator) {
return false;
@@ -333,7 +328,7 @@
finally {
boolean set = myState.compareAndSet(indicator, READY);
assert set : myState.get();
- log("r: changed back " + indicator + "->" + READY);
+ log("r: changed back ", indicator, "->", READY);
}
return true;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
index 1d74a2f..48e10ee 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
@@ -40,6 +40,7 @@
import com.intellij.util.containers.HashSet;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -384,8 +385,10 @@
}
@Nullable
- public static HighlightInfo checkElementInTypeParameterExtendsList(PsiReferenceList referenceList, JavaResolveResult resolveResult, PsiElement element) {
- PsiClass aClass = (PsiClass)referenceList.getParent();
+ public static HighlightInfo checkElementInTypeParameterExtendsList(@NotNull PsiReferenceList referenceList,
+ @NotNull PsiClass aClass,
+ @NotNull JavaResolveResult resolveResult,
+ @NotNull PsiElement element) {
final PsiJavaCodeReferenceElement[] referenceElements = referenceList.getReferenceElements();
PsiClass extendFrom = (PsiClass)resolveResult.getElement();
if (extendFrom == null) return null;
@@ -462,7 +465,7 @@
return null;
}
- public static HighlightInfo checkOverrideEquivalentMethods(final PsiClass aClass) {
+ public static HighlightInfo checkOverrideEquivalentMethods(@NotNull PsiClass aClass) {
final Collection<HierarchicalMethodSignature> signaturesWithSupers = aClass.getVisibleSignatures();
PsiManager manager = aClass.getManager();
Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods =
@@ -520,10 +523,10 @@
}
@Nullable
- private static HighlightInfo checkSameErasureNotSubSignatureInner(final HierarchicalMethodSignature signature,
- final PsiManager manager,
- final PsiClass aClass,
- final Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods) {
+ private static HighlightInfo checkSameErasureNotSubSignatureInner(@NotNull HierarchicalMethodSignature signature,
+ @NotNull PsiManager manager,
+ @NotNull PsiClass aClass,
+ @NotNull Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods) {
PsiMethod method = signature.getMethod();
JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
if (!facade.getResolveHelper().isAccessible(method, aClass, null)) return null;
@@ -549,10 +552,11 @@
if (superSignature.isRaw() && !signature.isRaw()) {
final PsiType[] parameterTypes = signature.getParameterTypes();
- PsiType[] types = superSignature.getParameterTypes();
- for (int i = 0; i < types.length; i++) {
- if (!Comparing.equal(parameterTypes[i], TypeConversionUtil.erasure(types[i]))) {
- return getSameErasureMessage(false, method, superSignature.getMethod(), HighlightNamesUtil.getClassDeclarationTextRange(aClass));
+ PsiType[] erasedTypes = superSignature.getErasedParameterTypes();
+ for (int i = 0; i < erasedTypes.length; i++) {
+ if (!Comparing.equal(parameterTypes[i], erasedTypes[i])) {
+ return getSameErasureMessage(false, method, superSignature.getMethod(),
+ HighlightNamesUtil.getClassDeclarationTextRange(aClass));
}
}
}
@@ -601,10 +605,10 @@
!(checkEqualsSuper && Arrays.equals(superSignature.getParameterTypes(), signatureToCheck.getParameterTypes())) &&
!atLeast17) {
int idx = 0;
- final PsiType[] parameterTypes = signatureToCheck.getParameterTypes();
- boolean erasure = parameterTypes.length > 0;
+ final PsiType[] erasedTypes = signatureToCheck.getErasedParameterTypes();
+ boolean erasure = erasedTypes.length > 0;
for (PsiType type : superSignature.getParameterTypes()) {
- erasure &= Comparing.equal(type, TypeConversionUtil.erasure(parameterTypes[idx]));
+ erasure &= Comparing.equal(type, erasedTypes[idx]);
idx++;
}
@@ -624,9 +628,9 @@
}
}
- private static HighlightInfo getSameErasureMessage(final boolean sameClass, final PsiMethod method, final PsiMethod superMethod,
+ private static HighlightInfo getSameErasureMessage(final boolean sameClass, @NotNull PsiMethod method, @NotNull PsiMethod superMethod,
TextRange textRange) {
- @NonNls final String key = sameClass ? "generics.methods.have.same.erasure" :
+ @NonNls final String key = sameClass ? "generics.methods.have.same.erasure" :
method.hasModifierProperty(PsiModifier.STATIC) ?
"generics.methods.have.same.erasure.hide" :
"generics.methods.have.same.erasure.override";
@@ -1275,7 +1279,7 @@
if (resolve instanceof PsiClass) {
final PsiClass containingClass = ((PsiClass)resolve).getContainingClass();
if (containingClass != null) {
- if (psiClass.isInheritor(containingClass, true) ||
+ if (psiClass.isInheritor(containingClass, true) ||
unqualifiedNestedClassReferenceAccessedViaContainingClassInheritance(containingClass, ((PsiClass)resolve).getExtendsList()) ||
unqualifiedNestedClassReferenceAccessedViaContainingClassInheritance(containingClass, ((PsiClass)resolve).getImplementsList())) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(((PsiClass)resolve).getName() + " is not accessible in current context").range(ref).create();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
index 4f6f099..ae32b61 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
@@ -55,10 +55,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
+import java.util.*;
public class HighlightClassUtil {
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
@@ -94,19 +91,32 @@
static HighlightInfo checkClassWithAbstractMethods(PsiClass aClass, PsiElement implementsFixElement, TextRange range) {
PsiMethod abstractMethod = ClassUtil.getAnyAbstractMethod(aClass);
- if (abstractMethod == null || abstractMethod.getContainingClass() == null) {
+ if (abstractMethod == null) {
return null;
}
+
+ final PsiClass superClass = abstractMethod.getContainingClass();
+ if (superClass == null) {
+ return null;
+ }
+
String baseClassName = HighlightUtil.formatClass(aClass, false);
String methodName = JavaHighlightUtil.formatMethod(abstractMethod);
String message = JavaErrorMessages.message(aClass instanceof PsiEnumConstantInitializer || implementsFixElement instanceof PsiEnumConstant ? "enum.constant.should.implement.method" : "class.must.be.abstract",
baseClassName,
methodName,
- HighlightUtil.formatClass(abstractMethod.getContainingClass(), false));
+ HighlightUtil.formatClass(superClass, false));
HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(message).create();
- if (ClassUtil.getAnyMethodToImplement(aClass) != null) {
- QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementMethodsFix(implementsFixElement));
+ final PsiMethod anyMethodToImplement = ClassUtil.getAnyMethodToImplement(aClass);
+ if (anyMethodToImplement != null) {
+ if (!anyMethodToImplement.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) ||
+ JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, superClass)) {
+ QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementMethodsFix(implementsFixElement));
+ } else {
+ QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix(anyMethodToImplement, PsiModifier.PROTECTED, true, true));
+ QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix(anyMethodToImplement, PsiModifier.PUBLIC, true, true));
+ }
}
if (!(aClass instanceof PsiAnonymousClass)
&& HighlightUtil.getIncompatibleModifier(PsiModifier.ABSTRACT, aClass.getModifierList()) == null) {
@@ -985,7 +995,7 @@
if (classReference == null) return;
final PsiClass psiClass = (PsiClass)classReference.resolve();
if (psiClass == null) return;
- final MemberChooser<PsiMethodMember> chooser = chooseMethodsToImplement(editor, startElement, psiClass);
+ final MemberChooser<PsiMethodMember> chooser = chooseMethodsToImplement(editor, startElement, psiClass, false);
if (chooser == null) return;
final List<PsiMethodMember> selectedElements = chooser.getSelectedElements();
@@ -999,12 +1009,17 @@
newExpression = (PsiNewExpression)startElement.replace(newExpression);
final PsiClass psiClass = newExpression.getAnonymousClass();
if (psiClass == null) return;
- PsiClassType baseClassType = ((PsiAnonymousClass)psiClass).getBaseClassType();
- PsiClass resolve = baseClassType.resolve();
- if (resolve == null) return;
- PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(resolve, psiClass, PsiSubstitutor.EMPTY);
+ Map<PsiClass, PsiSubstitutor> subst = new HashMap<PsiClass, PsiSubstitutor>();
for (PsiMethodMember selectedElement : selectedElements) {
- selectedElement.setSubstitutor(superClassSubstitutor);
+ final PsiClass baseClass = selectedElement.getElement().getContainingClass();
+ if (baseClass != null) {
+ PsiSubstitutor substitutor = subst.get(baseClass);
+ if (substitutor == null) {
+ substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, psiClass, PsiSubstitutor.EMPTY);
+ subst.put(baseClass, substitutor);
+ }
+ selectedElement.setSubstitutor(substitutor);
+ }
}
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, psiClass, selectedElements, chooser.isCopyJavadoc(),
chooser.isInsertOverrideAnnotation());
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index 80f4b17..2d1a4db 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -35,6 +35,7 @@
import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.ui.ColorUtil;
+import com.intellij.util.containers.MostlySingularMultiMap;
import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.intellij.lang.annotations.Language;
@@ -833,18 +834,15 @@
}
@Nullable
- static HighlightInfo checkDuplicateMethod(PsiClass aClass, PsiMethod method) {
+ static HighlightInfo checkDuplicateMethod(PsiClass aClass,
+ @NotNull PsiMethod method,
+ @NotNull MostlySingularMultiMap<MethodSignature, PsiMethod> duplicateMethods) {
if (aClass == null || method instanceof ExternallyDefinedPsiElement) return null;
MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
- int methodCount = 0;
- final PsiMethod[] methodsByName = aClass.findMethodsByName(method.getName(), false);
- for (PsiMethod other : methodsByName) {
- if (other instanceof ExternallyDefinedPsiElement) continue;
- if (other == method ||
- other.isConstructor() == method.isConstructor() && other.getSignature(PsiSubstitutor.EMPTY).equals(methodSignature)) {
- methodCount++;
- if (methodCount > 1) break;
- }
+ int methodCount = 1;
+ List<PsiMethod> methods = (List<PsiMethod>)duplicateMethods.get(methodSignature);
+ if (methods.size() > 1) {
+ methodCount++;
}
if (methodCount == 1 && aClass.isEnum() &&
@@ -874,6 +872,7 @@
if (hasNoBody) {
if (isExtension) {
description = JavaErrorMessages.message("extension.method.should.have.a.body");
+ additionalFixes.add(new AddMethodBodyFix(method));
}
else if (isInterface && isStatic) {
description = "Static methods in interfaces should have a body";
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index 94508df..e7b3d6b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
@@ -2516,7 +2516,7 @@
PsiClass aClass = (PsiClass)resolved;
if (refGrandParent instanceof PsiClass) {
if (refGrandParent instanceof PsiTypeParameter) {
- highlightInfo = GenericsHighlightUtil.checkElementInTypeParameterExtendsList(referenceList, resolveResult, ref);
+ highlightInfo = GenericsHighlightUtil.checkElementInTypeParameterExtendsList(referenceList, (PsiClass)refGrandParent, resolveResult, ref);
}
else {
highlightInfo = HighlightClassUtil.checkExtendsClassAndImplementsInterface(referenceList, resolveResult, ref);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
index 1c0e2ec..c705951 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
@@ -39,11 +39,9 @@
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTagValue;
-import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.psi.util.*;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.containers.MostlySingularMultiMap;
import gnu.trove.THashMap;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
@@ -82,11 +80,27 @@
}
}
};
+ private final Map<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>> myDuplicateMethods = new THashMap<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>>();
public HighlightVisitorImpl(@NotNull PsiResolveHelper resolveHelper) {
myResolveHelper = resolveHelper;
}
+ @NotNull
+ private MostlySingularMultiMap<MethodSignature, PsiMethod> getDuplicateMethods(PsiClass aClass) {
+ MostlySingularMultiMap<MethodSignature, PsiMethod> signatures = myDuplicateMethods.get(aClass);
+ if (signatures == null) {
+ signatures = new MostlySingularMultiMap<MethodSignature, PsiMethod>();
+ for (PsiMethod method : aClass.getMethods()) {
+ MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY);
+ signatures.add(signature, method);
+ }
+
+ myDuplicateMethods.put(aClass, signatures);
+ }
+ return signatures;
+ }
+
@Override
@NotNull
public HighlightVisitorImpl clone() {
@@ -130,12 +144,13 @@
Project project = file.getProject();
DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).getFileStatusMap();
- RefCountHolder refCountHolder = RefCountHolder.startUsing(file);
+ ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
+ if (indicator == null) throw new IllegalStateException("Must be run under progress");
+ RefCountHolder refCountHolder = RefCountHolder.startUsing(file, indicator);
myRefCountHolder = refCountHolder;
Document document = PsiDocumentManager.getInstance(project).getDocument(file);
TextRange dirtyScope = document == null ? file.getTextRange() : fileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL);
- ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
- success = indicator != null && refCountHolder.analyze(file, dirtyScope, action, indicator);
+ success = refCountHolder.analyze(file, dirtyScope, action, indicator);
}
else {
myRefCountHolder = null;
@@ -152,6 +167,7 @@
myRefCountHolder = null;
myFile = null;
myHolder = null;
+ myDuplicateMethods.clear();
}
return success;
@@ -775,7 +791,7 @@
}
PsiClass aClass = method.getContainingClass();
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method));
}
@@ -932,7 +948,10 @@
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkCannotPassInner(ref));
if (resolved != null && parent instanceof PsiReferenceList) {
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkElementInReferenceList(ref, (PsiReferenceList)parent, result));
+ if (!myHolder.hasErrorResults()) {
+ PsiReferenceList referenceList = (PsiReferenceList)parent;
+ myHolder.add(HighlightUtil.checkElementInReferenceList(ref, referenceList, result));
+ }
}
if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference())) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java
index 4457e5d..0057749 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java
@@ -102,8 +102,8 @@
return true;
}
- public static void register(HighlightInfo highlightInfo, PsiExpression expression, PsiType lType) {
- if (expression instanceof PsiConditionalExpression) {
+ public static void register(HighlightInfo highlightInfo, PsiExpression expression, @NotNull PsiType lType) {
+ if (lType != PsiType.NULL && expression instanceof PsiConditionalExpression) {
final PsiExpression thenExpression = ((PsiConditionalExpression)expression).getThenExpression();
final PsiExpression elseExpression = ((PsiConditionalExpression)expression).getElseExpression();
if (thenExpression != null && elseExpression != null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
index ad63c63..667143b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
@@ -134,7 +134,7 @@
JVMElementFactory factory = JVMElementFactories.getFactory(aClass.getLanguage(), aClass.getProject());
- LOG.assertTrue(!aClass.isInterface(), "Interface bodies should be already set up");
+ LOG.assertTrue(!aClass.isInterface() || method.hasModifierProperty(PsiModifier.DEFAULT), "Interface bodies should be already set up");
FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(template.getExtension());
Properties properties = new Properties();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
index 24ba71d..919c6b4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
@@ -54,8 +54,11 @@
if (!super.isAvailableImpl(offset)) return false;
if(myReferenceExpression.isQualified()) return false;
PsiElement scope = PsiTreeUtil.getParentOfType(myReferenceExpression, PsiModifierListOwner.class);
+ if (scope instanceof PsiAnonymousClass) {
+ scope = PsiTreeUtil.getParentOfType(scope, PsiModifierListOwner.class, true);
+ }
return scope instanceof PsiMethod || scope instanceof PsiClassInitializer ||
- scope instanceof PsiLocalVariable || scope instanceof PsiAnonymousClass;
+ scope instanceof PsiLocalVariable;
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java
index f9c9b7b..5e63273 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java
@@ -28,16 +28,13 @@
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiEnumConstant;
-import com.intellij.psi.PsiFile;
+import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
public class ImplementMethodsFix extends LocalQuickFixAndIntentionActionOnPsiElement {
public ImplementMethodsFix(PsiElement aClass) {
@@ -75,7 +72,7 @@
if (editor == null || !FileModificationService.getInstance().prepareFileForWrite(myPsiElement.getContainingFile())) return;
if (myPsiElement instanceof PsiEnumConstant) {
- final MemberChooser<PsiMethodMember> chooser = chooseMethodsToImplement(editor, startElement, ((PsiEnumConstant)myPsiElement).getContainingClass());
+ final MemberChooser<PsiMethodMember> chooser = chooseMethodsToImplement(editor, startElement, ((PsiEnumConstant)myPsiElement).getContainingClass(), true);
if (chooser == null) return;
final List<PsiMethodMember> selectedElements = chooser.getSelectedElements();
@@ -103,10 +100,14 @@
@Nullable
- protected static MemberChooser<PsiMethodMember> chooseMethodsToImplement(Editor editor, PsiElement startElement, PsiClass aClass) {
+ protected static MemberChooser<PsiMethodMember> chooseMethodsToImplement(Editor editor,
+ PsiElement startElement,
+ PsiClass aClass,
+ boolean implemented) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT);
+ final Collection<CandidateInfo> overrideImplement = OverrideImplementExploreUtil.getMapToOverrideImplement(aClass, true, implemented).values();
return OverrideImplementUtil
- .showOverrideImplementChooser(editor, startElement, true, OverrideImplementExploreUtil.getMethodsToOverrideImplement(aClass, true), Collections.<CandidateInfo>emptyList());
+ .showOverrideImplementChooser(editor, startElement, true, overrideImplement, ContainerUtil.<CandidateInfo>newArrayList());
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
index a2bebf6..2e23f7e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
@@ -107,6 +107,7 @@
return super.getRequiredMemberName(reference);
}
+ @NotNull
@Override
protected List<PsiClass> filterByContext(@NotNull List<PsiClass> candidates, @NotNull PsiJavaCodeReferenceElement ref) {
PsiElement typeElement = ref.getParent();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
index e34ad18..bfb7c45 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
@@ -184,6 +184,7 @@
return null;
}
+ @NotNull
protected List<PsiClass> filterByContext(@NotNull List<PsiClass> candidates, @NotNull T ref) {
return candidates;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
index 6ac2e5d..0d71068 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
@@ -141,6 +141,7 @@
final PsiModifierList myModifierList = (PsiModifierList)startElement;
final PsiVariable variable = myVariable == null ? null : myVariable.getElement();
if (!FileModificationService.getInstance().preparePsiElementForWrite(myModifierList)) return;
+ if (variable != null && !FileModificationService.getInstance().preparePsiElementForWrite(variable)) return;
final List<PsiModifierList> modifierLists = new ArrayList<PsiModifierList>();
final PsiFile containingFile = myModifierList.getContainingFile();
final PsiModifierList modifierList;
@@ -180,8 +181,6 @@
}));
}
- if (!FileModificationService.getInstance().prepareFileForWrite(containingFile)) return;
-
if (!modifierLists.isEmpty()) {
if (Messages.showYesNoDialog(project,
QuickFixBundle.message("change.inheritors.visibility.warning.text"),
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
index e08b1a9..7f906c1 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -51,7 +51,7 @@
return null;
}
- final ArrayList<ReferenceTransferableData.ReferenceData> array = new ArrayList<ReferenceTransferableData.ReferenceData>();
+ final ArrayList<ReferenceData> array = new ArrayList<ReferenceData>();
for (int j = 0; j < startOffsets.length; j++) {
final int startOffset = startOffsets[j];
for (final PsiElement element : CollectHighlightsUtil.getElementsInRange(file, startOffset, endOffsets[j])) {
@@ -63,10 +63,10 @@
return null;
}
- return new ReferenceTransferableData(array.toArray(new ReferenceTransferableData.ReferenceData[array.size()]));
+ return new ReferenceTransferableData(array.toArray(new ReferenceData[array.size()]));
}
- protected abstract void addReferenceData(PsiFile file, int startOffset, PsiElement element, ArrayList<ReferenceTransferableData.ReferenceData> to);
+ protected abstract void addReferenceData(PsiFile file, int startOffset, PsiElement element, ArrayList<ReferenceData> to);
@Override
@Nullable
@@ -74,7 +74,7 @@
ReferenceTransferableData referenceData = null;
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE != CodeInsightSettings.NO) {
try {
- final DataFlavor flavor = ReferenceTransferableData.ReferenceData.getDataFlavor();
+ final DataFlavor flavor = ReferenceData.getDataFlavor();
if (flavor != null) {
referenceData = (ReferenceTransferableData)content.getTransferData(flavor);
}
@@ -109,7 +109,7 @@
}
PsiDocumentManager.getInstance(project).commitAllDocuments();
- final ReferenceTransferableData.ReferenceData[] referenceData = value.getData();
+ final ReferenceData[] referenceData = value.getData();
final TRef[] refs = findReferencesToRestore(file, bounds, referenceData);
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.ASK) {
askReferencesToRestore(project, refs, referenceData);
@@ -124,12 +124,12 @@
}
protected static void addReferenceData(final PsiElement element,
- final ArrayList<ReferenceTransferableData.ReferenceData> array,
+ final ArrayList<ReferenceData> array,
final int startOffset,
final String qClassName, @Nullable final String staticMemberName) {
final TextRange range = element.getTextRange();
array.add(
- new ReferenceTransferableData.ReferenceData(
+ new ReferenceData(
range.getStartOffset() - startOffset,
range.getEndOffset() - startOffset,
qClassName, staticMemberName));
@@ -137,13 +137,13 @@
protected abstract TRef[] findReferencesToRestore(PsiFile file,
RangeMarker bounds,
- ReferenceTransferableData.ReferenceData[] referenceData);
+ ReferenceData[] referenceData);
- protected abstract void restoreReferences(ReferenceTransferableData.ReferenceData[] referenceData,
+ protected abstract void restoreReferences(ReferenceData[] referenceData,
TRef[] refs);
private static void askReferencesToRestore(Project project, PsiElement[] refs,
- ReferenceTransferableData.ReferenceData[] referenceData) {
+ ReferenceData[] referenceData) {
PsiManager manager = PsiManager.getInstance(project);
ArrayList<Object> array = new ArrayList<Object>();
@@ -152,7 +152,7 @@
PsiElement ref = refs[i];
if (ref != null) {
LOG.assertTrue(ref.isValid());
- ReferenceTransferableData.ReferenceData data = referenceData[i];
+ ReferenceData data = referenceData[i];
PsiClass refClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(data.qClassName, ref.getResolveScope());
if (refClass == null) continue;
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
index 85ea365..51edddd 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
@@ -30,7 +30,7 @@
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.JavaCopyPasteReferenceProcessor");
@Override
- protected void addReferenceData(PsiFile file, int startOffset, PsiElement element, ArrayList<ReferenceTransferableData.ReferenceData> to) {
+ protected void addReferenceData(PsiFile file, int startOffset, PsiElement element, ArrayList<ReferenceData> to) {
if (element instanceof PsiJavaCodeReferenceElement) {
if (!((PsiJavaCodeReferenceElement)element).isQualified()) {
final JavaResolveResult resolveResult = ((PsiJavaCodeReferenceElement)element).advancedResolve(false);
@@ -61,13 +61,13 @@
@Override
protected PsiJavaCodeReferenceElement[] findReferencesToRestore(PsiFile file,
RangeMarker bounds,
- ReferenceTransferableData.ReferenceData[] referenceData) {
+ ReferenceData[] referenceData) {
PsiManager manager = file.getManager();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
PsiResolveHelper helper = facade.getResolveHelper();
PsiJavaCodeReferenceElement[] refs = new PsiJavaCodeReferenceElement[referenceData.length];
for (int i = 0; i < referenceData.length; i++) {
- ReferenceTransferableData.ReferenceData data = referenceData[i];
+ ReferenceData data = referenceData[i];
PsiClass refClass = facade.findClass(data.qClassName, file.getResolveScope());
if (refClass == null) continue;
@@ -105,14 +105,14 @@
}
@Override
- protected void restoreReferences(ReferenceTransferableData.ReferenceData[] referenceData,
+ protected void restoreReferences(ReferenceData[] referenceData,
PsiJavaCodeReferenceElement[] refs) {
for (int i = 0; i < refs.length; i++) {
PsiJavaCodeReferenceElement reference = refs[i];
if (reference == null || !reference.isValid()) continue;
try {
PsiManager manager = reference.getManager();
- ReferenceTransferableData.ReferenceData refData = referenceData[i];
+ ReferenceData refData = referenceData[i];
PsiClass refClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(refData.qClassName, reference.getResolveScope());
if (refClass != null) {
if (refData.staticMemberName == null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/ReferenceData.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/ReferenceData.java
new file mode 100644
index 0000000..8cc6f8d
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/ReferenceData.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import org.jetbrains.annotations.NonNls;
+
+import java.awt.datatransfer.DataFlavor;
+import java.io.Serializable;
+
+/**
+* @author Denis Fokin
+*/
+public class ReferenceData implements Cloneable, Serializable {
+ public static @NonNls DataFlavor ourFlavor;
+
+ public int startOffset;
+ public int endOffset;
+ public final String qClassName;
+ public final String staticMemberName;
+
+ public ReferenceData(int startOffset, int endOffset, String qClassName, String staticMemberDescriptor) {
+ this.startOffset = startOffset;
+ this.endOffset = endOffset;
+ this.qClassName = qClassName;
+ this.staticMemberName = staticMemberDescriptor;
+ }
+
+ @Override
+ public Object clone() {
+ try{
+ return super.clone();
+ }
+ catch(CloneNotSupportedException e){
+ throw new RuntimeException();
+ }
+ }
+
+ public static DataFlavor getDataFlavor() {
+ if (ourFlavor != null) {
+ return ourFlavor;
+ }
+ try {
+ ourFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + ReferenceData.class.getName(), "ReferenceData");
+ }
+ catch (NoClassDefFoundError e) {
+ return null;
+ }
+ catch (IllegalArgumentException e) {
+ return null;
+ }
+ return ourFlavor;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/ReferenceTransferableData.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/ReferenceTransferableData.java
index 8b2e56e..76c3754 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/ReferenceTransferableData.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/ReferenceTransferableData.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -15,8 +15,6 @@
*/
package com.intellij.codeInsight.editorActions;
-import org.jetbrains.annotations.NonNls;
-
import java.awt.datatransfer.DataFlavor;
import java.io.Serializable;
@@ -70,46 +68,4 @@
public ReferenceData[] getData() {
return myReferenceDatas;
}
-
- public static class ReferenceData implements Cloneable, Serializable {
- public static @NonNls DataFlavor ourFlavor;
-
- public int startOffset;
- public int endOffset;
- public final String qClassName;
- public final String staticMemberName;
-
- public ReferenceData(int startOffset, int endOffset, String qClassName, String staticMemberDescriptor) {
- this.startOffset = startOffset;
- this.endOffset = endOffset;
- this.qClassName = qClassName;
- this.staticMemberName = staticMemberDescriptor;
- }
-
- @Override
- public Object clone() {
- try{
- return super.clone();
- }
- catch(CloneNotSupportedException e){
- throw new RuntimeException();
- }
- }
-
- public static DataFlavor getDataFlavor() {
- if (ourFlavor != null) {
- return ourFlavor;
- }
- try {
- ourFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + ReferenceData.class.getName(), "ReferenceData");
- }
- catch (NoClassDefFoundError e) {
- return null;
- }
- catch (IllegalArgumentException e) {
- return null;
- }
- return ourFlavor;
- }
- }
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterHandler.java
index d7aca70..1306e20 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterHandler.java
@@ -37,7 +37,7 @@
protected GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException {
if (original instanceof PropertyClassMember) {
final PropertyClassMember propertyClassMember = (PropertyClassMember)original;
- final GenerationInfo[] getters = propertyClassMember.generateGetters();
+ final GenerationInfo[] getters = propertyClassMember.generateGetters(aClass);
if (getters != null) {
return getters;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
index 5a8eea4..a58dfe3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.generation;
+import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
@@ -22,6 +23,7 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
@@ -30,6 +32,7 @@
import com.intellij.psi.impl.light.LightTypeElement;
import com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl;
import com.intellij.psi.javadoc.PsiDocComment;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -42,10 +45,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
public class GenerateMembersUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.GenerateMembersUtil");
@@ -266,7 +266,17 @@
substituteTypeParameters(factory, target, sourceMethod.getTypeParameterList(), resultMethod.getTypeParameterList(), substitutor, sourceMethod);
substituteReturnType(PsiManager.getInstance(project), resultMethod, sourceMethod.getReturnType(), collisionResolvedSubstitutor);
substituteParameters(factory, codeStyleManager, sourceMethod.getParameterList(), resultMethod.getParameterList(), collisionResolvedSubstitutor, target);
- substituteThrows(factory, sourceMethod.getThrowsList(), resultMethod.getThrowsList(), collisionResolvedSubstitutor, sourceMethod);
+ final List<PsiClassType> thrownTypes = ExceptionUtil.collectSubstituted(collisionResolvedSubstitutor, sourceMethod.getThrowsList().getReferencedTypes());
+ if (target instanceof PsiClass) {
+ final PsiClass[] supers = ((PsiClass)target).getSupers();
+ for (PsiClass aSuper : supers) {
+ final PsiMethod psiMethod = aSuper.findMethodBySignature(sourceMethod, true);
+ if (psiMethod != null && psiMethod != sourceMethod) {
+ ExceptionUtil.retainExceptions(thrownTypes, ExceptionUtil.collectSubstituted(TypeConversionUtil.getSuperClassSubstitutor(aSuper, (PsiClass)target, PsiSubstitutor.EMPTY), psiMethod.getThrowsList().getReferencedTypes()));
+ }
+ }
+ }
+ substituteThrows(factory, resultMethod.getThrowsList(), collisionResolvedSubstitutor, sourceMethod, thrownTypes);
return resultMethod;
}
catch (IncorrectOperationException e) {
@@ -400,11 +410,11 @@
}
private static void substituteThrows(@NotNull JVMElementFactory factory,
- @NotNull PsiReferenceList sourceThrowsList,
@NotNull PsiReferenceList targetThrowsList,
- @NotNull PsiSubstitutor substitutor,
- @NotNull PsiMethod sourceMethod) {
- for (PsiClassType thrownType : sourceThrowsList.getReferencedTypes()) {
+ @NotNull PsiSubstitutor substitutor,
+ @NotNull PsiMethod sourceMethod,
+ List<PsiClassType> thrownTypes) {
+ for (PsiClassType thrownType : thrownTypes) {
targetThrowsList.add(factory.createReferenceElementByType((PsiClassType)substituteType(substitutor, thrownType, sourceMethod)));
}
}
@@ -504,7 +514,7 @@
PsiModifierList targetModifierList = targetParam.getModifierList();
if (sourceModifierList != null && targetModifierList != null) {
if (sourceParam.getLanguage() == targetParam.getLanguage()) {
- targetModifierList.replace(sourceModifierList);
+ targetModifierList = (PsiModifierList)targetModifierList.replace(sourceModifierList);
}
else {
JVMElementFactory factory = JVMElementFactories.requireFactory(targetParam.getLanguage(), targetParam.getProject());
@@ -515,6 +525,30 @@
targetModifierList.setModifierProperty(m, sourceParam.hasModifierProperty(m));
}
}
+ processAnnotations(sourceModifierList.getProject(), targetModifierList, targetModifierList.getResolveScope());
+ }
+ }
+
+ private static void processAnnotations(Project project, PsiModifierList modifierList, GlobalSearchScope moduleScope) {
+ final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+ final Set<String> toRemove = new HashSet<String>();
+ for (PsiAnnotation annotation : modifierList.getAnnotations()) {
+ final String qualifiedName = annotation.getQualifiedName();
+ if (qualifiedName != null) {
+ for (OverrideImplementsAnnotationsHandler handler : Extensions.getExtensions(OverrideImplementsAnnotationsHandler.EP_NAME)) {
+ final String[] annotations2Remove = handler.annotationsToRemove(project, qualifiedName);
+ Collections.addAll(toRemove, annotations2Remove);
+ if (moduleScope != null && psiFacade.findClass(qualifiedName, moduleScope) == null) {
+ toRemove.add(qualifiedName);
+ }
+ }
+ }
+ }
+ for (String fqn : toRemove) {
+ final PsiAnnotation psiAnnotation = modifierList.findAnnotation(fqn);
+ if (psiAnnotation != null) {
+ psiAnnotation.delete();
+ }
}
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateSetterHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateSetterHandler.java
index e33f1b8..76a2251 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateSetterHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateSetterHandler.java
@@ -29,7 +29,7 @@
protected GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException {
if (original instanceof PropertyClassMember) {
final PropertyClassMember propertyClassMember = (PropertyClassMember)original;
- final GenerationInfo[] getters = propertyClassMember.generateSetters();
+ final GenerationInfo[] getters = propertyClassMember.generateSetters(aClass);
if (getters != null) {
return getters;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GetterSetterPrototypeProvider.java b/java/java-impl/src/com/intellij/codeInsight/generation/GetterSetterPrototypeProvider.java
index 727bd81..5214457 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GetterSetterPrototypeProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GetterSetterPrototypeProvider.java
@@ -17,6 +17,7 @@
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
+import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
@@ -31,6 +32,17 @@
public abstract boolean canGeneratePrototypeFor(PsiField field);
public abstract PsiMethod[] generateGetters(PsiField field);
public abstract PsiMethod[] generateSetters(PsiField field);
+ public PsiMethod[] findGetters(PsiClass psiClass, String propertyName) {
+ return null;
+ }
+
+ public String suggestGetterName(String propertyName) {
+ return null;
+ }
+
+ public boolean isSimpleGetter(PsiMethod method, String oldPropertyName) {
+ return false;
+ }
public abstract boolean isReadOnly(PsiField field);
@@ -51,4 +63,27 @@
}
return field.hasModifierProperty(PsiModifier.FINAL);
}
+
+ public static PsiMethod[] findGetters(PsiClass aClass, String propertyName, boolean isStatic) {
+ if (!isStatic) {
+ for (GetterSetterPrototypeProvider provider : Extensions.getExtensions(EP_NAME)) {
+ final PsiMethod[] getterSetter = provider.findGetters(aClass, propertyName);
+ if (getterSetter != null) return getterSetter;
+ }
+ }
+ final PsiMethod propertyGetterSetter = PropertyUtil.findPropertyGetter(aClass, propertyName, isStatic, false);
+ if (propertyGetterSetter != null) {
+ return new PsiMethod[] {propertyGetterSetter};
+ }
+ return null;
+ }
+
+ public static String suggestNewGetterName(String oldPropertyName, String newPropertyName, PsiMethod method) {
+ for (GetterSetterPrototypeProvider provider : Extensions.getExtensions(EP_NAME)) {
+ if (provider.isSimpleGetter(method, oldPropertyName)) {
+ return provider.suggestGetterName(newPropertyName);
+ }
+ }
+ return null;
+ }
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
index 68c3684..53630f6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
@@ -435,17 +435,6 @@
Collection<CandidateInfo> secondary = toImplement || aClass.isInterface() ?
ContainerUtil.<CandidateInfo>newArrayList() : getMethodsToOverrideImplement(aClass, true);
- if (toImplement && PsiUtil.isLanguageLevel8OrHigher(aClass)) {
- for (Iterator<CandidateInfo> iterator = candidates.iterator(); iterator.hasNext(); ) {
- CandidateInfo candidate = iterator.next();
- PsiElement element = candidate.getElement();
- if (element instanceof PsiMethod && ((PsiMethod)element).hasModifierProperty(PsiModifier.DEFAULT)) {
- iterator.remove();
- secondary.add(candidate);
- }
- }
- }
-
final MemberChooser<PsiMethodMember> chooser = showOverrideImplementChooser(editor, aClass, toImplement, candidates, secondary);
if (chooser == null) return;
@@ -461,6 +450,9 @@
}.execute();
}
+ /**
+ * @param candidates, secondary should allow modifications
+ */
@Nullable
public static MemberChooser<PsiMethodMember> showOverrideImplementChooser(Editor editor,
final PsiElement aClass,
@@ -468,6 +460,17 @@
final Collection<CandidateInfo> candidates,
Collection<CandidateInfo> secondary) {
+ if (toImplement && PsiUtil.isLanguageLevel8OrHigher(aClass)) {
+ for (Iterator<CandidateInfo> iterator = candidates.iterator(); iterator.hasNext(); ) {
+ CandidateInfo candidate = iterator.next();
+ PsiElement element = candidate.getElement();
+ if (element instanceof PsiMethod && ((PsiMethod)element).hasModifierProperty(PsiModifier.DEFAULT)) {
+ iterator.remove();
+ secondary.add(candidate);
+ }
+ }
+ }
+
final JavaOverrideImplementMemberChooser chooser =
JavaOverrideImplementMemberChooser.create(aClass, toImplement, candidates, secondary);
if (chooser == null) {
@@ -612,7 +615,7 @@
finally {
PsiFile psiFile = psiClass.getContainingFile();
- Editor editor = fileEditorManager.openTextEditor(new OpenFileDescriptor(psiFile.getProject(), psiFile.getVirtualFile()), false);
+ Editor editor = fileEditorManager.openTextEditor(new OpenFileDescriptor(psiFile.getProject(), psiFile.getVirtualFile()), true);
if (editor != null && !results.isEmpty()) {
results.get(0).positionCaret(editor, true);
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/PropertyClassMember.java b/java/java-impl/src/com/intellij/codeInsight/generation/PropertyClassMember.java
index 006e5e5..7c5378f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/PropertyClassMember.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/PropertyClassMember.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.generation;
+import com.intellij.psi.PsiClass;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nullable;
@@ -25,13 +26,15 @@
public interface PropertyClassMember extends EncapsulatableClassMember {
/**
* @return PsiElement or TemplateGenerationInfo
+ * @param aClass
*/
@Nullable
- GenerationInfo[] generateGetters() throws IncorrectOperationException;
+ GenerationInfo[] generateGetters(PsiClass aClass) throws IncorrectOperationException;
/**
* @return PsiElement or TemplateGenerationInfo
+ * @param aClass
*/
@Nullable
- GenerationInfo[] generateSetters() throws IncorrectOperationException;
+ GenerationInfo[] generateSetters(PsiClass aClass) throws IncorrectOperationException;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java b/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java
index a4817c5..a14108b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java
@@ -42,38 +42,37 @@
@Nullable
@Override
public GenerationInfo generateGetter() throws IncorrectOperationException {
- final GenerationInfo[] infos = generateGetters();
+ final GenerationInfo[] infos = generateGetters(getElement().getContainingClass());
return infos != null && infos.length > 0 ? infos[0] : null;
}
@Nullable
@Override
- public GenerationInfo[] generateGetters() throws IncorrectOperationException {
- final PsiField field = getElement();
- return createGenerateInfos(field, GetterSetterPrototypeProvider.generateGetterSetters(field, true));
+ public GenerationInfo[] generateGetters(PsiClass aClass) throws IncorrectOperationException {
+ return createGenerateInfos(aClass, GetterSetterPrototypeProvider.generateGetterSetters(getElement(), true));
}
@Nullable
@Override
public GenerationInfo generateSetter() throws IncorrectOperationException {
- final GenerationInfo[] infos = generateSetters();
+ final GenerationInfo[] infos = generateSetters(getElement().getContainingClass());
return infos != null && infos.length > 0 ? infos[0] : null;
}
@Override
@Nullable
- public GenerationInfo[] generateSetters() {
+ public GenerationInfo[] generateSetters(PsiClass aClass) {
final PsiField field = getElement();
if (GetterSetterPrototypeProvider.isReadOnlyProperty(field)) {
return null;
}
- return createGenerateInfos(field, GetterSetterPrototypeProvider.generateGetterSetters(field, false));
+ return createGenerateInfos(aClass, GetterSetterPrototypeProvider.generateGetterSetters(field, false));
}
- private static GenerationInfo[] createGenerateInfos(PsiField field, PsiMethod[] prototypes) {
+ private static GenerationInfo[] createGenerateInfos(PsiClass aClass, PsiMethod[] prototypes) {
final List<GenerationInfo> methods = new ArrayList<GenerationInfo>();
for (PsiMethod prototype : prototypes) {
- final PsiMethod method = createMethodIfNotExists(field, prototype);
+ final PsiMethod method = createMethodIfNotExists(aClass, prototype);
if (method != null) {
methods.add(new PsiGenerationInfo(method));
}
@@ -82,8 +81,7 @@
}
@Nullable
- private static PsiMethod createMethodIfNotExists(final PsiField field, final PsiMethod template) {
- final PsiClass aClass = field.getContainingClass();
+ private static PsiMethod createMethodIfNotExists(PsiClass aClass, final PsiMethod template) {
PsiMethod existing = aClass.findMethodBySignature(template, false);
if (existing == null) {
if (template != null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/actions/GenerateCreateUIAction.java b/java/java-impl/src/com/intellij/codeInsight/generation/actions/GenerateCreateUIAction.java
index dee80a6..16ec3cc 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/actions/GenerateCreateUIAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/actions/GenerateCreateUIAction.java
@@ -17,6 +17,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTypesUtil;
+import com.intellij.util.containers.HashSet;
/**
* @author Konstantin Bulenkov
@@ -27,12 +28,12 @@
}
@Override
- protected boolean isValidForClass(PsiClass targetClass) {
+ public boolean isValidForClass(PsiClass targetClass) {
final PsiModifierList list = targetClass.getModifierList();
return list != null
&& !list.hasModifierProperty(PsiModifier.ABSTRACT)
&& !hasCreateUIMethod(targetClass)
- && isComponentUI(targetClass);
+ && isComponentUI(targetClass, new HashSet<PsiClass>());
}
private static boolean hasCreateUIMethod(PsiClass aClass) {
@@ -49,8 +50,9 @@
return false;
}
- private static boolean isComponentUI(PsiClass aClass) {
+ private static boolean isComponentUI(PsiClass aClass, HashSet<PsiClass> classes) {
while (aClass != null) {
+ if (!classes.add(aClass)) return false;
if ("javax.swing.plaf.ComponentUI".equals(aClass.getQualifiedName())) {
return true;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithTryFinallySurrounder.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithTryFinallySurrounder.java
index c9a13f6..e757dde 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithTryFinallySurrounder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithTryFinallySurrounder.java
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.generation.surroundWith;
import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
@@ -28,6 +29,8 @@
import org.jetbrains.annotations.NonNls;
class JavaWithTryFinallySurrounder extends JavaStatementsSurrounder{
+ private static final Logger LOG = Logger.getInstance("#" + JavaWithTryFinallySurrounder.class.getName());
+
@Override
public String getTemplateDescription() {
return CodeInsightBundle.message("surround.with.try.finally.template");
@@ -67,7 +70,9 @@
final Document document = editor.getDocument();
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
editor.getSelectionModel().removeSelection();
- final PsiStatement firstTryStmt = tryBlock.getStatements()[0];
+ final PsiStatement[] tryBlockStatements = tryBlock.getStatements();
+ LOG.assertTrue(tryBlockStatements.length > 0, tryBlock.getText());
+ final PsiStatement firstTryStmt = tryBlockStatements[0];
final int indent = firstTryStmt.getTextOffset() - document.getLineStartOffset(document.getLineNumber(firstTryStmt.getTextOffset()));
EditorModificationUtil.insertStringAtCaret(editor, StringUtil.repeat(" ", indent), false, true);
return new TextRange(editor.getCaretModel().getOffset(), editor.getCaretModel().getOffset());
diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
index 2e92545..9d6fe88 100644
--- a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
@@ -25,11 +25,7 @@
import com.intellij.codeInsight.daemon.impl.LocalInspectionsPass;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.InspectionProfile;
-import com.intellij.codeInspection.InspectionProfileEntry;
-import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
-import com.intellij.codeInspection.ex.InspectionManagerEx;
-import com.intellij.codeInspection.ex.InspectionProfileImpl;
-import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.ex.*;
import com.intellij.codeInspection.reference.RefManagerImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -122,20 +118,20 @@
if (!(value instanceof String)) {
continue;
}
- final InspectionProfileEntry toolById = ((InspectionProfileImpl)inspectionProfile).getToolById((String)value, target);
- if (!(toolById instanceof LocalInspectionToolWrapper)) {
+ InspectionToolWrapper toolWrapperById = ((InspectionProfileImpl)inspectionProfile).getToolById((String)value, target);
+ if (!(toolWrapperById instanceof LocalInspectionToolWrapper)) {
continue;
}
- final LocalInspectionToolWrapper tool = ((LocalInspectionToolWrapper)toolById).createCopy();
+ final LocalInspectionToolWrapper toolWrapper = ((LocalInspectionToolWrapper)toolWrapperById).createCopy();
final InspectionManagerEx managerEx = (InspectionManagerEx)InspectionManager.getInstance(project);
final GlobalInspectionContextImpl context = managerEx.createNewGlobalContext(false);
- tool.initialize(context);
+ toolWrapper.initialize(context);
((RefManagerImpl)context.getRefManager()).inspectionReadActionStarted();
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
Runnable inspect = new Runnable() {
@Override
public void run() {
- pass.doInspectInBatch(managerEx, Collections.<LocalInspectionToolWrapper>singletonList(tool));
+ pass.doInspectInBatch(managerEx, Collections.<LocalInspectionToolWrapper>singletonList(toolWrapper));
}
};
if (indicator == null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConcatenationToMessageFormatAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConcatenationToMessageFormatAction.java
index 544440f..9bc47e3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConcatenationToMessageFormatAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConcatenationToMessageFormatAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -25,7 +25,6 @@
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiConcatenationUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
@@ -60,7 +59,7 @@
if (concatenation == null) return;
StringBuilder formatString = new StringBuilder();
List<PsiExpression> args = new ArrayList<PsiExpression>();
- buildMessageFormatString(concatenation, formatString, args);
+ PsiConcatenationUtil.buildFormatString(concatenation, formatString, args, false);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiMethodCallExpression call = (PsiMethodCallExpression)
@@ -87,47 +86,6 @@
concatenation.replace(call);
}
- public static void buildMessageFormatString(PsiExpression expression,
- StringBuilder formatString,
- List<PsiExpression> args)
- throws IncorrectOperationException {
- PsiConcatenationUtil.buildFormatString(expression, formatString, args, false);
-
- }
-
- private static void appendArgument(List<PsiExpression> args, PsiExpression argument, StringBuilder formatString) throws IncorrectOperationException {
- formatString.append("{").append(args.size()).append("}");
- args.add(getBoxedArgument(argument));
- }
-
- private static PsiExpression getBoxedArgument(PsiExpression arg) throws IncorrectOperationException {
- arg = PsiUtil.deparenthesizeExpression(arg);
- assert arg != null;
- if (PsiUtil.isLanguageLevel5OrHigher(arg)) {
- return arg;
- }
- final PsiType type = arg.getType();
- if (!(type instanceof PsiPrimitiveType) || type.equals(PsiType.NULL)) {
- return arg;
- }
- final PsiPrimitiveType primitiveType = (PsiPrimitiveType)type;
- final String boxedQName = primitiveType.getBoxedTypeName();
- if (boxedQName == null) {
- return arg;
- }
- final GlobalSearchScope resolveScope = arg.getResolveScope();
- final PsiElementFactory factory = JavaPsiFacade.getElementFactory(arg.getProject());
- final PsiJavaCodeReferenceElement ref = factory.createReferenceElementByFQClassName(boxedQName, resolveScope);
- final PsiNewExpression newExpr = (PsiNewExpression)factory.createExpressionFromText("new A(b)", null);
- final PsiElement classRef = newExpr.getClassReference();
- assert classRef != null;
- classRef.replace(ref);
- final PsiExpressionList argumentList = newExpr.getArgumentList();
- assert argumentList != null;
- argumentList.getExpressions()[0].replace(arg);
- return newExpr;
- }
-
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (PsiUtil.getLanguageLevel(file).compareTo(LanguageLevel.JDK_1_4) < 0) return false;
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
index 51089f5..7b69611 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -18,6 +18,7 @@
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
+import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
@@ -42,6 +43,7 @@
if (element instanceof PsiCompiledElement) return false;
if (!element.getManager().isInProject(element)) return false;
+ if (!element.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return false;
final PsiElement context = PsiTreeUtil.getParentOfType(element, PsiDeclarationStatement.class, PsiClass.class);
if (context instanceof PsiDeclarationStatement) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocExternalFilter.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocExternalFilter.java
index 1713f6b..cac3b57 100644
--- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocExternalFilter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocExternalFilter.java
@@ -59,7 +59,7 @@
protected static @NonNls final Pattern ourAnchorsuffix = Pattern.compile("#(.*)$");
protected static @NonNls final Pattern ourHTMLFilesuffix = Pattern.compile("/([^/]*[.][hH][tT][mM][lL]?)$");
private static @NonNls final Pattern ourHREFselector = Pattern.compile("<A.*?HREF=\"([^>\"]*)\"", Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
- private static @NonNls final Pattern ourMethodHeading = Pattern.compile("<H3>(.+?)</H3>", Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
+ private static @NonNls final Pattern ourMethodHeading = Pattern.compile("<H[34]>(.+?)</H[34]>", Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
protected static @NonNls final String DOC_ELEMENT_PROTOCOL = "doc_element://";
@NonNls protected static final String H2 = "</H2>";
@NonNls protected static final String HTML_CLOSE = "</HTML>";
diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java
index 9fa4834..db14eca 100644
--- a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java
+++ b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java
@@ -169,8 +169,9 @@
PsiClass containingClass = field.getContainingClass();
if (containingClass != null && containingClass.getName() != null) {
- context.getDocument().insertString(context.getStartOffset(), ".");
+ OffsetKey oldStart = context.trackOffset(context.getStartOffset(), true);
JavaCompletionUtil.insertClassReference(containingClass, file, context.getStartOffset());
+ context.getDocument().insertString(context.getOffsetMap().getOffset(oldStart), ".");
PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument());
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/macro/MacroUtil.java b/java/java-impl/src/com/intellij/codeInsight/template/macro/MacroUtil.java
index 059c047..6010a7a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/macro/MacroUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/macro/MacroUtil.java
@@ -27,11 +27,13 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
public class MacroUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.template.macro.MacroUtil");
@@ -158,11 +160,15 @@
return new PsiVariable[0];
}
+ final Set<String> usedNames = ContainerUtil.newHashSet();
final List<PsiVariable> list = new ArrayList<PsiVariable>();
VariablesProcessor varproc = new VariablesProcessor(prefix, true, list) {
@Override
public boolean execute(@NotNull PsiElement pe, ResolveState state) {
if (pe instanceof PsiVariable) {
+ if (!usedNames.add(((PsiVariable)pe).getName())) {
+ return false;
+ }
//exclude variables that are initialized in 'place'
final PsiExpression initializer = ((PsiVariable)pe).getInitializer();
if (initializer != null && PsiTreeUtil.isAncestor(initializer, place, false)) return true;
diff --git a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java b/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
index f65d580..354af57 100644
--- a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
@@ -19,10 +19,8 @@
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction;
import com.intellij.codeInspection.ex.*;
-import com.intellij.codeInspection.reference.RefClass;
-import com.intellij.codeInspection.reference.RefElement;
-import com.intellij.codeInspection.reference.RefJavaVisitor;
-import com.intellij.codeInspection.reference.RefManagerImpl;
+import com.intellij.codeInspection.reference.*;
+import com.intellij.codeInspection.ui.InspectionToolPresentation;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -116,7 +114,7 @@
return checkElement(psiClass, manager, project);
}
- public CommonProblemDescriptor[] checkElement(@NotNull final PsiElement psiElement, @NotNull InspectionManager manager, @NotNull Project project) {
+ public CommonProblemDescriptor[] checkElement(@NotNull final PsiElement psiElement, @NotNull final InspectionManager manager, @NotNull Project project) {
final Map<PsiElement, Collection<String>> suppressedScopes = new THashMap<PsiElement, Collection<String>>();
psiElement.accept(new JavaRecursiveElementWalkingVisitor() {
@Override public void visitModifierList(PsiModifierList list) {
@@ -141,7 +139,7 @@
private void checkElement(final PsiElement owner) {
String idsString = SuppressManager.getInstance().getSuppressedInspectionIdsIn(owner);
- if (idsString != null && idsString.length() != 0) {
+ if (idsString != null && !idsString.isEmpty()) {
List<String> ids = StringUtil.split(idsString, ",");
if (IGNORE_ALL && (ids.contains(SuppressionUtil.ALL) || ids.contains(SuppressionUtil.ALL.toLowerCase()))) return;
Collection<String> suppressed = suppressedScopes.get(owner);
@@ -162,27 +160,29 @@
if (suppressedScopes.values().isEmpty()) return null;
// have to visit all file from scratch since inspections can be written in any perversive way including checkFile() overriding
- Collection<InspectionTool> suppressedTools = new THashSet<InspectionTool>();
- InspectionTool[] tools = getInspectionTools(psiElement, manager);
+ Collection<InspectionToolWrapper> suppressedTools = new THashSet<InspectionToolWrapper>();
+ InspectionToolWrapper[] toolWrappers = getInspectionTools(psiElement, manager);
for (Collection<String> ids : suppressedScopes.values()) {
for (Iterator<String> iterator = ids.iterator(); iterator.hasNext(); ) {
final String shortName = iterator.next().trim();
- for (InspectionTool tool : tools) {
- if (tool instanceof LocalInspectionToolWrapper && ((LocalInspectionToolWrapper)tool).getTool().getID().equals(shortName)) {
- if (!((LocalInspectionToolWrapper)tool).isUnfair()) {
- suppressedTools.add(tool);
- } else {
+ for (InspectionToolWrapper toolWrapper : toolWrappers) {
+ if (toolWrapper instanceof LocalInspectionToolWrapper && ((LocalInspectionToolWrapper)toolWrapper).getTool().getID().equals(shortName)) {
+ if (((LocalInspectionToolWrapper)toolWrapper).isUnfair()) {
iterator.remove();
break;
}
+ else {
+ suppressedTools.add(toolWrapper);
+ }
}
- else if (tool.getShortName().equals(shortName)) {
+ else if (toolWrapper.getShortName().equals(shortName)) {
//ignore global unused as it won't be checked anyway
- if (!(tool instanceof LocalInspectionToolWrapper) && !(tool instanceof GlobalInspectionToolWrapper)) {
+ if (toolWrapper instanceof LocalInspectionToolWrapper || toolWrapper instanceof GlobalInspectionToolWrapper) {
+ suppressedTools.add(toolWrapper);
+ }
+ else {
iterator.remove();
break;
- } else {
- suppressedTools.add(tool);
}
}
}
@@ -190,31 +190,44 @@
}
final AnalysisScope scope = new AnalysisScope(psiElement.getContainingFile());
- final InspectionManagerEx inspectionManagerEx = ((InspectionManagerEx)InspectionManager.getInstance(project));
- GlobalInspectionContextImpl globalContext = inspectionManagerEx.createNewGlobalContext(false);
+ final InspectionManagerEx inspectionManagerEx = (InspectionManagerEx)InspectionManager.getInstance(project);
+ final GlobalInspectionContextImpl globalContext = inspectionManagerEx.createNewGlobalContext(false);
globalContext.setCurrentScope(scope);
- final RefManagerImpl refManager = ((RefManagerImpl)globalContext.getRefManager());
+ final RefManagerImpl refManager = (RefManagerImpl)globalContext.getRefManager();
refManager.inspectionReadActionStarted();
final List<ProblemDescriptor> result;
try {
result = new ArrayList<ProblemDescriptor>();
- for (InspectionTool tool : suppressedTools) {
- String toolId = tool instanceof LocalInspectionToolWrapper ? ((LocalInspectionToolWrapper)tool).getTool().getID() : tool.getShortName();
- tool.initialize(globalContext);
+ for (InspectionToolWrapper toolWrapper : suppressedTools) {
+ String toolId = toolWrapper instanceof LocalInspectionToolWrapper ? ((LocalInspectionToolWrapper)toolWrapper).getTool().getID() : toolWrapper.getShortName();
+ toolWrapper.initialize(globalContext);
Collection<CommonProblemDescriptor> descriptors;
- if (tool instanceof LocalInspectionToolWrapper) {
- LocalInspectionToolWrapper local = (LocalInspectionToolWrapper)tool;
+ final InspectionToolPresentation presentation = globalContext.getPresentation(toolWrapper);
+ if (toolWrapper instanceof LocalInspectionToolWrapper) {
+ LocalInspectionToolWrapper local = (LocalInspectionToolWrapper)toolWrapper;
if (local.isUnfair()) continue; //cant't work with passes other than LocalInspectionPass
- local.processFile(psiElement.getContainingFile(), false, manager);
- descriptors = local.getProblemDescriptors();
+ List<ProblemDescriptor> results = local.getTool().processFile(psiElement.getContainingFile(), manager);
+ InspectionToolPresentation toolPresentation = globalContext.getPresentation(local);
+ LocalDescriptorsUtil.addProblemDescriptors(results, toolPresentation, false, globalContext, local.getTool());
+ descriptors = presentation.getProblemDescriptors();
}
- else if (tool instanceof GlobalInspectionToolWrapper) {
- GlobalInspectionToolWrapper global = (GlobalInspectionToolWrapper)tool;
- if (global.getTool().isGraphNeeded()) {
+ else if (toolWrapper instanceof GlobalInspectionToolWrapper) {
+ final GlobalInspectionToolWrapper global = (GlobalInspectionToolWrapper)toolWrapper;
+ GlobalInspectionTool globalTool = global.getTool();
+ if (globalTool.isGraphNeeded()) {
refManager.findAllDeclarations();
}
- global.processFile(scope, manager, globalContext, false);
- descriptors = global.getProblemDescriptors();
+ final InspectionToolPresentation toolPresentation = globalContext.getPresentation(global);
+ globalContext.getRefManager().iterate(new RefVisitor() {
+ @Override public void visitElement(@NotNull RefEntity refEntity) {
+ CommonProblemDescriptor[]
+ descriptors1 = global.getTool().checkElement(refEntity, scope, manager, globalContext, toolPresentation);
+ if (descriptors1 != null) {
+ toolPresentation.addProblemElement(refEntity, false, descriptors1);
+ }
+ }
+ });
+ descriptors = presentation.getProblemDescriptors();
}
else {
continue;
@@ -283,9 +296,8 @@
return result.toArray(new ProblemDescriptor[result.size()]);
}
- protected InspectionTool[] getInspectionTools(PsiElement psiElement, InspectionManager manager) {
- final ModifiableModel
- model = InspectionProjectProfileManager.getInstance(manager.getProject()).getInspectionProfile().getModifiableModel();
+ protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, @NotNull InspectionManager manager) {
+ ModifiableModel model = InspectionProjectProfileManager.getInstance(manager.getProject()).getInspectionProfile().getModifiableModel();
InspectionProfileWrapper profile = new InspectionProfileWrapper((InspectionProfile)model);
profile.init(manager.getProject());
diff --git a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java b/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
index 35a997f..105bee1 100644
--- a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
@@ -177,7 +177,8 @@
}
@Override
- protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext,
+ protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager,
+ @NotNull final GlobalJavaInspectionContext globalContext,
@NotNull final ProblemDescriptionsProcessor problemsProcessor) {
for (RefElement entryPoint : globalContext.getEntryPointsManager(manager).getEntryPoints()) {
problemsProcessor.ignoreElement(entryPoint);
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
index 348d3df..c22571a 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
@@ -46,6 +46,7 @@
}
private class OptionsPanel extends JPanel {
+ private final JCheckBox myIgnoreAssertions;
private final JCheckBox mySuggestNullables;
private final JCheckBox myDontReportTrueAsserts;
@@ -77,6 +78,15 @@
DONT_REPORT_TRUE_ASSERT_STATEMENTS = myDontReportTrueAsserts.isSelected();
}
});
+
+ myIgnoreAssertions = new JCheckBox("Ignore assert statements");
+ myIgnoreAssertions.setSelected(IGNORE_ASSERT_STATEMENTS);
+ myIgnoreAssertions.getModel().addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ IGNORE_ASSERT_STATEMENTS = myIgnoreAssertions.isSelected();
+ }
+ });
gc.insets = new Insets(0, 0, 0, 0);
gc.gridy = 0;
@@ -121,6 +131,9 @@
gc.insets.left = 0;
gc.gridy++;
add(myDontReportTrueAsserts, gc);
+
+ gc.gridy++;
+ add(myIgnoreAssertions, gc);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DeadHTMLComposer.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DeadHTMLComposer.java
index 9b5cb30..88f5618 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DeadHTMLComposer.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DeadHTMLComposer.java
@@ -28,8 +28,8 @@
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ex.DescriptorComposer;
import com.intellij.codeInspection.ex.HTMLComposerImpl;
-import com.intellij.codeInspection.ex.InspectionTool;
import com.intellij.codeInspection.reference.*;
+import com.intellij.codeInspection.ui.InspectionToolPresentation;
import com.intellij.codeInspection.ui.InspectionTreeNode;
import com.intellij.codeInspection.ui.RefElementNode;
import org.jetbrains.annotations.NonNls;
@@ -41,11 +41,11 @@
import java.util.Set;
public class DeadHTMLComposer extends HTMLComposerImpl {
- private final InspectionTool myTool;
+ private final InspectionToolPresentation myToolPresentation;
private final HTMLJavaHTMLComposer myComposer;
- public DeadHTMLComposer(@NotNull InspectionTool tool) {
- myTool = tool;
+ public DeadHTMLComposer(@NotNull InspectionToolPresentation presentation) {
+ myToolPresentation = presentation;
myComposer = getExtension(HTMLJavaHTMLComposer.COMPOSER);
}
@@ -64,7 +64,7 @@
//noinspection HardCodedStringLiteral
buf.append("<br><br>");
- appendResolution(buf, refElement, DescriptorComposer.quickFixTexts(refElement, myTool));
+ appendResolution(buf, refElement, DescriptorComposer.quickFixTexts(refElement, myToolPresentation));
refElement.accept(new RefJavaVisitor() {
@Override public void visitClass(@NotNull RefClass aClass) {
appendClassInstantiations(buf, aClass);
@@ -339,7 +339,7 @@
}
private void appendCallesList(RefElement element, StringBuffer buf, Set<RefElement> mentionedElements, boolean appendCallees){
- final Set<RefElement> possibleChildren = getPossibleChildren(new RefElementNode(element, myTool), element);
+ final Set<RefElement> possibleChildren = getPossibleChildren(new RefElementNode(element, myToolPresentation), element);
if (!possibleChildren.isEmpty()) {
if (appendCallees){
appendHeading(buf, InspectionsBundle.message("inspection.export.results.callees"));
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
new file mode 100644
index 0000000..531c88c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2013 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.codeInspection.deadCode;
+
+import com.intellij.codeInspection.InspectionsBundle;
+import com.intellij.codeInspection.ex.*;
+import com.intellij.codeInspection.reference.RefElement;
+import com.intellij.codeInspection.reference.RefEntity;
+import com.intellij.codeInspection.ui.InspectionNode;
+import com.intellij.codeInspection.ui.InspectionTreeNode;
+import com.intellij.codeInspection.util.RefFilter;
+import org.jetbrains.annotations.NotNull;
+
+public class DummyEntryPointsPresentation extends UnusedDeclarationPresentation {
+ private static final RefEntryPointFilter myFilter = new RefEntryPointFilter();
+ private QuickFixAction[] myQuickFixActions;
+
+ public DummyEntryPointsPresentation(UnusedDeclarationInspection inspection, @NotNull InspectionToolWrapper toolWrapper) {
+ super(toolWrapper);
+ }
+
+ @Override
+ public RefFilter getFilter() {
+ return myFilter;
+ }
+
+ @Override
+ public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements) {
+ if (myQuickFixActions == null) {
+ myQuickFixActions = new QuickFixAction[]{new MoveEntriesToSuspicious(getToolWrapper())};
+ }
+ return myQuickFixActions;
+ }
+
+ private class MoveEntriesToSuspicious extends QuickFixAction {
+ private MoveEntriesToSuspicious(@NotNull InspectionToolWrapper toolWrapper) {
+ super(InspectionsBundle.message("inspection.dead.code.remove.from.entry.point.quickfix"), null, null, toolWrapper);
+ }
+
+ @Override
+ protected boolean applyFix(RefEntity[] refElements) {
+ final EntryPointsManager entryPointsManager =
+ getContext().getExtension(GlobalJavaInspectionContextImpl.CONTEXT).getEntryPointsManager(getContext().getRefManager());
+ for (RefEntity refElement : refElements) {
+ if (refElement instanceof RefElement) {
+ entryPointsManager.removeEntryPoint((RefElement)refElement);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ @NotNull
+ @Override
+ public InspectionNode createToolNode(@NotNull GlobalInspectionContextImpl context, @NotNull InspectionNode node,
+ @NotNull InspectionRVContentProvider provider,
+ @NotNull InspectionTreeNode parentNode,
+ boolean showStructure) {
+ return node;
+ }
+
+ @Override
+ @NotNull
+ public HTMLComposerImpl getComposer() {
+ return new DeadHTMLComposer(this);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
index 1b8ef74..524f333 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
@@ -19,39 +19,31 @@
import com.intellij.codeInspection.GlobalInspectionContext;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.codeInspection.ex.*;
-import com.intellij.codeInspection.reference.RefElement;
-import com.intellij.codeInspection.reference.RefEntity;
-import com.intellij.codeInspection.util.RefFilter;
-import org.jdom.Element;
+import com.intellij.codeInspection.ProblemDescriptionsProcessor;
+import com.intellij.codeInspection.ex.InspectionPresentationProvider;
+import com.intellij.codeInspection.ex.InspectionToolWrapper;
+import com.intellij.codeInspection.ex.JobDescriptor;
+import com.intellij.codeInspection.ui.InspectionToolPresentation;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* @author max
*/
-public class DummyEntryPointsTool extends FilteringInspectionTool {
- private static final RefEntryPointFilter myFilter = new RefEntryPointFilter();
- private QuickFixAction[] myQuickFixActions;
-
- public DummyEntryPointsTool(@NotNull UnusedDeclarationInspection owner) {
- initialize(owner.getContext());
+public class DummyEntryPointsTool extends UnusedDeclarationInspection implements InspectionPresentationProvider {
+ public DummyEntryPointsTool() {
}
@Override
- public RefFilter getFilter() {
- return myFilter;
+ public void runInspection(@NotNull AnalysisScope scope,
+ @NotNull InspectionManager manager,
+ @NotNull GlobalInspectionContext globalContext,
+ @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) {
}
+ @Nullable
@Override
- public void runInspection(@NotNull AnalysisScope scope, @NotNull final InspectionManager manager) {}
-
- @Override
- public void exportResults(@NotNull Element parentNode, @NotNull RefEntity refEntity) {
- }
-
- @Override
- @NotNull
- public JobDescriptor[] getJobDescriptors(@NotNull GlobalInspectionContext globalInspectionContext) {
+ public JobDescriptor[] getAdditionalJobs() {
return JobDescriptor.EMPTY_ARRAY;
}
@@ -73,34 +65,9 @@
return "";
}
- @Override
@NotNull
- public HTMLComposerImpl getComposer() {
- return new DeadHTMLComposer(this);
- }
-
@Override
- public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements) {
- if (myQuickFixActions == null) {
- myQuickFixActions = new QuickFixAction[]{new MoveEntriesToSuspicious()};
- }
- return myQuickFixActions;
- }
-
- private class MoveEntriesToSuspicious extends QuickFixAction {
- private MoveEntriesToSuspicious() {
- super(InspectionsBundle.message("inspection.dead.code.remove.from.entry.point.quickfix"), null, null, DummyEntryPointsTool.this);
- }
-
- @Override
- protected boolean applyFix(RefElement[] refElements) {
- final EntryPointsManager entryPointsManager =
- getContext().getExtension(GlobalJavaInspectionContextImpl.CONTEXT).getEntryPointsManager(getContext().getRefManager());
- for (RefElement refElement : refElements) {
- entryPointsManager.removeEntryPoint(refElement);
- }
-
- return true;
- }
+ public InspectionToolPresentation createPresentation(@NotNull InspectionToolWrapper toolWrapper) {
+ return new DummyEntryPointsPresentation(this, toolWrapper);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java
index 5984cf1..b00d749 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java
@@ -24,17 +24,19 @@
*/
package com.intellij.codeInspection.deadCode;
-import com.intellij.codeInspection.ex.InspectionTool;
+import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
import com.intellij.codeInspection.reference.*;
import com.intellij.codeInspection.util.RefFilter;
import org.jetbrains.annotations.NotNull;
public class RefUnreachableFilter extends RefFilter {
@NotNull
- protected InspectionTool myTool;
+ protected UnusedDeclarationInspection myTool;
+ @NotNull protected final GlobalInspectionContextImpl myContext;
- public RefUnreachableFilter(@NotNull InspectionTool tool) {
+ public RefUnreachableFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
myTool = tool;
+ myContext = context;
}
@Override
@@ -42,7 +44,7 @@
if (refElement instanceof RefParameter) return 0;
if (refElement.isSyntheticJSP()) return 0;
if (!(refElement instanceof RefMethod || refElement instanceof RefClass || refElement instanceof RefField)) return 0;
- if (!myTool.getContext().isToCheckMember(refElement, myTool)) return 0;
+ if (!myContext.isToCheckMember(refElement, myTool)) return 0;
return ((RefElementImpl)refElement).isSuspicious() ? 1 : 0;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java
index 32dc522..923e577 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java
@@ -24,13 +24,13 @@
*/
package com.intellij.codeInspection.deadCode;
-import com.intellij.codeInspection.ex.InspectionTool;
+import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
import com.intellij.codeInspection.reference.*;
import org.jetbrains.annotations.NotNull;
public class UnreferencedFilter extends RefUnreachableFilter {
- public UnreferencedFilter(@NotNull InspectionTool tool) {
- super(tool);
+ public UnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
+ super(tool, context);
}
@Override
@@ -39,7 +39,7 @@
if (refElement.isEntry() || !((RefElementImpl)refElement).isSuspicious() || refElement.isSyntheticJSP()) return 0;
if (!(refElement instanceof RefMethod || refElement instanceof RefClass || refElement instanceof RefField)) return 0;
- if (!myTool.getContext().isToCheckMember(refElement, myTool)) return 0;
+ if (!myContext.isToCheckMember(refElement, myTool)) return 0;
if (refElement instanceof RefField) {
RefField refField = (RefField) refElement;
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
index fa341a0..7799cc2 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
@@ -31,27 +31,17 @@
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtilBase;
-import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.*;
import com.intellij.codeInspection.reference.*;
-import com.intellij.codeInspection.ui.EntryPointsNode;
-import com.intellij.codeInspection.ui.InspectionNode;
-import com.intellij.codeInspection.ui.InspectionTreeNode;
+import com.intellij.codeInspection.ui.InspectionToolPresentation;
import com.intellij.codeInspection.util.RefFilter;
-import com.intellij.icons.AllIcons;
-import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiClassImplUtil;
@@ -59,15 +49,9 @@
import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.util.PsiMethodUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtilCore;
-import com.intellij.refactoring.safeDelete.SafeDeleteHandler;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SeparatorFactory;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
-import com.intellij.util.text.CharArrayUtil;
-import com.intellij.util.text.DateFormatUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -77,40 +61,27 @@
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
import java.util.*;
import java.util.List;
-public class UnusedDeclarationInspection extends FilteringInspectionTool {
+public class UnusedDeclarationInspection extends GlobalInspectionTool implements InspectionPresentationProvider {
public boolean ADD_MAINS_TO_ENTRIES = true;
public boolean ADD_APPLET_TO_ENTRIES = true;
public boolean ADD_SERVLET_TO_ENTRIES = true;
public boolean ADD_NONJAVA_TO_ENTRIES = true;
- private HashSet<RefElement> myProcessedSuspicious = null;
+ private Set<RefElement> myProcessedSuspicious = null;
private int myPhase;
- private final QuickFixAction[] myQuickFixActions;
public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.dead.code.display.name");
- private WeakUnreferencedFilter myFilter;
- private DeadHTMLComposer myComposer;
@NonNls public static final String SHORT_NAME = "UnusedDeclaration";
@NonNls private static final String ALTERNATIVE_ID = "unused";
- private static final String COMMENT_OUT_QUICK_FIX = InspectionsBundle.message("inspection.dead.code.comment.quickfix");
- private static final String DELETE_QUICK_FIX = InspectionsBundle.message("inspection.dead.code.safe.delete.quickfix");
-
- @NonNls private static final String DELETE = "delete";
- @NonNls private static final String COMMENT = "comment";
- @NonNls private static final String [] HINTS = {COMMENT, DELETE};
-
public final EntryPoint[] myExtensions;
private static final Logger LOG = Logger.getInstance("#" + UnusedDeclarationInspection.class.getName());
+ private GlobalInspectionContextImpl myContext;
public UnusedDeclarationInspection() {
-
- myQuickFixActions = new QuickFixAction[]{new PermanentDeleteAction(), new CommentOutBin(), new MoveToEntries()};
ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL);
final EntryPoint[] deadCodeAddins = new EntryPoint[point.getExtensions().length];
EntryPoint[] extensions = point.getExtensions();
@@ -132,10 +103,8 @@
myExtensions = deadCodeAddins;
}
- @Override
- public void initialize(@NotNull final GlobalInspectionContextImpl context) {
- super.initialize(context);
- ((EntryPointsManagerImpl)getEntryPointsManager()).setAddNonJavaEntries(ADD_NONJAVA_TO_ENTRIES);
+ private GlobalInspectionContextImpl getContext() {
+ return myContext;
}
private class OptionsPanel extends JPanel {
@@ -368,9 +337,13 @@
}
@Override
- public void runInspection(@NotNull final AnalysisScope scope, @NotNull final InspectionManager manager) {
- getRefManager().iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull final RefEntity refEntity) {
+ public void runInspection(@NotNull final AnalysisScope scope,
+ @NotNull InspectionManager manager,
+ @NotNull final GlobalInspectionContext globalContext,
+ @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) {
+ globalContext.getRefManager().iterate(new RefJavaVisitor() {
+ @Override
+ public void visitElement(@NotNull final RefEntity refEntity) {
if (refEntity instanceof RefJavaElement) {
final RefElementImpl refElement = (RefElementImpl)refEntity;
if (!refElement.isSuspicious()) return;
@@ -379,7 +352,7 @@
if (file == null) return;
final boolean isSuppressed = refElement.isSuppressed(getShortName(), ALTERNATIVE_ID);
- if (!getContext().isToCheckFile(file, UnusedDeclarationInspection.this) || isSuppressed) {
+ if (!((GlobalInspectionContextImpl)globalContext).isToCheckFile(file, UnusedDeclarationInspection.this) || isSuppressed) {
if (isSuppressed || !scope.contains(file)) {
getEntryPointsManager().addEntryPoint(refElement, false);
}
@@ -387,13 +360,15 @@
}
refElement.accept(new RefJavaVisitor() {
- @Override public void visitMethod(@NotNull RefMethod method) {
+ @Override
+ public void visitMethod(@NotNull RefMethod method) {
if (isAddMainsEnabled() && method.isAppMain()) {
getEntryPointsManager().addEntryPoint(method, false);
}
}
- @Override public void visitClass(@NotNull RefClass aClass) {
+ @Override
+ public void visitClass(@NotNull RefClass aClass) {
if (isAddAppletEnabled() && aClass.isApplet() ||
isAddServletEnabled() && aClass.isServlet()) {
getEntryPointsManager().addEntryPoint(aClass, false);
@@ -406,19 +381,21 @@
if (isAddNonJavaUsedEnabled()) {
checkForReachables();
+ final StrictUnreferencedFilter strictUnreferencedFilter = new StrictUnreferencedFilter(this,
+ (GlobalInspectionContextImpl)globalContext);
ProgressManager.getInstance().runProcess(new Runnable() {
@Override
public void run() {
- final RefFilter filter = new StrictUnreferencedFilter(UnusedDeclarationInspection.this);
- final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(getRefManager().getProject());
- getRefManager().iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull final RefEntity refEntity) {
- if (refEntity instanceof RefClass && filter.accepts((RefClass)refEntity)) {
+ final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(globalContext.getRefManager().getProject());
+ globalContext.getRefManager().iterate(new RefJavaVisitor() {
+ @Override
+ public void visitElement(@NotNull final RefEntity refEntity) {
+ if (refEntity instanceof RefClass && strictUnreferencedFilter.accepts((RefClass)refEntity)) {
findExternalClassReferences((RefClass)refEntity);
}
else if (refEntity instanceof RefMethod) {
RefMethod refMethod = (RefMethod)refEntity;
- if (refMethod.isConstructor() && filter.accepts(refMethod)) {
+ if (refMethod.isConstructor() && strictUnreferencedFilter.accepts(refMethod)) {
findExternalClassReferences(refMethod.getOwnerClass());
}
}
@@ -436,7 +413,7 @@
return false;
}
},
- GlobalSearchScope.projectScope(getContext().getProject()));
+ GlobalSearchScope.projectScope(globalContext.getProject()));
}
}
});
@@ -514,9 +491,10 @@
return false;
}
+
private static class StrictUnreferencedFilter extends UnreferencedFilter {
- private StrictUnreferencedFilter(@NotNull InspectionTool tool) {
- super(tool);
+ private StrictUnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
+ super(tool, context);
}
@Override
@@ -527,34 +505,25 @@
}
}
- private static class WeakUnreferencedFilter extends UnreferencedFilter {
- private WeakUnreferencedFilter(@NotNull InspectionTool tool) {
- super(tool);
- }
-
- @Override
- public int getElementProblemCount(final RefJavaElement refElement) {
- final int problemCount = super.getElementProblemCount(refElement);
- if (problemCount > - 1) return problemCount;
- if (!((RefElementImpl)refElement).hasSuspiciousCallers() || ((RefJavaElementImpl)refElement).isSuspiciousRecursive()) return 1;
- return 0;
- }
- }
-
@Override
- public boolean queryExternalUsagesRequests(@NotNull final InspectionManager manager) {
+ public boolean queryExternalUsagesRequests(@NotNull InspectionManager manager,
+ @NotNull GlobalInspectionContext globalContext,
+ @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) {
checkForReachables();
- final RefFilter filter = myPhase == 1 ? new StrictUnreferencedFilter(this) : new RefUnreachableFilter(this);
+ final RefFilter filter = myPhase == 1 ? new StrictUnreferencedFilter(this, (GlobalInspectionContextImpl)globalContext) :
+ new RefUnreachableFilter(this, (GlobalInspectionContextImpl)globalContext);
final boolean[] requestAdded = {false};
- getRefManager().iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull RefEntity refEntity) {
+ globalContext.getRefManager().iterate(new RefJavaVisitor() {
+ @Override
+ public void visitElement(@NotNull RefEntity refEntity) {
if (!(refEntity instanceof RefJavaElement)) return;
if (refEntity instanceof RefClass && ((RefClass)refEntity).isAnonymous()) return;
- RefJavaElement refElement= (RefJavaElement)refEntity;
+ RefJavaElement refElement = (RefJavaElement)refEntity;
if (filter.accepts(refElement) && !myProcessedSuspicious.contains(refElement)) {
refEntity.accept(new RefJavaVisitor() {
- @Override public void visitField(@NotNull final RefField refField) {
+ @Override
+ public void visitField(@NotNull final RefField refField) {
myProcessedSuspicious.add(refField);
PsiField psiField = refField.getElement();
if (isSerializationImplicitlyUsedField(psiField)) {
@@ -572,7 +541,8 @@
}
}
- @Override public void visitMethod(@NotNull final RefMethod refMethod) {
+ @Override
+ public void visitMethod(@NotNull final RefMethod refMethod) {
myProcessedSuspicious.add(refMethod);
if (refMethod instanceof RefImplicitConstructor) {
visitClass(refMethod.getOwnerClass());
@@ -593,7 +563,8 @@
}
}
- @Override public void visitClass(@NotNull final RefClass refClass) {
+ @Override
+ public void visitClass(@NotNull final RefClass refClass) {
myProcessedSuspicious.add(refClass);
if (!refClass.isAnonymous()) {
getJavaContext().enqueueDerivedClassesProcessor(refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() {
@@ -654,295 +625,24 @@
}
}
- public GlobalJavaInspectionContext getJavaContext() {
+ private GlobalJavaInspectionContext getJavaContext() {
return getContext().getExtension(GlobalJavaInspectionContext.CONTEXT);
}
- @Override
- public RefFilter getFilter() {
- if (myFilter == null) {
- myFilter = new WeakUnreferencedFilter(this);
- }
- return myFilter;
- }
-
- @Override
- @NotNull
- public HTMLComposerImpl getComposer() {
- if (myComposer == null) {
- myComposer = new DeadHTMLComposer(this);
- }
- return myComposer;
- }
-
- @Override
- public void exportResults(@NotNull final Element parentNode, @NotNull RefEntity refEntity) {
- if (!(refEntity instanceof RefJavaElement)) return;
- final WeakUnreferencedFilter filter = new WeakUnreferencedFilter(this);
- if (!getIgnoredRefElements().contains(refEntity) && filter.accepts((RefJavaElement)refEntity)) {
- if (refEntity instanceof RefImplicitConstructor) refEntity = ((RefImplicitConstructor)refEntity).getOwnerClass();
- Element element = refEntity.getRefManager().export(refEntity, parentNode, -1);
- if (element == null) return;
- @NonNls Element problemClassElement = new Element(InspectionsBundle.message("inspection.export.results.problem.element.tag"));
-
- final RefElement refElement = (RefElement)refEntity;
- final HighlightSeverity severity = getCurrentSeverity(refElement);
- final String attributeKey =
- getTextAttributeKey(refElement.getRefManager().getProject(), severity, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
- problemClassElement.setAttribute("severity", severity.myName);
- problemClassElement.setAttribute("attribute_key", attributeKey);
-
- problemClassElement.addContent(InspectionsBundle.message("inspection.export.results.dead.code"));
- element.addContent(problemClassElement);
-
- @NonNls Element hintsElement = new Element("hints");
-
- for (String hint : HINTS) {
- @NonNls Element hintElement = new Element("hint");
- hintElement.setAttribute("value", hint);
- hintsElement.addContent(hintElement);
- }
- element.addContent(hintsElement);
-
-
- Element descriptionElement = new Element(InspectionsBundle.message("inspection.export.results.description.tag"));
- StringBuffer buf = new StringBuffer();
- DeadHTMLComposer.appendProblemSynopsis((RefElement)refEntity, buf);
- descriptionElement.addContent(buf.toString());
- element.addContent(descriptionElement);
- }
- }
-
- @Override
- public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements) {
- return myQuickFixActions;
- }
-
- @NotNull
- @Override
- public JobDescriptor[] getJobDescriptors(@NotNull GlobalInspectionContext context) {
- return new JobDescriptor[]{context.getStdJobDescriptors().BUILD_GRAPH,
- context.getStdJobDescriptors().FIND_EXTERNAL_USAGES};
- }
-
- private static void commentOutDead(PsiElement psiElement) {
- PsiFile psiFile = psiElement.getContainingFile();
-
- if (psiFile != null) {
- Document doc = PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(psiFile);
- if (doc != null) {
- TextRange textRange = psiElement.getTextRange();
- String date = DateFormatUtil.formatDateTime(new Date());
-
- int startOffset = textRange.getStartOffset();
- CharSequence chars = doc.getCharsSequence();
- while (CharArrayUtil.regionMatches(chars, startOffset, InspectionsBundle.message("inspection.dead.code.comment"))) {
- int line = doc.getLineNumber(startOffset) + 1;
- if (line < doc.getLineCount()) {
- startOffset = doc.getLineStartOffset(line);
- startOffset = CharArrayUtil.shiftForward(chars, startOffset, " \t");
- }
- }
-
- int endOffset = textRange.getEndOffset();
-
- int line1 = doc.getLineNumber(startOffset);
- int line2 = doc.getLineNumber(endOffset - 1);
-
- if (line1 == line2) {
- doc.insertString(startOffset, InspectionsBundle.message("inspection.dead.code.date.comment", date));
- }
- else {
- for (int i = line1; i <= line2; i++) {
- doc.insertString(doc.getLineStartOffset(i), "//");
- }
-
- doc.insertString(doc.getLineStartOffset(Math.min(line2 + 1, doc.getLineCount() - 1)),
- InspectionsBundle.message("inspection.dead.code.stop.comment", date));
- doc.insertString(doc.getLineStartOffset(line1), InspectionsBundle.message("inspection.dead.code.start.comment", date));
- }
- }
- }
- }
-
- @Override
@Nullable
- public IntentionAction findQuickFixes(final CommonProblemDescriptor descriptor, final String hint) {
- if (descriptor instanceof ProblemDescriptor) {
- if (DELETE.equals(hint)) {
- return new PermanentDeleteFix(((ProblemDescriptor)descriptor).getPsiElement());
- }
- if (COMMENT.equals(hint)) {
- return new CommentOutFix(((ProblemDescriptor)descriptor).getPsiElement());
- }
- }
- return null;
+ @Override
+ public JobDescriptor[] getAdditionalJobs() {
+ return new JobDescriptor[]{getContext().getStdJobDescriptors().BUILD_GRAPH, getContext().getStdJobDescriptors().FIND_EXTERNAL_USAGES};
}
- private class PermanentDeleteAction extends QuickFixAction {
- private PermanentDeleteAction() {
- super(DELETE_QUICK_FIX, AllIcons.Actions.Cancel, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), UnusedDeclarationInspection.this);
- }
- @Override
- protected boolean applyFix(final RefElement[] refElements) {
- if (!super.applyFix(refElements)) return false;
- final ArrayList<PsiElement> psiElements = new ArrayList<PsiElement>();
- for (RefElement refElement : refElements) {
- PsiElement psiElement = refElement.getElement();
- if (psiElement == null) continue;
- if (getFilter().getElementProblemCount((RefJavaElement)refElement) == 0) continue;
- psiElements.add(psiElement);
- }
-
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- final Project project = getContext().getProject();
- SafeDeleteHandler.invoke(project, PsiUtilCore.toPsiElementArray(psiElements), false, new Runnable() {
- @Override
- public void run() {
- removeElements(refElements, project, UnusedDeclarationInspection.this);
- }
- });
- }
- });
-
- return false; //refresh after safe delete dialog is closed
- }
- }
-
- private static class PermanentDeleteFix implements IntentionAction {
- private final PsiElement myElement;
-
- private PermanentDeleteFix(final PsiElement element) {
- myElement = element;
- }
-
- @Override
- @NotNull
- public String getText() {
- return DELETE_QUICK_FIX;
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getText();
- }
-
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return true;
- }
-
- @Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- if (myElement != null && myElement.isValid()) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- SafeDeleteHandler
- .invoke(myElement.getProject(), new PsiElement[]{PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class)}, false);
- }
- });
- }
- }
-
- @Override
- public boolean startInWriteAction() {
- return true;
- }
- }
-
- private class CommentOutBin extends QuickFixAction {
- private CommentOutBin() {
- super(COMMENT_OUT_QUICK_FIX, null, KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, SystemInfo.isMac ? InputEvent.META_MASK : InputEvent.CTRL_MASK),
- UnusedDeclarationInspection.this);
- }
-
- @Override
- protected boolean applyFix(RefElement[] refElements) {
- if (!super.applyFix(refElements)) return false;
- ArrayList<RefElement> deletedRefs = new ArrayList<RefElement>(1);
- for (RefElement refElement : refElements) {
- PsiElement psiElement = refElement.getElement();
- if (psiElement == null) continue;
- if (getFilter().getElementProblemCount((RefJavaElement)refElement) == 0) continue;
- commentOutDead(psiElement);
- refElement.getRefManager().removeRefElement(refElement, deletedRefs);
- }
-
- EntryPointsManager entryPointsManager = getEntryPointsManager();
- for (RefElement refElement : deletedRefs) {
- entryPointsManager.removeEntryPoint(refElement);
- }
-
- return true;
- }
- }
-
- private static class CommentOutFix implements IntentionAction {
- private final PsiElement myElement;
-
- private CommentOutFix(final PsiElement element) {
- myElement = element;
- }
-
- @Override
- @NotNull
- public String getText() {
- return COMMENT_OUT_QUICK_FIX;
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getText();
- }
-
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return true;
- }
-
- @Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- if (myElement != null && myElement.isValid()) {
- commentOutDead(PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class));
- }
- }
-
- @Override
- public boolean startInWriteAction() {
- return true;
- }
- }
-
- private class MoveToEntries extends QuickFixAction {
- private MoveToEntries() {
- super(InspectionsBundle.message("inspection.dead.code.entry.point.quickfix"), null, KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), UnusedDeclarationInspection.this);
- }
-
- @Override
- protected boolean applyFix(RefElement[] refElements) {
- final EntryPointsManager entryPointsManager = getEntryPointsManager();
- for (RefElement refElement : refElements) {
- entryPointsManager.addEntryPoint(refElement, true);
- }
-
- return true;
- }
-
-
- }
-
- private void checkForReachables() {
+ void checkForReachables() {
CodeScanner codeScanner = new CodeScanner();
// Cleanup previous reachability information.
- getRefManager().iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull RefEntity refEntity) {
+ getContext().getRefManager().iterate(new RefJavaVisitor() {
+ @Override
+ public void visitElement(@NotNull RefEntity refEntity) {
if (refEntity instanceof RefJavaElement) {
final RefJavaElementImpl refElement = (RefJavaElementImpl)refEntity;
if (!getContext().isToCheckMember(refElement, UnusedDeclarationInspection.this)) return;
@@ -1094,17 +794,27 @@
}
}
+
+ @NotNull
@Override
- public void updateContent() {
- checkForReachables();
- super.updateContent();
+ public InspectionToolPresentation createPresentation(@NotNull InspectionToolWrapper toolWrapper) {
+ return new UnusedDeclarationPresentation(toolWrapper);
}
@Override
- public InspectionNode createToolNode(@NotNull final InspectionRVContentProvider provider, final InspectionTreeNode parentNode, final boolean showStructure) {
- final InspectionNode toolNode = super.createToolNode(provider, parentNode, showStructure);
- final EntryPointsNode entryPointsNode = new EntryPointsNode(this);
- provider.appendToolNodeContent(entryPointsNode, toolNode, showStructure);
- return entryPointsNode;
+ public void initialize(@NotNull GlobalInspectionContext context) {
+ super.initialize(context);
+ myContext = (GlobalInspectionContextImpl)context;
+ }
+
+ @Override
+ public void cleanup() {
+ super.cleanup();
+ myContext = null;
+ }
+
+ @Override
+ public boolean isGraphNeeded() {
+ return true;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
new file mode 100644
index 0000000..29f0578
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright 2000-2013 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.codeInspection.deadCode;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.*;
+import com.intellij.codeInspection.ex.*;
+import com.intellij.codeInspection.reference.*;
+import com.intellij.codeInspection.ui.*;
+import com.intellij.codeInspection.util.RefFilter;
+import com.intellij.icons.AllIcons;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vcs.FileStatus;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiModifierListOwner;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.refactoring.safeDelete.SafeDeleteHandler;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.text.CharArrayUtil;
+import com.intellij.util.text.DateFormatUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.*;
+
+public class UnusedDeclarationPresentation extends DefaultInspectionToolPresentation {
+ private Map<String, Set<RefEntity>> myPackageContents = new HashMap<String, Set<RefEntity>>();
+
+ private Map<String, Set<RefEntity>> myOldPackageContents = null;
+
+ private final Set<RefEntity> myIgnoreElements = new HashSet<RefEntity>();
+ private WeakUnreferencedFilter myFilter;
+ private DeadHTMLComposer myComposer;
+ @NonNls private static final String DELETE = "delete";
+ @NonNls private static final String COMMENT = "comment";
+ @NonNls private static final String [] HINTS = {COMMENT, DELETE};
+
+ public UnusedDeclarationPresentation(@NotNull InspectionToolWrapper toolWrapper) {
+ super(toolWrapper);
+ myQuickFixActions = createQuickFixes(toolWrapper);
+ }
+
+ public RefFilter getFilter() {
+ if (myFilter == null) {
+ myFilter = new WeakUnreferencedFilter(getTool(), getContext());
+ }
+ return myFilter;
+ }
+ private static class WeakUnreferencedFilter extends UnreferencedFilter {
+ private WeakUnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
+ super(tool, context);
+ }
+
+ @Override
+ public int getElementProblemCount(final RefJavaElement refElement) {
+ final int problemCount = super.getElementProblemCount(refElement);
+ if (problemCount > - 1) return problemCount;
+ if (!((RefElementImpl)refElement).hasSuspiciousCallers() || ((RefJavaElementImpl)refElement).isSuspiciousRecursive()) return 1;
+ return 0;
+ }
+ }
+
+ @NotNull
+ UnusedDeclarationInspection getTool() {
+ return (UnusedDeclarationInspection)getToolWrapper().getTool();
+ }
+
+
+ @Override
+ @NotNull
+ public HTMLComposerImpl getComposer() {
+ if (myComposer == null) {
+ myComposer = new DeadHTMLComposer(this);
+ }
+ return myComposer;
+ }
+
+ @Override
+ public void exportResults(@NotNull final Element parentNode, @NotNull RefEntity refEntity) {
+ if (!(refEntity instanceof RefJavaElement)) return;
+ final RefFilter filter = getFilter();
+ if (!getIgnoredRefElements().contains(refEntity) && filter.accepts((RefJavaElement)refEntity)) {
+ refEntity = getRefManager().getRefinedElement(refEntity);
+ Element element = refEntity.getRefManager().export(refEntity, parentNode, -1);
+ if (element == null) return;
+ @NonNls Element problemClassElement = new Element(InspectionsBundle.message("inspection.export.results.problem.element.tag"));
+
+ final RefElement refElement = (RefElement)refEntity;
+ final HighlightSeverity severity = getSeverity(refElement, getContext(), getToolWrapper());
+ final String attributeKey =
+ getTextAttributeKey(refElement.getRefManager().getProject(), severity, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
+ problemClassElement.setAttribute("severity", severity.myName);
+ problemClassElement.setAttribute("attribute_key", attributeKey);
+
+ problemClassElement.addContent(InspectionsBundle.message("inspection.export.results.dead.code"));
+ element.addContent(problemClassElement);
+
+ @NonNls Element hintsElement = new Element("hints");
+
+ for (String hint : HINTS) {
+ @NonNls Element hintElement = new Element("hint");
+ hintElement.setAttribute("value", hint);
+ hintsElement.addContent(hintElement);
+ }
+ element.addContent(hintsElement);
+
+
+ Element descriptionElement = new Element(InspectionsBundle.message("inspection.export.results.description.tag"));
+ StringBuffer buf = new StringBuffer();
+ DeadHTMLComposer.appendProblemSynopsis((RefElement)refEntity, buf);
+ descriptionElement.addContent(buf.toString());
+ element.addContent(descriptionElement);
+ }
+ }
+
+ @Override
+ public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements) {
+ return myQuickFixActions;
+ }
+
+ final QuickFixAction[] myQuickFixActions;
+
+ @NotNull
+ private QuickFixAction[] createQuickFixes(@NotNull InspectionToolWrapper toolWrapper) {
+ return new QuickFixAction[]{new PermanentDeleteAction(toolWrapper), new CommentOutBin(toolWrapper), new MoveToEntries(toolWrapper)};
+ }
+ private static final String DELETE_QUICK_FIX = InspectionsBundle.message("inspection.dead.code.safe.delete.quickfix");
+
+ class PermanentDeleteAction extends QuickFixAction {
+ PermanentDeleteAction(@NotNull InspectionToolWrapper toolWrapper) {
+ super(DELETE_QUICK_FIX, AllIcons.Actions.Cancel, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), toolWrapper);
+ }
+
+ @Override
+ protected boolean applyFix(final RefEntity[] refElements) {
+ if (!super.applyFix(refElements)) return false;
+ final ArrayList<PsiElement> psiElements = new ArrayList<PsiElement>();
+ for (RefEntity refElement : refElements) {
+ PsiElement psiElement = refElement instanceof RefElement ? ((RefElement)refElement).getElement() : null;
+ if (psiElement == null) continue;
+ if (getFilter().getElementProblemCount((RefJavaElement)refElement) == 0) continue;
+ psiElements.add(psiElement);
+ }
+
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ final Project project = getContext().getProject();
+ SafeDeleteHandler.invoke(project, PsiUtilCore.toPsiElementArray(psiElements), false, new Runnable() {
+ @Override
+ public void run() {
+ removeElements(refElements, project, myToolWrapper);
+ }
+ });
+ }
+ });
+
+ return false; //refresh after safe delete dialog is closed
+ }
+ }
+
+ private EntryPointsManager getEntryPointsManager() {
+ return getContext().getExtension(GlobalJavaInspectionContext.CONTEXT).getEntryPointsManager(getContext().getRefManager());
+ }
+
+ class MoveToEntries extends QuickFixAction {
+ MoveToEntries(@NotNull InspectionToolWrapper toolWrapper) {
+ super(InspectionsBundle.message("inspection.dead.code.entry.point.quickfix"), null, KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), toolWrapper);
+ }
+
+ @Override
+ protected boolean applyFix(RefEntity[] refElements) {
+ final EntryPointsManager entryPointsManager = getEntryPointsManager();
+ for (RefEntity refElement : refElements) {
+ if (refElement instanceof RefElement) {
+ entryPointsManager.addEntryPoint((RefElement)refElement, true);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ class CommentOutBin extends QuickFixAction {
+ CommentOutBin(@NotNull InspectionToolWrapper toolWrapper) {
+ super(COMMENT_OUT_QUICK_FIX, null, KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, SystemInfo.isMac ? InputEvent.META_MASK : InputEvent.CTRL_MASK),
+ toolWrapper);
+ }
+
+ @Override
+ protected boolean applyFix(RefEntity[] refElements) {
+ if (!super.applyFix(refElements)) return false;
+ ArrayList<RefElement> deletedRefs = new ArrayList<RefElement>(1);
+ for (RefEntity refElement : refElements) {
+ PsiElement psiElement = refElement instanceof RefElement ? ((RefElement)refElement).getElement() : null;
+ if (psiElement == null) continue;
+ if (getFilter().getElementProblemCount((RefJavaElement)refElement) == 0) continue;
+ commentOutDead(psiElement);
+ refElement.getRefManager().removeRefElement((RefElement)refElement, deletedRefs);
+ }
+
+ EntryPointsManager entryPointsManager = getEntryPointsManager();
+ for (RefElement refElement : deletedRefs) {
+ entryPointsManager.removeEntryPoint(refElement);
+ }
+
+ return true;
+ }
+ }
+
+ private static final String COMMENT_OUT_QUICK_FIX = InspectionsBundle.message("inspection.dead.code.comment.quickfix");
+ private static class CommentOutFix implements IntentionAction {
+ private final PsiElement myElement;
+
+ private CommentOutFix(final PsiElement element) {
+ myElement = element;
+ }
+
+ @Override
+ @NotNull
+ public String getText() {
+ return COMMENT_OUT_QUICK_FIX;
+ }
+
+ @Override
+ @NotNull
+ public String getFamilyName() {
+ return getText();
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ return true;
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ if (myElement != null && myElement.isValid()) {
+ commentOutDead(PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class));
+ }
+ }
+
+ @Override
+ public boolean startInWriteAction() {
+ return true;
+ }
+ }
+ private static void commentOutDead(PsiElement psiElement) {
+ PsiFile psiFile = psiElement.getContainingFile();
+
+ if (psiFile != null) {
+ Document doc = PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(psiFile);
+ if (doc != null) {
+ TextRange textRange = psiElement.getTextRange();
+ String date = DateFormatUtil.formatDateTime(new Date());
+
+ int startOffset = textRange.getStartOffset();
+ CharSequence chars = doc.getCharsSequence();
+ while (CharArrayUtil.regionMatches(chars, startOffset, InspectionsBundle.message("inspection.dead.code.comment"))) {
+ int line = doc.getLineNumber(startOffset) + 1;
+ if (line < doc.getLineCount()) {
+ startOffset = doc.getLineStartOffset(line);
+ startOffset = CharArrayUtil.shiftForward(chars, startOffset, " \t");
+ }
+ }
+
+ int endOffset = textRange.getEndOffset();
+
+ int line1 = doc.getLineNumber(startOffset);
+ int line2 = doc.getLineNumber(endOffset - 1);
+
+ if (line1 == line2) {
+ doc.insertString(startOffset, InspectionsBundle.message("inspection.dead.code.date.comment", date));
+ }
+ else {
+ for (int i = line1; i <= line2; i++) {
+ doc.insertString(doc.getLineStartOffset(i), "//");
+ }
+
+ doc.insertString(doc.getLineStartOffset(Math.min(line2 + 1, doc.getLineCount() - 1)),
+ InspectionsBundle.message("inspection.dead.code.stop.comment", date));
+ doc.insertString(doc.getLineStartOffset(line1), InspectionsBundle.message("inspection.dead.code.start.comment", date));
+ }
+ }
+ }
+ }
+
+ @NotNull
+ @Override
+ public InspectionNode createToolNode(@NotNull GlobalInspectionContextImpl context,
+ @NotNull InspectionNode node,
+ @NotNull InspectionRVContentProvider provider,
+ @NotNull InspectionTreeNode parentNode,
+ boolean showStructure) {
+ final EntryPointsNode entryPointsNode = new EntryPointsNode(context);
+ InspectionToolWrapper dummyToolWrapper = entryPointsNode.getToolWrapper();
+ InspectionToolPresentation presentation = context.getPresentation(dummyToolWrapper);
+ presentation.updateContent();
+ provider.appendToolNodeContent(context, entryPointsNode, node, showStructure);
+ return entryPointsNode;
+ }
+
+ @Override
+ public void initialize(@NotNull GlobalInspectionContextImpl context) {
+ super.initialize(context);
+ ((EntryPointsManagerImpl)getEntryPointsManager()).setAddNonJavaEntries(getTool().ADD_NONJAVA_TO_ENTRIES);
+ }
+
+ @Override
+ public void updateContent() {
+ getTool().checkForReachables();
+ myPackageContents = new HashMap<String, Set<RefEntity>>();
+ getContext().getRefManager().iterate(new RefJavaVisitor() {
+ @Override public void visitElement(@NotNull RefEntity refEntity) {
+ if (!(refEntity instanceof RefJavaElement)) return;//dead code doesn't work with refModule | refPackage
+ RefJavaElement refElement = (RefJavaElement)refEntity;
+ if (!(getContext().getUIOptions().FILTER_RESOLVED_ITEMS && getIgnoredRefElements().contains(refElement)) && refElement.isValid() && getFilter().accepts(refElement)) {
+ String packageName = RefJavaUtil.getInstance().getPackageName(refEntity);
+ Set<RefEntity> content = myPackageContents.get(packageName);
+ if (content == null) {
+ content = new HashSet<RefEntity>();
+ myPackageContents.put(packageName, content);
+ }
+ content.add(refEntity);
+ }
+ }
+ });
+ }
+
+ @Override
+ public boolean hasReportedProblems() {
+ final GlobalInspectionContextImpl context = getContext();
+ if (context != null && context.getUIOptions().SHOW_ONLY_DIFF){
+ return containsOnlyDiff(myPackageContents) ||
+ myOldPackageContents != null && containsOnlyDiff(myOldPackageContents);
+ }
+ if (!myPackageContents.isEmpty()) return true;
+ return isOldProblemsIncluded() && !myOldPackageContents.isEmpty();
+ }
+
+ private boolean containsOnlyDiff(@NotNull Map<String, Set<RefEntity>> packageContents) {
+ for (String packageName : packageContents.keySet()) {
+ final Set<RefEntity> refElements = packageContents.get(packageName);
+ if (refElements != null){
+ for (RefEntity refElement : refElements) {
+ if (getElementStatus(refElement) != FileStatus.NOT_CHANGED){
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Map<String, Set<RefEntity>> getContent() {
+ return myPackageContents;
+ }
+
+ @Override
+ public Map<String, Set<RefEntity>> getOldContent() {
+ return myOldPackageContents;
+ }
+
+ @Override
+ public void ignoreCurrentElement(RefEntity refEntity) {
+ if (refEntity == null) return;
+ myIgnoreElements.add(refEntity);
+ }
+
+ @Override
+ public void amnesty(RefEntity refEntity) {
+ myIgnoreElements.remove(refEntity);
+ }
+
+ @Override
+ public void cleanup() {
+ super.cleanup();
+ myOldPackageContents = null;
+ myPackageContents.clear();
+ myIgnoreElements.clear();
+ }
+
+
+ @Override
+ public void finalCleanup() {
+ super.finalCleanup();
+ myOldPackageContents = null;
+ }
+
+ @Override
+ public boolean isGraphNeeded() {
+ return true;
+ }
+
+ @Override
+ public boolean isElementIgnored(final RefEntity element) {
+ for (RefEntity entity : myIgnoreElements) {
+ if (Comparing.equal(entity, element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ @NotNull
+ @Override
+ public FileStatus getElementStatus(final RefEntity element) {
+ final GlobalInspectionContextImpl context = getContext();
+ if (context != null && context.getUIOptions().SHOW_DIFF_WITH_PREVIOUS_RUN){
+ if (myOldPackageContents != null){
+ final boolean old = RefUtil.contains(element, collectRefElements(myOldPackageContents));
+ final boolean current = RefUtil.contains(element, collectRefElements(myPackageContents));
+ return calcStatus(old, current);
+ }
+ return FileStatus.ADDED;
+ }
+ return FileStatus.NOT_CHANGED;
+ }
+
+ @Override
+ @NotNull
+ public Collection<RefEntity> getIgnoredRefElements() {
+ return myIgnoreElements;
+ }
+
+ private static Set<RefEntity> collectRefElements(Map<String, Set<RefEntity>> packageContents) {
+ Set<RefEntity> allAvailable = new HashSet<RefEntity>();
+ for (Set<RefEntity> elements : packageContents.values()) {
+ allAvailable.addAll(elements);
+ }
+ return allAvailable;
+ }
+
+ @Override
+ @Nullable
+ public IntentionAction findQuickFixes(@NotNull final CommonProblemDescriptor descriptor, final String hint) {
+ if (descriptor instanceof ProblemDescriptor) {
+ if (DELETE.equals(hint)) {
+ return new PermanentDeleteFix(((ProblemDescriptor)descriptor).getPsiElement());
+ }
+ if (COMMENT.equals(hint)) {
+ return new CommentOutFix(((ProblemDescriptor)descriptor).getPsiElement());
+ }
+ }
+ return null;
+ }
+
+
+ private static class PermanentDeleteFix implements IntentionAction {
+ private final PsiElement myElement;
+
+ private PermanentDeleteFix(final PsiElement element) {
+ myElement = element;
+ }
+
+ @Override
+ @NotNull
+ public String getText() {
+ return DELETE_QUICK_FIX;
+ }
+
+ @Override
+ @NotNull
+ public String getFamilyName() {
+ return getText();
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ return true;
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ if (myElement != null && myElement.isValid()) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ SafeDeleteHandler
+ .invoke(myElement.getProject(), new PsiElement[]{PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class)}, false);
+ }
+ });
+ }
+ }
+
+ @Override
+ public boolean startInWriteAction() {
+ return true;
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java b/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
index 4792728..a2a95d7 100644
--- a/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
@@ -202,7 +202,8 @@
}
@Override
- protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext context,
+ protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager,
+ @NotNull final GlobalJavaInspectionContext context,
@NotNull final ProblemDescriptionsProcessor descriptionsProcessor) {
manager.iterate(new RefJavaVisitor() {
@Override public void visitElement(@NotNull RefEntity refEntity) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/FilteringInspectionTool.java b/java/java-impl/src/com/intellij/codeInspection/ex/FilteringInspectionTool.java
deleted file mode 100644
index 71a49a4..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/ex/FilteringInspectionTool.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection.ex;
-
-import com.intellij.codeInsight.daemon.HighlightDisplayKey;
-import com.intellij.codeInspection.SuppressIntentionAction;
-import com.intellij.codeInspection.SuppressManager;
-import com.intellij.codeInspection.reference.RefEntity;
-import com.intellij.codeInspection.reference.RefJavaElement;
-import com.intellij.codeInspection.reference.RefJavaUtil;
-import com.intellij.codeInspection.reference.RefJavaVisitor;
-import com.intellij.codeInspection.util.RefFilter;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.util.containers.HashMap;
-import com.intellij.util.containers.HashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author max
- */
-public abstract class FilteringInspectionTool extends InspectionTool {
- public abstract RefFilter getFilter();
- private Map<String, Set<RefEntity>> myPackageContents = new HashMap<String, Set<RefEntity>>();
-
- private Map<String, Set<RefEntity>> myOldPackageContents = null;
-
- private final Set<RefEntity> myIgnoreElements = new HashSet<RefEntity>();
-
- @Override
- public void updateContent() {
- myPackageContents = new HashMap<String, Set<RefEntity>>();
- getContext().getRefManager().iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull RefEntity refEntity) {
- if (!(refEntity instanceof RefJavaElement)) return;//dead code doesn't work with refModule | refPackage
- RefJavaElement refElement = (RefJavaElement)refEntity;
- if (!(getContext().getUIOptions().FILTER_RESOLVED_ITEMS && myIgnoreElements.contains(refElement)) && refElement.isValid() && getFilter().accepts(refElement)) {
- String packageName = RefJavaUtil.getInstance().getPackageName(refEntity);
- Set<RefEntity> content = myPackageContents.get(packageName);
- if (content == null) {
- content = new HashSet<RefEntity>();
- myPackageContents.put(packageName, content);
- }
- content.add(refEntity);
- }
- }
- });
- }
-
- @Override
- public boolean hasReportedProblems() {
- final GlobalInspectionContextImpl context = getContext();
- if (context != null && context.getUIOptions().SHOW_ONLY_DIFF){
- return containsOnlyDiff(myPackageContents) ||
- myOldPackageContents != null && containsOnlyDiff(myOldPackageContents);
- }
- if (!myPackageContents.isEmpty()) return true;
- return isOldProblemsIncluded() && !myOldPackageContents.isEmpty();
- }
-
- private boolean containsOnlyDiff(@NotNull Map<String, Set<RefEntity>> packageContents) {
- for (String packageName : packageContents.keySet()) {
- final Set<RefEntity> refElements = packageContents.get(packageName);
- if (refElements != null){
- for (RefEntity refElement : refElements) {
- if (getElementStatus(refElement) != FileStatus.NOT_CHANGED){
- return true;
- }
- }
- }
- }
- return false;
- }
-
- @Override
- public Map<String, Set<RefEntity>> getContent() {
- return myPackageContents;
- }
-
- @Override
- public Map<String, Set<RefEntity>> getOldContent() {
- return myOldPackageContents;
- }
-
- @Override
- public void ignoreCurrentElement(RefEntity refEntity) {
- if (refEntity == null) return;
- myIgnoreElements.add(refEntity);
- }
-
- @Override
- public void amnesty(RefEntity refEntity) {
- myIgnoreElements.remove(refEntity);
- }
-
- @Override
- public void cleanup() {
- super.cleanup();
- myOldPackageContents = null;
- myPackageContents.clear();
- myIgnoreElements.clear();
- }
-
-
- @Override
- public void finalCleanup() {
- super.finalCleanup();
- myOldPackageContents = null;
- }
-
- @Override
- public boolean isGraphNeeded() {
- return true;
- }
-
- @Override
- public boolean isElementIgnored(final RefEntity element) {
- for (RefEntity entity : myIgnoreElements) {
- if (Comparing.equal(entity, element)) {
- return true;
- }
- }
- return false;
- }
-
-
- @NotNull
- @Override
- public FileStatus getElementStatus(final RefEntity element) {
- final GlobalInspectionContextImpl context = getContext();
- if (context != null && context.getUIOptions().SHOW_DIFF_WITH_PREVIOUS_RUN){
- if (myOldPackageContents != null){
- final boolean old = contains(element, collectRefElements(myOldPackageContents));
- final boolean current = contains(element, collectRefElements(myPackageContents));
- return calcStatus(old, current);
- }
- return FileStatus.ADDED;
- }
- return FileStatus.NOT_CHANGED;
- }
-
- @NotNull
- @Override
- public Collection<RefEntity> getIgnoredRefElements() {
- return myIgnoreElements;
- }
-
- private static Set<RefEntity> collectRefElements(Map<String, Set<RefEntity>> packageContents) {
- Set<RefEntity> allAvailable = new HashSet<RefEntity>();
- for (Set<RefEntity> elements : packageContents.values()) {
- allAvailable.addAll(elements);
- }
- return allAvailable;
- }
-
- @Override
- @Nullable
- public SuppressIntentionAction[] getSuppressActions() {
- return SuppressManager.getInstance().createSuppressActions(HighlightDisplayKey.find(getShortName()));
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
index 86ff16c..cd70665 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
@@ -25,6 +25,7 @@
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.reference.*;
+import com.intellij.codeInspection.ui.InspectionToolPresentation;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -68,8 +69,8 @@
public void enqueueClassUsagesProcessor(RefClass refClass, UsagesProcessor p) {
if (myClassUsagesRequests == null) myClassUsagesRequests = new THashMap<SmartPsiElementPointer, List<UsagesProcessor>>();
enqueueRequestImpl(refClass, myClassUsagesRequests, p);
- }
+ }
@Override
public void enqueueDerivedClassesProcessor(RefClass refClass, DerivedClassesProcessor p) {
if (myDerivedClassesRequests == null) myDerivedClassesRequests = new THashMap<SmartPsiElementPointer, List<DerivedClassesProcessor>>();
@@ -101,7 +102,7 @@
}
@SuppressWarnings({"UseOfSystemOutOrSystemErr"})
- public static boolean isInspectionsEnabled(final boolean online, Project project) {
+ public static boolean isInspectionsEnabled(final boolean online, @NotNull Project project) {
final Module[] modules = ModuleManager.getInstance(project).getModules();
if (online) {
if (modules.length == 0) {
@@ -413,12 +414,14 @@
}
@Override
- public void performPreRunActivities(final List<Tools> globalTools, final List<Tools> localTools,
- final GlobalInspectionContext context) {
+ public void performPreRunActivities(@NotNull final List<Tools> globalTools,
+ @NotNull final List<Tools> localTools,
+ @NotNull final GlobalInspectionContext context) {
getEntryPointsManager(context.getRefManager()).resolveEntryPoints(context.getRefManager());
+ // UnusedDeclarationInspection should run first
for (int i = 0; i < globalTools.size(); i++) {
- InspectionProfileEntry tool = globalTools.get(i).getTool();
- if (UnusedDeclarationInspection.SHORT_NAME.equals(tool.getShortName())) {
+ InspectionToolWrapper toolWrapper = globalTools.get(i).getTool();
+ if (UnusedDeclarationInspection.SHORT_NAME.equals(toolWrapper.getShortName())) {
Collections.swap(globalTools, i, 0);
break;
}
@@ -428,17 +431,22 @@
@Override
- public void performPostRunActivities(List<InspectionProfileEntry> needRepeatSearchRequest, final GlobalInspectionContext context) {
+ public void performPostRunActivities(@NotNull List<InspectionToolWrapper> needRepeatSearchRequest, @NotNull final GlobalInspectionContext context) {
JobDescriptor progress = context.getStdJobDescriptors().FIND_EXTERNAL_USAGES;
progress.setTotalAmount(getRequestCount());
do {
processSearchRequests(context);
- InspectionProfileEntry[] requestors = needRepeatSearchRequest.toArray(new InspectionProfileEntry[needRepeatSearchRequest.size()]);
- for (InspectionProfileEntry requestor : requestors) {
- if (requestor instanceof InspectionTool &&
- !((InspectionTool)requestor).queryExternalUsagesRequests(InspectionManager.getInstance(context.getProject()))) {
- needRepeatSearchRequest.remove(requestor);
+ InspectionToolWrapper[] requestors = needRepeatSearchRequest.toArray(new InspectionToolWrapper[needRepeatSearchRequest.size()]);
+ InspectionManager inspectionManager = InspectionManager.getInstance(context.getProject());
+ for (InspectionToolWrapper toolWrapper : requestors) {
+ boolean result = false;
+ if (toolWrapper instanceof GlobalInspectionToolWrapper) {
+ InspectionToolPresentation presentation = ((GlobalInspectionContextImpl)context).getPresentation(toolWrapper);
+ result = ((GlobalInspectionToolWrapper)toolWrapper).getTool().queryExternalUsagesRequests(inspectionManager, context, presentation);
+ }
+ if (!result) {
+ needRepeatSearchRequest.remove(toolWrapper);
}
}
int oldSearchRequestCount = progress.getTotalAmount();
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/JavaInspectionExtensionsFactory.java b/java/java-impl/src/com/intellij/codeInspection/ex/JavaInspectionExtensionsFactory.java
index 21cf2f8..d5f607e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ex/JavaInspectionExtensionsFactory.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/JavaInspectionExtensionsFactory.java
@@ -31,6 +31,7 @@
import com.intellij.codeInspection.reference.RefManagerImpl;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class JavaInspectionExtensionsFactory extends InspectionExtensionsFactory {
@@ -62,7 +63,7 @@
}
@Override
- public boolean isProjectConfiguredToRunInspections(final Project project, final boolean online) {
+ public boolean isProjectConfiguredToRunInspections(@NotNull final Project project, final boolean online) {
return GlobalJavaInspectionContextImpl.isInspectionsEnabled(online, project);
}
}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java
index 5d9bd6c..7dd9282 100644
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java
@@ -92,6 +92,6 @@
@Override
public RefClass getOwnerClass() {
- return myOwnerClass == null ? super.getOwnerClass() : myOwnerClass;
+ return myOwnerClass;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
index bf78af2..8ebd6ab 100644
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
@@ -110,7 +110,7 @@
@Override
protected Ref<UnusedDeclarationInspection> compute(PsiFile file, RefManagerImpl refManager) {
Tools tools = ((GlobalInspectionContextImpl)refManager.getContext()).getTools().get(UnusedDeclarationInspection.SHORT_NAME);
- InspectionToolWrapper toolWrapper = tools != null ? (InspectionToolWrapper)tools.getEnabledTool(file) : null;
+ InspectionToolWrapper toolWrapper = tools == null ? null : tools.getEnabledTool(file);
InspectionProfileEntry tool = toolWrapper == null ? null : toolWrapper.getTool();
return Ref.create(tool instanceof UnusedDeclarationInspection ? (UnusedDeclarationInspection)tool : null);
}
@@ -283,8 +283,9 @@
return null;
}
+ @NotNull
@Override
- public RefEntity getRefinedElement(final RefEntity ref) {
+ public RefEntity getRefinedElement(@NotNull final RefEntity ref) {
if (ref instanceof RefImplicitConstructor) {
return ((RefImplicitConstructor)ref).getOwnerClass();
}
@@ -312,7 +313,7 @@
}
@Override
- public void export(final RefEntity refEntity, final Element element) {
+ public void export(@NotNull final RefEntity refEntity, @NotNull final Element element) {
if (refEntity instanceof RefElement) {
final SmartPsiElementPointer pointer = ((RefElement)refEntity).getPointer();
if (pointer != null) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java b/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
index 5106360..7363d43 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
@@ -16,7 +16,9 @@
package com.intellij.codeInspection.ui;
import com.intellij.codeInspection.deadCode.DummyEntryPointsTool;
-import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
+import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
+import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper;
+import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.icons.AllIcons;
import org.jetbrains.annotations.NotNull;
@@ -26,9 +28,14 @@
* @author max
*/
public class EntryPointsNode extends InspectionNode {
- public EntryPointsNode(@NotNull UnusedDeclarationInspection tool) {
- super(new DummyEntryPointsTool(tool));
- getTool().updateContent();
+ public EntryPointsNode(@NotNull GlobalInspectionContextImpl context) {
+ super(createDummyWrapper(context));
+ }
+
+ private static InspectionToolWrapper createDummyWrapper(@NotNull GlobalInspectionContextImpl context) {
+ InspectionToolWrapper toolWrapper = new GlobalInspectionToolWrapper(new DummyEntryPointsTool());
+ toolWrapper.initialize(context);
+ return toolWrapper;
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInspection/util/XMLExportUtl.java b/java/java-impl/src/com/intellij/codeInspection/util/XMLExportUtl.java
deleted file mode 100644
index 6854148..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/util/XMLExportUtl.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: May 23, 2002
- * Time: 2:36:58 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.util;
-
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
-import com.intellij.psi.javadoc.PsiDocComment;
-import com.intellij.psi.javadoc.PsiDocTag;
-import com.intellij.psi.util.PsiFormatUtil;
-import org.jdom.Element;
-
-@SuppressWarnings({"HardCodedStringLiteral"})
-@Deprecated
-public class XMLExportUtl {
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.util.XMLExportUtl");
-
- private XMLExportUtl() {
- }
-
- public static Element createElement(RefEntity refEntity, Element parentNode, int actualLine, final TextRange range) {
- refEntity = refEntity.getRefManager().getRefinedElement(refEntity);
-
- Element problem = new Element("problem");
-
- if (refEntity instanceof RefElement) {
- final RefElement refElement = (RefElement)refEntity;
- PsiElement psiElement = refElement.getElement();
- PsiFile psiFile = psiElement.getContainingFile();
-
- Element fileElement = new Element("file");
- Element lineElement = new Element("line");
- final VirtualFile virtualFile = psiFile.getVirtualFile();
- LOG.assertTrue(virtualFile != null);
- fileElement.addContent(virtualFile.getUrl());
-
- if (actualLine == -1) {
- final Document document = PsiDocumentManager.getInstance(refElement.getRefManager().getProject()).getDocument(psiFile);
- LOG.assertTrue(document != null);
- lineElement.addContent(String.valueOf(document.getLineNumber(psiElement.getTextOffset()) + 1));
- }
- else {
- lineElement.addContent(String.valueOf(actualLine));
- }
-
- problem.addContent(fileElement);
- problem.addContent(lineElement);
- appendModule(problem, refElement.getModule());
- }
- else if (refEntity instanceof RefModule) {
- final RefModule refModule = (RefModule)refEntity;
- final VirtualFile moduleFile = refModule.getModule().getModuleFile();
- final Element fileElement = new Element("file");
- fileElement.addContent(moduleFile != null? moduleFile.getUrl() : refEntity.getName());
- problem.addContent(fileElement);
- appendModule(problem, refModule);
- appendFakePackage(problem);
- } else if (refEntity instanceof RefPackage) {
- Element packageElement = new Element("package");
- packageElement.addContent(refEntity.getName());
- problem.addContent(packageElement);
- }
-
- new SmartRefElementPointerImpl(refEntity, true).writeExternal(problem);
-
- if (refEntity instanceof RefMethod) {
- RefMethod refMethod = (RefMethod)refEntity;
- appendMethod(refMethod, problem);
- }
- else if (refEntity instanceof RefField) {
- RefField refField = (RefField)refEntity;
- appendField(refField, problem);
- }
- else if (refEntity instanceof RefClass) {
- RefClass refClass = (RefClass)refEntity;
- appendClass(refClass, problem);
- } else if (refEntity instanceof RefFile) {
- appendFakePackage(problem);
- }
- parentNode.addContent(problem);
-
- return problem;
- }
-
- private static void appendModule(final Element problem, final RefModule refModule) {
- if (refModule != null) {
- Element moduleElement = new Element("module");
- moduleElement.addContent(refModule.getName());
- problem.addContent(moduleElement);
- }
- }
-
- private static void appendFakePackage(final Element problem) {
- final Element fakePackage = new Element("package");
- fakePackage.addContent(InspectionsBundle.message("inspection.export.results.default"));
- problem.addContent(fakePackage);
- }
-
- private static void appendClass(RefClass refClass, Element parentNode) {
- PsiClass psiClass = refClass.getElement();
- PsiDocComment psiDocComment = psiClass.getDocComment();
-
- PsiFile psiFile = psiClass.getContainingFile();
-
- if (psiFile instanceof PsiJavaFile) {
- String packageName = ((PsiJavaFile)psiFile).getPackageName();
- Element packageElement = new Element("package");
- packageElement.addContent(packageName.length() > 0 ? packageName : InspectionsBundle.message("inspection.export.results.default"));
- parentNode.addContent(packageElement);
- }
-
- Element classElement = new Element("class");
- if (psiDocComment != null) {
- PsiDocTag[] tags = psiDocComment.getTags();
- for (PsiDocTag tag : tags) {
- if ("author".equals(tag.getName()) && tag.getValueElement() != null) {
- classElement.setAttribute("author", tag.getValueElement().getText());
- }
- }
- }
-
- String name = PsiFormatUtil.formatClass(psiClass, PsiFormatUtil.SHOW_NAME);
- Element nameElement = new Element("name");
- nameElement.addContent(name);
- classElement.addContent(nameElement);
-
- Element displayName = new Element("display_name");
- displayName.addContent(refClass.getQualifiedName());
- classElement.addContent(displayName);
-
- parentNode.addContent(classElement);
-
- RefClass topClass = RefJavaUtil.getInstance().getTopLevelClass(refClass);
- if (topClass != refClass) {
- appendClass(topClass, classElement);
- }
- }
-
- private static void appendMethod(final RefMethod refMethod, Element parentNode) {
- Element methodElement = new Element(refMethod.isConstructor() ? "constructor" : "method");
-
- PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
- String name = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_FQ_NAME |
- PsiFormatUtil.SHOW_TYPE | PsiFormatUtil.SHOW_PARAMETERS,
- PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE);
-
- Element shortNameElement = new Element("name");
- shortNameElement.addContent(name);
- methodElement.addContent(shortNameElement);
-
- Element displayName = new Element("name");
- displayName.addContent(refMethod.getQualifiedName());
- methodElement.addContent(displayName);
-
- appendClass(RefJavaUtil.getInstance().getTopLevelClass(refMethod), methodElement);
-
- parentNode.addContent(methodElement);
- }
-
- private static void appendField(final RefField refField, Element parentNode) {
- Element fieldElement = new Element("field");
- PsiField psiField = refField.getElement();
- String name = PsiFormatUtil.formatVariable(psiField, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE, PsiSubstitutor.EMPTY);
-
- Element shortNameElement = new Element("name");
- shortNameElement.addContent(name);
- fieldElement.addContent(shortNameElement);
-
- Element displayName = new Element("display_name");
- displayName.addContent(refField.getQualifiedName());
- fieldElement.addContent(displayName);
-
- appendClass(RefJavaUtil.getInstance().getTopLevelClass(refField), fieldElement);
-
- parentNode.addContent(fieldElement);
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/BaseConvertToLocalQuickFix.java b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/BaseConvertToLocalQuickFix.java
index 6dd3558..1862d7e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/BaseConvertToLocalQuickFix.java
+++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/BaseConvertToLocalQuickFix.java
@@ -46,7 +46,7 @@
* @author Danila Ponomarenko
*/
public abstract class BaseConvertToLocalQuickFix<V extends PsiVariable> implements LocalQuickFix {
- private static final Logger LOG = Logger.getInstance(BaseConvertToLocalQuickFix.class);
+ protected static final Logger LOG = Logger.getInstance(BaseConvertToLocalQuickFix.class);
@Override
@NotNull
@@ -89,10 +89,14 @@
}
@Nullable
- private PsiElement moveDeclaration(@NotNull Project project, @NotNull V variable) {
+ protected PsiElement moveDeclaration(@NotNull Project project, @NotNull V variable) {
final Collection<PsiReference> references = ReferencesSearch.search(variable).findAll();
if (references.isEmpty()) return null;
+ return moveDeclaration(project, variable, references, true);
+ }
+
+ protected PsiElement moveDeclaration(Project project, V variable, final Collection<PsiReference> references, boolean delete) {
final PsiCodeBlock anchorBlock = findAnchorBlock(references);
if (anchorBlock == null) return null; //was assert, but need to fix the case when obsolete inspection highlighting is left
if (!CodeInsightUtil.preparePsiElementsForWrite(anchorBlock)) return null;
@@ -113,6 +117,7 @@
anchorAssignmentExpression.getRExpression(),
variable,
refsSet,
+ delete,
new NotNullFunction<PsiDeclarationStatement, PsiElement>() {
@NotNull
@Override
@@ -132,6 +137,7 @@
variable.getInitializer(),
variable,
references,
+ delete,
new NotNullFunction<PsiDeclarationStatement, PsiElement>() {
@NotNull
@Override
@@ -147,7 +153,7 @@
@Nullable final PsiExpression initializer,
@NotNull final V variable,
@NotNull final Collection<PsiReference> references,
- @NotNull final NotNullFunction<PsiDeclarationStatement, PsiElement> action) {
+ final boolean delete, @NotNull final NotNullFunction<PsiDeclarationStatement, PsiElement> action) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
return ApplicationManager.getApplication().runWriteAction(
@@ -155,9 +161,11 @@
@Override
public PsiElement compute() {
final PsiElement newDeclaration = moveDeclaration(elementFactory, localName, variable, initializer, action, references);
- beforeDelete(project, variable, newDeclaration);
- variable.normalizeDeclaration();
- variable.delete();
+ if (delete) {
+ beforeDelete(project, variable, newDeclaration);
+ variable.normalizeDeclaration();
+ variable.delete();
+ }
return newDeclaration;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
index 8eb5198..c82e779 100644
--- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
@@ -25,6 +25,7 @@
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
import com.intellij.lang.java.JavaCommenter;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
@@ -36,6 +37,7 @@
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.javadoc.PsiDocComment;
+import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.RefactoringUtil;
@@ -47,10 +49,8 @@
import javax.swing.*;
import java.awt.*;
-import java.util.Collection;
-import java.util.LinkedHashSet;
+import java.util.*;
import java.util.List;
-import java.util.Set;
/**
* @author ven
@@ -271,6 +271,63 @@
private static class ConvertFieldToLocalQuickFix extends BaseConvertToLocalQuickFix<PsiField> {
+ @Nullable
+ @Override
+ protected PsiElement moveDeclaration(@NotNull final Project project, @NotNull final PsiField variable) {
+ final Map<PsiCodeBlock, Collection<PsiReference>> refs = new HashMap<PsiCodeBlock, Collection<PsiReference>>();
+ groupByCodeBlocks(ReferencesSearch.search(variable).findAll(), refs);
+ PsiElement element = null;
+ for (Collection<PsiReference> psiReferences : refs.values()) {
+ element = super.moveDeclaration(project, variable, psiReferences, false);
+ }
+ if (element != null) {
+ final PsiElement finalElement = element;
+ Runnable runnable = new Runnable() {
+ public void run() {
+ beforeDelete(project, variable, finalElement);
+ variable.normalizeDeclaration();
+ variable.delete();
+ }
+ };
+ ApplicationManager.getApplication().runWriteAction(runnable);
+ }
+ return element;
+ }
+
+ private static void groupByCodeBlocks(final Collection<PsiReference> allReferences, Map<PsiCodeBlock, Collection<PsiReference>> refs) {
+ for (PsiReference psiReference : allReferences) {
+ final PsiElement element = psiReference.getElement();
+ final PsiCodeBlock block = PsiTreeUtil.getParentOfType(element, PsiCodeBlock.class);
+ LOG.assertTrue(block != null);
+ Collection<PsiReference> references = refs.get(block);
+ if (references == null) {
+ references = new ArrayList<PsiReference>();
+ if (findExistentBlock(refs, psiReference, block, references)) continue;
+ refs.put(block, references);
+ }
+ references.add(psiReference);
+ }
+ }
+
+ private static boolean findExistentBlock(Map<PsiCodeBlock, Collection<PsiReference>> refs,
+ PsiReference psiReference,
+ PsiCodeBlock block,
+ Collection<PsiReference> references) {
+ for (Iterator<PsiCodeBlock> iterator = refs.keySet().iterator(); iterator.hasNext(); ) {
+ PsiCodeBlock codeBlock = iterator.next();
+ if (PsiTreeUtil.isAncestor(codeBlock, block, false)) {
+ refs.get(codeBlock).add(psiReference);
+ return true;
+ }
+ else if (PsiTreeUtil.isAncestor(block, codeBlock, false)) {
+ references.addAll(refs.get(codeBlock));
+ iterator.remove();
+ break;
+ }
+ }
+ return false;
+ }
+
@Override
@Nullable
protected PsiField getVariable(@NotNull ProblemDescriptor descriptor) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/ParameterCanBeLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/ParameterCanBeLocalInspection.java
index 66980e9..a0fb322 100644
--- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/ParameterCanBeLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/ParameterCanBeLocalInspection.java
@@ -153,11 +153,12 @@
@Override
protected PsiElement applyChanges(@NotNull final Project project,
- @NotNull final String localName,
- @Nullable final PsiExpression initializer,
- @NotNull final PsiParameter parameter,
- @NotNull final Collection<PsiReference> references,
- @NotNull final NotNullFunction<PsiDeclarationStatement, PsiElement> action) {
+ @NotNull final String localName,
+ @Nullable final PsiExpression initializer,
+ @NotNull final PsiParameter parameter,
+ @NotNull final Collection<PsiReference> references,
+ boolean delete,
+ @NotNull final NotNullFunction<PsiDeclarationStatement, PsiElement> action) {
final PsiElement scope = parameter.getDeclarationScope();
if (scope instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)scope;
diff --git a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java b/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java
index 4036509..ab0a63e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java
+++ b/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java
@@ -17,7 +17,8 @@
import com.intellij.codeInspection.ProblemDescriptionsProcessor;
import com.intellij.codeInspection.reference.RefManager;
+import org.jetbrains.annotations.NotNull;
public interface VisibilityExtension {
- void fillIgnoreList(RefManager refManager, ProblemDescriptionsProcessor processor);
+ void fillIgnoreList(@NotNull RefManager refManager, @NotNull ProblemDescriptionsProcessor processor);
}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java b/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
index 112c379..88ff09b 100644
--- a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
@@ -403,7 +403,8 @@
@Override
- protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext,
+ protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager,
+ @NotNull final GlobalJavaInspectionContext globalContext,
@NotNull final ProblemDescriptionsProcessor processor) {
final EntryPointsManager entryPointsManager = globalContext.getEntryPointsManager(manager);
for (RefElement entryPoint : entryPointsManager.getEntryPoints()) {
diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/call/CallHierarchyNodeDescriptor.java b/java/java-impl/src/com/intellij/ide/hierarchy/call/CallHierarchyNodeDescriptor.java
index c5847af..866e2ce 100644
--- a/java/java-impl/src/com/intellij/ide/hierarchy/call/CallHierarchyNodeDescriptor.java
+++ b/java/java-impl/src/com/intellij/ide/hierarchy/call/CallHierarchyNodeDescriptor.java
@@ -40,6 +40,7 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.ui.LayeredIcon;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -51,12 +52,11 @@
private final List<PsiReference> myReferences = new ArrayList<PsiReference>();
private final boolean myNavigateToReference;
- public CallHierarchyNodeDescriptor(
- final Project project,
- final HierarchyNodeDescriptor parentDescriptor,
- final PsiElement element,
- final boolean isBase,
- final boolean navigateToReference){
+ public CallHierarchyNodeDescriptor(@NotNull Project project,
+ final HierarchyNodeDescriptor parentDescriptor,
+ @NotNull PsiElement element,
+ final boolean isBase,
+ final boolean navigateToReference) {
super(project, parentDescriptor, element, isBase);
myNavigateToReference = navigateToReference;
}
diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/call/CallerMethodsTreeStructure.java b/java/java-impl/src/com/intellij/ide/hierarchy/call/CallerMethodsTreeStructure.java
index 16ed3e9..b8770ed 100644
--- a/java/java-impl/src/com/intellij/ide/hierarchy/call/CallerMethodsTreeStructure.java
+++ b/java/java-impl/src/com/intellij/ide/hierarchy/call/CallerMethodsTreeStructure.java
@@ -27,6 +27,7 @@
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Map;
@@ -38,7 +39,7 @@
/**
* Should be called in read action
*/
- public CallerMethodsTreeStructure(final Project project, final PsiMethod method, final String scopeType) {
+ public CallerMethodsTreeStructure(@NotNull Project project, @NotNull PsiMethod method, final String scopeType) {
super(project, new CallHierarchyNodeDescriptor(project, null, method, true, false));
myScopeType = scopeType;
}
diff --git a/java/java-impl/src/com/intellij/ide/highlighter/JavaClsStructureViewBuilderProvider.java b/java/java-impl/src/com/intellij/ide/highlighter/JavaClsStructureViewBuilderProvider.java
index 3d4f103..7361877 100644
--- a/java/java-impl/src/com/intellij/ide/highlighter/JavaClsStructureViewBuilderProvider.java
+++ b/java/java-impl/src/com/intellij/ide/highlighter/JavaClsStructureViewBuilderProvider.java
@@ -27,6 +27,7 @@
import com.intellij.lang.Language;
import com.intellij.lang.LanguageStructureViewBuilder;
import com.intellij.lang.PsiStructureViewFactory;
+import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.ContentBasedFileSubstitutor;
import com.intellij.openapi.fileTypes.FileType;
@@ -39,6 +40,7 @@
import org.jetbrains.annotations.Nullable;
public class JavaClsStructureViewBuilderProvider implements StructureViewBuilderProvider {
+ @Override
@Nullable
public StructureViewBuilder getStructureViewBuilder(@NotNull final FileType fileType, @NotNull final VirtualFile file, @NotNull final Project project) {
@@ -58,9 +60,10 @@
final PsiJavaFile javaFile = (PsiJavaFile)psiFile;
if (javaFile == null) return null;
return new TreeBasedStructureViewBuilder() {
+ @Override
@NotNull
- public StructureViewModel createStructureViewModel() {
- return new JavaFileTreeModel(javaFile);
+ public StructureViewModel createStructureViewModel(@Nullable Editor editor) {
+ return new JavaFileTreeModel(javaFile, editor);
}
};
}
diff --git a/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaFileTreeModel.java b/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaFileTreeModel.java
index d9c25eb..962bf5f 100644
--- a/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaFileTreeModel.java
+++ b/java/java-impl/src/com/intellij/ide/structureView/impl/java/JavaFileTreeModel.java
@@ -23,9 +23,11 @@
import com.intellij.ide.util.treeView.smartTree.Grouper;
import com.intellij.ide.util.treeView.smartTree.NodeProvider;
import com.intellij.ide.util.treeView.smartTree.Sorter;
+import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.ui.PlaceHolder;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
@@ -36,11 +38,12 @@
private final PsiClassOwner myFile;
private String myPlace;
- public JavaFileTreeModel(@NotNull PsiClassOwner file) {
- super(file);
+ public JavaFileTreeModel(@NotNull PsiClassOwner file, @Nullable Editor editor) {
+ super(editor, file);
myFile = file;
}
+ @Override
@NotNull
public Filter[] getFilters() {
return new Filter[]{new FieldsFilter(),
@@ -53,20 +56,24 @@
return NODE_PROVIDERS;
}
+ @Override
@NotNull
public Grouper[] getGroupers() {
return new Grouper[]{new SuperTypesGrouper(), new PropertiesGrouper()};
}
+ @Override
@NotNull
public StructureViewTreeElement getRoot() {
return new JavaFileTreeElement(myFile);
}
+ @Override
public boolean shouldEnterElement(final Object element) {
return element instanceof PsiClass;
}
+ @Override
@NotNull
public Sorter[] getSorters() {
return new Sorter[] {
@@ -76,15 +83,18 @@
Sorter.ALPHA_SORTER};
}
+ @Override
protected PsiFile getPsiFile() {
return myFile;
}
+ @Override
public boolean isAlwaysShowsPlus(StructureViewTreeElement element) {
Object value = element.getValue();
return value instanceof PsiClass || value instanceof PsiFile;
}
+ @Override
public boolean isAlwaysLeaf(StructureViewTreeElement element) {
Object value = element.getValue();
return value instanceof PsiMethod || value instanceof PsiField;
@@ -113,6 +123,7 @@
return false;
}
+ @Override
@NotNull
protected Class[] getSuitableClasses() {
return new Class[]{PsiClass.class, PsiMethod.class, PsiField.class, PsiJavaFile.class};
diff --git a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java
index e42aff9..402e7f5 100644
--- a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java
+++ b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java
@@ -19,18 +19,20 @@
import com.intellij.navigation.ChooseByNameContributor;
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.psi.*;
+import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
public class DefaultSymbolNavigationContributor implements ChooseByNameContributor {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.DefaultSymbolNavigationContributor");
@@ -52,45 +54,41 @@
GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project);
- PsiMethod[] methods = cache.getMethodsByName(name, scope);
- methods = filterInheritedMethods(methods);
- PsiField[] fields = cache.getFieldsByName(name, scope);
- PsiClass[] classes = cache.getClassesByName(name, scope);
-
List<PsiMember> result = new ArrayList<PsiMember>();
- ContainerUtil.addAll(result, methods);
- ContainerUtil.addAll(result, fields);
- ContainerUtil.addAll(result, classes);
- filterOutNonOpenable(result);
+ for (PsiMethod method : cache.getMethodsByName(name, scope)) {
+ if (!method.isConstructor() && isOpenable(method) && !hasSuperMethod(method)) {
+ result.add(method);
+ }
+ }
+ for (PsiField field : cache.getFieldsByName(name, scope)) {
+ if (isOpenable(field)) {
+ result.add(field);
+ }
+ }
+ for (PsiClass aClass : cache.getClassesByName(name, scope)) {
+ if (isOpenable(aClass)) {
+ result.add(aClass);
+ }
+ }
PsiMember[] array = result.toArray(new PsiMember[result.size()]);
Arrays.sort(array, MyComparator.INSTANCE);
return array;
}
- private static void filterOutNonOpenable(List<PsiMember> members) {
- ListIterator<PsiMember> it = members.listIterator();
- while (it.hasNext()) {
- PsiMember member = it.next();
- if (isNonOpenable(member)) {
- it.remove();
+ private static boolean isOpenable(PsiMember member) {
+ return member.getContainingFile().getVirtualFile() != null;
+ }
+
+ private static boolean hasSuperMethod(PsiMethod method) {
+ PsiClass containingClass = method.getContainingClass();
+ if (containingClass == null) return false;
+
+ for (PsiMethod candidate : containingClass.findMethodsByName(method.getName(), true)) {
+ if (candidate.getContainingClass() != containingClass && PsiSuperMethodImplUtil.isSuperMethodSmart(method, candidate)) {
+ return true;
}
}
- }
-
- private static boolean isNonOpenable(PsiMember member) {
- return member.getContainingFile().getVirtualFile() == null;
- }
-
- private static PsiMethod[] filterInheritedMethods(PsiMethod[] methods) {
- ArrayList<PsiMethod> list = new ArrayList<PsiMethod>(methods.length);
- for (PsiMethod method : methods) {
- ProgressManager.checkCanceled();
- if (method.isConstructor()) continue;
- PsiMethod[] supers = method.findSuperMethods();
- if (supers.length > 0) continue;
- list.add(method);
- }
- return list.toArray(new PsiMethod[list.size()]);
+ return false;
}
private static class MyComparator implements Comparator<PsiModifierListOwner>{
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaStructureViewBuilderFactory.java b/java/java-impl/src/com/intellij/lang/java/JavaStructureViewBuilderFactory.java
index a353cff..e8d4eba 100644
--- a/java/java-impl/src/com/intellij/lang/java/JavaStructureViewBuilderFactory.java
+++ b/java/java-impl/src/com/intellij/lang/java/JavaStructureViewBuilderFactory.java
@@ -24,6 +24,7 @@
import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
import com.intellij.ide.structureView.impl.java.JavaFileTreeModel;
import com.intellij.lang.PsiStructureViewFactory;
+import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import org.jetbrains.annotations.NotNull;
@@ -37,8 +38,8 @@
return new TreeBasedStructureViewBuilder() {
@Override
@NotNull
- public StructureViewModel createStructureViewModel() {
- return new JavaFileTreeModel((PsiJavaFile)psiFile);
+ public StructureViewModel createStructureViewModel(@Nullable Editor editor) {
+ return new JavaFileTreeModel((PsiJavaFile)psiFile, editor);
}
@Override
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
index e81e167..1376f44 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
@@ -296,7 +296,12 @@
}
else if (myRole1 == ChildRole.FIELD) {
int lines = Math.max(getLinesAroundField(), getLinesAroundMethod()) + 1;
- myResult = Spacing.createSpacing(0, mySettings.SPACE_BEFORE_CLASS_LBRACE ? 1 : 0, 0, true, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE,
+ // IJ has been keeping initialization block which starts at the same line as a field for a while.
+ // However, it's not convenient for a situation when particular code is created via PSI - it's easier to not bothering
+ // with whitespace elements when inserting, say, new initialization blocks. That's why we don't enforce new line
+ // only during explicit reformatting ('Reformat' action).
+ int minLineFeeds = FormatterUtil.isFormatterCalledExplicitly() ? 0 : 1;
+ myResult = Spacing.createSpacing(0, mySettings.SPACE_BEFORE_CLASS_LBRACE ? 1 : 0, 1, true, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE,
lines);
}
else if (myRole1 == ChildRole.CLASS) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/PackagePrefixElementFinder.java b/java/java-impl/src/com/intellij/psi/impl/PackagePrefixElementFinder.java
index 7f58413..0f2df2d 100644
--- a/java/java-impl/src/com/intellij/psi/impl/PackagePrefixElementFinder.java
+++ b/java/java-impl/src/com/intellij/psi/impl/PackagePrefixElementFinder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -68,7 +68,7 @@
final String qualifiedName = psiPackage.getQualifiedName();
for (final String prefix : myPackagePrefixIndex.getAllPackagePrefixes(scope)) {
- if (StringUtil.isEmpty(qualifiedName) || StringUtil.startsWithConcatenationOf(prefix, qualifiedName, ".")) {
+ if (StringUtil.isEmpty(qualifiedName) || StringUtil.startsWithConcatenation(prefix, qualifiedName, ".")) {
final int i = prefix.indexOf('.', qualifiedName.length() + 1);
String childName = i >= 0 ? prefix.substring(0, i) : prefix;
if (!packagesMap.containsKey(childName)) {
@@ -83,7 +83,7 @@
public boolean packagePrefixExists(String packageQName) {
for (final String prefix : myPackagePrefixIndex.getAllPackagePrefixes(null)) {
- if (StringUtil.startsWithConcatenationOf(prefix, packageQName, ".") || prefix.equals(packageQName)) {
+ if (StringUtil.startsWithConcatenation(prefix, packageQName, ".") || prefix.equals(packageQName)) {
return true;
}
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
index a80ffad..57f919f 100644
--- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
+++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
@@ -20,6 +20,7 @@
import com.intellij.psi.impl.source.PsiFileWithStubSupport;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubTree;
+import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.util.XmlTagUtil;
import org.jetbrains.annotations.NotNull;
@@ -55,7 +56,7 @@
@Nullable
static PsiElement getAnchor(PsiElement element) {
- LOG.assertTrue(element.isValid());
+ PsiUtilCore.ensureValid(element);
PsiElement anchor = null;
if (element instanceof PsiClass) {
if (element instanceof PsiAnonymousClass) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
index 1571656..39a8cdc 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
@@ -124,7 +124,7 @@
}
public static void collectOnDemandImports(List<Pair<String, Boolean>> resultList,
- final Set<String> classesOrPackagesToImportOnDemand,
+ final Set<String> classesOrPackagesToImportOnDemand,
final CodeStyleSettings settings) {
TObjectIntHashMap<String> packageToCountMap = new TObjectIntHashMap<String>();
TObjectIntHashMap<String> classToCountMap = new TObjectIntHashMap<String>();
@@ -132,7 +132,7 @@
String name = pair.getFirst();
Boolean isStatic = pair.getSecond();
String packageOrClassName = getPackageOrClassName(name);
- if (packageOrClassName.length() == 0) continue;
+ if (packageOrClassName.isEmpty()) continue;
if (isStatic) {
int count = classToCountMap.get(packageOrClassName);
classToCountMap.put(packageOrClassName, count + 1);
@@ -209,12 +209,12 @@
String name = pair.getFirst();
Boolean isStatic = pair.getSecond();
String prefix = getPackageOrClassName(name);
- if (prefix.length() == 0) continue;
+ if (prefix.isEmpty()) continue;
final boolean isImplicitlyImported = implicitlyImportedPackages.contains(prefix);
if (!onDemandImports.contains(prefix) && !isImplicitlyImported) continue;
String shortName = PsiNameHelper.getShortClassName(name);
- String thisPackageClass = thisPackageName.length() > 0 ? thisPackageName + "." + shortName : shortName;
+ String thisPackageClass = !thisPackageName.isEmpty() ? thisPackageName + "." + shortName : shortName;
if (JavaPsiFacade.getInstance(manager.getProject()).findClass(thisPackageClass, resolveScope) != null) {
namesToUseSingle.add(name);
continue;
@@ -303,7 +303,7 @@
conflicts.addAll(inter);
}
}
- if (!conflicts.isEmpty()) {
+ if (!conflicts.isEmpty() && !(file instanceof PsiCompiledElement)) {
file.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
@@ -382,7 +382,7 @@
}
boolean useOnDemand = true;
- if (packageName.length() == 0){
+ if (packageName.isEmpty()){
useOnDemand = false;
}
@@ -640,7 +640,7 @@
int limitCount = isStaticImportNeeded ? settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND :
settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND;
if (classCount >= limitCount) return true;
- if (packageName.length() == 0) return false;
+ if (packageName.isEmpty()) return false;
PackageEntryTable table = settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND;
return table != null && table.contains(packageName);
}
@@ -839,21 +839,23 @@
final boolean[] hasResolveProblem = {false};
// do not visit imports
for (PsiClass aClass : file.getClasses()) {
- aClass.accept(new JavaRecursiveElementWalkingVisitor() {
- @Override
- public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
- String name = reference.getReferenceName();
- Pair<String, Boolean> pair = unresolvedNames.get(name);
- if (reference.multiResolve(false).length == 0) {
- hasResolveProblem[0] = true;
- if (pair != null) {
- namesToImport.add(pair);
- unresolvedNames.remove(name);
+ if (!(aClass instanceof PsiCompiledElement)) {
+ aClass.accept(new JavaRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
+ String name = reference.getReferenceName();
+ Pair<String, Boolean> pair = unresolvedNames.get(name);
+ if (reference.multiResolve(false).length == 0) {
+ hasResolveProblem[0] = true;
+ if (pair != null) {
+ namesToImport.add(pair);
+ unresolvedNames.remove(name);
+ }
}
+ super.visitReferenceElement(reference);
}
- super.visitReferenceElement(reference);
- }
- });
+ });
+ }
}
if (hasResolveProblem[0]) {
namesToImport.addAll(unresolvedOnDemand);
@@ -872,7 +874,7 @@
public static boolean hasPackage(@NotNull String className, @NotNull String packageName){
if (!className.startsWith(packageName)) return false;
if (className.length() == packageName.length()) return false;
- if (packageName.length() > 0 && className.charAt(packageName.length()) != '.') return false;
+ if (!packageName.isEmpty() && className.charAt(packageName.length()) != '.') return false;
return className.indexOf('.', packageName.length() + 1) < 0;
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDClassComment.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDClassComment.java
index ad0e0d5..354e853 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDClassComment.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDClassComment.java
@@ -15,9 +15,11 @@
*/
package com.intellij.psi.impl.source.codeStyle.javadoc;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
+import java.util.List;
/**
* Class comment
@@ -25,51 +27,45 @@
* @author Dmitry Skavish
*/
public class JDClassComment extends JDParamListOwnerComment {
- public JDClassComment(CommentFormatter formatter) {
+ private List<String> myAuthorsList;
+ private String myVersion;
+
+ public JDClassComment(@NotNull CommentFormatter formatter) {
super(formatter);
}
- private ArrayList authorsList;
- private String version;
-
@Override
- protected void generateSpecial(String prefix, @NonNls StringBuffer sb) {
+ protected void generateSpecial(@NotNull String prefix, @NotNull StringBuilder sb) {
super.generateSpecial(prefix, sb);
- if (!isNull(authorsList)) {
- for (Object aAuthorsList : authorsList) {
- String s = (String)aAuthorsList;
+ if (!isNull(myAuthorsList)) {
+ JDTag tag = JDTag.AUTHOR;
+ for (String author : myAuthorsList) {
sb.append(prefix);
- sb.append("@author ");
- sb.append(myFormatter.getParser().splitIntoCLines(s, prefix + " ", false));
+ sb.append(tag.getWithEndWhitespace());
+ sb.append(myFormatter.getParser().formatJDTagDescription(author, tag.getDescriptionPrefix(prefix)));
}
}
- if (!isNull(version)) {
+ if (!isNull(myVersion)) {
sb.append(prefix);
- sb.append("@version ");
- sb.append(myFormatter.getParser().splitIntoCLines(version, prefix + " ", false));
+ JDTag tag = JDTag.VERSION;
+ sb.append(tag.getWithEndWhitespace());
+ sb.append(myFormatter.getParser().formatJDTagDescription(myVersion, tag.getDescriptionPrefix(prefix)));
}
}
- public void addAuthor(String author) {
- if (authorsList == null) {
- authorsList = new ArrayList();
+ public void addAuthor(@NotNull String author) {
+ if (myAuthorsList == null) {
+ myAuthorsList = ContainerUtilRt.newArrayList();
}
- authorsList.add(author);
+ myAuthorsList.add(author);
}
- public ArrayList getAuthorsList() {
- return authorsList;
- }
-
- public void setAuthorsList(ArrayList authorsList) {
- this.authorsList = authorsList;
- }
-
+ @Nullable
public String getVersion() {
- return version;
+ return myVersion;
}
- public void setVersion(String version) {
- this.version = version;
+ public void setVersion(@NotNull String version) {
+ this.myVersion = version;
}
}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
index cedc964..28dc6a3 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
@@ -15,9 +15,11 @@
*/
package com.intellij.psi.impl.source.codeStyle.javadoc;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
+import java.util.List;
/**
* @author max
@@ -27,43 +29,42 @@
* @author Dmitry Skavish
*/
public class JDComment {
- protected CommentFormatter myFormatter;
+ protected final CommentFormatter myFormatter;
- String description;
- protected ArrayList unknownList;
- protected ArrayList seeAlsoList;
- protected String since;
- String deprecated;
+ private String myDescription;
+ private List<String> myUnknownList;
+ private List<String> mySeeAlsoList;
+ private String mySince;
+ private String myDeprecated;
- //protected LinkedHashMap xdocTagMap = new LinkedHashMap();
-
- public JDComment(CommentFormatter formatter) {
+ public JDComment(@NotNull CommentFormatter formatter) {
myFormatter = formatter;
}
- protected static boolean isNull(String s) {
+ protected static boolean isNull(@Nullable String s) {
return s == null || s.trim().length() == 0;
}
- protected static boolean isNull(ArrayList l) {
+ protected static boolean isNull(@Nullable List<?> l) {
return l == null || l.size() == 0;
}
- public String generate(String indent) {
+ @Nullable
+ public String generate(@NotNull String indent) {
final String prefix;
+
if (myFormatter.getSettings().JD_LEADING_ASTERISKS_ARE_ENABLED) {
prefix = indent + " * ";
} else {
prefix = indent;
}
- @NonNls StringBuffer sb = new StringBuffer();
-// sb.append("/**\n");
-
+ StringBuilder sb = new StringBuilder();
int start = sb.length();
- if (!isNull(description)) {
- sb.append(myFormatter.getParser().splitIntoCLines(description, prefix));
+ if (!isNull(myDescription)) {
+ sb.append(prefix);
+ sb.append(myFormatter.getParser().formatJDTagDescription(myDescription, prefix));
if (myFormatter.getSettings().JD_ADD_BLANK_AFTER_DESCRIPTION) {
sb.append(prefix);
@@ -73,48 +74,40 @@
generateSpecial(prefix, sb);
- if (!isNull(unknownList) && myFormatter.getSettings().JD_KEEP_INVALID_TAGS) {
- for (Object aUnknownList : unknownList) {
- String s = (String)aUnknownList;
- sb.append(myFormatter.getParser().splitIntoCLines(s, prefix));
- }
- }
-
- /*
- if( xdocTagMap.size() > 0 ) {
- Iterator it = xdocTagMap.values().iterator();
- while( it.hasNext() ) {
- ArrayList list = (ArrayList) it.next();
- for( int i = 0; i<list.size(); i++ ) {
- XDTag tag = (XDTag) list.get(i);
- tag.append(sb, prefix);
- if( myFormatter.getSettings().add_blank_after_xdoclet_tag ) {
- sb.append(prefix);
- sb.append('\n');
- }
- }
- }
- }*/
-
- if (!isNull(seeAlsoList)) {
- for (Object aSeeAlsoList : seeAlsoList) {
- String s = (String)aSeeAlsoList;
+ if (!isNull(myUnknownList) && myFormatter.getSettings().JD_KEEP_INVALID_TAGS) {
+ for (String aUnknownList : myUnknownList) {
sb.append(prefix);
- sb.append("@see ");
- sb.append(myFormatter.getParser().splitIntoCLines(s, prefix + " ", false));
+ sb.append(myFormatter.getParser().formatJDTagDescription(aUnknownList, prefix));
}
}
- if (!isNull(since)) {
- sb.append(prefix);
- sb.append("@since ");
- sb.append(myFormatter.getParser().splitIntoCLines(since, prefix + " ", false));
+ if (!isNull(mySeeAlsoList)) {
+ JDTag tag = JDTag.SEE;
+ for (String aSeeAlsoList : mySeeAlsoList) {
+ sb.append(prefix);
+ sb.append(tag.getWithEndWhitespace());
+ StringBuilder tagDescription = myFormatter.getParser()
+ .formatJDTagDescription(aSeeAlsoList, prefix, true, tag.getDescriptionPrefix(prefix).length());
+ sb.append(tagDescription);
+ }
}
- if (deprecated != null) {
+ if (!isNull(mySince)) {
+ JDTag tag = JDTag.SINCE;
sb.append(prefix);
- sb.append("@deprecated ");
- sb.append(myFormatter.getParser().splitIntoCLines(deprecated, prefix + " ", false));
+ sb.append(tag.getWithEndWhitespace());
+ StringBuilder tagDescription = myFormatter.getParser()
+ .formatJDTagDescription(mySince, prefix, true, tag.getDescriptionPrefix(prefix).length());
+ sb.append(tagDescription);
+ }
+
+ if (myDeprecated != null) {
+ JDTag tag = JDTag.DEPRECATED;
+ sb.append(prefix);
+ sb.append(tag.getWithEndWhitespace());
+ StringBuilder tagDescription = myFormatter.getParser()
+ .formatJDTagDescription(myDeprecated, prefix, true, tag.getDescriptionPrefix(prefix).length());
+ sb.append(tagDescription);
}
if (sb.length() == start) return null;
@@ -139,77 +132,37 @@
return sb.toString();
}
- protected void generateSpecial(String prefix, StringBuffer sb) {
+ protected void generateSpecial(@NotNull String prefix, @NotNull StringBuilder sb) {
}
- public void addSeeAlso(String seeAlso) {
- if (seeAlsoList == null) {
- seeAlsoList = new ArrayList();
+ public void addSeeAlso(@NotNull String seeAlso) {
+ if (mySeeAlsoList == null) {
+ mySeeAlsoList = ContainerUtilRt.newArrayList();
}
- seeAlsoList.add(seeAlso);
+ mySeeAlsoList.add(seeAlso);
}
- public void addUnknownTag(String unknownTag) {
- if (unknownList == null) {
- unknownList = new ArrayList();
+ public void addUnknownTag(@NotNull String unknownTag) {
+ if (myUnknownList == null) {
+ myUnknownList = ContainerUtilRt.newArrayList();
}
- unknownList.add(unknownTag);
- }
-/*
- public void addXDocTag( XDTag tag ) {
- getXdocTagList(tag.getNamespaceDesc()).add(tag);
- }
-
- public ArrayList getXdocTagList( String nsName ) {
- ArrayList list = (ArrayList) xdocTagMap.get(nsName);
- if( list == null ) {
- list = new ArrayList();
- xdocTagMap.put(nsName, list);
- }
- return list;
- }
-
- public ArrayList getXdocTagList( XDNamespaceDesc desc ) {
- return getXdocTagList(desc.getName());
- }
-*/
- public ArrayList getSeeAlsoList() {
- return seeAlsoList;
+ myUnknownList.add(unknownTag);
}
- public void setUnknownList(ArrayList unknownList) {
- this.unknownList = unknownList;
+ public void setSince(@Nullable String since) {
+ this.mySince = since;
}
- public void setSeeAlsoList(ArrayList seeAlsoList) {
- this.seeAlsoList = seeAlsoList;
+ public void setDeprecated(@Nullable String deprecated) {
+ this.myDeprecated = deprecated;
}
- public ArrayList getUnknownList() {
- return unknownList;
- }
-
- public String getSince() {
- return since;
- }
-
- public void setSince(String since) {
- this.since = since;
- }
-
- public String getDeprecated() {
- return deprecated;
- }
-
- public void setDeprecated(String deprecated) {
- this.deprecated = deprecated;
- }
-
+ @Nullable
public String getDescription() {
- return description;
+ return myDescription;
}
- public void setDescription(String description) {
- this.description = description;
+ public void setDescription(@Nullable String description) {
+ this.myDescription = description;
}
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDMethodComment.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDMethodComment.java
index 6fd664b..0059b2f 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDMethodComment.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDMethodComment.java
@@ -15,9 +15,11 @@
*/
package com.intellij.psi.impl.source.codeStyle.javadoc;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
+import java.util.List;
/**
* Method comment
@@ -25,26 +27,23 @@
* @author Dmitry Skavish
*/
public class JDMethodComment extends JDParamListOwnerComment {
- public JDMethodComment(CommentFormatter formatter) {
+ private String myReturnTag;
+ private List<NameDesc> myThrowsList;
+
+ public JDMethodComment(@NotNull CommentFormatter formatter) {
super(formatter);
}
- private String returnTag;
- private ArrayList<NameDesc> throwsList;
-
- private static final @NonNls String THROWS_TAG = "@throws ";
- private static final @NonNls String EXCEPTION_TAG = "@exception ";
-
@Override
- protected void generateSpecial(String prefix, @NonNls StringBuffer sb) {
-
+ protected void generateSpecial(@NotNull String prefix, @NotNull StringBuilder sb) {
super.generateSpecial(prefix, sb);
- if (returnTag != null) {
- if (returnTag.trim().length() != 0 || myFormatter.getSettings().JD_KEEP_EMPTY_RETURN) {
+ if (myReturnTag != null) {
+ if (myFormatter.getSettings().JD_KEEP_EMPTY_RETURN || myReturnTag.trim().length() != 0) {
+ JDTag tag = JDTag.RETURN;
sb.append(prefix);
- sb.append("@return ");
- sb.append(myFormatter.getParser().splitIntoCLines(returnTag, prefix + " ", false));
+ sb.append(tag.getWithEndWhitespace());
+ sb.append(myFormatter.getParser().formatJDTagDescription(myReturnTag, prefix, true, tag.getDescriptionPrefix(prefix).length()));
if (myFormatter.getSettings().JD_ADD_BLANK_AFTER_RETURN) {
sb.append(prefix);
sb.append('\n');
@@ -52,48 +51,24 @@
}
}
- if (throwsList != null) {
- String tag = myFormatter.getSettings().JD_USE_THROWS_NOT_EXCEPTION ? THROWS_TAG : EXCEPTION_TAG;
- generateList(prefix, sb, throwsList, tag,
+ if (myThrowsList != null) {
+ JDTag tag = myFormatter.getSettings().JD_USE_THROWS_NOT_EXCEPTION ? JDTag.THROWS : JDTag.EXCEPTION;
+ generateList(prefix, sb, myThrowsList, tag.getWithEndWhitespace(),
myFormatter.getSettings().JD_ALIGN_EXCEPTION_COMMENTS,
- myFormatter.getSettings().JD_MIN_EXCEPTION_NAME_LENGTH,
- myFormatter.getSettings().JD_MAX_EXCEPTION_NAME_LENGTH,
myFormatter.getSettings().JD_KEEP_EMPTY_EXCEPTION,
myFormatter.getSettings().JD_PARAM_DESCRIPTION_ON_NEW_LINE
);
}
}
- public String getReturnTag() {
- return returnTag;
+ public void setReturnTag(@NotNull String returnTag) {
+ this.myReturnTag = returnTag;
}
- public void setReturnTag(String returnTag) {
- this.returnTag = returnTag;
- }
-
- public void removeThrow(NameDesc nd) {
- if (throwsList == null) return;
- throwsList.remove(nd);
- }
-
- public ArrayList<NameDesc> getThrowsList() {
- return throwsList;
- }
-
- public void addThrow(String className, String description) {
- if (throwsList == null) {
- throwsList = new ArrayList<NameDesc>();
+ public void addThrow(@NotNull String className, @Nullable String description) {
+ if (myThrowsList == null) {
+ myThrowsList = ContainerUtilRt.newArrayList();
}
- throwsList.add(new NameDesc(className, description));
+ myThrowsList.add(new NameDesc(className, description));
}
-
- public NameDesc getThrow(String name) {
- return getNameDesc(name, throwsList);
- }
-
- public void setThrowsList(ArrayList<NameDesc> throwsList) {
- this.throwsList = throwsList;
- }
-
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParamListOwnerComment.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParamListOwnerComment.java
index 64af287..c004bc9 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParamListOwnerComment.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParamListOwnerComment.java
@@ -22,28 +22,28 @@
import com.intellij.formatting.IndentInfo;
import com.intellij.ide.highlighter.JavaFileType;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
+import java.util.List;
-public class JDParamListOwnerComment extends JDComment{
- protected ArrayList<NameDesc> parmsList;
- private static final @NonNls String PARAM_TAG = "@param ";
+public class JDParamListOwnerComment extends JDComment {
+ protected List<NameDesc> myParamsList;
- public JDParamListOwnerComment(CommentFormatter formatter) {
+ public JDParamListOwnerComment(@NotNull CommentFormatter formatter) {
super(formatter);
}
@Override
- protected void generateSpecial(String prefix, StringBuffer sb) {
- if (parmsList != null) {
+ protected void generateSpecial(@NotNull String prefix, @NotNull StringBuilder sb) {
+ if (myParamsList != null) {
int before = sb.length();
- generateList(prefix, sb, parmsList, PARAM_TAG,
+ generateList(prefix, sb, myParamsList, JDTag.PARAM.getWithEndWhitespace(),
myFormatter.getSettings().JD_ALIGN_PARAM_COMMENTS,
- myFormatter.getSettings().JD_MIN_PARM_NAME_LENGTH,
- myFormatter.getSettings().JD_MAX_PARM_NAME_LENGTH,
myFormatter.getSettings().JD_KEEP_EMPTY_PARAMETER,
myFormatter.getSettings().JD_PARAM_DESCRIPTION_ON_NEW_LINE
);
@@ -56,35 +56,25 @@
}
}
- public NameDesc getParameter(String name) {
- return getNameDesc(name, parmsList);
+ @Nullable
+ public NameDesc getParameter(@Nullable String name) {
+ return getNameDesc(name, myParamsList);
}
- public void removeParameter(NameDesc nd) {
- if (parmsList == null) return;
- parmsList.remove(nd);
- }
-
- public ArrayList<NameDesc> getParmsList() {
- return parmsList;
- }
-
- public void addParameter(String name, String description) {
- if (parmsList == null) {
- parmsList = new ArrayList<NameDesc>();
+ public void addParameter(@NotNull String name, @Nullable String description) {
+ if (myParamsList == null) {
+ myParamsList = ContainerUtilRt.newArrayList();
}
- parmsList.add(new NameDesc(name, description));
+ myParamsList.add(new NameDesc(name, description));
}
- public void setParmsList(ArrayList<NameDesc> parmsList) {
- this.parmsList = parmsList;
- }
-
- static NameDesc getNameDesc(String name, ArrayList<NameDesc> list) {
+ @Nullable
+ private static NameDesc getNameDesc(@Nullable String name, @Nullable List<NameDesc> list) {
if (list == null) return null;
- for (Object aList : list) {
- NameDesc parameter = (NameDesc)aList;
- if (parameter.name.equals(name)) return parameter;
+ for (NameDesc aList : list) {
+ if (aList.name.equals(name)) {
+ return aList;
+ }
}
return null;
}
@@ -93,59 +83,56 @@
* Generates parameters or exceptions
*
*/
- protected void generateList(String prefix, StringBuffer sb, ArrayList<NameDesc> list, String tag, boolean align_comments,
- int min_name_length, int max_name_length, boolean generate_empty_tags, boolean wrapDescription)
+ protected void generateList(@NotNull String prefix,
+ @NotNull StringBuilder sb,
+ @NotNull List<NameDesc> list,
+ @NotNull String tag,
+ boolean align_comments,
+ boolean generate_empty_tags,
+ boolean wrapDescription)
{
CodeStyleSettings settings = myFormatter.getSettings();
CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptions(JavaFileType.INSTANCE);
String continuationIndent = new IndentInfo(0, indentOptions.CONTINUATION_INDENT_SIZE, 0).generateNewWhiteSpace(indentOptions);
+
int max = 0;
- if (align_comments && ! wrapDescription) {
- for (Object aList : list) {
- NameDesc nd = (NameDesc)aList;
- int l = nd.name.length();
+
+ if (align_comments && !wrapDescription) {
+ for (NameDesc nd: list) {
+ int currentLength = nd.name.length();
if (isNull(nd.desc) && !generate_empty_tags) continue;
- if (l > max && l <= max_name_length) max = l;
+ //finding longest parameter length
+ if (currentLength > max) {
+ max = currentLength;
+ }
}
}
- max = Math.max(max, min_name_length);
-
- // create filler
- StringBuffer fill = new StringBuffer(prefix.length() + tag.length() + max + 1);
+ StringBuilder fill = new StringBuilder(prefix.length() + tag.length() + max + 1);
fill.append(prefix);
- int k = max + 1 + tag.length();
- for (int i = 0; i < k; i++) fill.append(' ');
+ StringUtil.repeatSymbol(fill, ' ', max + 1 + tag.length());
String wrapParametersPrefix = prefix + continuationIndent;
-
- for (Object aList1 : list) {
- NameDesc nd = (NameDesc)aList1;
+ for (NameDesc nd : list) {
if (isNull(nd.desc) && !generate_empty_tags) continue;
if (wrapDescription && !isNull(nd.desc)) {
sb.append(prefix).append(tag).append(nd.name).append("\n");
- sb.append(myFormatter.getParser().splitIntoCLines(nd.desc, wrapParametersPrefix));
+ sb.append(wrapParametersPrefix);
+ sb.append(myFormatter.getParser().formatJDTagDescription(nd.desc, wrapParametersPrefix));
}
else if (align_comments) {
sb.append(prefix);
sb.append(tag);
sb.append(nd.name);
-
- if (nd.name.length() > max_name_length) {
- sb.append('\n');
- sb.append(myFormatter.getParser().splitIntoCLines(nd.desc, fill, true));
- }
- else {
- int len = max - nd.name.length() + 1;
- for (int j = 0; j < len; j++) {
- sb.append(' ');
- }
- sb.append(myFormatter.getParser().splitIntoCLines(nd.desc, fill, false));
- }
+ int spacesNumber = max + 1 - nd.name.length();
+ StringUtil.repeatSymbol(sb, ' ', Math.max(0, spacesNumber));
+ sb.append(myFormatter.getParser().formatJDTagDescription(nd.desc, fill));
}
else {
- sb.append(myFormatter.getParser().splitIntoCLines(tag + nd.name + " " + nd.desc, prefix, true));
+ sb.append(prefix);
+ String description = (nd.desc == null) ? "" : nd.desc;
+ sb.append(myFormatter.getParser().formatJDTagDescription(tag + nd.name + " " + description, prefix));
}
}
}
-}
\ No newline at end of file
+}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
index 1f7d047..859e848 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
@@ -16,8 +16,9 @@
package com.intellij.psi.impl.source.codeStyle.javadoc;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.CodeStyleSettings;
-import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -26,27 +27,31 @@
/**
* Javadoc parser
- *
+ *
* @author Dmitry Skavish
*/
public class JDParser {
-
+
private static final String PRE_TAG_START = "<pre>";
private static final String PRE_TAG_END = "</pre>";
-
+ private static final String P_END_TAG = "</p>";
+ private static final String P_START_TAG = "<p>";
+ private static final String SELF_CLOSED_P_TAG = "<p/>";
+
private final CodeStyleSettings mySettings;
- public JDParser(CodeStyleSettings settings) {
+ public JDParser(@NotNull CodeStyleSettings settings) {
mySettings = settings;
}
private static final char lineSeparator = '\n';
- public JDComment parse(String text, JDComment c) {
+ @NotNull
+ public JDComment parse(@Nullable String text, @NotNull JDComment c) {
if (text == null) return c;
- ArrayList<Boolean> markers = new ArrayList<Boolean>();
- ArrayList<String> l = toArray(text, "\n", markers);
+ List<Boolean> markers = new ArrayList<Boolean>();
+ List<String> l = toArray(text, "\n", markers);
if (l == null) return c;
int size = l.size();
if (size == 0) return c;
@@ -73,7 +78,7 @@
l.set(i, line);
}
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
String tag = null;
for (int i = 0; i <= size; i++) {
String line = i == size ? null : l.get(i);
@@ -126,42 +131,22 @@
}
/**
- * Breaks the specified string by lineseparator into array of strings
- *
- * @param s the specified string
- * @return array of strings (lines)
- */
- public ArrayList<String> toArrayByNL(String s) {
- return toArray(s, "\n", null);
- }
-
- /**
- * Breaks the specified string by comma into array of strings
- *
- * @param s the specified string
- * @return list of strings
- */
- public ArrayList<String> toArrayByComma(String s) {
- return toArray(s, ",", null);
- }
-
- /**
* Breaks the specified string by the specified separators into array of strings
- *
+ *
* @param s the specified string
* @param separators the specified separators
* @param markers if this parameter is not null then it will be filled with Boolean values:
- * true if the correspoding line in returned list is inside <pre> tag,
+ * true if the corresponding line in returned list is inside <pre> tag,
* false if it is outside
* @return array of strings (lines)
*/
- @SuppressWarnings({"HardCodedStringLiteral"})
- private ArrayList<String> toArray(String s, String separators, ArrayList<Boolean> markers) {
+ @Nullable
+ private List<String> toArray(@Nullable String s, @NotNull String separators, @Nullable List<Boolean> markers) {
if (s == null) return null;
s = s.trim();
if (s.length() == 0) return null;
boolean p2nl = markers != null && mySettings.JD_P_AT_EMPTY_LINES;
- ArrayList<String> list = new ArrayList<String>();
+ List<String> list = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(s, separators, true);
boolean first = true;
int preCount = 0;
@@ -170,7 +155,7 @@
String token = st.nextToken();
curPos += token.length();
- if (separators.indexOf(token) >= 0) {
+ if (separators.contains(token)) {
if (!first) {
list.add("");
if (markers != null) markers.add(Boolean.valueOf(preCount > 0));
@@ -180,7 +165,7 @@
else {
first = true;
if (p2nl) {
- if (isParaTag(token) && s.indexOf("</p>", curPos) < 0) {
+ if (isParaTag(token) && s.indexOf(P_END_TAG, curPos) < 0) {
list.add("");
markers.add(Boolean.valueOf(preCount > 0));
continue;
@@ -191,9 +176,9 @@
list.add(token);
if (markers != null) {
- if (token.indexOf("<pre>") >= 0) preCount++;
+ if (token.contains(PRE_TAG_START)) preCount++;
markers.add(Boolean.valueOf(preCount > 0));
- if (token.indexOf("</pre>") >= 0) preCount--;
+ if (token.contains(PRE_TAG_END)) preCount--;
}
}
@@ -201,56 +186,30 @@
return list;
}
- @SuppressWarnings({"HardCodedStringLiteral"})
- private boolean isParaTag(final String token) {
+ private static boolean isParaTag(@NotNull final String token) {
String withoutWS = removeWhiteSpacesFrom(token).toLowerCase();
- return withoutWS.equals("<p/>") || withoutWS.equals("<p>");
+ return withoutWS.equals(SELF_CLOSED_P_TAG) || withoutWS.equals(P_START_TAG);
}
- private String removeWhiteSpacesFrom(final String token) {
- final StringBuffer result = new StringBuffer();
+ @NotNull
+ private static String removeWhiteSpacesFrom(@NotNull final String token) {
+ final StringBuilder result = new StringBuilder();
for (char c : token.toCharArray()) {
if (c != ' ') result.append(c);
}
return result.toString();
}
- public static String toLines(ArrayList l) {
- if (l == null || l.size() == 0) return null;
- StringBuffer sb = new StringBuffer();
- for (Object aL : l) {
- String s = (String)aL;
- if (sb.length() > 0) {
- sb.append(lineSeparator);
- }
- sb.append(s);
- }
- return sb.toString();
- }
-
- public static String toCommaSeparated(ArrayList<String> l) {
- if (l == null || l.size() == 0) return null;
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < l.size(); i++) {
- String s = l.get(i);
- if (i != 0) {
- sb.append(", ");
- }
- sb.append(s);
- }
- return sb.toString();
- }
-
/**
- * Processes all lines (char sequences separated by line feed symbol) from the given string slitting them if necessary
- * ensuring that every returned line contains less symbols than the given width.
- *
+ * Processes all lines (char sequences separated by line feed symbol) from the given string slitting them if necessary
+ * ensuring that every returned line contains less symbols than the given width.
+ *
* @param s the specified string
* @param width width of the wrapped text
* @return array of strings (lines)
*/
@Nullable
- private List<String> toArrayWrapping(String s, int width) {
+ private List<String> toArrayWrapping(@Nullable String s, int width) {
List<String> list = new ArrayList<String>();
List<Pair<String, Boolean>> pairs = splitToParagraphs(s);
if (pairs == null) {
@@ -305,7 +264,7 @@
/**
* Processes given string and produces on its basis set of pairs like <code>'(string; flag)'</code> where <code>'string'</code>
* is interested line and <code>'flag'</code> indicates if it is wrapped to {@code <pre>} tag.
- *
+ *
* @param s string to process
* @return processing result
*/
@@ -313,15 +272,16 @@
private List<Pair<String, Boolean>> splitToParagraphs(@Nullable String s) {
if (s == null) return null;
s = s.trim();
- if (s == null /* just to make inspection happy*/ || s.isEmpty()) return null;
+ if (s.isEmpty()) return null;
List<Pair<String, Boolean>> result = new ArrayList<Pair<String, Boolean>>();
-
+
StringBuilder sb = new StringBuilder();
- ArrayList<Boolean> markers = new ArrayList<Boolean>();
- ArrayList<String> list = toArray(s, "\n", markers);
+ List<Boolean> markers = new ArrayList<Boolean>();
+ List<String> list = toArray(s, "\n", markers);
Boolean[] marks = markers.toArray(new Boolean[markers.size()]);
markers.clear();
+ assert list != null;
for (int i = 0; i < list.size(); i++) {
String s1 = list.get(i);
if (marks[i].booleanValue()) {
@@ -353,27 +313,17 @@
}
return result;
}
-
- static abstract class TagParser {
+
+ abstract static class TagParser {
abstract boolean parse(String tag, String line, JDComment c);
}
- private static final @NonNls String SEE_TAG = "see";
- private static final @NonNls String SINCE_TAG = "since";
- private static final @NonNls String VERSION_TAG = "version";
- private static final @NonNls String DEPRECATED_TAG = "deprecated";
- private static final @NonNls String RETURN_TAG = "return";
- private static final @NonNls String PARAM_TAG = "param";
- private static final @NonNls String THROWS_TAG = "throws";
- private static final @NonNls String EXCEPTION_TAG = "exception";
- private static final @NonNls String AUTHOR_TAG = "author";
-
private static final TagParser[] tagParsers = {
new TagParser() {
@Override
boolean parse(String tag, String line, JDComment c) {
- boolean isMyTag = SEE_TAG.equals(tag);
+ boolean isMyTag = JDTag.SEE.tagEqual(tag);
if (isMyTag) {
c.addSeeAlso(line);
}
@@ -383,7 +333,7 @@
new TagParser() {
@Override
boolean parse(String tag, String line, JDComment c) {
- boolean isMyTag = SINCE_TAG.equals(tag);
+ boolean isMyTag = JDTag.SINCE.tagEqual(tag);
if (isMyTag) {
c.setSince(line);
}
@@ -393,7 +343,7 @@
new TagParser() {
@Override
boolean parse(String tag, String line, JDComment c) {
- boolean isMyTag = c instanceof JDClassComment && VERSION_TAG.equals(tag);
+ boolean isMyTag = c instanceof JDClassComment && JDTag.VERSION.tagEqual(tag);
if (isMyTag) {
((JDClassComment)c).setVersion(line);
}
@@ -403,7 +353,7 @@
new TagParser() {
@Override
boolean parse(String tag, String line, JDComment c) {
- boolean isMyTag = DEPRECATED_TAG.equals(tag);
+ boolean isMyTag = JDTag.DEPRECATED.tagEqual(tag);
if (isMyTag) {
c.setDeprecated(line);
}
@@ -413,7 +363,7 @@
new TagParser() {
@Override
boolean parse(String tag, String line, JDComment c) {
- boolean isMyTag = c instanceof JDMethodComment && RETURN_TAG.equals(tag);
+ boolean isMyTag = c instanceof JDMethodComment && JDTag.RETURN.tagEqual(tag);
if (isMyTag) {
JDMethodComment mc = (JDMethodComment)c;
mc.setReturnTag(line);
@@ -424,7 +374,7 @@
new TagParser() {
@Override
boolean parse(String tag, String line, JDComment c) {
- boolean isMyTag = c instanceof JDParamListOwnerComment && PARAM_TAG.equals(tag);
+ boolean isMyTag = c instanceof JDParamListOwnerComment && JDTag.PARAM.tagEqual(tag);
if (isMyTag) {
JDParamListOwnerComment mc = (JDParamListOwnerComment)c;
int idx;
@@ -447,7 +397,7 @@
new TagParser() {
@Override
boolean parse(String tag, String line, JDComment c) {
- boolean isMyTag = c instanceof JDMethodComment && (THROWS_TAG.equals(tag) || EXCEPTION_TAG.equals(tag));
+ boolean isMyTag = c instanceof JDMethodComment && (JDTag.THROWS.tagEqual(tag) || JDTag.EXCEPTION.tagEqual(tag));
if (isMyTag) {
JDMethodComment mc = (JDMethodComment)c;
int idx;
@@ -470,7 +420,7 @@
new TagParser() {
@Override
boolean parse(String tag, String line, JDComment c) {
- boolean isMyTag = c instanceof JDClassComment && AUTHOR_TAG.equals(tag);
+ boolean isMyTag = c instanceof JDClassComment && JDTag.AUTHOR.tagEqual(tag);
if (isMyTag) {
JDClassComment cl = (JDClassComment)c;
cl.addAuthor(line.trim());
@@ -478,33 +428,72 @@
return isMyTag;
}
},
-/* new TagParser() {
- boolean parse( String tag, String line, JDComment c ) {
- XDTag xdtag = XDTag.parse(tag, line);
- if( xdtag != null ) {
- c.addXDocTag(xdtag);
- }
- return xdtag != null;
- }
- },*/
};
- protected StringBuffer splitIntoCLines(String s, String prefix) {
- return splitIntoCLines(s, prefix, true);
+ /**
+ * @see JDParser#formatJDTagDescription(String, CharSequence, boolean, int)
+ */
+ @NotNull
+ protected StringBuilder formatJDTagDescription(@Nullable String s, @NotNull CharSequence prefix) {
+ return formatJDTagDescription(s, prefix, false, 0);
}
- protected StringBuffer splitIntoCLines(String s, String prefix, boolean add_prefix_to_first_line) {
- return splitIntoCLines(s, new StringBuffer(prefix), add_prefix_to_first_line);
+ private static boolean lineHasUnclosedPreTag(@NotNull String line) {
+ return StringUtil.getOccurrenceCount(line, PRE_TAG_START) > StringUtil.getOccurrenceCount(line, PRE_TAG_END);
}
- protected StringBuffer splitIntoCLines(String s, StringBuffer prefix, boolean add_prefix_to_first_line) {
- @NonNls StringBuffer sb = new StringBuffer();
- if (add_prefix_to_first_line) {
- sb.append(prefix);
+ /**
+ * Returns formatted JavaDoc tag description, according to selected configuration
+ * @param str JavaDoc tag description
+ * @param prefix JavaDoc prefix(like " * ") which will be appended to every new line
+ * @param firstLineShorter flag if first line should be shorter (has another prefix length than other lines)
+ * @param firstLinePrefixLength first line prefix length
+ * @return formatted JavaDoc tag description
+ */
+ @NotNull
+ protected StringBuilder formatJDTagDescription(@Nullable String str,
+ @NotNull CharSequence prefix,
+ boolean firstLineShorter,
+ int firstLinePrefixLength)
+ {
+ StringBuilder sb = new StringBuilder();
+ List<String> list;
+
+ //If wrap comments selected, comments should be wrapped by the right margin
+ if (mySettings.WRAP_COMMENTS) {
+ list = toArrayWrapping(str, mySettings.RIGHT_MARGIN - prefix.length());
+
+ if (firstLineShorter
+ && list != null && !list.isEmpty()
+ && list.get(0).length() > mySettings.RIGHT_MARGIN - firstLinePrefixLength)
+ {
+ list = new ArrayList<String>();
+ //want the first line to be shorter, according to it's prefix
+ String firstLine = toArrayWrapping(str, mySettings.RIGHT_MARGIN - firstLinePrefixLength).get(0);
+ //so now first line is exactly same width we need
+ list.add(firstLine);
+ str = str.substring(firstLine.length());
+ //actually there is one more problem - when first line has unclosed <pre> tag, substring should be processed if it's inside <pre>
+ boolean unclosedPreTag = lineHasUnclosedPreTag(firstLine);
+ if (unclosedPreTag) {
+ str = PRE_TAG_START + str.replaceAll("^\\s+", "");
+ }
+
+ //getting all another lines according to their prefix
+ List<String> subList = toArrayWrapping(str, mySettings.RIGHT_MARGIN - prefix.length());
+
+ //removing pre tag
+ if (unclosedPreTag) {
+ String firstLineTagRemoved = subList.get(0).substring(PRE_TAG_START.length());
+ subList.set(0, firstLineTagRemoved);
+ }
+ list.addAll(subList);
+ }
}
- List<String> list = mySettings.WRAP_COMMENTS
- ? toArrayWrapping(s, mySettings.RIGHT_MARGIN - prefix.length())
- : toArray(s, "\n", new ArrayList<Boolean>());
+ else {
+ list = toArray(str, "\n", new ArrayList<Boolean>());
+ }
+
if (list == null) {
sb.append('\n');
}
@@ -515,11 +504,11 @@
if (line.length() == 0 && !mySettings.JD_KEEP_EMPTY_LINES) continue;
if (i != 0) sb.append(prefix);
if (line.length() == 0 && mySettings.JD_P_AT_EMPTY_LINES && !insidePreTag) {
- sb.append("<p/>");
+ sb.append(SELF_CLOSED_P_TAG);
}
else {
sb.append(line);
-
+
// We want to track if we're inside <pre>...</pre> in order to not generate <p/> there.
if (PRE_TAG_START.equals(line)) {
insidePreTag = true;
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDTag.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDTag.java
new file mode 100644
index 0000000..1b35145
--- /dev/null
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDTag.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.codeStyle.javadoc;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * User: Lepenkin Y.
+ * Date: 7/1/13
+ * Time: 4:15 PM
+ */
+public enum JDTag {
+ SEE("see"),
+ AUTHOR("author"),
+ VERSION("version"),
+ THROWS("throws"),
+ EXCEPTION("exception"),
+ RETURN("return"),
+ PARAM("param"),
+ SINCE("since"),
+ DEPRECATED("deprecated");
+
+
+ @NotNull private final String myTag;
+
+ JDTag(@NotNull String tag) {
+ this.myTag = tag;
+ }
+
+ @NotNull
+ public String getDescriptionPrefix(@NotNull String prefix) {
+ return prefix + StringUtil.repeatSymbol(' ', getWithEndWhitespace().length());
+ }
+
+ @NotNull
+ public String getWithEndWhitespace() {
+ return "@" + myTag + " ";
+ }
+
+ public boolean tagEqual(@Nullable String tag) {
+ return myTag.equals(tag);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/NameDesc.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/NameDesc.java
index d7de91b..6e8ee10 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/NameDesc.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/NameDesc.java
@@ -15,29 +15,25 @@
*/
package com.intellij.psi.impl.source.codeStyle.javadoc;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
/**
*
* @author Dmitry Skavish
*/
public class NameDesc {
+ @NotNull public final String name;
+ @Nullable public final String desc;
- public String name;
- public String desc;
- private String type;
-
- public NameDesc(String name, String desc) {
+ public NameDesc(@NotNull String name, @Nullable String desc) {
this.name = name;
this.desc = desc;
}
- public NameDesc(String name, String desc, String type) {
- this.name = name;
- this.desc = desc;
- this.type = type;
- }
-
+ @NotNull
+ @Override
public String toString() {
- if (type == null) return name;
- return name + ": " + type;
+ return name;
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/OptimizeImportsRefactoringHelper.java b/java/java-impl/src/com/intellij/refactoring/OptimizeImportsRefactoringHelper.java
index 5f6072a..cd8613d 100644
--- a/java/java-impl/src/com/intellij/refactoring/OptimizeImportsRefactoringHelper.java
+++ b/java/java-impl/src/com/intellij/refactoring/OptimizeImportsRefactoringHelper.java
@@ -39,12 +39,9 @@
Set<PsiJavaFile> javaFiles = new HashSet<PsiJavaFile>();
for (UsageInfo usage : usages) {
if (usage.isNonCodeUsage) continue;
- final PsiElement element = usage.getElement();
- if (element != null) {
- final PsiFile file = element.getContainingFile();
- if (file instanceof PsiJavaFile) {
- javaFiles.add((PsiJavaFile)file);
- }
+ final PsiFile file = usage.getFile();
+ if (file instanceof PsiJavaFile) {
+ javaFiles.add((PsiJavaFile)file);
}
}
return javaFiles;
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java
index 6faaf8e..eba4ae9 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java
@@ -111,8 +111,9 @@
public String extractSignature(PsiElement element, @NotNull ChangeInfo initialChangeInfo) {
final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false);
if (method != null && isInsideMethodSignature(element, method) && method == initialChangeInfo.getMethod()) {
- final TextRange signatureRange = getSignatureRange(method);
- return element.getContainingFile().getText().substring(signatureRange.getStartOffset(), signatureRange.getEndOffset());
+ final PsiCodeBlock body = method.getBody();
+ final TextRange signatureRange = new TextRange(0, body != null ? body.getStartOffsetInParent() : method.getTextLength());
+ return signatureRange.substring(method.getText());
} else if (element instanceof PsiIdentifier && element.getParent() instanceof PsiNamedElement) {
return element.getText();
}
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
index 647cd09..d46fa20 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
@@ -30,7 +30,6 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ValidationInfo;
-import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
@@ -50,13 +49,13 @@
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.ui.*;
-import com.intellij.ui.components.JBLabel;
import com.intellij.ui.table.JBTable;
import com.intellij.ui.table.TableView;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.*;
import com.intellij.util.ui.DialogUtil;
import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.table.JBListTable;
import com.intellij.util.ui.table.JBTableRow;
import com.intellij.util.ui.table.JBTableRowEditor;
import org.jetbrains.annotations.NotNull;
@@ -228,7 +227,6 @@
@Override
protected JComponent getRowPresentation(ParameterTableModelItemBase<ParameterInfoImpl> item, boolean selected, final boolean focused) {
- final JPanel panel = new JPanel(new BorderLayout());
final String typeText = item.typeCodeFragment.getText();
final String separator = StringUtil.repeatSymbol(' ', getTypesMaxLength() - typeText.length() + 1);
String text = typeText + separator + item.parameter.getName();
@@ -246,28 +244,7 @@
if (!StringUtil.isEmpty(tail)) {
text += " //" + tail;
}
- final EditorTextField field = new EditorTextField(" " + text, getProject(), getFileType()) {
- @Override
- protected boolean shouldHaveBorder() {
- return false;
- }
- };
-
- Font font = EditorColorsManager.getInstance().getGlobalScheme().getFont(EditorFontType.PLAIN);
- font = new Font(font.getFontName(), font.getStyle(), 12);
- field.setFont(font);
-
- if (selected && focused) {
- panel.setBackground(UIUtil.getTableSelectionBackground());
- field.setAsRendererWithSelection(UIUtil.getTableSelectionBackground(), UIUtil.getTableSelectionForeground());
- } else {
- panel.setBackground(UIUtil.getTableBackground());
- if (selected && !focused) {
- panel.setBorder(new DottedBorder(UIUtil.getTableForeground()));
- }
- }
- panel.add(field, BorderLayout.WEST);
- return panel;
+ return JBListTable.createEditorTextFieldPresentation(getProject(), getFileType(), " " + text, selected, focused);
}
private int getTypesMaxLength() {
@@ -311,43 +288,20 @@
private EditorTextField myDefaultValueEditor;
private JCheckBox myAnyVar;
- class MyDocumentListener extends DocumentAdapter {
- private int myColumn;
-
- private MyDocumentListener(int column) {
- myColumn = column;
- }
-
- @Override
- public void documentChanged(DocumentEvent e) {
- fireDocumentChanged(e, myColumn);
- }
- }
-
@Override
public void prepareEditor(JTable table, int row) {
setLayout(new BorderLayout());
- final JPanel typePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 4, 2, true, false));
final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(item.typeCodeFragment);
myTypeEditor = new EditorTextField(document, getProject(), getFileType());
myTypeEditor.addDocumentListener(mySignatureUpdater);
- final JBLabel typeLabel = new JBLabel("Type:", UIUtil.ComponentStyle.SMALL);
- IJSwingUtilities.adjustComponentsOnMac(typeLabel, myTypeEditor);
- typePanel.add(typeLabel);
- typePanel.add(myTypeEditor);
myTypeEditor.setPreferredWidth(t.getWidth() / 2);
- myTypeEditor.addDocumentListener(new MyDocumentListener(0));
- add(typePanel, BorderLayout.WEST);
+ myTypeEditor.addDocumentListener(new RowEditorChangeListener(0));
+ add(createLabeledPanel("Type:", myTypeEditor), BorderLayout.WEST);
- final JPanel namePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 4, 2, true, false));
myNameEditor = new EditorTextField(item.parameter.getName(), getProject(), getFileType());
myNameEditor.addDocumentListener(mySignatureUpdater);
- myNameEditor.addDocumentListener(new MyDocumentListener(1));
- final JBLabel nameLabel = new JBLabel("Name:", UIUtil.ComponentStyle.SMALL);
- IJSwingUtilities.adjustComponentsOnMac(nameLabel, myNameEditor);
- namePanel.add(nameLabel);
- namePanel.add(myNameEditor);
- add(namePanel, BorderLayout.CENTER);
+ myNameEditor.addDocumentListener(new RowEditorChangeListener(1));
+ add(createLabeledPanel("Name:", myNameEditor), BorderLayout.CENTER);
new TextFieldCompletionProvider() {
@Override
@@ -377,17 +331,12 @@
if (!item.isEllipsisType() && item.parameter.getOldIndex() == -1) {
final JPanel additionalPanel = new JPanel(new BorderLayout());
- final JPanel defaultValuePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 4, 2, true, false));
final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(item.defaultValueCodeFragment);
myDefaultValueEditor = new EditorTextField(doc, getProject(), getFileType());
((PsiExpressionCodeFragment)item.defaultValueCodeFragment).setExpectedType(getRowType(item));
- final JBLabel defaultValueLabel = new JBLabel("Default value:", UIUtil.ComponentStyle.SMALL);
- IJSwingUtilities.adjustComponentsOnMac(defaultValueLabel, myDefaultValueEditor);
- defaultValuePanel.add(defaultValueLabel);
- defaultValuePanel.add(myDefaultValueEditor);
myDefaultValueEditor.setPreferredWidth(t.getWidth() / 2);
- myDefaultValueEditor.addDocumentListener(new MyDocumentListener(2));
- additionalPanel.add(defaultValuePanel, BorderLayout.WEST);
+ myDefaultValueEditor.addDocumentListener(new RowEditorChangeListener(2));
+ additionalPanel.add(createLabeledPanel("Default value:", myDefaultValueEditor), BorderLayout.WEST);
if (!isGenerateDelegate()) {
myAnyVar = new JCheckBox("&Use Any Var");
diff --git a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java
index 34c4308..c3a8d72 100644
--- a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java
@@ -187,7 +187,7 @@
myTypeParameterReplacements = buildTypeParameterReplacements();
List<PsiClass> inheritors = new ArrayList<PsiClass>();
- RefactoringUtil.sortDepthFirstRightLeftOrder(usages);
+ CommonRefactoringUtil.sortDepthFirstRightLeftOrder(usages);
// Process usages
for (final UsageInfo usage : usages) {
diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
index a081ff2..b6e3be4 100644
--- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
@@ -37,6 +37,7 @@
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.move.moveClassesOrPackages.MoveDirectoryWithClassesProcessor;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ArrayUtilRt;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -183,14 +184,16 @@
String className = null;
boolean openInEditor = true;
if (copyOneClass(classes)) {
- final String commonPath = ArrayUtil.find(elements, classes.values().iterator().next()) == -1 ? normalizeRelativeMap(relativePathsMap) : null;
+ final String commonPath =
+ ArrayUtilRt.find(elements, classes.values().iterator().next()) == -1 ? normalizeRelativeMap(relativePathsMap) : null;
CopyClassDialog dialog = new CopyClassDialog(classes.values().iterator().next()[0], defaultTargetDirectory, project, false){
@Override
protected String getQualifiedName() {
- if (commonPath != null && !commonPath.isEmpty()) {
- return StringUtil.getQualifiedName(super.getQualifiedName(), commonPath.replaceAll("/", "."));
+ final String qualifiedName = super.getQualifiedName();
+ if (commonPath != null && !commonPath.isEmpty() && !qualifiedName.endsWith(commonPath)) {
+ return StringUtil.getQualifiedName(qualifiedName, commonPath.replaceAll("/", "."));
}
- return super.getQualifiedName();
+ return qualifiedName;
}
};
dialog.setTitle(RefactoringBundle.message("copy.handler.copy.class"));
diff --git a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsProcessor.java b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsProcessor.java
index 180e28d..fc87374 100644
--- a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsProcessor.java
@@ -299,7 +299,7 @@
for (List<MyUsageInfo> usageInfos : usagesInFiles.values()) {
//this is to avoid elements to become invalid as a result of processUsage
final MyUsageInfo[] infos = usageInfos.toArray(new MyUsageInfo[usageInfos.size()]);
- RefactoringUtil.sortDepthFirstRightLeftOrder(infos);
+ CommonRefactoringUtil.sortDepthFirstRightLeftOrder(infos);
for (MyUsageInfo info : infos) {
processUsage(info);
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java
index 3171175..41aa79b 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java
@@ -42,10 +42,8 @@
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.refactoring.util.RefactoringMessageDialog;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.Processor;
-import com.intellij.util.Query;
+import com.intellij.util.*;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -195,7 +193,7 @@
}
}
- final PsiElement writeAccess = checkRefsInAugmentedAssignmentOrUnaryModified(refsToInline);
+ final PsiElement writeAccess = checkRefsInAugmentedAssignmentOrUnaryModified(refsToInline, defToInline);
if (writeAccess != null) {
HighlightManager.getInstance(project).addOccurrenceHighlights(editor, new PsiElement[]{writeAccess}, writeAttributes, true, null);
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.is.accessed.for.writing", localName));
@@ -234,10 +232,11 @@
final Runnable runnable = new Runnable() {
public void run() {
try{
- PsiExpression[] exprs = new PsiExpression[refsToInline.length];
+ SmartPsiElementPointer<PsiExpression>[] exprs = new SmartPsiElementPointer[refsToInline.length];
+ final SmartPointerManager pointerManager = SmartPointerManager.getInstance(project);
for(int idx = 0; idx < refsToInline.length; idx++){
PsiJavaCodeReferenceElement refElement = (PsiJavaCodeReferenceElement)refsToInline[idx];
- exprs[idx] = InlineUtil.inlineVariable(local, defToInline, refElement);
+ exprs[idx] = pointerManager.createSmartPsiElementPointer(InlineUtil.inlineVariable(local, defToInline, refElement));
}
if (!isInliningVariableInitializer(defToInline)) {
@@ -251,12 +250,17 @@
}
if (editor != null && !ApplicationManager.getApplication().isUnitTestMode()) {
- highlightManager.addOccurrenceHighlights(editor, exprs, attributes, true, null);
+ highlightManager.addOccurrenceHighlights(editor, ContainerUtil.convert(exprs, new PsiExpression[refsToInline.length], new Function<SmartPsiElementPointer<PsiExpression>, PsiExpression>() {
+ @Override
+ public PsiExpression fun(SmartPsiElementPointer<PsiExpression> pointer) {
+ return pointer.getElement();
+ }
+ }), attributes, true, null);
WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
}
- for (final PsiExpression expr : exprs) {
- InlineUtil.tryToInlineArrayCreationForVarargs(expr);
+ for (final SmartPsiElementPointer<PsiExpression> expr : exprs) {
+ InlineUtil.tryToInlineArrayCreationForVarargs(expr.getElement());
}
}
catch (IncorrectOperationException e){
@@ -273,12 +277,13 @@
}
@Nullable
- public static PsiElement checkRefsInAugmentedAssignmentOrUnaryModified(final PsiElement[] refsToInline) {
+ public static PsiElement checkRefsInAugmentedAssignmentOrUnaryModified(final PsiElement[] refsToInline, PsiElement defToInline) {
for (PsiElement element : refsToInline) {
PsiElement parent = element.getParent();
if (parent instanceof PsiArrayAccessExpression) {
if (((PsiArrayAccessExpression)parent).getIndexExpression() == element) continue;
+ if (defToInline instanceof PsiExpression && !(defToInline instanceof PsiNewExpression)) continue;
element = parent;
parent = parent.getParent();
}
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java
index 1659cac..a82994d 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java
@@ -404,7 +404,7 @@
}
}
else {
- RefactoringUtil.sortDepthFirstRightLeftOrder(usages);
+ CommonRefactoringUtil.sortDepthFirstRightLeftOrder(usages);
if (myMethod.isConstructor()) {
for (UsageInfo usage : usages) {
PsiElement element = usage.getElement();
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
index e22f0b8..58d4d1e 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
@@ -125,7 +125,7 @@
if (rExpr != null) {
final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, psiParameter, refExpr);
- if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs) == null) {
+ if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs, def) == null) {
new WriteCommandAction(project) {
@Override
protected void run(Result result) throws Throwable {
diff --git a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringProcessor.java b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringProcessor.java
index 818b8c3..ab340a5 100644
--- a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringProcessor.java
@@ -32,10 +32,7 @@
import com.intellij.refactoring.inlineSuperClass.usageInfo.*;
import com.intellij.refactoring.memberPushDown.PushDownConflicts;
import com.intellij.refactoring.memberPushDown.PushDownProcessor;
-import com.intellij.refactoring.util.DocCommentPolicy;
-import com.intellij.refactoring.util.FixableUsageInfo;
-import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
-import com.intellij.refactoring.util.RefactoringUtil;
+import com.intellij.refactoring.util.*;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.refactoring.util.classMembers.MemberInfoStorage;
import com.intellij.usageView.UsageInfo;
@@ -290,7 +287,7 @@
} else {
super.performRefactoring(pushDownUsages);
}
- RefactoringUtil.sortDepthFirstRightLeftOrder(usages);
+ CommonRefactoringUtil.sortDepthFirstRightLeftOrder(usages);
for (UsageInfo usageInfo : usages) {
if (!(usageInfo instanceof ReplaceExtendsListUsageInfo || usageInfo instanceof RemoveImportUsageInfo)) {
try {
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java
index 8f0f5fb..ba3ba8a 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java
@@ -382,7 +382,7 @@
}
ChangeContextUtil.clearContextInfo(myParameterInitializer);
- // Replacing expression occurences
+ // Replacing expression occurrences
for (UsageInfo usage : usages) {
if (usage instanceof ChangedMethodCallInfo) {
PsiElement element = usage.getElement();
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
index 740c2cc..9d64136 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
@@ -134,12 +134,18 @@
}
else {
int selection;
- PsiExpression expression = expressions.get(0);
- if (expression instanceof PsiReferenceExpression && ((PsiReferenceExpression)expression).resolve() instanceof PsiLocalVariable) {
- selection = 1;
- }
- else {
- selection = -1;
+ if (statementsInRange.length == 1 &&
+ statementsInRange[0] instanceof PsiExpressionStatement &&
+ PsiUtilCore.hasErrorElementChild(statementsInRange[0])) {
+ selection = expressions.indexOf(((PsiExpressionStatement)statementsInRange[0]).getExpression());
+ } else {
+ PsiExpression expression = expressions.get(0);
+ if (expression instanceof PsiReferenceExpression && ((PsiReferenceExpression)expression).resolve() instanceof PsiLocalVariable) {
+ selection = 1;
+ }
+ else {
+ selection = -1;
+ }
}
IntroduceTargetChooser.showChooser(editor, expressions,
new Pass<PsiExpression>(){
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java
index eb5938c..c3562db 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java
@@ -20,6 +20,7 @@
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.command.impl.StartMarkAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
@@ -29,9 +30,11 @@
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.scope.processor.VariablesProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -105,6 +108,11 @@
}
@Override
+ protected StartMarkAction startRename() throws StartMarkAction.AlreadyStartedException {
+ return StartMarkAction.start(myEditor, myProject, getCommandName());
+ }
+
+ @Override
protected void beforeTemplateStart() {
super.beforeTemplateStart();
final ResolveSnapshotProvider resolveSnapshotProvider = VariableInplaceRenamer.INSTANCE.forLanguage(myScope.getLanguage());
@@ -169,6 +177,7 @@
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
}
if (myExpressionText != null) {
+ if (!ReadonlyStatusHandler.ensureDocumentWritable(myProject, InjectedLanguageUtil.getTopLevelEditor(myEditor).getDocument())) return;
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
final PsiDeclarationStatement element = myPointer.getElement();
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java
index 530660b..de994d9 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java
@@ -94,7 +94,8 @@
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(containingDirectory);
if (aPackage != null) {
final String qualifiedName = aPackage.getQualifiedName();
- final PsiPackageStatement packageStatement = qualifiedName.length() > 0
+ final PsiNameHelper helper = JavaPsiFacade.getInstance(file.getProject()).getNameHelper();
+ final PsiPackageStatement packageStatement = !StringUtil.isEmptyOrSpaces(qualifiedName) && helper.isQualifiedName(qualifiedName)
? JavaPsiFacade.getElementFactory(file.getProject()).createPackageStatement(qualifiedName)
: null;
if (file instanceof PsiJavaFile) {
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerImpl.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerImpl.java
index fe37b7d..c33cc48 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerImpl.java
@@ -34,14 +34,16 @@
public static final String REFACTORING_NAME = RefactoringBundle.message("move.inner.to.upper.level.title");
- public static void doMove(final Project project, PsiElement[] elements, final MoveCallback moveCallback) {
+ public static void doMove(final Project project, PsiElement[] elements, final MoveCallback moveCallback, @Nullable PsiElement targetContainer) {
if (elements.length != 1) return;
final PsiClass aClass = (PsiClass) elements[0];
boolean condition = aClass.getContainingClass() != null;
LOG.assertTrue(condition);
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, aClass)) return;
- final PsiElement targetContainer = getTargetContainer(aClass, true);
+ if (targetContainer == null) {
+ targetContainer = getTargetContainer(aClass, true);
+ }
if (targetContainer == null) return;
final MoveInnerDialog dialog = new MoveInnerDialog(
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java
index 35ca3e2..ddff1f0 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java
@@ -164,7 +164,7 @@
if (myParameterNameOuterClass != null) {
// pass outer as a parameter
field = factory.createField(myFieldNameOuterClass, factory.createType(myOuterClass));
- field = (PsiField)myInnerClass.add(field);
+ field = addOuterField(field);
myInnerClass = field.getContainingClass();
addFieldInitializationToConstructors(myInnerClass, field, myParameterNameOuterClass);
}
@@ -296,6 +296,19 @@
}
}
+ private PsiField addOuterField(PsiField field) {
+ final PsiMember[] members = PsiTreeUtil.getChildrenOfType(myInnerClass, PsiMember.class);
+ if (members != null) {
+ for (PsiMember member : members) {
+ if (!member.hasModifierProperty(PsiModifier.STATIC)) {
+ return (PsiField)myInnerClass.addBefore(field, member);
+ }
+ }
+ }
+
+ return (PsiField)myInnerClass.add(field);
+ }
+
protected void performPsiSpoilingRefactoring() {
if (myNonCodeUsages != null) {
RenameUtil.renameNonCodeUsages(myProject, myNonCodeUsages);
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerToUpperHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerToUpperHandler.java
index f807e89..706fc79 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerToUpperHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerToUpperHandler.java
@@ -17,6 +17,7 @@
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
@@ -35,9 +36,7 @@
public boolean canMove(final PsiElement[] elements, @Nullable final PsiElement targetContainer) {
if (elements.length != 1) return false;
PsiElement element = elements [0];
- return isNonStaticInnerClass(element) &&
- (targetContainer == null || targetContainer.equals(MoveInnerImpl.getTargetContainer((PsiClass)elements[0], false)));
-
+ return isNonStaticInnerClass(element);
}
private static boolean isNonStaticInnerClass(final PsiElement element) {
@@ -46,7 +45,7 @@
}
public void doMove(final Project project, final PsiElement[] elements, final PsiElement targetContainer, final MoveCallback callback) {
- MoveInnerImpl.doMove(project, elements, callback);
+ MoveInnerImpl.doMove(project, elements, callback, targetContainer);
}
public boolean tryToMove(final PsiElement element, final Project project, final DataContext dataContext, final PsiReference reference,
@@ -60,7 +59,7 @@
RefactoringBundle.message("move.title"), null);
return true;
}
- MoveInnerImpl.doMove(project, new PsiElement[]{aClass}, null);
+ MoveInnerImpl.doMove(project, new PsiElement[]{aClass}, null, LangDataKeys.TARGET_PSI_ELEMENT.getData(dataContext));
return true;
}
return false;
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerToUpperOrMembersHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerToUpperOrMembersHandler.java
index 823ee22..2ad1d53 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerToUpperOrMembersHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerToUpperOrMembersHandler.java
@@ -17,6 +17,7 @@
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
@@ -39,8 +40,7 @@
public boolean canMove(final PsiElement[] elements, @Nullable final PsiElement targetContainer) {
if (elements.length != 1) return false;
PsiElement element = elements [0];
- return isStaticInnerClass(element) &&
- (targetContainer == null || targetContainer.equals(MoveInnerImpl.getTargetContainer((PsiClass)elements[0], false)));
+ return isStaticInnerClass(element);
}
private static boolean isStaticInnerClass(final PsiElement element) {
@@ -64,13 +64,14 @@
final Editor editor) {
if (isStaticInnerClass(element) && !JavaMoveClassesOrPackagesHandler.isReferenceInAnonymousClass(reference)) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.move.moveInner");
+ final PsiElement targetContainer = LangDataKeys.TARGET_PSI_ELEMENT.getData(dataContext);
PsiClass aClass = (PsiClass) element;
SelectInnerOrMembersRefactoringDialog dialog = new SelectInnerOrMembersRefactoringDialog(aClass, project);
dialog.show();
if (dialog.isOK()) {
final MoveHandlerDelegate moveHandlerDelegate = dialog.getRefactoringHandler();
if (moveHandlerDelegate != null) {
- moveHandlerDelegate.doMove(project, new PsiElement[] { aClass }, null, null);
+ moveHandlerDelegate.doMove(project, new PsiElement[] { aClass }, targetContainer, null);
}
}
return true;
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java
index ea39904..4dda4d7 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java
@@ -193,7 +193,7 @@
}
}
else { // no qualifier
- if (usage.qualifierClass != null && PsiTreeUtil.getParentOfType(refExpr, PsiSwitchLabelStatement.class) == null) {
+ if (usage.qualifierClass != null && (!usage.qualifierClass.isEnum() || PsiTreeUtil.getParentOfType(refExpr, PsiSwitchLabelStatement.class) == null)) {
changeQualifier(refExpr, usage.qualifierClass, usage.member);
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java
index 3f4f59a..cc594a3 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java
@@ -116,7 +116,7 @@
PsiElement ref = psiReference.getElement();
final MoveMemberHandler handler = MoveMemberHandler.EP_NAME.forLanguage(ref.getLanguage());
MoveMembersUsageInfo usage = null;
- if (handler != null) {
+ if (handler != null && myTargetClass != null) {
usage = handler.getUsage(member, psiReference, myMembersToMove, myTargetClass);
}
if (usage != null) {
diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java
index 7e485dc..8c2f688 100644
--- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java
@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.rename;
+import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -43,10 +44,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.RenameJavaVariableProcessor");
@@ -150,7 +148,9 @@
String newPropertyName = manager.variableNameToPropertyName(newName, VariableKind.FIELD);
boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
- PsiMethod getter = PropertyUtil.findPropertyGetter(aClass, propertyName, isStatic, false);
+
+ PsiMethod[] getters = GetterSetterPrototypeProvider.findGetters(aClass, propertyName, isStatic);
+
PsiMethod setter = PropertyUtil.findPropertySetter(aClass, propertyName, isStatic, false);
boolean shouldRenameSetterParameter = false;
@@ -161,22 +161,31 @@
shouldRenameSetterParameter = parameterName.equals(setterParameter.getName());
}
- String newGetterName = "";
-
- if (getter != null) {
- String getterId = getter.getName();
- newGetterName = PropertyUtil.suggestGetterName(newPropertyName, field.getType(), getterId);
- if (newGetterName.equals(getterId)) {
- getter = null;
- newGetterName = null;
- } else {
- for (PsiMethod method : getter.findDeepestSuperMethods()) {
- if (method instanceof PsiCompiledElement) {
- getter = null;
- break;
- }
+ if (getters != null) {
+ List<PsiMethod> validGetters = new ArrayList<PsiMethod>();
+ for (PsiMethod getter : getters) {
+ String newGetterName = GetterSetterPrototypeProvider.suggestNewGetterName(propertyName, newPropertyName, getter);
+ String getterId = null;
+ if (newGetterName == null) {
+ getterId = getter.getName();
+ newGetterName = PropertyUtil.suggestGetterName(newPropertyName, field.getType(), getterId);
}
+ if (newGetterName.equals(getterId)) {
+ continue;
+ }
+ else {
+ boolean valid = true;
+ for (PsiMethod method : getter.findDeepestSuperMethods()) {
+ if (method instanceof PsiCompiledElement) {
+ valid = false;
+ break;
+ }
+ }
+ if (!valid) continue;
+ }
+ validGetters.add(getter);
}
+ getters = validGetters.isEmpty() ? null : validGetters.toArray(new PsiMethod[validGetters.size()]);
}
String newSetterName = "";
@@ -201,14 +210,20 @@
}
}
- if ((getter != null || setter != null) && askToRenameAccesors(getter, setter, newName, project)) {
- getter = null;
+ if ((getters != null || setter != null) && askToRenameAccesors(getters != null ? getters[0] : null, setter, newName, project)) {
+ getters = null;
setter = null;
shouldRenameSetterParameter = false;
}
- if (getter != null) {
- addOverriddenAndImplemented(getter, newGetterName, allRenames);
+ if (getters != null) {
+ for (PsiMethod getter : getters) {
+ String newGetterName = GetterSetterPrototypeProvider.suggestNewGetterName(propertyName, newPropertyName, getter);
+ if (newGetterName == null) {
+ newGetterName = PropertyUtil.suggestGetterName(newPropertyName, field.getType(), getter.getName());
+ }
+ addOverriddenAndImplemented(getter, newGetterName, allRenames);
+ }
}
if (setter != null) {
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
index 7f8ae6d..ac7a6d9 100644
--- a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
@@ -16,6 +16,7 @@
package com.intellij.refactoring.safeDelete;
import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableUtil;
+import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider;
import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter;
import com.intellij.ide.util.SuperMethodWarningUtil;
import com.intellij.openapi.application.ApplicationManager;
@@ -187,21 +188,30 @@
PsiClass aClass = field.getContainingClass();
if (aClass != null) {
boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
- PsiMethod getter = PropertyUtil.findPropertyGetter(aClass, propertyName, isStatic, false);
- if (allElementsToDelete.contains(getter) || getter != null && !getter.isPhysical()) getter = null;
+ PsiMethod[] getters = GetterSetterPrototypeProvider.findGetters(aClass, propertyName, isStatic);
+ if (getters != null) {
+ final List<PsiMethod> validGetters = new ArrayList<PsiMethod>(1);
+ for (PsiMethod getter : getters) {
+ if (!allElementsToDelete.contains(getter) && (getter != null && getter.isPhysical())) {
+ validGetters.add(getter);
+ }
+ }
+ getters = validGetters.isEmpty() ? null : validGetters.toArray(new PsiMethod[validGetters.size()]);
+ }
+
PsiMethod setter = PropertyUtil.findPropertySetter(aClass, propertyName, isStatic, false);
if (allElementsToDelete.contains(setter) || setter != null && !setter.isPhysical()) setter = null;
- if (askUser && (getter != null || setter != null)) {
+ if (askUser && (getters != null || setter != null)) {
final String message =
- RefactoringMessageUtil.getGetterSetterMessage(field.getName(), RefactoringBundle.message("delete.title"), getter, setter);
- if (Messages.showYesNoDialog(project, message, RefactoringBundle.message("safe.delete.title"), Messages.getQuestionIcon()) != 0) {
- getter = null;
+ RefactoringMessageUtil.getGetterSetterMessage(field.getName(), RefactoringBundle.message("delete.title"), getters != null ? getters[0] : null, setter);
+ if (!ApplicationManager.getApplication().isUnitTestMode() && Messages.showYesNoDialog(project, message, RefactoringBundle.message("safe.delete.title"), Messages.getQuestionIcon()) != 0) {
+ getters = null;
setter = null;
}
}
List<PsiElement> elements = new ArrayList<PsiElement>();
if (setter != null) elements.add(setter);
- if (getter != null) elements.add(getter);
+ if (getters != null) Collections.addAll(elements, getters);
return elements;
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java
index 45b0b1a..53c1b70 100644
--- a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java
+++ b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java
@@ -451,7 +451,6 @@
else if (declScope instanceof PsiForeachStatement) {
final PsiExpression iteratedValue = ((PsiForeachStatement)declScope).getIteratedValue();
addLink(type, iteratedValue);
- addLink(iteratedValue, type);
}
else if (declScope instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)declScope;
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java
index b0c8fea..1060495 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java
@@ -96,13 +96,12 @@
final PsiElement element = p.getFirst().retrieve();
LOG.assertTrue(element != null);
final PsiType type = ((PsiExpression)element).getType();
- report[j++] = "Cannot convert type of expression <b>" +
- StringUtil.escapeXml(element.getText()) +
- "</b>" +
- " from <b>" +
- StringUtil.escapeXml(type.getCanonicalText()) +
- "</b> to <b>" + StringUtil.escapeXml(p.getSecond().getCanonicalText()) +
- "</b><br>";
+ report[j++] = "Cannot convert type of expression <b>" + StringUtil.escapeXml(element.getText()) + "</b>" +
+ (type != null
+ ? " from <b>" + StringUtil.escapeXml(type.getCanonicalText()) + "</b>" +
+ " to <b>" + StringUtil.escapeXml(p.getSecond().getCanonicalText()) + "</b>"
+ : "")
+ + "<br>";
}
return report;
@@ -539,7 +538,6 @@
}
void markFailedConversion(final Pair<PsiType, PsiType> typePair, final PsiExpression expression) {
- LOG.assertTrue(expression.getType() != null);
LOG.assertTrue(typePair.getSecond() != null);
myFailedConversions.add(new Pair<PsiAnchor, PsiType>(PsiAnchor.create(expression), typePair.getSecond()));
}
diff --git a/java/java-impl/src/com/intellij/refactoring/util/FixableUsagesRefactoringProcessor.java b/java/java-impl/src/com/intellij/refactoring/util/FixableUsagesRefactoringProcessor.java
index 2c5fc9f..4ad49a9 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/FixableUsagesRefactoringProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/FixableUsagesRefactoringProcessor.java
@@ -38,7 +38,7 @@
}
protected void performRefactoring(UsageInfo[] usageInfos) {
- RefactoringUtil.sortDepthFirstRightLeftOrder(usageInfos);
+ CommonRefactoringUtil.sortDepthFirstRightLeftOrder(usageInfos);
for (UsageInfo usageInfo : usageInfos) {
if (usageInfo instanceof FixableUsageInfo) {
try {
diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
index 80a4a91..ca905b0 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
@@ -172,22 +172,6 @@
}
}
- //order of usages accross different files is irrelevant
- public static void sortDepthFirstRightLeftOrder(final UsageInfo[] usages) {
- Arrays.sort(usages, new Comparator<UsageInfo>() {
- public int compare(final UsageInfo usage1, final UsageInfo usage2) {
- final PsiElement element1 = usage1.getElement();
- final PsiElement element2 = usage2.getElement();
- if (element1 == null) {
- if (element2 == null) return 0;
- return 1;
- }
- if (element2 == null) return -1;
- return element2.getTextRange().getStartOffset() - element1.getTextRange().getStartOffset();
- }
- });
- }
-
@Nullable
public static String suggestNewOverriderName(String oldOverriderName, String oldBaseName, String newBaseName) {
if (oldOverriderName.equals(oldBaseName)) {
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java b/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java
index b85bd97..38465bd 100644
--- a/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java
+++ b/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java
@@ -21,6 +21,7 @@
import com.intellij.psi.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -84,6 +85,10 @@
@NotNull
public abstract String[] getAllClassNames();
+ public boolean processAllClassNames(Processor<String> processor) {
+ return ContainerUtil.process(getAllClassNames(), processor);
+ }
+
/**
* Adds the names of all classes in the project and (optionally) libraries
* to the specified set.
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java b/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java
index 269006b..52d5801 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java
@@ -23,6 +23,7 @@
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
@@ -94,6 +95,17 @@
}
@Override
+ public boolean processAllClassNames(Processor<String> processor) {
+ CommonProcessors.UniqueProcessor<String> uniqueProcessor = new CommonProcessors.UniqueProcessor<String>(processor);
+ for (PsiShortNamesCache cache : myCaches) {
+ if (!cache.processAllClassNames(uniqueProcessor)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
public void getAllClassNames(@NotNull HashSet<String> dest) {
for (PsiShortNamesCache cache : myCaches) {
cache.getAllClassNames(dest);
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
index 215c9eb..b17c4b1 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
@@ -101,13 +101,17 @@
@Override
@NotNull
public String[] getAllClassNames() {
- final Collection<String> names = JavaShortClassNameIndex.getInstance().getAllKeys(myManager.getProject());
- return ArrayUtil.toStringArray(names);
+ return ArrayUtil.toStringArray(JavaShortClassNameIndex.getInstance().getAllKeys(myManager.getProject()));
}
@Override
public void getAllClassNames(@NotNull HashSet<String> set) {
- set.addAll(JavaShortClassNameIndex.getInstance().getAllKeys(myManager.getProject()));
+ processAllClassNames(new CommonProcessors.CollectProcessor<String>(set));
+ }
+
+ @Override
+ public boolean processAllClassNames(Processor<String> processor) {
+ return JavaShortClassNameIndex.getInstance().processAllKeys(myManager.getProject(), processor);
}
@Override
@@ -147,13 +151,12 @@
@Override
@NotNull
public String[] getAllMethodNames() {
- final Collection<String> names = JavaMethodNameIndex.getInstance().getAllKeys(myManager.getProject());
- return ArrayUtil.toStringArray(names);
+ return ArrayUtil.toStringArray(JavaMethodNameIndex.getInstance().getAllKeys(myManager.getProject()));
}
@Override
public void getAllMethodNames(@NotNull HashSet<String> set) {
- set.addAll(JavaMethodNameIndex.getInstance().getAllKeys(myManager.getProject()));
+ JavaMethodNameIndex.getInstance().processAllKeys(myManager.getProject(), new CommonProcessors.CollectProcessor<String>(set));
}
@Override
@@ -186,13 +189,12 @@
@Override
@NotNull
public String[] getAllFieldNames() {
- final Collection<String> names = JavaFieldNameIndex.getInstance().getAllKeys(myManager.getProject());
- return ArrayUtil.toStringArray(names);
+ return ArrayUtil.toStringArray(JavaFieldNameIndex.getInstance().getAllKeys(myManager.getProject()));
}
@Override
public void getAllFieldNames(@NotNull HashSet<String> set) {
- set.addAll(JavaFieldNameIndex.getInstance().getAllKeys(myManager.getProject()));
+ JavaFieldNameIndex.getInstance().processAllKeys(myManager.getProject(), new CommonProcessors.CollectProcessor<String>(set));
}
private <T extends PsiMember> List<T> filterMembers(Collection<T> members, final GlobalSearchScope scope) {
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java
index 2521522..b2d61c4 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java
@@ -24,6 +24,7 @@
import com.intellij.psi.impl.search.JavaSourceFilterScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.annotations.NotNull;
@@ -45,6 +46,6 @@
@Override
public Collection<PsiAnonymousClass> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return super.get(s, project, new JavaSourceFilterScope(scope));
+ return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiAnonymousClass.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java
index 54eb0ed..e00f2bf 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java
@@ -24,6 +24,7 @@
import com.intellij.psi.impl.search.JavaSourceFilterScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.annotations.NotNull;
@@ -44,6 +45,6 @@
@Override
public Collection<PsiField> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return super.get(s, project, new JavaSourceFilterScope(scope));
+ return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiField.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java
index a92856f..51d28ad 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java
@@ -24,6 +24,7 @@
import com.intellij.psi.impl.search.JavaSourceFilterScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.annotations.NotNull;
@@ -44,6 +45,6 @@
@Override
public Collection<PsiMethod> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return super.get(s, project, new JavaSourceFilterScope(scope));
+ return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiMethod.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java
index a70b7ea..e1e8819 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java
@@ -24,6 +24,7 @@
import com.intellij.psi.impl.search.JavaSourceFilterScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.annotations.NotNull;
@@ -45,7 +46,7 @@
@Override
public Collection<PsiReferenceList> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return super.get(s, project, new JavaSourceFilterScope(scope));
+ return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiReferenceList.class);
}
@Override
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java
index bae6155..b2e0d84 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java
@@ -22,10 +22,11 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
-import com.intellij.psi.JavaRecursiveElementWalkingVisitor;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiElement;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
@@ -33,14 +34,17 @@
import com.intellij.psi.search.searches.AllClassesSearch;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
+import com.intellij.util.TimedReference;
import org.jetbrains.annotations.NotNull;
+import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class AllClassesSearchExecutor implements QueryExecutor<PsiClass, AllClassesSearch.SearchParameters> {
+ private static final Key<TimedReference<SoftReference<Pair<String[], Long>>>> ALL_CLASS_NAMES_CACHE = Key.create("ALL_CLASS_NAMES_CACHE");
@Override
public boolean execute(@NotNull final AllClassesSearch.SearchParameters queryParameters, @NotNull final Processor<PsiClass> consumer) {
SearchScope scope = queryParameters.getScope();
@@ -55,17 +59,30 @@
}
return true;
}
-
- private static boolean processAllClassesInGlobalScope(final GlobalSearchScope scope, final Processor<PsiClass> processor, AllClassesSearch.SearchParameters parameters) {
- final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(parameters.getProject());
-
- final String[] names = ApplicationManager.getApplication().runReadAction(new Computable<String[]>() {
+
+ private static String[] getAllClassNames(final Project project) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<String[]>() {
@Override
public String[] compute() {
- return cache.getAllClassNames();
+ final long modCount = PsiManager.getInstance(project).getModificationTracker().getJavaStructureModificationCount();
+ TimedReference<SoftReference<Pair<String[], Long>>> ref1 = project.getUserData(ALL_CLASS_NAMES_CACHE);
+ SoftReference<Pair<String[], Long>> ref2 = ref1 == null ? null : ref1.get();
+ Pair<String[], Long> pair = ref2 == null ? null : ref2.get();
+ if (pair != null && pair.second.equals(modCount)) {
+ return pair.first;
+ }
+
+ String[] names = PsiShortNamesCache.getInstance(project).getAllClassNames();
+ ref1 = new TimedReference<SoftReference<Pair<String[], Long>>>(null);
+ ref1.set(new SoftReference<Pair<String[], Long>>(Pair.create(names, modCount)));
+ project.putUserData(ALL_CLASS_NAMES_CACHE, ref1);
+ return names;
}
});
+ }
+ private static boolean processAllClassesInGlobalScope(final GlobalSearchScope scope, final Processor<PsiClass> processor, final AllClassesSearch.SearchParameters parameters) {
+ String[] names = getAllClassNames(parameters.getProject());
final ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
if (indicator != null) {
indicator.checkCanceled();
@@ -93,6 +110,7 @@
}
});
+ final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(parameters.getProject());
for (final String name : sorted) {
ProgressIndicatorProvider.checkCanceled();
final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
@@ -111,11 +129,10 @@
return true;
}
- private static boolean processScopeRootForAllClasses(PsiElement scopeRoot, final Processor<PsiClass> processor) {
- if (scopeRoot == null) return true;
- final boolean[] stopped = new boolean[]{false};
+ private static boolean processScopeRootForAllClasses(@NotNull PsiElement scopeRoot, final Processor<PsiClass> processor) {
+ final boolean[] stopped = {false};
- scopeRoot.accept(new JavaRecursiveElementWalkingVisitor() {
+ JavaElementVisitor visitor = scopeRoot instanceof PsiCompiledElement ? new JavaRecursiveElementVisitor() {
@Override
public void visitElement(PsiElement element) {
if (!stopped[0]) {
@@ -123,11 +140,26 @@
}
}
- @Override public void visitClass(PsiClass aClass) {
+ @Override
+ public void visitClass(PsiClass aClass) {
stopped[0] = !processor.process(aClass);
super.visitClass(aClass);
}
- });
+ } : new JavaRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitElement(PsiElement element) {
+ if (!stopped[0]) {
+ super.visitElement(element);
+ }
+ }
+
+ @Override
+ public void visitClass(PsiClass aClass) {
+ stopped[0] = !processor.process(aClass);
+ super.visitClass(aClass);
+ }
+ };
+ scopeRoot.accept(visitor);
return !stopped[0];
}
diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
index 7c25697..481f809 100644
--- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
@@ -23,7 +23,7 @@
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.containers.*;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,7 +39,8 @@
private GenericsUtil() {}
- public static PsiType getGreatestLowerBound(PsiType type1, PsiType type2) {
+ public static PsiType getGreatestLowerBound(@Nullable PsiType type1, @Nullable PsiType type2) {
+ if (type1 == null || type2 == null) return null;
return PsiIntersectionType.createIntersection(type1, type2);
}
@@ -185,18 +186,21 @@
public static PsiClass[] getLeastUpperClasses(PsiClass aClass, PsiClass bClass) {
if (InheritanceUtil.isInheritorOrSelf(aClass, bClass, true)) return new PsiClass[]{bClass};
Set<PsiClass> supers = new LinkedHashSet<PsiClass>();
- getLeastUpperClassesInner(aClass, bClass, supers);
+ Set<PsiClass> visited = new HashSet<PsiClass>();
+ getLeastUpperClassesInner(aClass, bClass, supers, visited);
return supers.toArray(new PsiClass[supers.size()]);
}
- private static void getLeastUpperClassesInner(PsiClass aClass, PsiClass bClass, Set<PsiClass> supers) {
+ private static void getLeastUpperClassesInner(PsiClass aClass, PsiClass bClass, Set<PsiClass> supers, Set<PsiClass> visited) {
if (bClass.isInheritor(aClass, true)) {
addSuper(supers, aClass);
}
else {
final PsiClass[] aSupers = aClass.getSupers();
for (PsiClass aSuper : aSupers) {
- getLeastUpperClassesInner(aSuper, bClass, supers);
+ if (visited.add(aSuper)) {
+ getLeastUpperClassesInner(aSuper, bClass, supers, visited);
+ }
}
}
}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java
index 6fe40d8..5f51304 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java
@@ -22,8 +22,8 @@
* @author ven
*/
public class PsiCapturedWildcardType extends PsiType {
- private final PsiWildcardType myExistential;
- private final PsiElement myContext;
+ @NotNull private final PsiWildcardType myExistential;
+ @NotNull private final PsiElement myContext;
public boolean equals(final Object o) {
if (!(o instanceof PsiCapturedWildcardType)) return false;
@@ -36,13 +36,14 @@
return myExistential.hashCode() + 31 * myContext.hashCode();
}
- private PsiCapturedWildcardType(PsiWildcardType existential, final PsiElement context) {
+ private PsiCapturedWildcardType(@NotNull PsiWildcardType existential, @NotNull PsiElement context) {
super(PsiAnnotation.EMPTY_ARRAY);//todo
myExistential = existential;
myContext = context;
}
- public static PsiCapturedWildcardType create(PsiWildcardType existential, final PsiElement context) {
+ @NotNull
+ public static PsiCapturedWildcardType create(@NotNull PsiWildcardType existential, @NotNull PsiElement context) {
return new PsiCapturedWildcardType(existential, context);
}
@@ -104,10 +105,12 @@
}
}
+ @NotNull
public PsiWildcardType getWildcard() {
return myExistential;
}
+ @NotNull
public PsiElement getContext() {
return myContext;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
index 37fd4a4..4b2b4da 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
@@ -24,6 +24,7 @@
private final PsiMethod myMethod;
private final boolean myIsRaw;
+ private final String myName;
protected MethodSignatureBackedByPsiMethod(@NotNull PsiMethod method,
@NotNull PsiSubstitutor substitutor,
@@ -32,16 +33,14 @@
@NotNull PsiTypeParameter[] methodTypeParameters) {
super(substitutor, parameterTypes, methodTypeParameters);
myIsRaw = isRaw;
- if (!method.isValid()) {
- LOG.error("Invalid method: "+method, new PsiInvalidElementAccessException(method));
- }
myMethod = method;
+ myName = method.getName();
}
@NotNull
@Override
public String getName() {
- return myMethod.getName();
+ return myName;
}
@Override
@@ -84,7 +83,6 @@
PsiType[] parameterTypes = new PsiType[parameters.length];
for (int i = 0; i < parameterTypes.length; i++) {
PsiType type = parameters[i].getType();
- assert type.isValid();
parameterTypes[i] = isRaw ? TypeConversionUtil.erasure(substitutor.substitute(type)) : type;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBase.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBase.java
index 2dd259d..fe2bbae 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBase.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBase.java
@@ -25,6 +25,7 @@
private final PsiSubstitutor mySubstitutor;
private final PsiType[] myParameterTypes;
+ private volatile PsiType[] myErasedParameterTypes;
protected final PsiTypeParameter[] myTypeParameters;
protected MethodSignatureBase(@NotNull PsiSubstitutor substitutor, @NotNull PsiType[] parameterTypes, @NotNull PsiTypeParameter[] typeParameters) {
@@ -33,16 +34,23 @@
myParameterTypes = parameterTypes.length == 0 ? PsiType.EMPTY_ARRAY : new PsiType[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
PsiType type = parameterTypes[i];
- assert type == null || type.isValid();
+ if (type != null) {
+ PsiUtil.ensureValidType(type);
+ }
if (type instanceof PsiEllipsisType) type = ((PsiEllipsisType) type).toArrayType();
myParameterTypes[i] = substitutor.substitute(type);
}
myTypeParameters = typeParameters;
}
- protected MethodSignatureBase(@NotNull PsiSubstitutor substitutor, PsiParameterList parameterList, @Nullable PsiTypeParameterList typeParameterList) {
+ protected MethodSignatureBase(@NotNull PsiSubstitutor substitutor,
+ @Nullable PsiParameterList parameterList,
+ @Nullable PsiTypeParameterList typeParameterList) {
mySubstitutor = substitutor;
- if (parameterList != null) {
+ if (parameterList == null) {
+ myParameterTypes = PsiType.EMPTY_ARRAY;
+ }
+ else {
final PsiParameter[] parameters = parameterList.getParameters();
myParameterTypes = parameters.length == 0 ? PsiType.EMPTY_ARRAY : new PsiType[parameters.length];
for (int i = 0; i < parameters.length; i++) {
@@ -51,9 +59,6 @@
myParameterTypes[i] = substitutor.substitute(type);
}
}
- else {
- myParameterTypes = PsiType.EMPTY_ARRAY;
- }
myTypeParameters = typeParameterList == null ? PsiTypeParameter.EMPTY_ARRAY : typeParameterList.getTypeParameters();
}
@@ -70,6 +75,14 @@
return myTypeParameters;
}
+ public PsiType[] getErasedParameterTypes() {
+ PsiType[] result = myErasedParameterTypes;
+ if (result == null) {
+ myErasedParameterTypes = result = MethodSignatureUtil.calcErasedParameterTypes(this);
+ }
+ return result;
+ }
+
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MethodSignature)) return false;
@@ -80,9 +93,13 @@
public int hashCode() {
int result = getName().hashCode();
-
- final PsiType[] parameterTypes = getParameterTypes();
- result += 37 * parameterTypes.length;
+ final PsiType[] parameterTypes = getErasedParameterTypes();
+ result = 31 * result + parameterTypes.length;
+ for (int i = 0, length = Math.min(3, parameterTypes.length); i < length; i++) {
+ PsiType type = parameterTypes[i];
+ if (type == null) continue;
+ result = 31 * result + type.hashCode();
+ }
return result;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
index f97ff17..8692a22 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
@@ -23,6 +23,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -48,38 +49,37 @@
new TObjectHashingStrategy<MethodSignature>() {
@Override
public int computeHashCode(final MethodSignature signature) {
- int result = signature.isConstructor() ? 0 : signature.getName().hashCode();
-
- PsiType[] parameterTypes = signature.getParameterTypes();
- result += 37 * parameterTypes.length;
- PsiType firstParamType = parameterTypes.length == 0 ? null : parameterTypes[0];
- if (firstParamType != null) {
- firstParamType = TypeConversionUtil.erasure(firstParamType, signature.getSubstitutor());
- assert firstParamType != null : parameterTypes[0];
- result = 31*result + firstParamType.hashCode();
- }
- return result;
+ return signature.hashCode();
}
@Override
public boolean equals(MethodSignature method1, MethodSignature method2) {
- if (method1.isConstructor() != method2.isConstructor()) return false;
- if (!method1.isConstructor() && !method1.getName().equals(method2.getName())) return false;
- final PsiType[] parameterTypes1 = method1.getParameterTypes();
- final PsiType[] parameterTypes2 = method2.getParameterTypes();
- if (parameterTypes1.length != parameterTypes2.length) return false;
-
- final PsiSubstitutor substitutor1 = method1.getSubstitutor();
- final PsiSubstitutor substitutor2 = method2.getSubstitutor();
- for (int i = 0; i < parameterTypes1.length; i++) {
- final PsiType type1 = TypeConversionUtil.erasure(substitutor1.substitute(parameterTypes1[i]), substitutor1);
- final PsiType type2 = TypeConversionUtil.erasure(substitutor2.substitute(parameterTypes2[i]), substitutor2);
- if (!Comparing.equal(type1, type2)) return false;
- }
- return true;
+ return areSignaturesEqualLightweight(method1, method2) && areErasedParametersEqual(method1, method2);
}
};
+ private static boolean areErasedParametersEqual(@NotNull MethodSignature method1, @NotNull MethodSignature method2) {
+ PsiType[] erased1 = method1 instanceof MethodSignatureBase
+ ? ((MethodSignatureBase)method1).getErasedParameterTypes() : calcErasedParameterTypes(method1);
+ PsiType[] erased2 = method2 instanceof MethodSignatureBase
+ ? ((MethodSignatureBase)method2).getErasedParameterTypes() : calcErasedParameterTypes(method2);
+ return Arrays.equals(erased1, erased2);
+ }
+
+ @NotNull
+ public static PsiType[] calcErasedParameterTypes(@NotNull MethodSignature signature) {
+ PsiType[] parameterTypes = signature.getParameterTypes();
+ if (parameterTypes.length == 0) return PsiType.EMPTY_ARRAY;
+
+ PsiSubstitutor substitutor = signature.getSubstitutor();
+ PsiType[] erasedTypes = new PsiType[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ erasedTypes[i] = TypeConversionUtil.erasure(substitutor.substitute(parameterTypes[i]), substitutor);
+ }
+ return erasedTypes;
+ }
+
+ @NotNull
public static MethodSignature createMethodSignature(@NonNls @NotNull String name,
@Nullable PsiParameterList parameterTypes,
@Nullable PsiTypeParameterList typeParameterList,
@@ -87,6 +87,7 @@
return createMethodSignature(name, parameterTypes, typeParameterList, substitutor, false);
}
+ @NotNull
public static MethodSignature createMethodSignature(@NonNls @NotNull String name,
@Nullable PsiParameterList parameterTypes,
@Nullable PsiTypeParameterList typeParameterList,
@@ -95,6 +96,7 @@
return new MethodSignatureHandMade(name, parameterTypes, typeParameterList, substitutor, isConstructor);
}
+ @NotNull
public static MethodSignature createMethodSignature(@NonNls @NotNull String name,
@NotNull PsiType[] parameterTypes,
@NotNull PsiTypeParameter[] typeParameterList,
@@ -102,6 +104,7 @@
return createMethodSignature(name, parameterTypes, typeParameterList, substitutor, false);
}
+ @NotNull
public static MethodSignature createMethodSignature(@NonNls @NotNull String name,
@NotNull PsiType[] parameterTypes,
@NotNull PsiTypeParameter[] typeParameterList,
@@ -110,22 +113,22 @@
return new MethodSignatureHandMade(name, parameterTypes, typeParameterList, substitutor, isConstructor);
}
- public static boolean areSignaturesEqual(PsiMethod method1, PsiMethod method2) {
+ public static boolean areSignaturesEqual(@NotNull PsiMethod method1, @NotNull PsiMethod method2) {
return method1.getSignature(PsiSubstitutor.EMPTY).equals(method2.getSignature(PsiSubstitutor.EMPTY));
}
- public static boolean areSignaturesEqual(MethodSignature method1, MethodSignature method2) {
+ public static boolean areSignaturesEqual(@NotNull MethodSignature method1, @NotNull MethodSignature method2) {
if (method2 == method1) return true;
if (!areSignaturesEqualLightweight(method1, method2)) return false;
- PsiSubstitutor unifyingSubstitutor = getSuperMethodSignatureSubstitutor(method1, method2);
- return checkSignaturesEqualInner(method1, method2, unifyingSubstitutor);
+ return checkSignaturesEqualInner(method1, method2, getSuperMethodSignatureSubstitutor(method1, method2))
+ || checkSignaturesEqualInner(method2, method1, getSuperMethodSignatureSubstitutor(method2, method1));
}
- private static boolean checkSignaturesEqualInner(final MethodSignature subSignature,
- final MethodSignature superSignature,
+ private static boolean checkSignaturesEqualInner(@NotNull MethodSignature subSignature,
+ @NotNull MethodSignature superSignature,
final PsiSubstitutor unifyingSubstitutor) {
if (unifyingSubstitutor == null) return false;
- if (!METHOD_PARAMETERS_ERASURE_EQUALITY.equals(subSignature, superSignature)) return false;
+ if (!areErasedParametersEqual(subSignature, superSignature)) return false;
final PsiType[] subParameterTypes = subSignature.getParameterTypes();
final PsiType[] superParameterTypes = superSignature.getParameterTypes();
@@ -140,12 +143,12 @@
return true;
}
- public static boolean areSignaturesEqualLightweight(final MethodSignature sig1, final MethodSignature sig2) {
+ public static boolean areSignaturesEqualLightweight(@NotNull MethodSignature sig1, @NotNull MethodSignature sig2) {
final boolean isConstructor1 = sig1.isConstructor();
final boolean isConstructor2 = sig2.isConstructor();
if (isConstructor1 != isConstructor2) return false;
- if (!isConstructor1 && !isConstructor2 || !(sig1 instanceof HierarchicalMethodSignature || sig2 instanceof HierarchicalMethodSignature)) {
+ if (!isConstructor1 || !(sig1 instanceof HierarchicalMethodSignature || sig2 instanceof HierarchicalMethodSignature)) {
final String name1 = sig1.getName();
final String name2 = sig2.getName();
if (!name1.equals(name2)) return false;
@@ -166,7 +169,7 @@
return true;
}
- public static boolean isSuperMethod(final PsiMethod superMethodCandidate, final PsiMethod derivedMethod) {
+ public static boolean isSuperMethod(@NotNull PsiMethod superMethodCandidate, @NotNull PsiMethod derivedMethod) {
PsiClass superClassCandidate = superMethodCandidate.getContainingClass();
PsiClass derivedClass = derivedMethod.getContainingClass();
if (derivedClass == null || superClassCandidate == null) return false;
@@ -181,16 +184,16 @@
@Nullable
public static PsiMethod findMethodInSuperClassBySignatureInDerived(@NotNull final PsiClass aClass,
@NotNull final PsiClass superClass,
- final MethodSignature signature,
+ @NotNull MethodSignature signature,
final boolean checkDeep) {
PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY);
return doFindMethodInSuperClassBySignatureInDerived(superClass, superSubstitutor, signature, checkDeep);
}
@Nullable
- private static PsiMethod doFindMethodInSuperClassBySignatureInDerived(final PsiClass superClass,
- final PsiSubstitutor superSubstitutor,
- final MethodSignature signature,
+ private static PsiMethod doFindMethodInSuperClassBySignatureInDerived(@NotNull PsiClass superClass,
+ @NotNull PsiSubstitutor superSubstitutor,
+ @NotNull MethodSignature signature,
final boolean checkDeep) {
final String name = signature.getName();
final PsiMethod[] methods = superClass.findMethodsByName(name, false);
@@ -212,12 +215,12 @@
}
@Nullable
- public static PsiMethod findMethodBySignature(final PsiClass aClass, final PsiMethod pattenMethod, boolean checkBases) {
+ public static PsiMethod findMethodBySignature(@NotNull PsiClass aClass, @NotNull PsiMethod pattenMethod, boolean checkBases) {
return findMethodBySignature(aClass, pattenMethod.getSignature(PsiSubstitutor.EMPTY), checkBases);
}
@Nullable
- public static PsiMethod findMethodBySignature(final PsiClass aClass, final MethodSignature methodSignature, boolean checkBases) {
+ public static PsiMethod findMethodBySignature(@NotNull PsiClass aClass, @NotNull MethodSignature methodSignature, boolean checkBases) {
String name = methodSignature.isConstructor() ? aClass.getName() : methodSignature.getName();
List<Pair<PsiMethod, PsiSubstitutor>> pairs = aClass.findMethodsAndTheirSubstitutorsByName(name, checkBases);
for (Pair<PsiMethod, PsiSubstitutor> pair : pairs) {
@@ -230,7 +233,7 @@
}
@Nullable
- public static PsiMethod findMethodBySuperSignature(final PsiClass aClass, final MethodSignature methodSignature, final boolean checkBases) {
+ public static PsiMethod findMethodBySuperSignature(@NotNull PsiClass aClass, @NotNull MethodSignature methodSignature, final boolean checkBases) {
String name = methodSignature.isConstructor() ? aClass.getName() : methodSignature.getName();
List<Pair<PsiMethod, PsiSubstitutor>> pairs = aClass.findMethodsAndTheirSubstitutorsByName(name, checkBases);
for (Pair<PsiMethod, PsiSubstitutor> pair : pairs) {
@@ -243,7 +246,7 @@
}
@Nullable
- public static PsiMethod findMethodBySuperMethod(final PsiClass aClass, final PsiMethod method, final boolean checkBases) {
+ public static PsiMethod findMethodBySuperMethod(@NotNull PsiClass aClass, @NotNull PsiMethod method, final boolean checkBases) {
List<Pair<PsiMethod, PsiSubstitutor>> pairs = aClass.findMethodsAndTheirSubstitutorsByName(method.getName(), checkBases);
for (Pair<PsiMethod, PsiSubstitutor> pair : pairs) {
PsiMethod candidate = pair.first;
@@ -260,22 +263,23 @@
return null;
}
- public static boolean hasOverloads(PsiMethod method) {
+ public static boolean hasOverloads(@NotNull PsiMethod method) {
return getOverloads(method).length > 1;
}
- public static PsiMethod[] getOverloads(PsiMethod method) {
+ @NotNull
+ public static PsiMethod[] getOverloads(@NotNull PsiMethod method) {
PsiClass aClass = method.getContainingClass();
if (aClass == null) return new PsiMethod[]{method};
return aClass.findMethodsByName(method.getName(), false);
}
- public static boolean areParametersErasureEqual(PsiMethod method1, PsiMethod method2) {
+ public static boolean areParametersErasureEqual(@NotNull PsiMethod method1, @NotNull PsiMethod method2) {
if (method1.getParameterList().getParametersCount() != method2.getParameterList().getParametersCount()) return false;
return areSignaturesErasureEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY));
}
- public static boolean areSignaturesErasureEqual(MethodSignature signature1, MethodSignature signature2) {
+ public static boolean areSignaturesErasureEqual(@NotNull MethodSignature signature1, @NotNull MethodSignature signature2) {
return METHOD_PARAMETERS_ERASURE_EQUALITY.equals(signature1, signature2);
}
@@ -285,7 +289,7 @@
* @return null if signatures do not match
*/
@Nullable
- public static PsiSubstitutor getSuperMethodSignatureSubstitutor(MethodSignature methodSignature, MethodSignature superMethodSignature) {
+ public static PsiSubstitutor getSuperMethodSignatureSubstitutor(@NotNull MethodSignature methodSignature, @NotNull MethodSignature superMethodSignature) {
PsiSubstitutor result = getSuperMethodSignatureSubstitutorImpl(methodSignature, superMethodSignature);
if (result == null) return null;
@@ -315,7 +319,7 @@
}
@Nullable
- private static PsiSubstitutor getSuperMethodSignatureSubstitutorImpl(MethodSignature methodSignature, MethodSignature superSignature) {
+ private static PsiSubstitutor getSuperMethodSignatureSubstitutorImpl(@NotNull MethodSignature methodSignature, @NotNull MethodSignature superSignature) {
// normalize generic method declarations: correlate type parameters
// todo: correlate type params by name?
PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters();
@@ -334,7 +338,8 @@
return result;
}
- public static PsiSubstitutor combineSubstitutors(PsiSubstitutor substitutor1, PsiSubstitutor substitutor2) {
+ @NotNull
+ public static PsiSubstitutor combineSubstitutors(@NotNull PsiSubstitutor substitutor1, @NotNull PsiSubstitutor substitutor2) {
if (substitutor1 == PsiSubstitutor.EMPTY) return substitutor2;
Set<PsiTypeParameter> parameters1 = substitutor1.getSubstitutionMap().keySet();
final PsiTypeParameter[] typeParameters = parameters1.toArray(new PsiTypeParameter[parameters1.size()]);
@@ -355,7 +360,7 @@
}
@NotNull
- public static PsiMethod[] convertMethodSignaturesToMethods(List<? extends MethodSignatureBackedByPsiMethod> sameNameMethodList) {
+ public static PsiMethod[] convertMethodSignaturesToMethods(@NotNull List<? extends MethodSignatureBackedByPsiMethod> sameNameMethodList) {
final PsiMethod[] methods = new PsiMethod[sameNameMethodList.size()];
for (int i = 0; i < sameNameMethodList.size(); i++) {
methods[i] = sameNameMethodList.get(i).getMethod();
@@ -363,7 +368,7 @@
return methods;
}
- public static boolean isSubsignature(MethodSignature superSignature, MethodSignature subSignature) {
+ public static boolean isSubsignature(@NotNull MethodSignature superSignature, @NotNull MethodSignature subSignature) {
if (subSignature == superSignature) return true;
if (!areSignaturesEqualLightweight(superSignature, subSignature)) return false;
PsiSubstitutor unifyingSubstitutor = getSuperMethodSignatureSubstitutor(subSignature, superSignature);
diff --git a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
index 2852584..faa1e50 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
@@ -251,8 +251,8 @@
final JavaResolveResult newResult = newCall.getMethodExpression().advancedResolve(false);
if (!newResult.isValidResult()) return;
final PsiMethod newTargetMethod = (PsiMethod)newResult.getElement();
- final PsiType newReturnType = newResult.getSubstitutor().substitute(newTargetMethod.getReturnType());
- final PsiType oldReturnType = resolveResult.getSubstitutor().substitute(targetMethod.getReturnType());
+ final PsiType newReturnType = newCall.getType();
+ final PsiType oldReturnType = methodCall.getType();
if (Comparing.equal(newReturnType, oldReturnType)) {
if (newTargetMethod.equals(targetMethod) ||
(newTargetMethod.getSignature(newResult.getSubstitutor()).equals(targetMethod.getSignature(resolveResult.getSubstitutor())) &&
diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
index 9cce64d..2675e39 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
@@ -445,8 +445,6 @@
/**
* @param tokenType JavaTokenType enumeration
- * @param lOperand
- * @param rOperand
* @param strict true if operator result type should be convertible to the left operand
* @return true if lOperand operator rOperand expression is syntactically correct
*/
@@ -480,16 +478,14 @@
}
else {
if (isPrimitiveAndNotNull(ltype)) {
- if (rtype instanceof PsiClassType && ((PsiClassType)rtype).getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_7)) {
- return areTypesConvertible(ltype, rtype);
- }
- return false;
+ return rtype instanceof PsiClassType &&
+ ((PsiClassType)rtype).getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_7) &&
+ areTypesConvertible(ltype, rtype);
}
if (isPrimitiveAndNotNull(rtype)) {
- if (ltype instanceof PsiClassType && ((PsiClassType)ltype).getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_7)) {
- return areTypesConvertible(rtype, ltype);
- }
- return false;
+ return ltype instanceof PsiClassType &&
+ ((PsiClassType)ltype).getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_7) &&
+ areTypesConvertible(rtype, ltype);
}
isApplicable = areTypesConvertible(ltype, rtype) || areTypesConvertible(rtype, ltype);
}
@@ -693,10 +689,7 @@
final PsiType lType = lLambdaExpression.getFunctionalInterfaceType();
return Comparing.equal(rType, lType);
}
- if (left instanceof PsiArrayType) {
- return false;
- }
- return LambdaUtil.isAcceptable(rLambdaExpression, left, false);
+ return !(left instanceof PsiArrayType) && LambdaUtil.isAcceptable(rLambdaExpression, left, false);
}
if (left instanceof PsiIntersectionType) {
@@ -745,9 +738,7 @@
if (lCompType instanceof PsiPrimitiveType) {
return lCompType.equals(rCompType);
}
- else {
- return !(rCompType instanceof PsiPrimitiveType) && isAssignable(lCompType, rCompType, allowUncheckedConversion);
- }
+ return !(rCompType instanceof PsiPrimitiveType) && isAssignable(lCompType, rCompType, allowUncheckedConversion);
}
if (left instanceof PsiDisjunctionType) {
@@ -828,12 +819,10 @@
if (left instanceof PsiPrimitiveType && !PsiType.NULL.equals(left)) {
return right instanceof PsiClassType && isAssignable(left, right);
}
- else {
- return left instanceof PsiClassType
- && right instanceof PsiPrimitiveType
- && !PsiType.NULL.equals(right)
- && isAssignable(left, right);
- }
+ return left instanceof PsiClassType
+ && right instanceof PsiPrimitiveType
+ && !PsiType.NULL.equals(right)
+ && isAssignable(left, right);
}
private static final Key<CachedValue<Set<String>>> POSSIBLE_BOXED_HOLDER_TYPES = Key.create("Types that may be possibly assigned from primitive ones");
@@ -932,7 +921,7 @@
}
private static final RecursionGuard ourGuard = RecursionManager.createGuard("isAssignable");
-
+
public static boolean typesAgree(PsiType typeLeft, PsiType typeRight, final boolean allowUncheckedConversion) {
if (typeLeft instanceof PsiWildcardType) {
final PsiWildcardType leftWildcard = (PsiWildcardType)typeLeft;
@@ -985,7 +974,7 @@
}
}
- private static Boolean containsWildcards(PsiType leftBound) {
+ private static boolean containsWildcards(@NotNull PsiType leftBound) {
final WildcardDetector wildcardDetector = new WildcardDetector();
if (leftBound instanceof PsiIntersectionType) {
for (PsiType conjunctType :((PsiIntersectionType)leftBound).getConjuncts()) {
@@ -993,7 +982,7 @@
}
return true;
}
-
+
return leftBound.accept(wildcardDetector);
}
@@ -1020,9 +1009,6 @@
* <code>superClass</code> must be a super class/interface of <code>derivedClass</code> (as in
* <code>InheritanceUtil.isInheritor(derivedClass, superClass, true)</code>
*
- * @param superClass
- * @param derivedClass
- * @param derivedSubstitutor
* @return substitutor (never returns <code>null</code>)
* @see InheritanceUtil#isInheritor(PsiClass, PsiClass, boolean)
*/
@@ -1228,7 +1214,7 @@
return typeParameterErasure(typeParameter, PsiSubstitutor.EMPTY);
}
- private static PsiType typeParameterErasure(@NotNull PsiTypeParameter typeParameter, final PsiSubstitutor beforeSubstitutor) {
+ private static PsiType typeParameterErasure(@NotNull PsiTypeParameter typeParameter, @NotNull PsiSubstitutor beforeSubstitutor) {
final PsiClassType[] extendsList = typeParameter.getExtendsList().getReferencedTypes();
if (extendsList.length > 0) {
final PsiClass psiClass = extendsList[0].resolve();
@@ -1274,7 +1260,7 @@
return erasure(type, PsiSubstitutor.EMPTY);
}
- public static PsiType erasure(@Nullable final PsiType type, final PsiSubstitutor beforeSubstitutor) {
+ public static PsiType erasure(@Nullable final PsiType type, @NotNull final PsiSubstitutor beforeSubstitutor) {
if (type == null) return null;
return type.accept(new PsiTypeVisitor<PsiType>() {
@Override
@@ -1283,9 +1269,7 @@
if (aClass instanceof PsiTypeParameter) {
return typeParameterErasure((PsiTypeParameter)aClass, beforeSubstitutor);
}
- else {
- return classType.rawType();
- }
+ return classType.rawType();
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
index 269114b..8d75564 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
@@ -302,7 +302,7 @@
Set<PsiFile> possibleAnnotationsXmls = new THashSet<PsiFile>();
for (VirtualFile root : getExternalAnnotationsRoots(virtualFile)) {
- final VirtualFile ext = root.findFileByRelativePath(packageName.replace(".", "/") + "/" + ANNOTATIONS_XML);
+ final VirtualFile ext = root.findFileByRelativePath(packageName.replace('.', '/') + "/" + ANNOTATIONS_XML);
if (ext == null) continue;
final PsiFile psiFile = myPsiManager.findFile(ext);
if (psiFile == null) continue;
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
index 1aa0ac2..4b245a0 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
@@ -20,10 +20,11 @@
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.impl.PsiImplUtil;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.psi.infos.CandidateInfo;
+import com.intellij.psi.scope.MethodProcessorSetupFailedException;
+import com.intellij.psi.scope.processor.MethodResolverProcessor;
+import com.intellij.psi.scope.util.PsiScopesUtil;
+import com.intellij.psi.util.*;
import com.intellij.util.NullableFunction;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
@@ -62,7 +63,7 @@
}
@NotNull
- private static List<PsiClassType> filterOutUncheckedExceptions(List<PsiClassType> exceptions) {
+ private static List<PsiClassType> filterOutUncheckedExceptions(@NotNull List<PsiClassType> exceptions) {
List<PsiClassType> array = ContainerUtil.newArrayList();
for (PsiClassType exception : exceptions) {
if (!isUncheckedException(exception)) array.add(exception);
@@ -95,9 +96,13 @@
final PsiExpression expr = ((PsiThrowStatement)element).getException();
if (expr == null) return Collections.emptyList();
final List<PsiType> types = getPreciseThrowTypes(expr);
- final List<PsiClassType> classTypes = ContainerUtil.mapNotNull(types, new NullableFunction<PsiType, PsiClassType>() {
- @Override public PsiClassType fun(PsiType type) { return type instanceof PsiClassType ? (PsiClassType)type : null; }
- });
+ List<PsiClassType> classTypes =
+ new ArrayList<PsiClassType>(ContainerUtil.mapNotNull(types, new NullableFunction<PsiType, PsiClassType>() {
+ @Override
+ public PsiClassType fun(PsiType type) {
+ return type instanceof PsiClassType ? (PsiClassType)type : null;
+ }
+ }));
addExceptions(classTypes, getThrownExceptions(expr));
return classTypes;
}
@@ -115,7 +120,8 @@
return getThrownExceptions(element.getChildren());
}
- private static List<PsiClassType> getTryExceptions(PsiTryStatement tryStatement) {
+ @NotNull
+ private static List<PsiClassType> getTryExceptions(@NotNull PsiTryStatement tryStatement) {
List<PsiClassType> array = ContainerUtil.newArrayList();
PsiResourceList resourceList = tryStatement.getResourceList();
@@ -169,7 +175,7 @@
}
@NotNull
- private static List<PsiClassType> getExceptionsByMethodAndChildren(PsiElement element, JavaResolveResult resolveResult) {
+ private static List<PsiClassType> getExceptionsByMethodAndChildren(@NotNull PsiElement element, @NotNull JavaResolveResult resolveResult) {
List<PsiClassType> result = ContainerUtil.newArrayList();
PsiMethod method = (PsiMethod)resolveResult.getElement();
@@ -197,13 +203,13 @@
return result;
}
- private static void addExceptions(List<PsiClassType> array, Collection<PsiClassType> exceptions) {
+ private static void addExceptions(@NotNull List<PsiClassType> array, @NotNull Collection<PsiClassType> exceptions) {
for (PsiClassType exception : exceptions) {
addException(array, exception);
}
}
- private static void addException(List<PsiClassType> array, PsiClassType exception) {
+ private static void addException(@NotNull List<PsiClassType> array, @Nullable PsiClassType exception) {
if (exception == null) return ;
for (int i = array.size()-1; i>=0; i--) {
PsiClassType exception1 = array.get(i);
@@ -311,7 +317,8 @@
return foundExceptions;
}
- private static Collection<PsiClassType> getUnhandledExceptions(PsiMethodReferenceExpression methodReferenceExpression,
+ @NotNull
+ private static Collection<PsiClassType> getUnhandledExceptions(@NotNull PsiMethodReferenceExpression methodReferenceExpression,
PsiElement topElement) {
final JavaResolveResult resolveResult = methodReferenceExpression.advancedResolve(false);
final PsiElement resolve = resolveResult.getElement();
@@ -321,7 +328,7 @@
return Collections.emptyList();
}
- private static boolean firstStatementIsConstructorCall(PsiCodeBlock constructorBody) {
+ private static boolean firstStatementIsConstructorCall(@NotNull PsiCodeBlock constructorBody) {
final PsiStatement[] statements = constructorBody.getStatements();
if (statements.length == 0) return false;
if (!(statements[0] instanceof PsiExpressionStatement)) return false;
@@ -333,29 +340,29 @@
}
@NotNull
- public static List<PsiClassType> getUnhandledExceptions(PsiElement[] elements) {
+ public static List<PsiClassType> getUnhandledExceptions(@NotNull PsiElement[] elements) {
final List<PsiClassType> array = ContainerUtil.newArrayList();
final PsiElementVisitor visitor = new JavaRecursiveElementWalkingVisitor() {
@Override
- public void visitCallExpression(PsiCallExpression expression) {
+ public void visitCallExpression(@NotNull PsiCallExpression expression) {
addExceptions(array, getUnhandledExceptions(expression, null));
visitElement(expression);
}
@Override
- public void visitThrowStatement(PsiThrowStatement statement) {
+ public void visitThrowStatement(@NotNull PsiThrowStatement statement) {
addExceptions(array, getUnhandledExceptions(statement, null));
visitElement(statement);
}
@Override
- public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
+ public void visitMethodReferenceExpression(@NotNull PsiMethodReferenceExpression expression) {
addExceptions(array, getUnhandledExceptions(expression, null));
visitElement(expression);
}
@Override
- public void visitResourceVariable(PsiResourceVariable resourceVariable) {
+ public void visitResourceVariable(@NotNull PsiResourceVariable resourceVariable) {
addExceptions(array, getUnhandledCloserExceptions(resourceVariable, null));
visitElement(resourceVariable);
}
@@ -386,12 +393,12 @@
}
@NotNull
- public static List<PsiClassType> getUnhandledExceptions(final PsiCallExpression methodCall, @Nullable final PsiElement topElement) {
+ public static List<PsiClassType> getUnhandledExceptions(@NotNull final PsiCallExpression methodCall, @Nullable final PsiElement topElement) {
return getUnhandledExceptions(methodCall, topElement, true);
}
@NotNull
- public static List<PsiClassType> getUnhandledExceptions(final PsiCallExpression methodCall,
+ public static List<PsiClassType> getUnhandledExceptions(@NotNull final PsiCallExpression methodCall,
@Nullable final PsiElement topElement,
boolean includeSelfCalls) {
final JavaResolveResult result = methodCall.resolveMethodGenerics();
@@ -400,29 +407,86 @@
return Collections.emptyList();
}
- final PsiSubstitutor substitutor = ApplicationManager.getApplication().runReadAction(new Computable<PsiSubstitutor>() {
- @Override
- public PsiSubstitutor compute() {
- return result.getSubstitutor();
+ final PsiSubstitutor substitutor = result.getSubstitutor();
+ if (method != null && !isArrayClone(method, methodCall) && methodCall instanceof PsiMethodCallExpression) {
+ final PsiClassType[] thrownExceptions = method.getThrowsList().getReferencedTypes();
+ if (thrownExceptions.length > 0) {
+ final MethodResolverProcessor processor = new MethodResolverProcessor((PsiMethodCallExpression)methodCall);
+ try {
+ PsiScopesUtil.setupAndRunProcessor(processor, methodCall, false);
+ final List<CandidateInfo> results = processor.getResults();
+ if (results.size() > 1) {
+ final List<PsiClassType> ex = collectSubstituted(substitutor, thrownExceptions);
+ for (CandidateInfo info : results) {
+ final PsiElement element = info.getElement();
+ if (element instanceof PsiMethod && MethodSignatureUtil.areSignaturesEqual(method, (PsiMethod)element)) {
+ final PsiClassType[] exceptions = ((PsiMethod)element).getThrowsList().getReferencedTypes();
+ if (exceptions.length == 0) {
+ return getUnhandledExceptions(methodCall, topElement, PsiSubstitutor.EMPTY, PsiClassType.EMPTY_ARRAY);
+ }
+ retainExceptions(ex, collectSubstituted(info.getSubstitutor(), exceptions));
+ }
+ }
+ return getUnhandledExceptions(methodCall, topElement, PsiSubstitutor.EMPTY, ex.toArray(new PsiClassType[ex.size()]));
+ }
+ }
+ catch (MethodProcessorSetupFailedException ignore) {
+ return Collections.emptyList();
+ }
}
- });
+ }
+
return getUnhandledExceptions(method, methodCall, topElement, substitutor);
}
+ public static void retainExceptions(List<PsiClassType> ex, List<PsiClassType> thrownEx) {
+ final List<PsiClassType> replacement = new ArrayList<PsiClassType>();
+ for (Iterator<PsiClassType> iterator = ex.iterator(); iterator.hasNext(); ) {
+ PsiClassType classType = iterator.next();
+ boolean found = false;
+ for (PsiClassType psiClassType : thrownEx) {
+ if (psiClassType.isAssignableFrom(classType)) {
+ found = true;
+ break;
+ } else if (classType.isAssignableFrom(psiClassType)) {
+ replacement.add(psiClassType);
+ iterator.remove();
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ iterator.remove();
+ }
+ }
+ ex.addAll(replacement);
+ }
+
+ public static List<PsiClassType> collectSubstituted(PsiSubstitutor substitutor, PsiClassType[] thrownExceptions) {
+ final List<PsiClassType> ex = new ArrayList<PsiClassType>();
+ for (PsiClassType thrownException : thrownExceptions) {
+ final PsiType psiType = substitutor.substitute(thrownException);
+ if (psiType instanceof PsiClassType) {
+ ex.add((PsiClassType)psiType);
+ }
+ }
+ return ex;
+ }
+
@NotNull
- public static List<PsiClassType> getCloserExceptions(final PsiResourceVariable resource) {
+ public static List<PsiClassType> getCloserExceptions(@NotNull final PsiResourceVariable resource) {
final PsiMethod method = PsiUtil.getResourceCloserMethod(resource);
return method != null ? getExceptionsByMethod(method, PsiSubstitutor.EMPTY) : Collections.<PsiClassType>emptyList();
}
@NotNull
- public static List<PsiClassType> getUnhandledCloserExceptions(final PsiResourceVariable resource, @Nullable final PsiElement topElement) {
+ public static List<PsiClassType> getUnhandledCloserExceptions(@NotNull final PsiResourceVariable resource, @Nullable final PsiElement topElement) {
final PsiMethod method = PsiUtil.getResourceCloserMethod(resource);
return method != null ? getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY) : Collections.<PsiClassType>emptyList();
}
@NotNull
- public static List<PsiClassType> getUnhandledExceptions(PsiThrowStatement throwStatement, @Nullable PsiElement topElement) {
+ public static List<PsiClassType> getUnhandledExceptions(@NotNull PsiThrowStatement throwStatement, @Nullable PsiElement topElement) {
List<PsiClassType> unhandled = new SmartList<PsiClassType>();
for (PsiType type : getPreciseThrowTypes(throwStatement.getException())) {
List<PsiType> types = type instanceof PsiDisjunctionType ? ((PsiDisjunctionType)type).getDisjunctions() : Collections.singletonList(type);
@@ -458,14 +522,21 @@
}
@NotNull
- private static List<PsiClassType> getUnhandledExceptions(PsiMethod method,
+ private static List<PsiClassType> getUnhandledExceptions(@Nullable PsiMethod method,
PsiElement element,
PsiElement topElement,
- PsiSubstitutor substitutor) {
+ @NotNull PsiSubstitutor substitutor) {
if (method == null || isArrayClone(method, element)) {
return Collections.emptyList();
}
final PsiClassType[] referencedTypes = method.getThrowsList().getReferencedTypes();
+ return getUnhandledExceptions(element, topElement, substitutor, referencedTypes);
+ }
+
+ private static List<PsiClassType> getUnhandledExceptions(PsiElement element,
+ PsiElement topElement,
+ PsiSubstitutor substitutor,
+ PsiClassType[] referencedTypes) {
if (referencedTypes.length > 0) {
List<PsiClassType> result = ContainerUtil.newArrayList();
@@ -487,7 +558,7 @@
return Collections.emptyList();
}
- private static boolean isArrayClone(PsiMethod method, PsiElement element) {
+ private static boolean isArrayClone(@NotNull PsiMethod method, PsiElement element) {
if (!method.getName().equals(CLONE_METHOD_NAME)) return false;
PsiClass containingClass = method.getContainingClass();
if (containingClass == null || !CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())) {
@@ -519,11 +590,11 @@
CommonClassNames.JAVA_LANG_EXCEPTION.equals(canonicalText);
}
- public static boolean isHandled(PsiClassType exceptionType, PsiElement throwPlace) {
+ public static boolean isHandled(@NotNull PsiClassType exceptionType, @NotNull PsiElement throwPlace) {
return isHandled(throwPlace, exceptionType, throwPlace.getContainingFile());
}
- private static boolean isHandled(PsiElement element, PsiClassType exceptionType, PsiElement topElement) {
+ private static boolean isHandled(@Nullable PsiElement element, @NotNull PsiClassType exceptionType, PsiElement topElement) {
if (element == null || element.getParent() == topElement || element.getParent() == null) return false;
final PsiElement parent = element.getParent();
@@ -590,7 +661,7 @@
return isHandled(parent, exceptionType, topElement);
}
- private static boolean isDeclaredBySAMMethod(PsiClassType exceptionType, PsiType interfaceType) {
+ private static boolean isDeclaredBySAMMethod(@NotNull PsiClassType exceptionType, @Nullable PsiType interfaceType) {
if (interfaceType != null) {
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(interfaceType);
if (interfaceMethod != null) {
@@ -600,7 +671,7 @@
return true;
}
- private static boolean areAllConstructorsThrow(final PsiClass aClass, PsiClassType exceptionType) {
+ private static boolean areAllConstructorsThrow(@Nullable final PsiClass aClass, @NotNull PsiClassType exceptionType) {
if (aClass == null) return false;
final PsiMethod[] constructors = aClass.getConstructors();
boolean thrown = constructors.length != 0;
@@ -613,7 +684,7 @@
return thrown;
}
- private static boolean isCaught(PsiTryStatement tryStatement, PsiClassType exceptionType) {
+ private static boolean isCaught(@NotNull PsiTryStatement tryStatement, @NotNull PsiClassType exceptionType) {
// if finally block completes abruptly, exception gets lost
PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
if (finallyBlock != null && blockCompletesAbruptly(finallyBlock)) return true;
@@ -627,7 +698,7 @@
return false;
}
- private static boolean blockCompletesAbruptly(final PsiCodeBlock finallyBlock) {
+ private static boolean blockCompletesAbruptly(@NotNull final PsiCodeBlock finallyBlock) {
try {
ControlFlow flow = ControlFlowFactory.getInstance(finallyBlock.getProject()).getControlFlow(finallyBlock, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
int completionReasons = ControlFlowUtil.getCompletionReasons(flow, 0, flow.getSize());
@@ -639,19 +710,19 @@
return false;
}
- private static boolean isHandledByMethodThrowsClause(PsiMethod method, PsiClassType exceptionType) {
+ private static boolean isHandledByMethodThrowsClause(@NotNull PsiMethod method, @NotNull PsiClassType exceptionType) {
final PsiClassType[] referencedTypes = method.getThrowsList().getReferencedTypes();
return isHandledBy(exceptionType, referencedTypes);
}
- public static boolean isHandledBy(PsiClassType exceptionType, @NotNull PsiClassType[] referencedTypes) {
+ public static boolean isHandledBy(@NotNull PsiClassType exceptionType, @NotNull PsiClassType[] referencedTypes) {
for (PsiClassType classType : referencedTypes) {
if (classType.isAssignableFrom(exceptionType)) return true;
}
return false;
}
- public static void sortExceptionsByHierarchy(List<PsiClassType> exceptions) {
+ public static void sortExceptionsByHierarchy(@NotNull List<PsiClassType> exceptions) {
if (exceptions.size() <= 1) return;
sortExceptionsByHierarchy(exceptions.subList(1, exceptions.size()));
for (int i=0; i<exceptions.size()-1;i++) {
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
index a29a0c5..6c273b2 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
@@ -30,12 +30,17 @@
@NotNull
public static Collection<MethodSignature> getMethodSignaturesToOverride(@NotNull PsiClass aClass) {
- if (aClass.isInterface()) return Collections.emptySet();
+ if (aClass.isAnnotationType()) return Collections.emptySet();
return getMapToOverrideImplement(aClass, false).keySet();
}
@NotNull
- private static Map<MethodSignature, CandidateInfo> getMapToOverrideImplement(PsiClass aClass, boolean toImplement) {
+ public static Map<MethodSignature, CandidateInfo> getMapToOverrideImplement(PsiClass aClass, boolean toImplement) {
+ return getMapToOverrideImplement(aClass, toImplement, true);
+ }
+
+ @NotNull
+ public static Map<MethodSignature, CandidateInfo> getMapToOverrideImplement(PsiClass aClass, boolean toImplement, boolean skipImplemented) {
Map<MethodSignature, PsiMethod> abstracts = new LinkedHashMap<MethodSignature,PsiMethod>();
Map<MethodSignature, PsiMethod> finals = new LinkedHashMap<MethodSignature,PsiMethod>();
Map<MethodSignature, PsiMethod> concretes = new LinkedHashMap<MethodSignature,PsiMethod>();
@@ -55,7 +60,7 @@
continue;
}
// filter already implemented
- if (MethodSignatureUtil.findMethodBySignature(aClass, signature, false) != null) {
+ if (skipImplemented && MethodSignatureUtil.findMethodBySignature(aClass, signature, false) != null) {
continue;
}
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
index 34dd67d..25da019 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
@@ -393,6 +393,7 @@
else if (dotTokenType == JavaTokenType.SUPER_KEYWORD) {
dotPos.drop();
final PsiBuilder.Marker refExpr = expr.precede();
+ builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
builder.advanceLexer();
refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
expr = refExpr;
diff --git a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
index b14a37d..8844055 100644
--- a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
@@ -287,7 +287,7 @@
}
public static boolean haveConstructorsGenericsParameters(@NotNull final PsiClass psiClass) {
- for (PsiMethod method : psiClass.getConstructors()) {
+ for (final PsiMethod method : psiClass.getConstructors()) {
for (PsiParameter parameter : method.getParameterList().getParameters()) {
final PsiType type = parameter.getType();
final Boolean accept = type.accept(new PsiTypeVisitor<Boolean>() {
@@ -304,7 +304,8 @@
if (typaParamFound != null && typaParamFound) return true;
}
}
- return PsiUtil.resolveClassInType(classType) instanceof PsiTypeParameter;
+ final PsiClass aClass = PsiUtil.resolveClassInType(classType);
+ return aClass instanceof PsiTypeParameter && ((PsiTypeParameter)aClass).getOwner() == method;
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
index 28fc636..247477e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
@@ -20,20 +20,43 @@
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.HashSet;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Map;
import java.util.Set;
public class InheritanceImplUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.InheritanceImplUtil");
- public static boolean isInheritor(@NotNull PsiClass candidateClass, @NotNull PsiClass baseClass, final boolean checkDeep) {
- return !(baseClass instanceof PsiAnonymousClass) && isInheritor(candidateClass, baseClass, checkDeep, null);
+ public static boolean isInheritor(@NotNull final PsiClass candidateClass, @NotNull PsiClass baseClass, final boolean checkDeep) {
+ if (baseClass instanceof PsiAnonymousClass) return false;
+ if (!checkDeep) return isInheritor(candidateClass, baseClass, false, null);
+
+ if (CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName())) return true;
+ Map<PsiClass, Boolean> map = CachedValuesManager.getManager(candidateClass.getProject()).
+ getCachedValue(candidateClass, new CachedValueProvider<Map<PsiClass, Boolean>>() {
+ @Nullable
+ @Override
+ public Result<Map<PsiClass, Boolean>> compute() {
+ final Map<PsiClass, Boolean> map = new ConcurrentHashMap<PsiClass, Boolean>();
+ return Result.create(map, candidateClass);
+ }
+ });
+
+ Boolean computed = map.get(baseClass);
+ if (computed == null) {
+ computed = isInheritor(candidateClass, baseClass, true, null);
+ map.put(baseClass, computed);
+ }
+ return computed;
}
private static boolean isInheritor(@NotNull PsiClass candidateClass, @NotNull PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java
index f80a099..2bde13a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java
@@ -182,7 +182,7 @@
if (cache == null) {
myPackageCache = new SoftReference<ConcurrentMap<String, PsiPackage>>(cache = new ConcurrentHashMap<String, PsiPackage>());
}
-
+
PsiPackage aPackage = cache.get(qualifiedName);
if (aPackage != null) {
return aPackage;
@@ -352,9 +352,9 @@
ContainerUtil.quickSort(list, new Comparator<PsiClass>() {
@Override
public int compare(PsiClass o1, PsiClass o2) {
- VirtualFile file2 = PsiUtilCore.getVirtualFile(o2);
VirtualFile file1 = PsiUtilCore.getVirtualFile(o1);
- return scope.compare(file2, file1);
+ VirtualFile file2 = PsiUtilCore.getVirtualFile(o2);
+ return file1 == null ? file2 == null ? 0 : -1 : file2 == null ? 1 : scope.compare(file2, file1);
}
});
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java
index 71dff8a..a0f3e9a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java
@@ -570,8 +570,8 @@
if (!processor.execute(candidateMethod, state.put(PsiSubstitutor.KEY, finalSubstitutor))) {
resolved = true;
}
- if (resolved) return false;
}
+ if (resolved) return false;
if (visited != null) {
for (Pair<PsiMember, PsiSubstitutor> aList : list) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
index 120b725..9ac1dd2 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
@@ -36,6 +36,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -46,9 +47,17 @@
public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements PsiElementFactory {
private PsiClass myArrayClass;
private PsiClass myArrayClass15;
+ private final ConcurrentHashMap<GlobalSearchScope, PsiClassType> myCachedObjectType = new ConcurrentHashMap<GlobalSearchScope, PsiClassType>();
- public PsiElementFactoryImpl(final PsiManager manager) {
+
+ public PsiElementFactoryImpl(final PsiManagerEx manager) {
super(manager);
+ manager.registerRunnableToRunOnChange(new Runnable() {
+ @Override
+ public void run() {
+ myCachedObjectType.clear();
+ }
+ });
}
@NotNull
@@ -56,14 +65,14 @@
public PsiClass getArrayClass(@NotNull final LanguageLevel languageLevel) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) {
if (myArrayClass == null) {
- final String body = "public class __Array__{\n public final int length;\n public Object clone() {}\n}";
+ @NonNls final String body = "public class __Array__{\n public final int length;\n public Object clone() {}\n}";
myArrayClass = createClassFromText(body, null).getInnerClasses()[0];
}
return myArrayClass;
}
else {
if (myArrayClass15 == null) {
- final String body = "public class __Array__<T>{\n public final int length;\n public T[] clone() {}\n}";
+ @NonNls final String body = "public class __Array__<T>{\n public final int length;\n public T[] clone() {}\n}";
myArrayClass15 = createClassFromText(body, null).getInnerClasses()[0];
}
return myArrayClass15;
@@ -171,7 +180,7 @@
@NotNull
@Override
public PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes) {
- StringBuilder builder = new StringBuilder();
+ @NonNls StringBuilder builder = new StringBuilder();
builder.append("public <").append(name);
if (superTypes.length > 1) {
builder.append(" extends ");
@@ -199,7 +208,7 @@
throw new IncorrectOperationException("Cannot create field with type \"null\".");
}
- final String text = "class _Dummy_ { private " + type.getCanonicalText() + " " + name + "; }";
+ @NonNls final String text = "class _Dummy_ { private " + type.getCanonicalText() + " " + name + "; }";
final PsiJavaFile aFile = createDummyJavaFile(text);
final PsiClass[] classes = aFile.getClasses();
if (classes.length < 1) {
@@ -385,6 +394,18 @@
@NotNull
@Override
public PsiClassType createTypeByFQClassName(@NotNull final String qName, @NotNull final GlobalSearchScope resolveScope) {
+ if (CommonClassNames.JAVA_LANG_OBJECT.equals(qName)) {
+ PsiClassType cachedObjectType = myCachedObjectType.get(resolveScope);
+ if (cachedObjectType != null) {
+ return cachedObjectType;
+ }
+ PsiClass aClass = JavaPsiFacade.getInstance(myManager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope);
+ if (aClass != null) {
+ cachedObjectType = new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY);
+ cachedObjectType = myCachedObjectType.cacheOrGet(resolveScope, cachedObjectType);
+ return cachedObjectType;
+ }
+ }
return new PsiClassReferenceType(createReferenceElementByFQClassName(qName, resolveScope), null);
}
@@ -455,7 +476,7 @@
@NotNull
@Override
public PsiParameterList createParameterList(@NotNull final String[] names, @NotNull final PsiType[] types) throws IncorrectOperationException {
- final StringBuilder builder = new StringBuilder();
+ @NonNls StringBuilder builder = new StringBuilder();
builder.append("void method(");
for (int i = 0; i < names.length; i++) {
if (i > 0) builder.append(", ");
@@ -468,7 +489,7 @@
@NotNull
@Override
public PsiReferenceList createReferenceList(@NotNull final PsiJavaCodeReferenceElement[] references) throws IncorrectOperationException {
- final StringBuilder builder = new StringBuilder();
+ @NonNls final StringBuilder builder = new StringBuilder();
builder.append("void method()");
if (references.length > 0){
builder.append(" throws ");
@@ -579,7 +600,7 @@
throw new IncorrectOperationException("Cannot create variable with type \"null\".");
}
- final String text = "X " + name + (initializer != null ? " = x" : "") + ";";
+ @NonNls final String text = "X " + name + (initializer != null ? " = x" : "") + ";";
final PsiDeclarationStatement statement = (PsiDeclarationStatement)createStatementFromText(text, null);
final PsiVariable variable = (PsiVariable)statement.getDeclaredElements()[0];
@@ -596,7 +617,7 @@
@NotNull
@Override
public PsiDocTag createParamTag(@NotNull final String parameterName, @NonNls final String description) throws IncorrectOperationException {
- final StringBuilder builder = new StringBuilder();
+ @NonNls final StringBuilder builder = new StringBuilder();
builder.append(" * @param ");
builder.append(parameterName);
builder.append(" ");
@@ -718,7 +739,7 @@
throw new IncorrectOperationException("Unexpected type:" + exceptionType);
}
- final String text = "catch (" + exceptionType.getCanonicalText() + " " + exceptionName + ") {}";
+ @NonNls final String text = "catch (" + exceptionType.getCanonicalText() + " " + exceptionName + ") {}";
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CATCH_SECTION, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiCatchSection)) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
index d0f0548..13040f2 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
@@ -504,7 +504,7 @@
return normalized;
}
- private static PsiType doNormalizeWildcardByPosition(final PsiType type, final PsiExpression expression, final PsiExpression toplevel) {
+ private static PsiType doNormalizeWildcardByPosition(final PsiType type, @NotNull PsiExpression expression, final PsiExpression toplevel) {
if (type instanceof PsiCapturedWildcardType) {
return doNormalizeWildcardByPosition(((PsiCapturedWildcardType)type).getWildcard(), expression, toplevel);
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java
index 15492b3..717d123 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java
@@ -37,6 +37,7 @@
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -255,7 +256,7 @@
public PsiType createTypeFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException {
return createTypeInner(text, context, false);
}
-
+
@NotNull
@Override
public PsiTypeElement createTypeElementFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException {
@@ -327,7 +328,7 @@
return (PsiExpression)element;
}
- protected PsiJavaFile createDummyJavaFile(final String text) {
+ protected PsiJavaFile createDummyJavaFile(@NonNls final String text) {
final FileType type = JavaFileType.INSTANCE;
return (PsiJavaFile)PsiFileFactory.getInstance(myManager.getProject()).createFileFromText(DUMMY_FILE_NAME, type, text);
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
index c7cd48a..61e71bb 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
@@ -130,10 +130,8 @@
// First bound
return substitute(extendsTypes[0]);
}
- else {
- // Object
- return PsiType.getJavaLangObject(typeParameter.getManager(), typeParameter.getResolveScope());
- }
+ // Object
+ return PsiType.getJavaLangObject(typeParameter.getManager(), typeParameter.getResolveScope());
}
private abstract static class SubstitutionVisitorBase extends PsiTypeVisitorEx<PsiType> {
@@ -291,7 +289,7 @@
return null;
}
PsiClassType result = JavaPsiFacade.getElementFactory(aClass.getProject()).createType(aClass, createSubstitutor(hashMap), classType.getLanguageLevel());
- assert result.isValid();
+ PsiUtil.ensureValidType(result);
return result;
}
@@ -357,8 +355,8 @@
if (substitutedBoundType != null && !(substitutedBoundType instanceof PsiWildcardType) && !substitutedBoundType.equalsToText(
CommonClassNames.JAVA_LANG_OBJECT)) {
if (originalBound == null ||
- (!TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(TypeConversionUtil.erasure(originalBound)) &&
- !TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(originalBound))) { //erasure is essential to avoid infinite recursion
+ !TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(TypeConversionUtil.erasure(originalBound)) &&
+ !TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(originalBound)) { //erasure is essential to avoid infinite recursion
if (wildcardType.isExtends()) {
final PsiType glb = GenericsUtil.getGreatestLowerBound(wildcardType.getBound(), substitutedBoundType);
if (glb != null) {
@@ -375,52 +373,45 @@
}
if (captureContext != null) {
- LOG.assertTrue(substituted instanceof PsiWildcardType);
substituted = oldSubstituted instanceof PsiCapturedWildcardType && substituted == ((PsiCapturedWildcardType)oldSubstituted).getWildcard()
? oldSubstituted : PsiCapturedWildcardType.create((PsiWildcardType)substituted, captureContext);
}
return substituted;
}
- private PsiType correctExternalSubstitution(PsiType substituted, final PsiType original) {
- if (original == null) return null;
-
- if (substituted == null) {
- return original.accept(new PsiTypeVisitor<PsiType>() {
- @Override
- public PsiType visitArrayType(PsiArrayType arrayType) {
- return new PsiArrayType(arrayType.getComponentType().accept(this));
- }
-
- @Override
- public PsiType visitEllipsisType(PsiEllipsisType ellipsisType) {
- return new PsiEllipsisType(ellipsisType.getComponentType().accept(this));
- }
-
- @Override
- public PsiType visitClassType(PsiClassType classType) {
- PsiClass aClass = classType.resolve();
- if (aClass != null) {
- if (aClass instanceof PsiTypeParameter) {
- return rawTypeForTypeParameter((PsiTypeParameter)aClass);
- }
- else {
- return JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(aClass);
- }
- }
- else {
- return classType;
- }
- }
-
- @Override
- public PsiType visitType(PsiType type) {
- LOG.error(type.getInternalCanonicalText());
- return null;
- }
- });
+ private PsiType correctExternalSubstitution(PsiType substituted, @NotNull PsiType original) {
+ if (substituted != null) {
+ return substituted;
}
- return substituted;
+ return original.accept(new PsiTypeVisitor<PsiType>() {
+ @Override
+ public PsiType visitArrayType(PsiArrayType arrayType) {
+ return new PsiArrayType(arrayType.getComponentType().accept(this));
+ }
+
+ @Override
+ public PsiType visitEllipsisType(PsiEllipsisType ellipsisType) {
+ return new PsiEllipsisType(ellipsisType.getComponentType().accept(this));
+ }
+
+ @Override
+ public PsiType visitClassType(PsiClassType classType) {
+ PsiClass aClass = classType.resolve();
+ if (aClass == null) {
+ return classType;
+ }
+ if (aClass instanceof PsiTypeParameter) {
+ return rawTypeForTypeParameter((PsiTypeParameter)aClass);
+ }
+ return JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(aClass);
+ }
+
+ @Override
+ public PsiType visitType(PsiType type) {
+ LOG.error(type.getInternalCanonicalText());
+ return null;
+ }
+ });
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
index f31d87c..f32b42d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
@@ -328,16 +328,24 @@
return map.values();
}
- @NotNull public static HierarchicalMethodSignature getHierarchicalMethodSignature(PsiMethod method) {
- PsiClass aClass = method.getContainingClass();
- HierarchicalMethodSignature result = null;
- if (aClass != null) {
- result = getSignaturesMap(aClass).get(method.getSignature(PsiSubstitutor.EMPTY));
- }
- if (result == null) {
- result = new HierarchicalMethodSignatureImpl((MethodSignatureBackedByPsiMethod)method.getSignature(PsiSubstitutor.EMPTY));
- }
- return result;
+ @NotNull
+ public static HierarchicalMethodSignature getHierarchicalMethodSignature(final PsiMethod method) {
+ return CachedValuesManager.getManager(method.getProject())
+ .getCachedValue(method, new CachedValueProvider<HierarchicalMethodSignature>() {
+ @Nullable
+ @Override
+ public Result<HierarchicalMethodSignature> compute() {
+ PsiClass aClass = method.getContainingClass();
+ HierarchicalMethodSignature result = null;
+ if (aClass != null) {
+ result = getSignaturesMap(aClass).get(method.getSignature(PsiSubstitutor.EMPTY));
+ }
+ if (result == null) {
+ result = new HierarchicalMethodSignatureImpl((MethodSignatureBackedByPsiMethod)method.getSignature(PsiSubstitutor.EMPTY));
+ }
+ return Result.create(result, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
+ }
+ });
}
private static Map<MethodSignature, HierarchicalMethodSignature> getSignaturesMap(final PsiClass aClass) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsAnnotationParameterListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsAnnotationParameterListImpl.java
index bb76064..0100ccc 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsAnnotationParameterListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsAnnotationParameterListImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl.compiled;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.TreeElement;
@@ -33,7 +34,11 @@
for (int i = 0; i < myAttributes.length; i++) {
String name = psiAttributes[i].getName();
PsiAnnotationMemberValue value = psiAttributes[i].getValue();
- assert value != null : "name=" + name + " value" + value;
+ if (value == null) {
+ String anno = parent instanceof ClsAnnotationImpl ? ((ClsAnnotationImpl)parent).getStub().getText() : parent.getText();
+ Logger.getInstance(getClass()).error("name=" + name + " anno=[" + anno + "]");
+ value = new ClsLiteralExpressionImpl(this, "null", PsiType.NULL, null);
+ }
myAttributes[i] = new ClsNameValuePairImpl(this, name, value);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java
index 8f0e58d..e73ac2a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java
@@ -129,12 +129,18 @@
@Override
@NotNull
public PsiClass[] getSupers() {
+ if (CommonClassNames.JAVA_LANG_OBJECT.equals(getQualifiedName())) {
+ return PsiClass.EMPTY_ARRAY;
+ }
return PsiClassImplUtil.getSupers(this);
}
@Override
@NotNull
public PsiClassType[] getSuperTypes() {
+ if (CommonClassNames.JAVA_LANG_OBJECT.equals(getQualifiedName())) {
+ return PsiClassType.EMPTY_ARRAY;
+ }
return PsiClassImplUtil.getSuperTypes(this);
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightClassReference.java b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightClassReference.java
index 10ae244..e47d896 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightClassReference.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightClassReference.java
@@ -31,7 +31,7 @@
private final PsiElement myContext;
private final GlobalSearchScope myResolveScope;
private final PsiClass myRefClass;
- private PsiSubstitutor mySubstitutor;
+ private final PsiSubstitutor mySubstitutor;
private LightReferenceParameterList myParameterList;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
index 348f6ba..72cd0de 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.impl.source;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -32,8 +31,7 @@
* @author max
*/
public class PsiClassReferenceType extends PsiClassType {
- private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiClassReferenceType");
-
+ @NotNull
private final PsiJavaCodeReferenceElement myReference;
public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel) {
@@ -173,10 +171,11 @@
return myReference.getTypeParameters();
}
+ @NotNull
public PsiClassType createImmediateCopy() {
ClassResolveResult resolveResult = resolveGenerics();
PsiClass element = resolveResult.getElement();
- return element != null ? new PsiImmediateClassType(element, resolveResult.getSubstitutor()) : this;
+ return element == null ? this : new PsiImmediateClassType(element, resolveResult.getSubstitutor());
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java
index e71bf63..47a1b8e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java
@@ -142,7 +142,9 @@
StubElement<?> stub = getStub();
if (stub != null) {
PsiImportList[] nodes = stub.getChildrenByType(JavaStubElementTypes.IMPORT_LIST, PsiImportList.ARRAY_FACTORY);
- assert nodes.length == 1 : stub + "; " + stub.getChildrenStubs();
+ if (nodes.length != 1) {
+ reportStubAstMismatch(stub + "; " + stub.getChildrenStubs(), getStubTree(), PsiDocumentManager.getInstance(getProject()).getCachedDocument(this));
+ }
return nodes[0];
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
index ec4cec3..bafbd37 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
@@ -159,7 +159,13 @@
@Override
public PsiTypeElement getTypeElement() {
- return PsiTreeUtil.getChildOfType(this, PsiTypeElement.class);
+ for (PsiElement child = getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child instanceof PsiTypeElement) {
+ //noinspection unchecked
+ return (PsiTypeElement)child;
+ }
+ }
+ return null;
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/InferenceGraphNode.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/InferenceGraphNode.java
new file mode 100644
index 0000000..221f482
--- /dev/null
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/InferenceGraphNode.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve;
+
+import com.intellij.psi.PsiTypeParameter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * User: anna
+ * Date: 7/4/13
+ */
+public class InferenceGraphNode<T> {
+ private final T myValue;
+ private final List<InferenceGraphNode<T>> myDependencies = new ArrayList<InferenceGraphNode<T>>();
+
+ private int index = -1;
+ private int lowlink;
+
+ public InferenceGraphNode(T value) {
+ myValue = value;
+ }
+
+ public T getValue() {
+ return myValue;
+ }
+
+ public List<InferenceGraphNode<T>> getDependencies() {
+ return myDependencies;
+ }
+
+ public void addDependency(InferenceGraphNode<T> node) {
+ myDependencies.add(node);
+ }
+
+ public static <T> List<List<InferenceGraphNode<T>>> tarjan(Collection<InferenceGraphNode<T>> nodes) {
+ final ArrayList<List<InferenceGraphNode<T>>> result = new ArrayList<List<InferenceGraphNode<T>>>();
+ final Stack<InferenceGraphNode<T>> currentStack = new Stack<InferenceGraphNode<T>>();
+ int index = 0;
+ for (InferenceGraphNode<T> node : nodes) {
+ if (node.index == -1) {
+ index += strongConnect(node, index, currentStack, result);
+ }
+ }
+ return result;
+ }
+
+ private static <T> int strongConnect(InferenceGraphNode<T> currentNode,
+ int index,
+ Stack<InferenceGraphNode<T>> currentStack,
+ ArrayList<List<InferenceGraphNode<T>>> result) {
+ currentNode.index = index;
+ currentNode.lowlink = index;
+ index++;
+
+ currentStack.push(currentNode);
+
+ for (InferenceGraphNode<T> dependantNode : currentNode.getDependencies()) {
+ if (dependantNode.index == -1) {
+ strongConnect(dependantNode, index, currentStack, result);
+ currentNode.lowlink = Math.min(currentNode.lowlink, dependantNode.lowlink);
+ }
+ else if (currentStack.contains(dependantNode)) {
+ currentNode.lowlink = Math.min(currentNode.lowlink, dependantNode.index);
+ }
+ }
+
+ if (currentNode.lowlink == currentNode.index) {
+ final ArrayList<InferenceGraphNode<T>> arrayList = new ArrayList<InferenceGraphNode<T>>();
+ InferenceGraphNode<T> cyclicNode;
+ do {
+ cyclicNode = currentStack.pop();
+ arrayList.add(cyclicNode);
+ }
+ while (cyclicNode != currentNode);
+ result.add(arrayList);
+ }
+ return index;
+ }
+}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
index d17355f..7389517 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
@@ -32,7 +32,6 @@
import com.intellij.psi.impl.source.PsiImmediateClassType;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.reference.SoftReference;
-import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import com.intellij.util.messages.MessageBus;
@@ -96,10 +95,8 @@
}
if (type == null) type = TypeConversionUtil.NULL_TYPE;
Reference<PsiType> ref = new SoftReference<PsiType>(type);
- Reference<PsiType> storedRef = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, expr, ref);
+ myCalculatedTypes.put(expr, ref);
- PsiType stored = ref == storedRef ? type : storedRef.get();
- type = stored == null ? type : stored;
if (type instanceof PsiClassReferenceType) {
// convert reference-based class type to the PsiImmediateClassType, since the reference may become invalid
PsiClassType.ClassResolveResult result = ((PsiClassReferenceType)type).resolveGenerics();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
index 60be7ad..6dd5439 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
@@ -361,6 +361,7 @@
@SuppressWarnings("unchecked")
Pair<PsiType, ConstraintType>[] constraints = new Pair[typeParameters.length];
PsiFile file = parent.getContainingFile();
+ LOG.assertTrue(file != null, parent);
final PsiManager manager = file.getManager();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(file);
for (int i = 0; i < typeParameters.length; i++) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
index 550da84..4b2dc0b 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
@@ -46,15 +46,14 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.CharTable;
-import com.intellij.util.Function;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.NullableFunction;
+import com.intellij.util.*;
+import com.intellij.util.containers.Stack;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -185,6 +184,14 @@
private static final class OurGenericsResolver implements ResolveCache.PolyVariantResolver<PsiJavaReference> {
private static final OurGenericsResolver INSTANCE = new OurGenericsResolver();
+ @SuppressWarnings("SSBasedInspection")
+ private static final ThreadLocal<Stack<Object>> ourQualifiers = new ThreadLocal<Stack<Object>>() {
+ @Override
+ protected Stack<Object> initialValue() {
+ return new Stack<Object>();
+ }
+ };
+
@Override
@NotNull
public JavaResolveResult[] resolve(@NotNull PsiJavaReference ref, boolean incompleteCode) {
@@ -192,29 +199,43 @@
CompositeElement treeParent = expression.getTreeParent();
IElementType parentType = treeParent == null ? null : treeParent.getElementType();
PsiFile file = expression.getContainingFile();
- resolveAllQualifiers(expression, file);
- JavaResolveResult[] result = expression.resolve(parentType, file);
- if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION) {
- result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, file);
+ List<ResolveResult[]> qualifierResults = resolveAllQualifiers(expression, file);
+ ourQualifiers.get().push(qualifierResults);
+ try {
+ JavaResolveResult[] result = expression.resolve(parentType, file);
+
+ if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION) {
+ result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, file);
+ }
+
+ JavaResolveUtil.substituteResults(expression, result);
+
+ return result;
}
-
- JavaResolveUtil.substituteResults(expression, result);
-
- return result;
+ finally {
+ ourQualifiers.get().pop();
+ }
}
- private static void resolveAllQualifiers(@NotNull PsiReferenceExpressionImpl expression, final PsiFile containingFile) {
+ private static List<ResolveResult[]> resolveAllQualifiers(@NotNull PsiReferenceExpressionImpl expression, final PsiFile containingFile) {
// to avoid SOE, resolve all qualifiers starting from the innermost
PsiElement qualifier = expression.getQualifier();
- if (qualifier == null) return;
+ if (qualifier == null) return Collections.emptyList();
+
+ final List<ResolveResult[]> qualifierResults = new SmartList<ResolveResult[]>();
final ResolveCache resolveCache = ResolveCache.getInstance(containingFile.getProject());
qualifier.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
- if (!(expression instanceof PsiReferenceExpressionImpl) || resolveCache.isCached(expression, true, false, true)) {
+ if (!(expression instanceof PsiReferenceExpressionImpl)) {
return;
}
+ ResolveResult[] cachedResults = resolveCache.getCachedResults(expression, true, false, true);
+ if (cachedResults == null) {
+ return;
+ }
+ qualifierResults.add(cachedResults);
visitElement(expression);
}
@@ -222,9 +243,10 @@
protected void elementFinished(PsiElement element) {
if (!(element instanceof PsiReferenceExpressionImpl)) return;
PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)element;
- resolveCache.resolveWithCaching(expression, INSTANCE, false, false, containingFile);
+ qualifierResults.add(resolveCache.resolveWithCaching(expression, INSTANCE, false, false, containingFile));
}
});
+ return qualifierResults;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java
index fcc7d7e..3f0878c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java
@@ -68,6 +68,7 @@
public void deleteChildInternal(@NotNull final ASTNode child) {
if (child.getPsi() instanceof PsiResourceVariable && getResourceVariablesCount() == 1) {
getTreeParent().deleteChildInternal(this);
+ return;
}
super.deleteChildInternal(child);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java
index 3eefe91..5af4858 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java
@@ -181,6 +181,26 @@
return true;
}
+ @Override
+ public void deleteChildInternal(@NotNull ASTNode child) {
+ if (child.getPsi() instanceof PsiResourceList && getCatchBlocks().length == 0 && getFinallyBlock() == null) {
+ final PsiCodeBlock tryBlock = getTryBlock();
+ if (tryBlock != null) {
+ final PsiCodeBlock block = (PsiCodeBlock)replace(tryBlock);
+ final PsiJavaToken lBrace = block.getLBrace();
+ final PsiJavaToken rBrace = block.getRBrace();
+ if (lBrace != null) {
+ lBrace.delete();
+ }
+ if (rBrace != null) {
+ rBrace.delete();
+ }
+ return;
+ }
+ }
+ super.deleteChildInternal(child);
+ }
+
public String toString() {
return "PsiTryStatement";
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
index f4b8aea..f74d883 100644
--- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
+++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
@@ -28,15 +28,14 @@
import com.intellij.psi.scope.PsiConflictResolver;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
+import com.intellij.util.containers.HashSet;
+import gnu.trove.THashMap;
import gnu.trove.THashSet;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* Created by IntelliJ IDEA.
@@ -102,6 +101,7 @@
}
private void checkLambdaApplicable(List<CandidateInfo> conflicts) {
+ if (!PsiUtil.isLanguageLevel8OrHigher(myArgumentsList)) return;
for (int i = 0; i < myActualParameterTypes.length; i++) {
PsiType parameterType = myActualParameterTypes[i];
if (parameterType instanceof PsiLambdaExpressionType) {
@@ -190,7 +190,17 @@
private void checkSameSignatures(final List<CandidateInfo> conflicts) {
// candidates should go in order of class hierarchy traversal
// in order for this to work
- Map<MethodSignature, CandidateInfo> signatures = new HashMap<MethodSignature, CandidateInfo>();
+ Map<MethodSignature, CandidateInfo> signatures = new THashMap<MethodSignature, CandidateInfo>(conflicts.size());
+ Set<PsiMethod> superMethods = new HashSet<PsiMethod>();
+ for (CandidateInfo conflict : conflicts) {
+ final PsiMethod method = ((MethodCandidateInfo)conflict).getElement();
+ for (HierarchicalMethodSignature methodSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) {
+ final PsiMethod superMethod = methodSignature.getMethod();
+ if (!CommonClassNames.JAVA_LANG_OBJECT.equals(superMethod.getContainingClass().getQualifiedName())) {
+ superMethods.add(superMethod);
+ }
+ }
+ }
nextConflict:
for (int i=0; i<conflicts.size();i++) {
ProgressManager.checkCanceled();
@@ -198,16 +208,10 @@
PsiMethod method = (PsiMethod)info.getElement();
assert method != null;
- if (!method.hasModifierProperty(PsiModifier.STATIC)) {
- for (int k=i-1; k>=0; k--) {
- ProgressManager.checkCanceled();
- PsiMethod existingMethod = (PsiMethod)conflicts.get(k).getElement();
- if (PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
- conflicts.remove(i);
- i--;
- continue nextConflict;
- }
- }
+ if (!method.hasModifierProperty(PsiModifier.STATIC) && superMethods.contains(method)) {
+ conflicts.remove(i);
+ i--;
+ continue;
}
PsiClass class1 = method.getContainingClass();
diff --git a/java/java-psi-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-psi-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java
index d44b9d8..7540384 100644
--- a/java/java-psi-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java
+++ b/java/java-psi-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java
@@ -394,6 +394,12 @@
match.registerReturnValue(new ContinueReturnValue());
} else if (pattern instanceof PsiBreakStatement) {
match.registerReturnValue(new BreakReturnValue());
+ }else if (pattern instanceof PsiMethodCallExpression) {
+ final PsiMethod patternMethod = ((PsiMethodCallExpression)pattern).resolveMethod();
+ final PsiMethod candidateMethod = ((PsiMethodCallExpression)candidate).resolveMethod();
+ if (patternMethod != null && candidateMethod != null) {
+ if (!MethodSignatureUtil.areSignaturesEqual(patternMethod, candidateMethod)) return false;
+ }
} else if (pattern instanceof PsiReferenceExpression) {
final PsiReferenceExpression patternRefExpr = (PsiReferenceExpression)pattern;
final PsiReferenceExpression candidateRefExpr = (PsiReferenceExpression)candidate;
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastWithGenerics-out.java b/java/java-tests/testData/codeInsight/completion/smartType/CastWithGenerics-out.java
index 9e5e012..39f34e4 100644
--- a/java/java-tests/testData/codeInsight/completion/smartType/CastWithGenerics-out.java
+++ b/java/java-tests/testData/codeInsight/completion/smartType/CastWithGenerics-out.java
@@ -1,9 +1,9 @@
public class Aaaaaaa {
- void foo(Class<? extends Object> c) {}
+ void foo(Class<? extends Aaaaaaa> c) {}
void bar() {
- foo((Class<Object>) <caret>Class.forName("sdd"));
+ foo((Class<? extends Aaaaaaa>) <caret>Class.forName("sdd"));
}
}
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/CastWithGenerics.java b/java/java-tests/testData/codeInsight/completion/smartType/CastWithGenerics.java
index 8e3735a..fa75169 100644
--- a/java/java-tests/testData/codeInsight/completion/smartType/CastWithGenerics.java
+++ b/java/java-tests/testData/codeInsight/completion/smartType/CastWithGenerics.java
@@ -1,6 +1,6 @@
public class Aaaaaaa {
- void foo(Class<? extends Object> c) {}
+ void foo(Class<? extends Aaaaaaa> c) {}
void bar() {
foo((<caret>Class.forName("sdd"));
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java
index b0e0ac5..7ac0b4f 100644
--- a/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java
+++ b/java/java-tests/testData/codeInsight/completion/smartType/DiamondNotCollapsed-out.java
@@ -1,6 +1,6 @@
class MyClass {
public void foo() {
- MyDD<String> d = new MyDD<String>(<caret>);
+ MyDD<String> d = new MyDD<>(<caret>);
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NoUnhandledExceptionsMultipleInheritance.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NoUnhandledExceptionsMultipleInheritance.java
new file mode 100644
index 0000000..327bc82
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NoUnhandledExceptionsMultipleInheritance.java
@@ -0,0 +1,77 @@
+import java.io.*;
+
+interface ThrowsCloneNotSupportedException {
+ void f() throws CloneNotSupportedException;
+}
+
+interface ThrowsIOException {
+ void f() throws IOException;
+}
+
+abstract class ThrowsNothing implements ThrowsCloneNotSupportedException, ThrowsIOException {
+ private void foo() {
+ f();
+ }
+}
+
+class Main {
+ public static void main(String[] args) {
+ ThrowsNothing throwsNothing = null;
+ throwsNothing.f();
+ }
+}
+
+
+interface A {
+ void close() throws Exception;
+}
+
+interface B {
+ void close() throws IOException;
+}
+
+abstract class AB implements A, B {}
+abstract class BA implements B, A {}
+
+class ABUsage {
+ void foo(AB ab) {
+ try {
+ ab.close();
+ }
+ catch (IOException ignored) {}
+ }
+
+ void foo(BA ba) {
+ try {
+ ba.close();
+ }
+ catch (IOException ignored) {}
+ }
+}
+
+interface C {
+ void close();
+}
+
+interface D {
+ void close() throws IOException;
+}
+
+abstract class CD implements C, D {}
+abstract class DC implements D, C {}
+
+class CDUsage {
+ void foo(CD cd) {
+ try {
+ cd.close();
+ }
+ catch (<error descr="Exception 'java.io.IOException' is never thrown in the corresponding try block">IOException ignored</error>) {}
+ }
+
+ void foo(DC dc) {
+ try {
+ dc.close();
+ }
+ catch (<error descr="Exception 'java.io.IOException' is never thrown in the corresponding try block">IOException ignored</error>) {}
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA109875.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA109875.java
new file mode 100644
index 0000000..a70b094
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA109875.java
@@ -0,0 +1,13 @@
+import java.util.Collections;
+import java.util.Set;
+
+public class Test<Y> {
+
+ public static <K> Test<K> doTest(K k){
+ return null;
+ }
+
+ public static void main(String[] args) {
+ Test.<Set<String>>doTest<error descr="'doTest(java.util.Set<java.lang.String>)' in 'Test' cannot be applied to '(java.util.Set<java.lang.Object>)'">(Collections.emptySet())</error>;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67672.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67672.java
index 939ce3f..db8282f 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67672.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67672.java
@@ -3,5 +3,5 @@
interface A
{
- <<error descr="'addAll(Collection<? extends E>)' in 'java.util.Collection' clashes with 'addAll(Collection<? extends E>)' in 'java.util.List'; both methods have same erasure, yet neither overrides the other"></error>T extends List<?> & Collection<? extends Cloneable>> void foo(T x);
+ <<error descr="'add(E)' in 'java.util.List' clashes with 'add(E)' in 'java.util.Collection'; both methods have same erasure, yet neither overrides the other"></error>T extends List<?> & Collection<? extends Cloneable>> void foo(T x);
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MethodSignatureEquality.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MethodSignatureEquality.java
index e41b471..cabf948 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MethodSignatureEquality.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MethodSignatureEquality.java
@@ -70,7 +70,7 @@
abstract class F<T extends Throwable> {
<error descr="'foo(F<?>)' is already defined in 'Test.F'">abstract void foo(F<?> y)</error>;
- abstract void foo(F<? extends Throwable> y);
+ <error descr="'foo(F<? extends Throwable>)' is already defined in 'Test.F'">abstract void foo(F<? extends Throwable> y)</error>;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SOEInLeastUpperClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SOEInLeastUpperClass.java
new file mode 100644
index 0000000..70ad266
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SOEInLeastUpperClass.java
@@ -0,0 +1,12 @@
+<error descr="Cyclic inheritance involving 'A'">interface A extends A</error> {}
+interface B {}
+
+<error descr="Cyclic inheritance involving 'A'">class T implements A, B</error>{
+ <T1> T1 foo(A a, B b) {
+ return null;
+ }
+
+ void bar (boolean a, A a1, B b1){
+ <error descr="Incompatible types. Found: 'java.lang.Object', required: 'T'">T t = a ? a1 : b1;</error>
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/afterDefaultMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/afterDefaultMethod.java
new file mode 100644
index 0000000..d11590f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/afterDefaultMethod.java
@@ -0,0 +1,7 @@
+// "Add Method Body" "true"
+interface a {
+ default String f() {
+ <selection>return null;</selection>
+ }
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/beforeDefaultMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/beforeDefaultMethod.java
new file mode 100644
index 0000000..65bd47a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/beforeDefaultMethod.java
@@ -0,0 +1,5 @@
+// "Add Method Body" "true"
+interface a {
+ default <caret>String f();
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/afterMultipleMethods.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/afterMultipleMethods.java
new file mode 100644
index 0000000..d5d911a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/afterMultipleMethods.java
@@ -0,0 +1,13 @@
+// "Convert to local" "true"
+class Test {
+
+ int getFoo1() {
+ int myFoo = 1;
+ return myFoo;
+ }
+
+ int getFoo2() {
+ int myFoo = 2;
+ return myFoo;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethods.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethods.java
new file mode 100644
index 0000000..f4afcf9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethods.java
@@ -0,0 +1,14 @@
+// "Convert to local" "true"
+class Test {
+ private int my<caret>Foo;
+
+ int getFoo1() {
+ myFoo = 1;
+ return myFoo;
+ }
+
+ int getFoo2() {
+ myFoo = 2;
+ return myFoo;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterAnonymous.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterAnonymous.java
new file mode 100644
index 0000000..8de7067
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterAnonymous.java
@@ -0,0 +1,7 @@
+// "Create Local Variable 'zeit'" "true"
+public class A {
+ {
+ Object zeit;
+ Runnable r = new Runnable(zeit) {};
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterWildcard.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterWildcard.java
new file mode 100644
index 0000000..2d533da
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterWildcard.java
@@ -0,0 +1,8 @@
+// "Create Local Variable 'a'" "true"
+public class A {
+ void foo() {
+ Class<?>[] a = get();
+ }
+
+ Class<?>[] get() {return null;}
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeAnonymous.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeAnonymous.java
new file mode 100644
index 0000000..1062727
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeAnonymous.java
@@ -0,0 +1,6 @@
+// "Create Local Variable 'zeit'" "true"
+public class A {
+ {
+ Runnable r = new Runnable(ze<caret>it) {};
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeAnonymousInField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeAnonymousInField.java
new file mode 100644
index 0000000..47da144
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeAnonymousInField.java
@@ -0,0 +1,4 @@
+// "Create Local Variable 'zeit'" "false"
+public class A {
+ Runnable r = new Runnable(ze<caret>it) {};
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeWildcard.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeWildcard.java
new file mode 100644
index 0000000..d04bee5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeWildcard.java
@@ -0,0 +1,8 @@
+// "Create Local Variable 'a'" "true"
+public class A {
+ void foo() {
+ <caret>a = get();
+ }
+
+ Class<?>[] get() {return null;}
+}
diff --git a/java/java-tests/testData/codeInsight/generate/generateCreateUI/beforeSOE.java b/java/java-tests/testData/codeInsight/generate/generateCreateUI/beforeSOE.java
new file mode 100644
index 0000000..24218d5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generate/generateCreateUI/beforeSOE.java
@@ -0,0 +1,3 @@
+class A extends A {
+ <caret>
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/overrideImplement/afterMultipleInheritedThrows.java b/java/java-tests/testData/codeInsight/overrideImplement/afterMultipleInheritedThrows.java
new file mode 100644
index 0000000..688387c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/overrideImplement/afterMultipleInheritedThrows.java
@@ -0,0 +1,17 @@
+import java.io.*;
+interface A {
+ void close() throws Exception;
+}
+
+interface B {
+ void close() throws IOException;
+}
+
+interface C<T extends Exception> {
+ void close() throws T;
+}
+
+interface AB extends A, C, B {
+ @Override
+ void close() throws IOException;
+}
diff --git a/java/java-tests/testData/codeInsight/overrideImplement/afterOverrideInInterface.java b/java/java-tests/testData/codeInsight/overrideImplement/afterOverrideInInterface.java
new file mode 100644
index 0000000..d314284
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/overrideImplement/afterOverrideInInterface.java
@@ -0,0 +1,8 @@
+interface A {
+ void foo();
+}
+
+interface B extends A {
+ @Override
+ void foo();
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/overrideImplement/afterSkipUnknownAnnotations.java b/java/java-tests/testData/codeInsight/overrideImplement/afterSkipUnknownAnnotations.java
new file mode 100644
index 0000000..004a0c0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/overrideImplement/afterSkipUnknownAnnotations.java
@@ -0,0 +1,9 @@
+interface A {
+ void f(@Unknown1 @Unknown2 String s, @Unknown3 s3);
+}
+class B implements A {
+ @Override
+ public void f(String s) {
+
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/overrideImplement/beforeMultipleInheritedThrows.java b/java/java-tests/testData/codeInsight/overrideImplement/beforeMultipleInheritedThrows.java
new file mode 100644
index 0000000..8b66b89
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/overrideImplement/beforeMultipleInheritedThrows.java
@@ -0,0 +1,16 @@
+import java.io.*;
+interface A {
+ void close() throws Exception;
+}
+
+interface B {
+ void close() throws IOException;
+}
+
+interface C<T extends Exception> {
+ void close() throws T;
+}
+
+interface AB extends A, C, B {
+ <caret>
+}
diff --git a/java/java-tests/testData/codeInsight/overrideImplement/beforeOverrideInInterface.java b/java/java-tests/testData/codeInsight/overrideImplement/beforeOverrideInInterface.java
new file mode 100644
index 0000000..dde843d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/overrideImplement/beforeOverrideInInterface.java
@@ -0,0 +1,7 @@
+interface A {
+ void foo();
+}
+
+interface B extends A {
+ <caret>
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/overrideImplement/beforeSkipUnknownAnnotations.java b/java/java-tests/testData/codeInsight/overrideImplement/beforeSkipUnknownAnnotations.java
new file mode 100644
index 0000000..870a74e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/overrideImplement/beforeSkipUnknownAnnotations.java
@@ -0,0 +1,6 @@
+interface A {
+ void f(@Unknown1 @Unknown2 String s, @Unknown3 s3);
+}
+class B implements A {
+ <caret>
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java b/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java
new file mode 100644
index 0000000..b055937
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java
@@ -0,0 +1,26 @@
+public class BrokenAlignment {
+
+ public static void main(String[] args) {
+
+ Throwable error = null;
+ try {
+ doSomething();
+ } catch (AssertionError e) {
+ // rethrow error
+ throw e;
+ } catch (Throwable e) {
+ // remember error
+ error = e;
+ }
+
+ if (error != null) { // <<--- inspection warning
+ // handle error ...
+ }
+
+ }
+
+ public static void doSomething() {
+ throw new RuntimeException("dummy");
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java b/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java
new file mode 100644
index 0000000..fa72072
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java
@@ -0,0 +1,19 @@
+import org.jetbrains.annotations.Nullable;
+
+public class Goo {
+ Permission permission;
+
+ {
+ Object category = permission.getCategory();
+ System.out.println(<warning descr="Method invocation 'category.hashCode()' may produce 'java.lang.NullPointerException'">category.hashCode()</warning>);
+ }
+}
+
+class Permission {
+ Object category;
+
+
+ @Nullable Object getCategory() {
+ return category;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/IgnoreAssertions.java b/java/java-tests/testData/inspection/dataFlow/fixture/IgnoreAssertions.java
new file mode 100644
index 0000000..5fa6f05
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/IgnoreAssertions.java
@@ -0,0 +1,10 @@
+class Foo {
+ Object getObjectFromElsewhere() { return null; }
+ void foo() {
+ Object object = getObjectFromElsewhere();
+ assert (object != null);
+ if (object != null) {
+ return;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/redundantCast/generics/GetClassProcessing/expected.xml b/java/java-tests/testData/inspection/redundantCast/generics/GetClassProcessing/expected.xml
new file mode 100644
index 0000000..4704d91
--- /dev/null
+++ b/java/java-tests/testData/inspection/redundantCast/generics/GetClassProcessing/expected.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems/>
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/redundantCast/generics/GetClassProcessing/src/Test.java b/java/java-tests/testData/inspection/redundantCast/generics/GetClassProcessing/src/Test.java
new file mode 100644
index 0000000..0fa9d05
--- /dev/null
+++ b/java/java-tests/testData/inspection/redundantCast/generics/GetClassProcessing/src/Test.java
@@ -0,0 +1,10 @@
+class B { }
+class A extends B { }
+
+class C {
+ void m(Class<? extends A> c) {}
+
+ void x(B b) {
+ m(((A)b).getClass());
+ }
+}
diff --git a/java/java-tests/testData/psi/parser-full/expressionParsing/QualifiedSuperMethodCall.txt b/java/java-tests/testData/psi/parser-full/expressionParsing/QualifiedSuperMethodCall.txt
index 02cb11f..0905da3 100644
--- a/java/java-tests/testData/psi/parser-full/expressionParsing/QualifiedSuperMethodCall.txt
+++ b/java/java-tests/testData/psi/parser-full/expressionParsing/QualifiedSuperMethodCall.txt
@@ -58,6 +58,8 @@
PsiJavaToken:LPARENTH('(')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:DOT('.')
+ PsiReferenceParameterList
+ <empty list>
PsiKeyword:super('super')
PsiExpressionList
PsiJavaToken:LPARENTH('(')
diff --git a/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall0.txt b/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall0.txt
index 6b22700..452d64a 100644
--- a/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall0.txt
+++ b/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall0.txt
@@ -14,6 +14,8 @@
PsiJavaToken:LPARENTH('(')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:DOT('.')
+ PsiReferenceParameterList
+ <empty list>
PsiKeyword:super('super')
PsiExpressionList
PsiJavaToken:LPARENTH('(')
diff --git a/java/java-tests/testData/refactoring/extractMethod/OverloadedMethods.java b/java/java-tests/testData/refactoring/extractMethod/OverloadedMethods.java
new file mode 100644
index 0000000..a951ea0
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractMethod/OverloadedMethods.java
@@ -0,0 +1,21 @@
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+
+public class Test {
+ public void myTest(List list, String s1, String s2) {
+ }
+
+ public void myTest(Collection list, String s1, String s2) {
+ }
+
+ public void usage() {
+ List list = new ArrayList();
+ String aa = "AA";
+ String bb = "bb";
+ myTest(list, aa, bb);
+ Collection col = new ArrayList();
+ <selection>myTest(col, aa, bb);</selection>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/extractMethod/OverloadedMethods_after.java b/java/java-tests/testData/refactoring/extractMethod/OverloadedMethods_after.java
new file mode 100644
index 0000000..dd8e4c5
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractMethod/OverloadedMethods_after.java
@@ -0,0 +1,25 @@
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+
+public class Test {
+ public void myTest(List list, String s1, String s2) {
+ }
+
+ public void myTest(Collection list, String s1, String s2) {
+ }
+
+ public void usage() {
+ List list = new ArrayList();
+ String aa = "AA";
+ String bb = "bb";
+ myTest(list, aa, bb);
+ Collection col = new ArrayList();
+ newMethod(aa, bb, col);
+ }
+
+ private void newMethod(String aa, String bb, Collection col) {
+ myTest(col, aa, bb);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/after/Test.java b/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/after/Test.java
new file mode 100644
index 0000000..7442184
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/after/Test.java
@@ -0,0 +1,3 @@
+public class Test {
+ public void m() {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/after/TestSubclass.java b/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/after/TestSubclass.java
new file mode 100644
index 0000000..840eeb4
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/after/TestSubclass.java
@@ -0,0 +1,18 @@
+import java.util.List;
+
+class TestSubclass extends Test {
+}
+
+
+class Base {
+ public void main(List<Test> tests) {
+ for (Test test : tests) {}
+ }
+}
+
+class Inheritor extends Base {
+ @Override
+ public void main(List<Test> tests) {
+ super.main(tests);
+ }
+}
diff --git a/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/before/Test.java b/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/before/Test.java
new file mode 100644
index 0000000..a490e06
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractSuperClass/emptyForeach/before/Test.java
@@ -0,0 +1,19 @@
+import java.util.List;
+
+class Test {
+ public void m() {}
+}
+
+
+class Base {
+ public void main(List<Test> tests) {
+ for (Test test : tests) {}
+ }
+}
+
+class Inheritor extends Base {
+ @Override
+ public void main(List<Test> tests) {
+ super.main(tests);
+ }
+}
diff --git a/java/java-tests/testData/refactoring/inlineLocal/ArrayMethodCallInitialized.java b/java/java-tests/testData/refactoring/inlineLocal/ArrayMethodCallInitialized.java
new file mode 100644
index 0000000..aa7c17c
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineLocal/ArrayMethodCallInitialized.java
@@ -0,0 +1,11 @@
+public class A {
+
+ public void testInlineRefactoring() {
+ int[] array = ar();
+ arr<caret>ay[1] = 22;
+ }
+
+ private int[] ar() {
+ return new int[0];
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineLocal/ArrayMethodCallInitialized.java.after b/java/java-tests/testData/refactoring/inlineLocal/ArrayMethodCallInitialized.java.after
new file mode 100644
index 0000000..72d6b9f
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineLocal/ArrayMethodCallInitialized.java.after
@@ -0,0 +1,10 @@
+public class A {
+
+ public void testInlineRefactoring() {
+ ar()[1] = 22;
+ }
+
+ private int[] ar() {
+ return new int[0];
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java b/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java
new file mode 100644
index 0000000..db06692
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java
@@ -0,0 +1,9 @@
+class Test {
+ void m() throws Exception {
+ try (AutoCloseable inl<caret>ineMe = null) {
+ try (AutoCloseable r2 = inlineMe) {
+ System.out.println(inlineMe + ", " + r2);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java.after b/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java.after
new file mode 100644
index 0000000..0ec3906
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java.after
@@ -0,0 +1,7 @@
+class Test {
+ void m() throws Exception {
+ try (AutoCloseable r2 = null) {
+ System.out.println(null + ", " + r2);
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/moveInner/scr30106/after/p/B.java b/java/java-tests/testData/refactoring/moveInner/scr30106/after/p/B.java
index 6fa9162..32301db 100644
--- a/java/java-tests/testData/refactoring/moveInner/scr30106/after/p/B.java
+++ b/java/java-tests/testData/refactoring/moveInner/scr30106/after/p/B.java
@@ -1,12 +1,12 @@
package p;
public class B extends X {
+ private A outer;
+
{
method();
}
- private A outer;
-
public B(A outer) {
this.outer = outer;
}
diff --git a/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/after/A.java b/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/after/A.java
new file mode 100644
index 0000000..c77f0cd
--- /dev/null
+++ b/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/after/A.java
@@ -0,0 +1,3 @@
+public class A {
+ public static final String ONE = "";
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/after/B.java b/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/after/B.java
new file mode 100644
index 0000000..6ad6775
--- /dev/null
+++ b/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/after/B.java
@@ -0,0 +1,8 @@
+public class B {
+ void foo(String s) {
+ switch (i) {
+ case A.ONE :
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/before/A.java b/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/before/A.java
new file mode 100644
index 0000000..61ff2ab
--- /dev/null
+++ b/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/before/A.java
@@ -0,0 +1,2 @@
+public class A {
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/before/B.java b/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/before/B.java
new file mode 100644
index 0000000..5ae2fae
--- /dev/null
+++ b/java/java-tests/testData/refactoring/moveMembers/stringConstantFromCaseStatement/before/B.java
@@ -0,0 +1,9 @@
+public class B {
+ public static final String ONE = "";
+ void foo(String s) {
+ switch (i) {
+ case ONE :
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableWithFinallyBlock.java b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableWithFinallyBlock.java
new file mode 100644
index 0000000..cbd6447
--- /dev/null
+++ b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableWithFinallyBlock.java
@@ -0,0 +1,6 @@
+class ARM {
+ void f() {
+ try (AutoCloseable <caret>r = null) {
+ } finally {}
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableWithFinallyBlock_after.java b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableWithFinallyBlock_after.java
new file mode 100644
index 0000000..04c6ee5
--- /dev/null
+++ b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableWithFinallyBlock_after.java
@@ -0,0 +1,6 @@
+class ARM {
+ void f() {
+ try {
+ } finally {}
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable_after.java b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable_after.java
index 299e83c..3b50367 100644
--- a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable_after.java
+++ b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable_after.java
@@ -1,6 +1,4 @@
class ARM {
void f() {
- try {
- }
}
}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateCreateUITest.java b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateCreateUITest.java
new file mode 100644
index 0000000..683a22a
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateCreateUITest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight;
+
+import com.intellij.codeInsight.generation.actions.GenerateCreateUIAction;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.testFramework.LightCodeInsightTestCase;
+
+/**
+ * @author anna
+ */
+public class GenerateCreateUITest extends LightCodeInsightTestCase {
+ public void testSOE() throws Exception {
+ configureByFile("/codeInsight/generate/generateCreateUI/beforeSOE.java");
+ final PsiClass targetClass = PsiTreeUtil.getParentOfType(getFile().findElementAt(getEditor().getCaretModel().getOffset()), PsiClass.class);
+ assertNotNull(targetClass);
+ assertFalse(new GenerateCreateUIAction().isValidForClass(targetClass));
+ }
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java
index 95de823..670b101 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java
@@ -70,6 +70,11 @@
public void testImplementExtensionMethods() { doTest8(false, true); }
public void testOverrideExtensionMethods() { doTest8(false, false); }
public void testDoNotImplementExtensionMethods() { doTest8(false, true); }
+ public void testSkipUnknownAnnotations() { doTest8(false, true); }
+
+
+ public void testOverrideInInterface() { doTest8(false, false); }
+ public void testMultipleInheritedThrows() {doTest8(false, false);}
public void testLongFinalParameterList() {
CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject()).clone();
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
index a55697a..4524ed7 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
@@ -21,6 +21,7 @@
import com.intellij.codeInsight.lookup.Lookup
import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.codeInsight.lookup.LookupManager
+import com.intellij.codeInsight.lookup.PsiTypeLookupItem
import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.ide.DataManager
@@ -740,7 +741,7 @@
myFixture.checkResult(" class Foo { { int iteraaa; iteraaa<caret> } } ")
assert !lookup
}
-
+
public void testChoosingItemDuringCopyCommit() {
registerContributor(LongReplacementOffsetContributor)
@@ -1023,8 +1024,7 @@
myFixture.addClass("package xxxxx; public class SYSTEM_EXCEPTION {}")
myFixture.configureByText "a.java", "import xxxxx.*; class Foo { S<caret> }"
type 'Ystem'
- assert 'java.lang.System' == ((JavaPsiClassReferenceElement) myFixture.lookupElements[0]).qualifiedName
- assert 'xxxxx.SYSTEM_EXCEPTION' == ((JavaPsiClassReferenceElement) myFixture.lookupElements[1]).qualifiedName
+ myFixture.assertPreferredCompletionItems 1, 'System', 'SYSTEM_EXCEPTION'
}
public void testSamePrefixIgnoreCase2() {
@@ -1032,9 +1032,7 @@
myFixture.addClass("package xxxxx; public class SYstem {}")
myFixture.configureByText "a.java", "import xxxxx.*; class Foo { S<caret> }"
type 'Ystem'
- assert 'xxxxx.SYstem' == ((JavaPsiClassReferenceElement) myFixture.lookupElements[0]).qualifiedName
- assert 'java.lang.System' == ((JavaPsiClassReferenceElement) myFixture.lookupElements[1]).qualifiedName
- assert 'xxxxx.SYSTEM_EXCEPTION' == ((JavaPsiClassReferenceElement) myFixture.lookupElements[2]).qualifiedName
+ myFixture.assertPreferredCompletionItems 0, 'SYstem', 'System', 'SYSTEM_EXCEPTION'
}
private FileEditor openEditorForUndo() {
@@ -1331,7 +1329,10 @@
}
}
'''
- type 'int['
+ type 'int'
+ myFixture.assertPreferredCompletionItems 0, 'int', 'Integer'
+ assert ((PsiTypeLookupItem) myFixture.lookupElements[0]).bracketsCount == 1
+ type '['
myFixture.checkResult '''
class Foo {
void foo() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
similarity index 78%
rename from java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.java
rename to java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
index 3c17cc8..6c5c239 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
@@ -1,26 +1,21 @@
-package com.intellij.codeInsight.completion;
-
-import com.intellij.JavaTestUtil;
-import com.intellij.codeInsight.CodeInsightSettings;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
-import com.intellij.lang.StdLanguages;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiReference;
-import com.intellij.psi.PsiReferenceBase;
-import com.intellij.psi.PsiReferenceProvider;
-import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.impl.source.resolve.reference.PsiReferenceRegistrarImpl;
-import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
-import com.intellij.psi.javadoc.PsiDocTag;
-import com.intellij.util.ObjectUtils;
-import com.intellij.util.ProcessingContext;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Arrays;
-import java.util.List;
-
-
+package com.intellij.codeInsight.completion
+import com.intellij.JavaTestUtil
+import com.intellij.codeInsight.CodeInsightSettings
+import com.intellij.codeInsight.lookup.LookupElement
+import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection
+import com.intellij.lang.StdLanguages
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiReference
+import com.intellij.psi.PsiReferenceBase
+import com.intellij.psi.PsiReferenceProvider
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager
+import com.intellij.psi.impl.source.resolve.reference.PsiReferenceRegistrarImpl
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
+import com.intellij.psi.javadoc.PsiDocTag
+import com.intellij.util.ObjectUtils
+import com.intellij.util.ProcessingContext
+import com.intellij.util.SystemProperties
+import org.jetbrains.annotations.NotNull
/**
* @author mike
*/
@@ -39,7 +34,7 @@
public void testNamesInClass() throws Exception {
configureByFile("ClassTagName.java");
- assertStringItems("author", "deprecated", "param", "see", "serial", "since", "version");
+ assertStringItems("author", 'author ' + SystemProperties.getUserName(), "deprecated", "param", "see", "serial", "since", "version");
}
public void testNamesInField() throws Exception {
@@ -54,7 +49,7 @@
public void testNamesInMethod1() throws Exception {
configureByFile("MethodTagName1.java");
- assertStringItems("see", "serialData", "since", "class", "throws");
+ assertStringItems("see", "serialData", "since", "throws");
}
public void testParamValueCompletion() throws Exception {
@@ -204,6 +199,39 @@
checkResultByFile(getTestName(false) + "_after.java");
}
+ public void "test suggest param names"() {
+ myFixture.configureByText "a.java", '''
+class Foo {
+ /**
+ * @par<caret>
+ */
+ void foo(int intParam, Object param2) {
+ }
+}
+'''
+ myFixture.completeBasic()
+ myFixture.assertPreferredCompletionItems 0, 'param', 'param intParam', 'param param2'
+ myFixture.type('\n intParam\n@para')
+ myFixture.completeBasic()
+ myFixture.assertPreferredCompletionItems 0, 'param', 'param param2'
+ }
+
+ public void "test see super class"() {
+ myFixture.addClass("package foo; public interface Foo {}")
+ myFixture.addClass("package bar; public class Bar {} ")
+ myFixture.configureByText "a.java", '''
+import foo.*;
+import bar.*;
+
+/**
+ * @se<caret>
+ */
+class Impl extends Bar implements Foo {}
+'''
+ myFixture.completeBasic()
+ myFixture.assertPreferredCompletionItems 0, 'see', 'see bar.Bar', 'see foo.Foo'
+ }
+
public void testCustomReferenceProvider() throws Exception {
PsiReferenceRegistrarImpl registrar =
(PsiReferenceRegistrarImpl) ReferenceProvidersRegistry.getInstance().getRegistrar(StdLanguages.JAVA);
@@ -211,7 +239,7 @@
@Override
@NotNull
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull final ProcessingContext context) {
- return new PsiReference[]{new PsiReferenceBase<PsiElement>(element) {
+ def ref = new PsiReferenceBase<PsiElement>(element) {
@Override
public PsiElement resolve() {
@@ -221,9 +249,10 @@
@Override
@NotNull
public Object[] getVariants() {
- return new Object[]{"1", "2", "3"};
+ return ["1", "2", "3"]
}
- }};
+ }
+ return [ref]
}
};
try {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
index 7c2bc5b..8a1bfe6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
@@ -60,7 +60,7 @@
final LookupImpl lookup = invokeCompletion(getTestName(false) + ".html");
assertPreferredItems(0, "p", "param", "pre");
incUseCount(lookup, 2);
- assertPreferredItems(0, "p", "pre", "param");
+ assertPreferredItems(1, "p", "pre", "param");
}
public void testUppercaseMatters2() throws Throwable {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
index fca0924..ec241b5 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
@@ -237,6 +237,7 @@
public void testIDEA22005() throws Exception { doTest5(false);}
public void testIDEA57259() throws Exception { doTest5(false);}
public void testIDEA107957() throws Exception { doTest6(false);}
+ public void testIDEA109875() throws Exception { doTest6(false);}
public void testIDEA106964() throws Exception { doTest5(false);}
public void testIDEA107782() throws Exception { doTest5(false);}
public void testInheritedWithDifferentArgsInTypeParams() throws Exception { doTest5(false);}
@@ -287,6 +288,7 @@
public void testIDEA104100() {doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);}
public void testIDEA104160() {doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);}
+ public void testSOEInLeastUpperClass() {doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);}
public void testJavaUtilCollections_NoVerify() throws Exception {
PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java
index a331e33..a0d0ffc 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java
@@ -91,6 +91,10 @@
private List<HighlightInfo> doTest(final int maxMillis) throws Exception {
configureByFile(getFilePath(""));
+ return startTest(maxMillis);
+ }
+
+ private List<HighlightInfo> startTest(int maxMillis) {
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
getFile().getText(); //to load text
CodeInsightTestFixtureImpl.ensureIndexesUpToDate(getProject());
@@ -124,4 +128,20 @@
fail("Actual: " + errors.size());
}
}
+
+ public void testDuplicateMethods() throws Exception {
+ StringBuilder text = new StringBuilder("class X {\n");
+ int N = 1000;
+ for (int i=0;i<N;i++) {
+ text.append("public void visit(C" + i + " param) {}\n");
+ }
+ for (int i=0;i<N;i++) {
+ text.append("class C" + i + " {}\n");
+ }
+ text.append("}");
+ configureFromFileText("x.java", text.toString());
+
+ List<HighlightInfo> infos = startTest(Math.max(1000, 10000 - JobSchedulerImpl.CORES_COUNT * 1000));
+ assertEmpty(infos);
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java
index 9cffb6d..c72853a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java
@@ -119,6 +119,7 @@
public void testFieldDoubleInitialization() { doTest(false, false); }
public void testAssignToFinal() { doTest(false, false); }
public void testUnhandledExceptionsInSuperclass() { doTest(false, false); }
+ public void testNoUnhandledExceptionsMultipleInheritance() { doTest(false, false); }
public void testAssignmentCompatible () { doTest(false, false); }
public void testMustBeBoolean() { doTest(false, false); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TarjanTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TarjanTest.java
new file mode 100644
index 0000000..1abbe2d
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TarjanTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.lambda;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.impl.source.resolve.InferenceGraphNode;
+import com.intellij.util.Function;
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 7/4/13
+ */
+public class TarjanTest extends TestCase {
+
+ //testdata from https://github.com/bwesterb/py-tarjan/
+ public void testResultGraph() throws Exception {
+ //{1:[2],2:[1,5],3:[4],4:[3,5],5:[6],6:[7],7:[8],8:[6,9],9:[]}
+ InferenceGraphNode<Integer>[] nodes = new InferenceGraphNode[9];
+ for (int i = 0; i < nodes.length; i++) {
+ nodes[i] = new InferenceGraphNode<Integer>(i + 1);
+ }
+
+ nodes[0].getDependencies().add(nodes[1]);
+
+ nodes[1].getDependencies().add(nodes[0]);
+ nodes[1].getDependencies().add(nodes[4]);
+
+ nodes[2].getDependencies().add(nodes[3]);
+
+ nodes[3].getDependencies().add(nodes[2]);
+ nodes[3].getDependencies().add(nodes[4]);
+
+ nodes[4].getDependencies().add(nodes[5]);
+
+ nodes[5].getDependencies().add(nodes[6]);
+
+ nodes[6].getDependencies().add(nodes[7]);
+
+ nodes[7].getDependencies().add(nodes[5]);
+ nodes[7].getDependencies().add(nodes[8]);
+
+ final List<List<InferenceGraphNode<Integer>>> tarjan = InferenceGraphNode.tarjan(Arrays.asList(nodes));
+ final String messages = StringUtil.join(tarjan, new Function<List<InferenceGraphNode<Integer>>, String>() {
+ @Override
+ public String fun(List<InferenceGraphNode<Integer>> nodes) {
+ return StringUtil.join(nodes, new Function<InferenceGraphNode<Integer>, String>() {
+ @Override
+ public String fun(InferenceGraphNode<Integer> node) {
+ return String.valueOf(node.getValue());
+ }
+ }, ",");
+ }
+ }, "\n");
+
+ Assert.assertEquals("9\n" +
+ "8,7,6\n" +
+ "5\n" +
+ "2,1\n" +
+ "4,3", messages);
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertFieldToLocalTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertFieldToLocalTest.java
new file mode 100644
index 0000000..d74b67f
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertFieldToLocalTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.quickFix;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.codeInspection.varScopeCanBeNarrowed.FieldCanBeLocalInspection;
+import org.jetbrains.annotations.NotNull;
+
+
+public class ConvertFieldToLocalTest extends LightQuickFixTestCase {
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ final FieldCanBeLocalInspection inspection = new FieldCanBeLocalInspection();
+ inspection.IGNORE_FIELDS_USED_IN_MULTIPLE_METHODS = false;
+ return new LocalInspectionTool[] { inspection };
+ }
+
+ public void test() throws Exception { doAllTests(); }
+
+ @Override
+ protected String getBasePath() {
+ return "/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local";
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
index f341e1d..4afe459 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
@@ -16,7 +16,7 @@
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.InspectionTool;
+import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection;
import com.intellij.psi.*;
@@ -32,8 +32,8 @@
final UncheckedWarningLocalInspection warningLocalInspection = new UncheckedWarningLocalInspection();
final RedundantSuppressInspection inspection = new RedundantSuppressInspection(){
@Override
- protected InspectionTool[] getInspectionTools(PsiElement psiElement, InspectionManager manager) {
- return new InspectionTool[]{
+ protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, @NotNull InspectionManager manager) {
+ return new InspectionToolWrapper[]{
new LocalInspectionToolWrapper(varargsInspection),
new LocalInspectionToolWrapper(warningLocalInspection)
};
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Suppress15InspectionsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Suppress15InspectionsTest.java
index 13ebabf..2ab3462 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Suppress15InspectionsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Suppress15InspectionsTest.java
@@ -1,4 +1,3 @@
-
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
@@ -19,7 +18,6 @@
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.accessStaticViaInstance.AccessStaticViaInstance;
import com.intellij.codeInspection.deprecation.DeprecationInspection;
-import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper;
import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection;
import com.intellij.codeInspection.sillyAssignment.SillyAssignmentInspection;
import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection;
@@ -33,7 +31,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- enableInspectionTool(new GlobalInspectionToolWrapper(new UnusedParametersInspection()));
+ enableInspectionTool(new UnusedParametersInspection());
}
@NotNull
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
index d3a7466..3ab71c0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
@@ -605,4 +605,15 @@
assert myFixture.editor.document.text.contains('List<Map.Entry<String, Integer>> result;')
}
+ public void "test name shadowing"() {
+ myFixture.configureByText "a.java", """class LiveTemplateVarSuggestion {
+ private Object value;
+ public void setValue(Object value, Object value1){
+ inn<caret>
+ }
+}"""
+ myFixture.type('\t')
+ assert myFixture.lookupElementStrings == ['value', 'value1']
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/ConcatenationToMessageFormatActionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/ConcatenationToMessageFormatActionTest.java
index 412104c..11f426a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/ConcatenationToMessageFormatActionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/ConcatenationToMessageFormatActionTest.java
@@ -3,36 +3,37 @@
*/
package com.intellij.codeInspection;
-import com.intellij.codeInsight.intention.impl.ConcatenationToMessageFormatAction;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiExpression;
+import com.intellij.psi.util.PsiConcatenationUtil;
import com.intellij.testFramework.LightIdeaTestCase;
import java.util.ArrayList;
public class ConcatenationToMessageFormatActionTest extends LightIdeaTestCase {
+
+ public void doTest(String expressionText, String messageFormatText, String... foundExpressionTexts) {
+ final PsiExpression expression = JavaPsiFacade.getElementFactory(getProject()).createExpressionFromText(expressionText, null);
+ final StringBuilder result = new StringBuilder();
+ final ArrayList<PsiExpression> args = new ArrayList<PsiExpression>();
+ PsiConcatenationUtil.buildFormatString(expression, result, args, false);
+ assertEquals(messageFormatText, result.toString());
+ assertEquals(foundExpressionTexts.length, args.size());
+ for (int i = 0; i < foundExpressionTexts.length; i++) {
+ final String foundExpressionText = foundExpressionTexts[i];
+ assertEquals(foundExpressionText, args.get(i).getText());
+ }
+ }
public void test1() throws Exception{
- final String text = "\"aaa 'bbb' '\" + ((java.lang.String)ccc) + \"'\"";
- final PsiExpression expression = JavaPsiFacade.getInstance(getProject()).getElementFactory().createExpressionFromText(
- text, null
- );
- final StringBuilder result = new StringBuilder();
- ConcatenationToMessageFormatAction.buildMessageFormatString(expression,
- result,
- new ArrayList<PsiExpression>());
- assertEquals("aaa ''bbb'' ''{0}''", result.toString());
+ doTest("\"aaa 'bbb' '\" + ((java.lang.String)ccc) + \"'\"", "aaa ''bbb'' ''{0}''", "ccc");
}
public void test2() throws Exception {
- final String text = "1 + 2 + 3 + \"{}'\" + '\\n' + ((java.lang.String)ccc)";
- final PsiExpression expression = JavaPsiFacade.getElementFactory(getProject()).createExpressionFromText(text, null);
- final StringBuilder result = new StringBuilder();
- final ArrayList<PsiExpression> args = new ArrayList<PsiExpression>();
- ConcatenationToMessageFormatAction.buildMessageFormatString(expression, result, args);
- assertEquals("{0}'{'}''\\n{1}", result.toString());
- assertEquals(2, args.size());
- assertEquals("1 + 2 + 3", args.get(0).getText());
- assertEquals("ccc", args.get(1).getText());
+ doTest("1 + 2 + 3 + \"{}'\" + '\\n' + ((java.lang.String)ccc)", "{0}'{}'''\\n{1}", "1 + 2 + 3", "ccc");
+ }
+
+ public void test3() throws Exception {
+ doTest("\"Test{A = \" + 1 + \", B = \" + 2 + \", C = \" + 3 + \"}\"", "Test'{'A = {0}, B = {1}, C = {2}'}'", "1", "2", "3");
}
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
index fc5824c..c156581 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
@@ -99,6 +99,7 @@
public void testReturningNullFromVoidMethod() throws Throwable { doTest(); }
public void testCatchRuntimeException() throws Throwable { doTest(); }
+ public void testCatchThrowable() throws Throwable { doTest(); }
public void testNotNullCatchParameter() { doTest(); }
public void testAssertFailInCatch() throws Throwable {
@@ -170,6 +171,8 @@
public void testEqualsHasNoSideEffects() { doTest(); }
+ public void testHonorGetterAnnotation() { doTest(); }
+
public void testIsNullCheck() throws Exception {
ConditionCheckManager.getInstance(myModule.getProject()).getIsNullCheckMethods().add(
buildConditionChecker("Value", "isNull", ConditionChecker.Type.IS_NULL_METHOD,
@@ -228,4 +231,11 @@
assert psiMethod != null;
return new ConditionChecker.FromPsiBuilder(psiMethod, psiMethod.getParameterList().getParameters()[0], type).build();
}
+
+ public void testIgnoreAssertions() {
+ final DataFlowInspection inspection = new DataFlowInspection();
+ inspection.IGNORE_ASSERT_STATEMENTS = true;
+ myFixture.enableInspections(inspection);
+ myFixture.testHighlighting(true, false, true, getTestName(false) + ".java");
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/GlobalInspectionContextTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/GlobalInspectionContextTest.java
index 872ae12..2cdf8a2 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/GlobalInspectionContextTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/GlobalInspectionContextTest.java
@@ -20,7 +20,9 @@
import com.intellij.codeInsight.CodeInsightTestCase;
import com.intellij.codeInspection.actions.RunInspectionIntention;
import com.intellij.codeInspection.ex.*;
+import com.intellij.codeInspection.ui.InspectionToolPresentation;
import com.intellij.codeInspection.visibility.VisibilityInspection;
+import com.intellij.psi.PsiFile;
import java.util.ArrayList;
import java.util.Arrays;
@@ -34,32 +36,36 @@
public void testProblemDuplication() throws Exception {
String shortName = new VisibilityInspection().getShortName();
InspectionProfileImpl profile = new InspectionProfileImpl("Foo");
- profile.disableAllTools();
- profile.enableTool(shortName);
+ profile.disableAllTools(getProject());
+ profile.enableTool(shortName, getProject());
GlobalInspectionContextImpl context = ((InspectionManagerEx)InspectionManager.getInstance(getProject())).createNewGlobalContext(false);
context.setExternalProfile(profile);
configureByFile("Foo.java");
AnalysisScope scope = new AnalysisScope(getFile());
- context.doInspections(scope, InspectionManager.getInstance(getProject()));
+ context.doInspections(scope);
Tools tools = context.getTools().get(shortName);
- GlobalInspectionToolWrapper tool = (GlobalInspectionToolWrapper)tools.getTool();
- assertEquals(1, tool.getProblemDescriptors().size());
+ GlobalInspectionToolWrapper toolWrapper = (GlobalInspectionToolWrapper)tools.getTool();
+ InspectionToolPresentation presentation = context.getPresentation(toolWrapper);
+ assertEquals(1, presentation.getProblemDescriptors().size());
- context.doInspections(scope, InspectionManager.getInstance(getProject()));
+ context.doInspections(scope);
tools = context.getTools().get(shortName);
- tool = (GlobalInspectionToolWrapper)tools.getTool();
- assertEquals(1, tool.getProblemDescriptors().size());
+ toolWrapper = (GlobalInspectionToolWrapper)tools.getTool();
+ presentation = context.getPresentation(toolWrapper);
+ assertEquals(1, presentation.getProblemDescriptors().size());
}
public void testRunInspectionContext() throws Exception {
InspectionProfile profile = new InspectionProfileImpl("foo");
- InspectionProfileEntry[] tools = profile.getInspectionTools(null);
- for (InspectionProfileEntry tool : tools) {
- if (!tool.isEnabledByDefault()) {
- GlobalInspectionContextImpl context = RunInspectionIntention.createContext(tool, (InspectionManagerEx)InspectionManager.getInstance(myProject), null);
+ InspectionToolWrapper[] tools = profile.getInspectionTools(null);
+ PsiFile file = createDummyFile("xx.txt", "xxx");
+ for (InspectionToolWrapper toolWrapper : tools) {
+ if (!toolWrapper.isEnabledByDefault()) {
+ InspectionManagerEx instance = (InspectionManagerEx)InspectionManager.getInstance(myProject);
+ GlobalInspectionContextImpl context = RunInspectionIntention.createContext(toolWrapper, instance, file);
context.initializeTools(new ArrayList<Tools>(), new ArrayList<Tools>(), new ArrayList<Tools>());
assertEquals(1, context.getTools().size());
return;
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java
index b6f20b9..ed2db87 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java
@@ -186,11 +186,10 @@
}
public void testLockProfile() throws Exception {
-
final List<InspectionToolWrapper> list = new ArrayList<InspectionToolWrapper>();
list.add(createTool("foo", true));
- InspectionToolRegistrar registrar = new InspectionToolRegistrar(null) {
+ InspectionToolRegistrar registrar = new InspectionToolRegistrar() {
@NotNull
@Override
public List<InspectionToolWrapper> createTools() {
@@ -200,10 +199,10 @@
InspectionProfileImpl profile = createProfile(registrar);
- List<ScopeToolState> tools = profile.getAllTools();
+ List<ScopeToolState> tools = profile.getAllTools(getProject());
assertEquals(1, tools.size());
assertTrue(profile.isToolEnabled(HighlightDisplayKey.find("foo")));
- assertTrue(profile.getToolDefaultState("foo").isEnabled());
+ assertTrue(profile.getToolDefaultState("foo", getProject()).isEnabled());
InspectionProfileImpl model = (InspectionProfileImpl)profile.getModifiableModel();
model.lockProfile(true);
@@ -226,15 +225,15 @@
profile = createProfile(registrar);
profile.readExternal(element);
- tools = profile.getAllTools();
+ tools = profile.getAllTools(getProject());
assertEquals(3, tools.size());
assertTrue(profile.isProfileLocked());
assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("bar")));
assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("disabled")));
- assertTrue(profile.getToolDefaultState("bar").isEnabled());
- assertFalse(profile.getToolDefaultState("disabled").isEnabled());
+ assertTrue(profile.getToolDefaultState("bar", getProject()).isEnabled());
+ assertFalse(profile.getToolDefaultState("disabled", getProject()).isEnabled());
assertEquals("<profile version=\"1.0\" is_locked=\"true\">\n" +
" <option name=\"myName\" value=\"Foo\" />\n" +
@@ -262,8 +261,8 @@
public void testGlobalInspectionContext() throws Exception {
InspectionProfileImpl profile = new InspectionProfileImpl("Foo");
- profile.disableAllTools();
- profile.enableTool(new UnusedDeclarationInspection().getShortName());
+ profile.disableAllTools(getProject());
+ profile.enableTool(new UnusedDeclarationInspection().getShortName(), getProject());
GlobalInspectionContextImpl context = ((InspectionManagerEx)InspectionManager.getInstance(getProject())).createNewGlobalContext(false);
context.setExternalProfile(profile);
@@ -285,7 +284,7 @@
model = foo.getModifiableModel();
assertEquals(0, countInitializedTools(model));
- List<ScopeToolState> tools = ((InspectionProfileImpl)model).getAllTools();
+ List<ScopeToolState> tools = ((InspectionProfileImpl)model).getAllTools(getProject());
for (ScopeToolState tool : tools) {
if (!tool.isEnabled()) {
tool.setEnabled(true);
@@ -299,23 +298,23 @@
InspectionProfileImpl profile = new InspectionProfileImpl("profile");
profile.setBaseProfile(InspectionProfileImpl.getDefaultProfile());
assertEquals(0, countInitializedTools(profile));
- InspectionProfileEntry[] tools = profile.getInspectionTools(null);
- assertTrue(tools.length > 0);
- InspectionProfileEntry tool = profile.getInspectionTool(new DataFlowInspection().getShortName());
- assertNotNull(tool);
- String id = tool.getShortName();
+ InspectionToolWrapper[] toolWrappers = profile.getInspectionTools(null);
+ assertTrue(toolWrappers.length > 0);
+ InspectionToolWrapper toolWrapper = profile.getInspectionTool(new DataFlowInspection().getShortName(), getProject());
+ assertNotNull(toolWrapper);
+ String id = toolWrapper.getShortName();
System.out.println(id);
if (profile.isToolEnabled(HighlightDisplayKey.findById(id))) {
- profile.disableTool(id);
+ profile.disableTool(id, getProject());
}
else {
- profile.enableTool(id);
+ profile.enableTool(id, getProject());
}
assertEquals(0, countInitializedTools(profile));
profile.writeExternal(new Element("profile"));
- List<InspectionProfileEntry> initializedTools = getInitializedTools(profile);
+ List<InspectionToolWrapper> initializedTools = getInitializedTools(profile);
if (initializedTools.size() != 1) {
- for (InspectionProfileEntry initializedTool : initializedTools) {
+ for (InspectionToolWrapper initializedTool : initializedTools) {
System.out.println(initializedTool.getShortName());
}
fail();
@@ -340,14 +339,14 @@
return getInitializedTools(foo).size();
}
- public static List<InspectionProfileEntry> getInitializedTools(Profile foo) {
- List<InspectionProfileEntry> initialized = new ArrayList<InspectionProfileEntry>();
- List<ScopeToolState> tools = ((InspectionProfileImpl)foo).getAllTools();
+ @NotNull
+ public static List<InspectionToolWrapper> getInitializedTools(@NotNull Profile foo) {
+ List<InspectionToolWrapper> initialized = new ArrayList<InspectionToolWrapper>();
+ List<ScopeToolState> tools = ((InspectionProfileImpl)foo).getAllTools(getProject());
for (ScopeToolState tool : tools) {
- InspectionProfileEntry entry = tool.getTool();
- assertTrue(entry instanceof InspectionToolWrapper);
- if (entry.isInitialized()) {
- initialized.add(entry);
+ InspectionToolWrapper toolWrapper = tool.getTool();
+ if (toolWrapper.isInitialized()) {
+ initialized.add(toolWrapper);
}
}
return initialized;
@@ -360,11 +359,11 @@
foo.groupDisplayName = s;
foo.level = "ERROR";
foo.enabledByDefault = enabled;
- foo.implementationClass = "com.intellij.codeInspection.InspectionProfileTest$TestTool";
+ foo.implementationClass = TestTool.class.getName();
return new LocalInspectionToolWrapper(foo);
}
- @SuppressWarnings({"UnusedDeclaration", "InspectionDescriptionNotFoundInspection"})
+ @SuppressWarnings("InspectionDescriptionNotFoundInspection")
public static class TestTool extends LocalInspectionTool {
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantCast15Test.java b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantCast15Test.java
index 15a238a..a20b8d0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantCast15Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantCast15Test.java
@@ -46,6 +46,7 @@
public void testIDEA22899() throws Exception { doTest();}
public void testRawCast1() throws Exception { doTest();}
public void testInferenceFromCast() throws Exception { doTest();}
+ public void testGetClassProcessing() throws Exception { doTest();}
public void testTypeParameterAccessChecksJava7() throws Exception {
((JavaVersionServiceImpl)JavaVersionService.getInstance()).setTestVersion(JavaSdkVersion.JDK_1_7, getTestRootDisposable());
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantSuppressTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantSuppressTest.java
index 9be168c..1d00526 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantSuppressTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantSuppressTest.java
@@ -5,22 +5,23 @@
import com.intellij.codeInspection.i18n.I18nInspection;
import com.intellij.psi.PsiElement;
import com.intellij.testFramework.InspectionTestCase;
+import org.jetbrains.annotations.NotNull;
public class RedundantSuppressTest extends InspectionTestCase {
private GlobalInspectionToolWrapper myWrapper;
- private InspectionTool[] myInspectionTools;
+ private InspectionToolWrapper[] myInspectionToolWrappers;
@Override
protected void setUp() throws Exception {
super.setUp();
InspectionToolRegistrar.getInstance().ensureInitialized();
- myInspectionTools = new InspectionTool[]{new LocalInspectionToolWrapper(new I18nInspection()),
+ myInspectionToolWrappers = new InspectionToolWrapper[]{new LocalInspectionToolWrapper(new I18nInspection()),
new GlobalInspectionToolWrapper(new EmptyMethodInspection())};
myWrapper = new GlobalInspectionToolWrapper(new RedundantSuppressInspection() {
@Override
- protected InspectionTool[] getInspectionTools(PsiElement psiElement, InspectionManager manager) {
- return myInspectionTools;
+ protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, @NotNull InspectionManager manager) {
+ return myInspectionToolWrappers;
}
});
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/SingleInspectionProfilePanelTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/SingleInspectionProfilePanelTest.java
index ab3a853..255358b 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/SingleInspectionProfilePanelTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/SingleInspectionProfilePanelTest.java
@@ -103,7 +103,7 @@
}
private JavaDocLocalInspection getInspection(InspectionProfileImpl profile) {
- LocalInspectionToolWrapper original = (LocalInspectionToolWrapper)profile.getInspectionTool(myInspection.getShortName());
+ LocalInspectionToolWrapper original = (LocalInspectionToolWrapper)profile.getInspectionTool(myInspection.getShortName(), getProject());
assert original != null;
return (JavaDocLocalInspection)original.getTool();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/UnusedDeclarationTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/UnusedDeclarationTest.java
index a9a1e4e..10604a1 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/UnusedDeclarationTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/UnusedDeclarationTest.java
@@ -18,6 +18,7 @@
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.ex.EntryPointsManagerImpl;
+import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.InspectionTestCase;
@@ -40,7 +41,7 @@
}
private void doTest() {
- doTest("deadCode/" + getTestName(true), myTool);
+ doTest("deadCode/" + getTestName(true), new GlobalInspectionToolWrapper(myTool));
}
public void testSCR6067() {
@@ -151,7 +152,7 @@
public void testJunitAbstractClassWithoutInheritor() {
doTest();
}
-
+
public void testJunitEntryPointCustomRunWith() {
doTest();
}
diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
index 36fcc43..65092f2 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
@@ -210,7 +210,7 @@
List<UsageInfo> usages = findUsages(findModel);
assertEquals(2, usages.size());
- if (!(usages.get(0).getElement().getContainingFile() instanceof PsiJavaFile)) {
+ if (!(usages.get(0).getFile() instanceof PsiJavaFile)) {
Collections.swap(usages, 0, 1);
}
PsiElement element = usages.get(0).getElement();
diff --git a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy
new file mode 100644
index 0000000..0e82ee3
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy
@@ -0,0 +1,185 @@
+package com.intellij.navigation
+import com.intellij.ide.util.gotoByName.ChooseByNameBase
+import com.intellij.ide.util.gotoByName.ChooseByNameModel
+import com.intellij.ide.util.gotoByName.ChooseByNamePopup
+import com.intellij.ide.util.gotoByName.GotoClassModel2
+import com.intellij.ide.util.gotoByName.GotoFileModel
+import com.intellij.ide.util.gotoByName.GotoSymbolModel2
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.application.ModalityState
+import com.intellij.openapi.util.Disposer
+import com.intellij.psi.PsiElement
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
+import com.intellij.util.Consumer
+import com.intellij.util.concurrency.Semaphore
+/**
+ * @author peter
+ */
+class ChooseByNameTest extends LightCodeInsightFixtureTestCase {
+ ChooseByNamePopup myPopup
+
+ @Override
+ protected void tearDown() throws Exception {
+ myPopup = null
+ super.tearDown()
+ }
+
+ public void "test goto class order by matching degree"() {
+ def startMatch = myFixture.addClass("class UiUtil {}")
+ def wordSkipMatch = myFixture.addClass("class UiAbstractUtil {}")
+ def camelMatch = myFixture.addClass("class UberInstructionUxTopicInterface {}")
+ def middleMatch = myFixture.addClass("class BaseUiUtil {}")
+ def elements = getPopupElements(new GotoClassModel2(project), "uiuti")
+ assert elements == [startMatch, wordSkipMatch, camelMatch, ChooseByNameBase.NON_PREFIX_SEPARATOR, middleMatch]
+ }
+
+ public void "test annotation syntax"() {
+ def match = myFixture.addClass("@interface Anno1 {}")
+ myFixture.addClass("class Anno2 {}")
+ def elements = getPopupElements(new GotoClassModel2(project), "@Anno")
+ assert elements == [match]
+ }
+
+ public void "test no result for empty patterns"() {
+ myFixture.addClass("@interface Anno1 {}")
+ myFixture.addClass("class Anno2 {}")
+
+ def popup = createPopup(new GotoClassModel2(project))
+ assert getPopupElements(popup, "") == []
+ popup.close(false)
+
+ popup = createPopup(new GotoClassModel2(project))
+ assert getPopupElements(popup, "@") == []
+ popup.close(false)
+
+ popup = createPopup(new GotoFileModel(project))
+ assert getPopupElements(popup, "foo/") == []
+ popup.close(false)
+ }
+
+ public void "test filter overridden methods from goto symbol"() {
+ def intf = myFixture.addClass("""
+class Intf {
+ void xxx1() {}
+ void xxx2() {}
+}""")
+ def impl = myFixture.addClass("""
+class Impl extends Intf {
+ void xxx1() {}
+ void xxx3() {}
+}
+""")
+
+ def elements = getPopupElements(new GotoSymbolModel2(project), "xxx")
+
+ assert intf.findMethodsByName('xxx1', false)[0] in elements
+ assert intf.findMethodsByName('xxx2', false)[0] in elements
+
+ assert impl.findMethodsByName('xxx3', false)[0] in elements
+ assert !(impl.findMethodsByName('xxx1', false)[0] in elements)
+ }
+
+ public void "test disprefer underscore"() {
+ def intf = myFixture.addClass("""
+class Intf {
+ void _xxx1() {}
+ void xxx2() {}
+}""")
+
+ def elements = getPopupElements(new GotoSymbolModel2(project), "xxx")
+ assert elements == [intf.findMethodsByName('xxx2', false), ChooseByNameBase.NON_PREFIX_SEPARATOR, intf.findMethodsByName('_xxx1', false)]
+ }
+
+ public void "test prefer exact extension matches"() {
+ def m = myFixture.addFileToProject("relaunch.m", "")
+ def mod = myFixture.addFileToProject("reference.mod", "")
+ def elements = getPopupElements(new GotoFileModel(project), "re*.m")
+ assert elements == [m, mod]
+ }
+
+ public void "test prefer better path matches"() {
+ def fooIndex = myFixture.addFileToProject("foo/index.html", "foo")
+ def fooBarIndex = myFixture.addFileToProject("foo/bar/index.html", "foo bar")
+ def barFooIndex = myFixture.addFileToProject("bar/foo/index.html", "bar foo")
+ def elements = getPopupElements(new GotoFileModel(project), "foo/index")
+ assert elements == [fooIndex, barFooIndex, fooBarIndex]
+ }
+
+ public void "test sort same-named items by path"() {
+ def files = (30..10).collect { i -> myFixture.addFileToProject("foo$i/index.html", "foo$i") }.reverse()
+ def elements = getPopupElements(new GotoFileModel(project), "index")
+ assert elements == files
+ }
+
+ public void "test middle matching for directories"() {
+ def fooIndex = myFixture.addFileToProject("foo/index.html", "foo")
+ def ooIndex = myFixture.addFileToProject("oo/index.html", "oo")
+ def fooBarIndex = myFixture.addFileToProject("foo/bar/index.html", "foo bar")
+ def elements = getPopupElements(new GotoFileModel(project), "oo/index")
+ assert elements == [ooIndex, fooIndex, fooBarIndex]
+ }
+
+ public void "test prefer files from current directory"() {
+ def fooIndex = myFixture.addFileToProject("foo/index.html", "foo")
+ def barIndex = myFixture.addFileToProject("bar/index.html", "bar")
+ def fooContext = myFixture.addFileToProject("foo/context.html", "")
+ def barContext = myFixture.addFileToProject("bar/context.html", "")
+
+ def popup = createPopup(new GotoFileModel(project), fooContext)
+ assert getPopupElements(popup, "index") == [fooIndex, barIndex]
+ popup.close(false)
+
+ popup = createPopup(new GotoFileModel(project), barContext)
+ assert getPopupElements(popup, "index") == [barIndex, fooIndex]
+
+ }
+
+ public void "test find method by qualified name"() {
+ def method = myFixture.addClass("package foo.bar; class Goo { void zzzZzz() {} }").methods[0]
+ assert getPopupElements(new GotoSymbolModel2(project), 'zzzZzz') == [method]
+ assert getPopupElements(new GotoSymbolModel2(project), 'goo.zzzZzz') == [method]
+ assert getPopupElements(new GotoSymbolModel2(project), 'foo.bar.goo.zzzZzz') == [method]
+ assert getPopupElements(new GotoSymbolModel2(project), 'foo.zzzZzz') == [method]
+ assert getPopupElements(new GotoSymbolModel2(project), 'bar.zzzZzz') == [method]
+ assert getPopupElements(new GotoSymbolModel2(project), 'bar.goo.zzzZzz') == [method]
+ }
+
+ private List<Object> getPopupElements(ChooseByNameModel model, String text) {
+ return getPopupElements(createPopup(model), text)
+ }
+
+ private static ArrayList<String> getPopupElements(ChooseByNamePopup popup, String text) {
+ List<Object> elements = ['empty']
+ def semaphore = new Semaphore()
+ semaphore.down()
+ popup.scheduleCalcElements(text, false, false, ModalityState.NON_MODAL, { set ->
+ elements = set as List
+ semaphore.up()
+ } as Consumer<Set<?>>)
+ if (!semaphore.waitFor(1000)) {
+ printThreadDump()
+ fail()
+ }
+ return elements
+ }
+
+ private ChooseByNamePopup createPopup(ChooseByNameModel model, PsiElement context = null) {
+ if (myPopup) {
+ myPopup.close(false)
+ }
+
+ def popup = myPopup = ChooseByNamePopup.createPopup(project, model, (PsiElement)context, "")
+ Disposer.register(testRootDisposable, { popup.close(false) } as Disposable)
+ popup
+ }
+
+ @Override
+ protected boolean runInDispatchThread() {
+ return false
+ }
+
+ @Override
+ protected void invokeTestRunnable(Runnable runnable) throws Exception {
+ runnable.run()
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/navigation/GotoImplementationHandlerTest.java b/java/java-tests/testSrc/com/intellij/navigation/GotoImplementationHandlerTest.java
index 161859e..bf9f09f 100644
--- a/java/java-tests/testSrc/com/intellij/navigation/GotoImplementationHandlerTest.java
+++ b/java/java-tests/testSrc/com/intellij/navigation/GotoImplementationHandlerTest.java
@@ -121,4 +121,32 @@
assertNotNull(aClass);
assertEquals(aClass.getName(), "X");
}
+
+ public void testImplicitInheritance() throws Throwable {
+ PsiFile file = myFixture.addFileToProject("Foo.java", "interface PackContainer {\n" +
+ " void foo();\n" +
+ "}\n" +
+ "interface PsiPackage extends PackContainer {}\n" +
+ "class PsiPackageBase implements PackContainer {\n" +
+ " public void foo() {}\n" +
+ "}\n" +
+ "class PsiPackageImpl extends PsiPackageBase implements PsiPackage {}\n" +
+ "\n" +
+ "class Foo {\n" +
+ " class Bar {\n" +
+ " void bar(PsiPackage i) {\n" +
+ " i.fo<caret>o();\n" +
+ " }\n" +
+ " }\n" +
+ "}");
+ myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
+
+ final PsiElement[] impls = new GotoImplementationHandler().getSourceAndTargetElements(myFixture.getEditor(), file).targets;
+ assertEquals(1, impls.length);
+ final PsiElement meth = impls[0];
+ assertTrue(meth instanceof PsiMethod);
+ final PsiClass aClass = ((PsiMethod)meth).getContainingClass();
+ assertNotNull(aClass);
+ assertEquals(aClass.getName(), "PsiPackageBase");
+ }
}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/projectView/FileStructureDialogTest.java b/java/java-tests/testSrc/com/intellij/projectView/FileStructureDialogTest.java
index eab9203..f460748 100644
--- a/java/java-tests/testSrc/com/intellij/projectView/FileStructureDialogTest.java
+++ b/java/java-tests/testSrc/com/intellij/projectView/FileStructureDialogTest.java
@@ -43,7 +43,7 @@
final StructureViewBuilder structureViewBuilder =
StructureViewBuilder.PROVIDER.getStructureViewBuilder(virtualFile.getFileType(), virtualFile, myProject);
assertNotNull(structureViewBuilder);
- final StructureViewModel structureViewModel = ((TreeBasedStructureViewBuilder)structureViewBuilder).createStructureViewModel();
+ final StructureViewModel structureViewModel = ((TreeBasedStructureViewBuilder)structureViewBuilder).createStructureViewModel(null);
final EditorFactory factory = EditorFactory.getInstance();
assertNotNull(factory);
diff --git a/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java b/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java
new file mode 100644
index 0000000..c23078e
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2004 JetBrains s.r.o. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * -Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduct the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of JetBrains or IntelliJ IDEA
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. JETBRAINS AND ITS LICENSORS SHALL NOT
+ * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
+ * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL JETBRAINS OR ITS LICENSORS BE LIABLE FOR ANY LOST
+ * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
+ * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
+ * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
+ * IF JETBRAINS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+package com.intellij.projectView;
+
+import com.intellij.ide.projectView.PresentationData;
+import com.intellij.ide.projectView.TreeStructureProvider;
+import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane;
+import com.intellij.ide.projectView.impl.ClassesTreeStructureProvider;
+import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.ide.util.treeView.NodeDescriptor;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.refactoring.rename.RenameProcessor;
+import com.intellij.testFramework.PlatformTestUtil;
+import com.intellij.uiDesigner.projectView.FormMergerTreeStructureProvider;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ui.tree.TreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+
+@SuppressWarnings({"HardCodedStringLiteral"})
+public class ProjectViewUpdatingTest extends BaseProjectViewTestCase {
+ public void testStandardProviders() throws Exception{
+ PsiFile element = JavaDirectoryService.getInstance().getClasses(getPackageDirectory())[0].getContainingFile();
+ final AbstractProjectViewPSIPane pane = myStructure.createPane();
+ getProjectTreeStructure().setProviders();
+ pane.select(element, element.getContainingFile().getVirtualFile(), true);
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
+ " -PsiDirectory: standardProviders\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " Class1.java\n" +
+ " Class2.java\n" +
+ " Class4.java\n" +
+ " Form1.form\n" +
+ " Form1.java\n" +
+ " Form2.form\n" +
+ getRootFiles() +
+ " +External Libraries\n"
+ );
+ final PsiClass[] classes = JavaDirectoryService.getInstance()
+ .getPackage(getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1")).getClasses();
+ sortClassesByName(classes);
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ public void run() {
+ classes[0].delete();
+ }
+ });
+
+
+ PlatformTestUtil.waitForAlarm(600);
+
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
+ " -PsiDirectory: standardProviders\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " Class2.java\n" +
+ " Class4.java\n" +
+ " Form1.form\n" +
+ " Form1.java\n" +
+ " Form2.form\n" +
+ getRootFiles() +
+ " +External Libraries\n");
+
+ }
+
+ public void testUpdateProjectView() throws Exception {
+ getProjectTreeStructure().setProviders(new ClassesTreeStructureProvider(myProject), new FormMergerTreeStructureProvider(myProject));
+
+ final AbstractProjectViewPSIPane pane = myStructure.createPane();
+ final JTree tree = pane.getTree();
+ PlatformTestUtil.assertTreeEqual(tree, "-Project\n" +
+ " +PsiDirectory: updateProjectView\n" +
+ getRootFiles() +
+ " +External Libraries\n");
+
+ final PsiJavaFile classFile = (PsiJavaFile)getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1").findFile("Form1.java");
+ final PsiClass aClass = classFile.getClasses()[0];
+ final PsiFile containingFile = aClass.getContainingFile();
+ pane.select(aClass, containingFile.getVirtualFile(), true);
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
+ " -PsiDirectory: updateProjectView\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " Class1\n" +
+ " +Class2.java\n" +
+ " Class4.java\n" +
+ " Form2.form\n" +
+ " -Form:Form1\n" +
+ " [Form1]\n" +
+ " Form1.form\n" +
+ getRootFiles() +
+ " +External Libraries\n", true);
+
+ CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+ @Override
+ public void run() {
+ new RenameProcessor(myProject, aClass, "Form1_renamed", false, false).run();
+ }
+ }, null, null);
+
+ PlatformTestUtil.waitForAlarm(600);
+ PlatformTestUtil.assertTreeEqual(tree, "-Project\n" +
+ " -PsiDirectory: updateProjectView\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " Class1\n" +
+ " +Class2.java\n" +
+ " Class4.java\n" +
+ " Form2.form\n" +
+ " -Form:Form1_renamed\n" +
+ " Form1.form\n" +
+ " [Form1_renamed]\n" +
+ getRootFiles() +
+ " +External Libraries\n", true);
+
+ TreeUtil.collapseAll(pane.getTree(), -1);
+ PlatformTestUtil.assertTreeEqual(tree, "-Project\n" +
+ " +PsiDirectory: updateProjectView\n" +
+ getRootFiles() +
+ " +External Libraries\n");
+
+ final PsiClass aClass2 = JavaDirectoryService.getInstance()
+ .createClass(getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1"), "Class6");
+ PlatformTestUtil.waitForAlarm(600);
+ final PsiFile containingFile2 = aClass2.getContainingFile();
+ pane.select(aClass2, containingFile2.getVirtualFile(), true);
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
+ " -PsiDirectory: updateProjectView\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " Class1\n" +
+ " +Class2.java\n" +
+ " Class4.java\n" +
+ " [Class6]\n" +
+ " Form2.form\n" +
+ " +Form:Form1_renamed\n" +
+ getRootFiles() +
+ " +External Libraries\n", true);
+ }
+
+ public void testShowClassMembers() throws Exception{
+
+ getProjectTreeStructure().setProviders(new ClassesTreeStructureProvider(myProject), new FormMergerTreeStructureProvider(myProject));
+
+ final AbstractProjectViewPSIPane pane = myStructure.createPane();
+ final JTree tree = pane.getTree();
+ PlatformTestUtil.assertTreeEqual(tree, "-Project\n" +
+ " +PsiDirectory: showClassMembers\n" +
+ getRootFiles() +
+ " +External Libraries\n");
+
+ myStructure.setShowMembers(true);
+
+ PsiJavaFile classFile = (PsiJavaFile)getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1").findFile("Class1.java");
+ PsiClass aClass = classFile.getClasses()[0];
+ PsiFile containingFile = aClass.getContainingFile();
+ pane.select(aClass, containingFile.getVirtualFile(), true);
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
+ " -PsiDirectory: showClassMembers\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " -[Class1]\n" +
+ " +InnerClass\n" +
+ " getValue():int\n" +
+ " myField1:boolean\n" +
+ " myField2:boolean\n" +
+ " +Class2\n" +
+ getRootFiles() +
+ " +External Libraries\n", true);
+
+
+ final Document document = FileDocumentManager.getInstance().getDocument(containingFile.getVirtualFile());
+ final int caretPosition = document.getText().indexOf("public class InnerClass") - 1;
+
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ public void run() {
+ CommandProcessor.getInstance().executeCommand(myProject,
+ new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(caretPosition, "\n");
+ }
+ },
+ "typing",
+ null);
+ }
+ });
+
+
+ PsiDocumentManager.getInstance(myProject).commitDocument(document);
+ PlatformTestUtil.waitForAlarm(600);
+
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
+ " -PsiDirectory: showClassMembers\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " -[Class1]\n" +
+ " +InnerClass\n" +
+ " getValue():int\n" +
+ " myField1:boolean\n" +
+ " myField2:boolean\n" +
+ " +Class2\n" +
+ getRootFiles() +
+ " +External Libraries\n", true);
+
+ classFile = (PsiJavaFile)getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1").findFile("Class1.java");
+ aClass = classFile.getClasses()[0];
+ final PsiField lastField = aClass.getFields()[1];
+ pane.select(lastField, containingFile.getVirtualFile(), true);
+
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
+ " -PsiDirectory: showClassMembers\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " -Class1\n" +
+ " +InnerClass\n" +
+ " getValue():int\n" +
+ " myField1:boolean\n" +
+ " [myField2:boolean]\n" +
+ " +Class2\n" +
+ getRootFiles() +
+ " +External Libraries\n", true);
+
+ CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ assertEquals("myField2", lastField.getName());
+ lastField.setName("_firstField");
+ }
+ catch (IncorrectOperationException e) {
+ fail(e.getMessage());
+ }
+ }
+ });
+ }
+ }, null, null);
+
+ PlatformTestUtil.waitForAlarm(600);
+
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" +
+ " -PsiDirectory: showClassMembers\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: com\n" +
+ " -PsiDirectory: package1\n" +
+ " -Class1\n" +
+ " +InnerClass\n" +
+ " getValue():int\n" +
+ " [_firstField:boolean]\n" +
+ " myField1:boolean\n" +
+ " +Class2\n" +
+ getRootFiles() +
+ " +External Libraries\n", true);
+ }
+
+ public void testAnnoyingScrolling() throws Exception{
+
+ getProjectTreeStructure().setProviders(new ClassesTreeStructureProvider(myProject));
+
+ final AbstractProjectViewPSIPane pane = myStructure.createPane();
+ final JTree tree = pane.getTree();
+
+ myStructure.setShowMembers(true);
+
+ PsiJavaFile classFile = (PsiJavaFile)getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1").findFile("Class1.java");
+ PsiClass aClass = classFile.getClasses()[0];
+ PsiFile containingFile = aClass.getContainingFile();
+ PsiDirectory directory = containingFile.getContainingDirectory();
+ pane.select(aClass, containingFile.getVirtualFile(), true);
+ Point viewPosition = ((JViewport)tree.getParent()).getViewPosition();
+ for (int i=0;i<100;i++) {
+ JavaDirectoryService.getInstance().createClass(directory, "A" + i);
+ }
+ PlatformTestUtil.waitForAlarm(600);
+ Point viewPositionAfter = ((JViewport)tree.getParent()).getViewPosition();
+ assertEquals(viewPosition, viewPositionAfter);
+
+ }
+
+ class NodeWrapper extends AbstractTreeNode<Object> {
+ String myName;
+ List<NodeWrapper> myChildren = new ArrayList<NodeWrapper>();
+
+ public NodeWrapper(final Project project, final String value) {
+ super(project, new Object());
+ myName = value;
+ }
+
+ @Override
+ @NotNull
+ public Collection<? extends AbstractTreeNode> getChildren() {
+ return myChildren;
+ }
+
+ @Override
+ protected void update(final PresentationData presentation) {
+ presentation.setPresentableText(myName);
+ }
+
+ public void addChild(final NodeWrapper nodeWrapper) {
+ myChildren.add(nodeWrapper);
+ }
+
+ public void setName(final String s) {
+ myName = s;
+ }
+ }
+
+ public void testUpdatingAfterRename() throws Exception{
+
+ final NodeWrapper rootWrapper = new NodeWrapper(myProject, "1");
+
+ final NodeWrapper wr11 = new NodeWrapper(myProject, "1.1");
+ final NodeWrapper wr12 = new NodeWrapper(myProject, "1.2");
+ final NodeWrapper wr13 = new NodeWrapper(myProject, "1.3");
+ final NodeWrapper wr111 = new NodeWrapper(myProject, "1.1.1");
+ final NodeWrapper wr112 = new NodeWrapper(myProject, "1.1.2");
+ final NodeWrapper wr113 = new NodeWrapper(myProject, "1.1.3");
+ final NodeWrapper wr121 = new NodeWrapper(myProject, "1.2.1");
+ final NodeWrapper wr122 = new NodeWrapper(myProject, "1.2.2");
+ final NodeWrapper wr123 = new NodeWrapper(myProject, "1.2.3");
+ final NodeWrapper wr131 = new NodeWrapper(myProject, "1.3.1");
+ final NodeWrapper wr132 = new NodeWrapper(myProject, "1.3.2");
+ final NodeWrapper wr133 = new NodeWrapper(myProject, "1.3.3");
+
+ rootWrapper.addChild(wr11);
+ rootWrapper.addChild(wr12);
+ rootWrapper.addChild(wr13);
+
+ wr11.addChild(wr111);
+ wr11.addChild(wr112);
+ wr11.addChild(wr113);
+
+ wr12.addChild(wr121);
+ wr12.addChild(wr122);
+ wr12.addChild(wr123);
+
+ wr13.addChild(wr131);
+ wr13.addChild(wr132);
+ wr13.addChild(wr133);
+
+
+ getProjectTreeStructure().setProviders(createWrapProvider(rootWrapper));
+
+ final AbstractProjectViewPSIPane pane = myStructure.createPane();
+
+ final JTree tree = pane.getTree();
+
+ pane.getTreeBuilder().setNodeDescriptorComparator(new Comparator<NodeDescriptor>() {
+ @Override
+ public int compare(final NodeDescriptor o1, final NodeDescriptor o2) {
+ if (o1 instanceof NodeWrapper && o2 instanceof NodeWrapper) {
+ return ((NodeWrapper)o1).getName().compareTo(((NodeWrapper)o2).getName());
+ }
+ else {
+ return 0;
+ }
+ }
+ });
+
+ tree.expandRow(2);
+ TreeUtil.selectPath(tree, tree.getPathForRow(4));
+
+ PlatformTestUtil.assertTreeEqual(tree, "-Project\n" +
+ " -1\n" +
+ " +1.1\n" +
+ " -1.2\n" +
+ " 1.2.1\n" +
+ " [1.2.2]\n" +
+ " 1.2.3\n" +
+ " +1.3\n", true);
+
+ wr12.setName("01.2");
+ wr122.setName("01.2.2");
+
+ pane.getTreeBuilder().updateFromRoot();
+
+ PlatformTestUtil.assertTreeEqual(tree, "-Project\n" +
+ " -1\n" +
+ " -01.2\n" +
+ " [01.2.2]\n" +
+ " 1.2.1\n" +
+ " 1.2.3\n" +
+ " +1.1\n" +
+ " +1.3\n", true);
+
+
+ }
+
+ private TreeStructureProvider createWrapProvider(final NodeWrapper rootWrapper) {
+ return new TreeStructureProvider() {
+ @Override
+ public Collection<AbstractTreeNode> modify(AbstractTreeNode parent, Collection<AbstractTreeNode> children, ViewSettings settings) {
+
+ if (parent instanceof NodeWrapper) {
+ return children;
+ }
+ List<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>();
+ result.add(rootWrapper);
+ return result;
+ }
+
+ @Override
+ @Nullable
+ public Object getData(Collection<AbstractTreeNode> selected, String dataName) {
+ return null;
+ }
+ };
+ }
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
new file mode 100644
index 0000000..e972b4f
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
@@ -0,0 +1,245 @@
+package com.intellij.psi;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.roots.LanguageLevelProjectExtension;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.java.LanguageLevel;
+import com.intellij.psi.impl.source.tree.LazyParseableElement;
+import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.PsiTestCase;
+import com.intellij.testFramework.PsiTestUtil;
+
+@PlatformTestCase.WrapInCommand
+public class MiscPsiTest extends PsiTestCase{
+ private VirtualFile myRoot;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ myRoot = PsiTestUtil.createTestProjectStructure(myProject, myModule, myFilesToDelete);
+ }
+
+ public void testCopyTextFile() throws Exception{
+ VirtualFile vFile = myRoot.createChildData(null, "Test.txt");
+ final String text = "1234567890";
+ vFile.setBinaryContent(text.getBytes());
+
+ VirtualFile vDir = myRoot.createChildDirectory(null, "dir");
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ PsiFile file = myPsiManager.findFile(vFile);
+ assertTrue(file instanceof PsiPlainTextFile);
+ PsiDirectory dir = myPsiManager.findDirectory(vDir);
+ PsiFile fileCopy = (PsiFile)file.copy();
+ fileCopy = (PsiFile) fileCopy.setName("NewTest.txt");
+ PsiFile newFile = (PsiFile)dir.add(fileCopy);
+ assertTrue(newFile instanceof PsiPlainTextFile);
+
+ assertEquals(text, new String(newFile.getVirtualFile().contentsToByteArray()));
+ assertEquals(newFile.getVirtualFile().getModificationStamp(), newFile.getViewProvider().getModificationStamp());
+ Document document = PsiDocumentManager.getInstance(myProject).getDocument(newFile);
+ assertEquals(newFile.getVirtualFile().getModificationStamp(), document.getModificationStamp());
+ }
+
+ public void testCopyBinaryFile() throws Exception{
+ VirtualFile vFile = myRoot.createChildData(null, "Test.xxx");
+ final byte[] bytes = new byte[]{12,34,56,78,90,45,83,0x22,(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xee};
+ vFile.setBinaryContent(bytes);
+
+ VirtualFile vDir = myRoot.createChildDirectory(null, "dir");
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ PsiFile file = myPsiManager.findFile(vFile);
+ assertTrue(file instanceof PsiBinaryFile);
+ PsiDirectory dir = myPsiManager.findDirectory(vDir);
+ PsiFile fileCopy = (PsiFile)file.copy();
+ fileCopy = (PsiFile) fileCopy.setName("NewTest.xxx");
+ PsiFile newFile = (PsiFile)dir.add(fileCopy);
+ assertTrue(newFile instanceof PsiBinaryFile);
+
+ assertOrderedEquals(newFile.getVirtualFile().contentsToByteArray(), bytes);
+ }
+
+ public void testCopyBinaryToTextFile() throws Exception{
+ VirtualFile vFile = myRoot.createChildData(null, "Test.xxx");
+ String text = "1234567890";
+ vFile.setBinaryContent(text.getBytes());
+
+ VirtualFile vDir = myRoot.createChildDirectory(null, "dir");
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ PsiFile file = myPsiManager.findFile(vFile);
+ PsiDirectory dir = myPsiManager.findDirectory(vDir);
+ PsiFile fileCopy = (PsiFile)file.copy();
+ fileCopy = (PsiFile) fileCopy.setName("NewTest.txt");
+ PsiFile newFile = (PsiFile)dir.add(fileCopy);
+ assertTrue(newFile instanceof PsiPlainTextFile);
+
+ assertEquals(text, VfsUtil.loadText(newFile.getVirtualFile()));
+ assertEquals(newFile.getVirtualFile().getModificationStamp(), newFile.getViewProvider().getModificationStamp());
+ assertFalse(FileDocumentManager.getInstance().isFileModified(newFile.getVirtualFile()));
+ }
+
+ public void testSCR4212() throws Exception{
+ VirtualFile vFile = myRoot.createChildData(null, "Test.java");
+ String text = "class A{{ return(Object)new String(); }}";
+ VfsUtil.saveText(vFile, text);
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(vFile);
+ PsiClass aClass = file.getClasses()[0];
+ PsiClassInitializer initializer = aClass.getInitializers()[0];
+ PsiStatement statement = initializer.getBody().getStatements()[0];
+ PsiTypeCastExpression typeCast = (PsiTypeCastExpression)((PsiReturnStatement)statement).getReturnValue();
+ typeCast.replace(typeCast.getOperand());
+
+ String textAfter = file.getText();
+ String expectedText = "class A{{ return new String(); }}";
+ assertEquals(expectedText, textAfter);
+ }
+
+ public void testDeleteFieldInMultipleDeclarations() throws Exception {
+ final PsiClass aClass = getJavaFacade().getElementFactory().createClassFromText("public int i, j;", null);
+
+ final PsiField aField = aClass.getFields()[0];
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ public void run() {
+ aField.delete();
+ }
+ });
+
+ assertEquals("public int j;", aClass.getFields()[0].getText());
+ }
+
+ public void testSCR5929() throws Exception {
+ VirtualFile vFileA = myRoot.createChildData(null, "A.java");
+ String text = "class A{ /** @see a.B */ }";
+ VfsUtil.saveText(vFileA, text);
+
+ VirtualFile dir = myRoot.createChildDirectory(null, "a");
+ VirtualFile vFileB = dir.createChildData(null, "B.java");
+ text = "class B{}";
+ VfsUtil.saveText(vFileB, text);
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ PsiFile fileA = myPsiManager.findFile(vFileA);
+ PsiJavaFile fileACopy = (PsiJavaFile)fileA.copy();
+ PsiClass aClass = fileACopy.getClasses()[0];
+ aClass.setName("A2");
+ fileA.getContainingDirectory().add(fileACopy);
+ }
+
+ public void testCopyClass() throws Exception {
+ VirtualFile vFile = myRoot.createChildData(null, "A.java");
+ String text = "package aaa; class A{}";
+ VfsUtil.saveText(vFile, text);
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ PsiFile file = myPsiManager.findFile(vFile);
+ PsiJavaFile fileACopy = (PsiJavaFile)file.copy();
+ PsiClass aClass = fileACopy.getClasses()[0];
+ aClass.setName("ANew");
+ PsiFile newFile = (PsiFile)file.getContainingDirectory().add(fileACopy);
+ Document document = PsiDocumentManager.getInstance(myProject).getDocument(newFile);
+ FileDocumentManager.getInstance().saveDocument(document);
+ assertEquals(newFile.getVirtualFile().getModificationStamp(), newFile.getViewProvider().getModificationStamp());
+ assertFalse(FileDocumentManager.getInstance().isFileModified(newFile.getVirtualFile()));
+ }
+
+ public void testSCR15954() throws Exception {
+ PsiJavaFile file = (PsiJavaFile)createFile("A.java", "class A{\nA(){}\n}");
+
+ PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(myProject);
+ Document document = psiDocumentManager.getDocument(file);
+ document.insertString(document.getTextLength(), " "); // insert a trailing space to strip
+ psiDocumentManager.commitAllDocuments();
+
+ PsiClass aClass = file.getClasses()[0];
+ aClass.setName("B");
+ }
+
+ public void testDeleteAnnotationAttribute() throws Exception {
+ final PsiAnnotation annotation = getJavaFacade().getElementFactory().createAnnotationFromText("@A(b,c)", null);
+ final PsiNameValuePair secondAttribute = annotation.getParameterList().getAttributes()[1];
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ public void run() {
+ secondAttribute.delete();
+ }
+ });
+
+ assertEquals("@A(b )", annotation.getText());
+ }
+
+ public void testDeleteAnnotationArrayInitializerElement() throws Exception {
+ final PsiAnnotation annotation = getJavaFacade().getElementFactory().createAnnotationFromText("@A({b,c})", null);
+ final PsiNameValuePair firstAttribute = annotation.getParameterList().getAttributes()[0];
+ assertTrue(firstAttribute.getValue() instanceof PsiArrayInitializerMemberValue);
+ final PsiAnnotationMemberValue firstInitializer = ((PsiArrayInitializerMemberValue)firstAttribute.getValue()).getInitializers()[0];
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ public void run() {
+ firstInitializer.delete();
+ }
+ });
+
+ assertEquals("@A({ c})", annotation.getText());
+ }
+
+ public void testJavaLangObjectSuperMethod() throws Exception {
+ final PsiClass aClass =
+ getJavaFacade().getElementFactory().createClassFromText("public String toString() {return null;}", null);
+ final PsiMethod method = aClass.getMethods()[0];
+ final PsiMethod[] superMethods = method.findSuperMethods();
+ assertEquals(1, superMethods.length);
+ assertEquals(CommonClassNames.JAVA_LANG_OBJECT, superMethods[0].getContainingClass().getQualifiedName());
+ }
+
+ public void testImportOnDemand() throws Exception {
+ final PsiJavaFile file = (PsiJavaFile)PsiFileFactory.getInstance(getProject()).createFileFromText("D.java",
+ "import java.util.Map.Entry");
+ PsiImportStatement importStatement = file.getImportList().getImportStatements()[0];
+ assertTrue(!importStatement.isOnDemand());
+ }
+
+ public void testDocCommentPrecededByLineComment() throws Exception {
+ final PsiJavaFile file = (PsiJavaFile)PsiFileFactory.getInstance(getProject()).createFileFromText("D.java",
+ "////////////////////////////////////////\n" +
+ "/** */\n" +
+ "/////////////////////////////////////////////////\n" +
+ "class Usage {\n" +
+ "}");
+ final PsiClass psiClass = file.getClasses()[0];
+ assertNotNull(psiClass.getDocComment());
+ }
+
+ public void testTopLevelEnumIsNotStatic() throws Exception {
+ final JavaPsiFacade facade = getJavaFacade();
+ final LanguageLevel prevLanguageLevel = LanguageLevelProjectExtension.getInstance(facade.getProject()).getLanguageLevel();
+ LanguageLevelProjectExtension.getInstance(facade.getProject()).setLanguageLevel(LanguageLevel.JDK_1_5);
+ final PsiClass aClass;
+ try {
+ aClass = JavaPsiFacade.getInstance(getProject()).getElementFactory().createEnum("E");
+ }
+ finally {
+ LanguageLevelProjectExtension.getInstance(facade.getProject()).setLanguageLevel(prevLanguageLevel);
+ }
+ assertTrue(aClass.isEnum());
+ assertFalse(aClass.hasModifierProperty(PsiModifier.STATIC));
+ }
+
+ public void testDoNotExpandNestedChameleons() throws Exception {
+ PsiJavaFile file = (PsiJavaFile)createFile("a.java", "class A {{{}}}");
+ file.getNode();
+
+ PsiCodeBlock initializer = file.getClasses()[0].getInitializers()[0].getBody();
+ assertFalse(assertInstanceOf(initializer.getNode(), LazyParseableElement.class).isParsed());
+
+ PsiCodeBlock nestedBlock = ((PsiBlockStatement)initializer.getStatements()[0]).getCodeBlock();
+ assertTrue(assertInstanceOf(initializer.getNode(), LazyParseableElement.class).isParsed());
+ assertFalse(assertInstanceOf(nestedBlock.getNode(), LazyParseableElement.class).isParsed());
+ }
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java
index c1d20b4..a9c2b5f 100644
--- a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java
@@ -19,6 +19,7 @@
*/
package com.intellij.psi;
+import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
import com.intellij.codeInsight.daemon.impl.HighlightInfoFilter;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
@@ -27,6 +28,7 @@
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.search.GlobalSearchScope;
@@ -60,7 +62,7 @@
PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete);
}
- private PsiJavaFile myFile;
+ private volatile PsiJavaFile myFile;
private volatile boolean writeActionInProgress;
public void testStress() throws Exception {
int numOfThreads = 10;
@@ -85,13 +87,18 @@
public void run() {
for (int i = 0; i < readIterations; i++) {
if (myPsiManager == null) return;
- ApplicationManager.getApplication().runReadAction(new Runnable() {
+ ProgressManager.getInstance().runProcess(new Runnable() {
@Override
public void run() {
- assertFalse(writeActionInProgress);
- readStep(random);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(writeActionInProgress);
+ readStep(random);
+ }
+ });
}
- });
+ }, new DaemonProgressIndicator());
}
reads.countDown();
@@ -130,7 +137,7 @@
assertTrue(psiClass.isValid());
return psiClass;
}
-
+
private synchronized void writeStep(final Random random) throws IncorrectOperationException {
switch (random.nextInt(2)) {
case 0 :
@@ -177,7 +184,7 @@
final HighlightInfoHolder infoHolder = new HighlightInfoHolder(myFile, HighlightInfoFilter.EMPTY_ARRAY);
final HighlightVisitorImpl visitor = new HighlightVisitorImpl(PsiResolveHelper.SERVICE.getInstance(getProject()));
- visitor.analyze(myFile, false, infoHolder, new Runnable() {
+ visitor.analyze(myFile, true, infoHolder, new Runnable() {
@Override
public void run() {
visitor.visit(element);
diff --git a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy
index b9a5732..da446c7 100644
--- a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy
@@ -14,15 +14,16 @@
* limitations under the License.
*/
package com.intellij.psi
-
import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.fileEditor.FileDocumentManager
+import com.intellij.openapi.vfs.VfsUtil
import com.intellij.psi.impl.source.PsiFileImpl
+import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil
-import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import com.intellij.reference.SoftReference
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import java.util.concurrent.CountDownLatch
-
/**
* @author peter
*/
@@ -79,4 +80,21 @@
}
latch.await()
}
+
+ public void "test external modification of a stubbed file with smart pointer switches the file to AST"() {
+ PsiFile file = myFixture.addFileToProject("A.java", "class A {}")
+ def oldClass = JavaPsiFacade.getInstance(project).findClass("A", GlobalSearchScope.allScope(project))
+ def pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(oldClass)
+
+ def document = FileDocumentManager.instance.getCachedDocument(file.virtualFile)
+ assert document
+ assert file == PsiDocumentManager.getInstance(project).getCachedPsiFile(document)
+ assert document == PsiDocumentManager.getInstance(project).getCachedDocument(file)
+
+ assert ((PsiFileImpl)file).stub
+
+ ApplicationManager.application.runWriteAction { VfsUtil.saveText(file.virtualFile, "import java.util.*; class A {}; class B {}") }
+ assert pointer.element == oldClass
+ assert ((PsiFileImpl)file).treeElement
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java
index b61689b..be33547 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java
@@ -40,7 +40,7 @@
// Checking that closing curly brace of initialization block that is not the first block on a line is correctly indented.
doTextTest("class Class {\n" + " private Type field; {\n" + " }\n" + "}",
- "class Class {\n" + " private Type field; {\n" + " }\n" + "}");
+ "class Class {\n" + " private Type field;\n\n {\n" + " }\n" + "}");
doTextTest(
"class T {\n" +
" private final DecimalFormat fmt = new DecimalFormat(); {\n" +
@@ -49,7 +49,7 @@
" }\n" +
"}",
"class T {\n" +
- " private final DecimalFormat fmt = new DecimalFormat(); {\n" +
+ " private final DecimalFormat fmt = new DecimalFormat();\n\n {\n" +
" fmt.setGroupingUsed(false);\n" +
" fmt.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));\n" +
" }\n" +
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
index d01f0f6..28e4de5 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
@@ -122,7 +122,31 @@
"}"
);
}
-
+
+ public void testParameterDescriptionNotOnNewLine() throws Exception {
+ // IDEA-107383
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().JD_ALIGN_PARAM_COMMENTS = true;
+
+ doClassTest(
+ "/**\n" +
+ " @param protocolId protocol id\n" +
+ " @param connectedUserIdHandlerFromServer user id\n" +
+ " @return\n" +
+
+ " */\n" +
+ "public void register(int protocolId, int connectedUserIdHandlerFromServer) {\n" +
+ "}",
+
+ "/**\n" +
+ " * @param protocolId protocol id\n" +
+ " * @param connectedUserIdHandlerFromServer user id\n" +
+ " * @return\n" +
+ " */\n" +
+ "public void register(int protocolId, int connectedUserIdHandlerFromServer) {\n" +
+ "}");
+ }
+
public void testWrappedParameterDescription() throws Exception {
// Inspired by IDEA-13072
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
@@ -155,4 +179,177 @@
"}"
);
}
+
+ public void testExceptionAlignmentCorrect() {
+ getCurrentCodeStyleSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getCurrentCodeStyleSettings().JD_ALIGN_EXCEPTION_COMMENTS = true;
+
+ String before =
+ "public class Controller {\n" +
+ "\n" +
+ " /**\n" +
+ " * @throws NoSearchServersConfiguredException If no search engine servers are configured.\n" +
+ " * @throws SearchServerUnavailableException If the search engine server is not accessible.\n" +
+ " * @throws InvalidSearchServerResponseException If the search engine server response was invalid.\n" +
+ " * @throws NotificationEncodingException If the request could not be encoded to UTF-8.\n" +
+ " * @throws NotificationUnavailableException If the notification server is not available or sent back an invalid response code.\n" +
+ " */\n" +
+ " public int superDangerousMethod() {\n" +
+ " return 68;\n" +
+ " }\n" +
+ "}";
+
+ String after =
+ "public class Controller {\n" +
+ "\n" +
+ " /**\n" +
+ " * @throws NoSearchServersConfiguredException If no search engine servers are configured.\n" +
+ " * @throws SearchServerUnavailableException If the search engine server is not accessible.\n" +
+ " * @throws InvalidSearchServerResponseException If the search engine server response was invalid.\n" +
+ " * @throws NotificationEncodingException If the request could not be encoded to UTF-8.\n" +
+ " * @throws NotificationUnavailableException If the notification server is not available or sent back an invalid response code.\n" +
+ " */\n" +
+ " public int superDangerousMethod() {\n" +
+ " return 68;\n" +
+ " }\n" +
+ "}";
+
+ doTextTest(before, after);
+ }
+
+ public void testReturnTagAlignment() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @return this is a return value documentation with a very long description that is longer than the right margin. It is more than 200 characters long, not including the comment indent and the asterisk characters, which should be greater than any sane right margin.\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }\n";
+
+ String after = "/**\n" +
+ " * @return this is a return value documentation with a very long description\n" +
+ " * that is longer than the right margin. It is more than 200 characters\n" +
+ " * long, not including the comment indent and the asterisk characters, which\n" +
+ " * should be greater than any sane right margin.\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}\n";
+
+ doClassTest(before, after);
+ }
+
+
+ public void testReturnTagAlignmentWithPreTagOnFirstLine() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @return <pre>this is a return value documentation with a very long description\n" +
+ " * that is longer than the right margin.</pre>\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }";
+
+ String after = "/**\n" +
+ " * @return <pre>this is a return value documentation with a very long\n" +
+ " * description\n" +
+ " * that is longer than the right margin.</pre>\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}";
+
+ doClassTest(before, after);
+ }
+
+ public void testSeeTagAlignment() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @see this is an additional documentation with a very long description that is longer than the right margin. It is more than 200 characters long, not including the comment indent and the asterisk characters which should be greater than any sane right margin\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }";
+
+ String after = "/**\n" +
+ " * @see this is an additional documentation with a very long description\n" +
+ " * that is longer than the right margin. It is more than 200 characters\n" +
+ " * long, not including the comment indent and the asterisk characters which\n" +
+ " * should be greater than any sane right margin\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}";
+
+ doClassTest(before, after);
+ }
+
+ public void testDummySinceTagAlignment() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @since this is an additional documentation with a very long description that is longer than the right margin. It is more than 200 characters long, not including the comment indent and the asterisk characters which should be greater than any sane right margin\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }";
+
+ String after = "/**\n" +
+ " * @since this is an additional documentation with a very long description\n" +
+ " * that is longer than the right margin. It is more than 200 characters\n" +
+ " * long, not including the comment indent and the asterisk characters which\n" +
+ " * should be greater than any sane right margin\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}";
+
+ doClassTest(before, after);
+ }
+
+ public void testDummyDeprecatedTagAlignment() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @deprecated this is an additional documentation with a very long description that is longer than the right margin. It is more than 200 characters long, not including the comment indent and the asterisk characters which should be greater than any sane right margin\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }";
+
+ String after = "/**\n" +
+ " * @deprecated this is an additional documentation with a very long\n" +
+ " * description that is longer than the right margin. It is more than 200\n" +
+ " * characters long, not including the comment indent and the asterisk\n" +
+ " * characters which should be greater than any sane right margin\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}";
+
+ doClassTest(before, after);
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
index 3639cbd..88537b7 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
@@ -583,6 +583,10 @@
doDuplicatesTest();
}
+ public void testOverloadedMethods() throws Exception {
+ doDuplicatesTest();
+ }
+
public void testTargetAnonymous() throws Exception {
doTest();
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractSuperClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractSuperClassTest.java
index 4775463..732ead7 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractSuperClassTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractSuperClassTest.java
@@ -56,6 +56,11 @@
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("m", PsiMethod.class));
}
+
+ public void testEmptyForeach() throws Exception {
+ doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("m", PsiMethod.class));
+ }
+
public void testConflictUsingPrivateMethod() throws Exception {
doTest("Test", "TestSubclass",
new String[] {"Method <b><code>Test.foo()</code></b> is private and will not be accessible from method <b><code>x()</code></b>."},
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java
index 596944b..ca97d36 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java
@@ -107,6 +107,10 @@
doTest("B", "A", 0);
}
+ public void testStringConstantFromCaseStatement() throws Exception {
+ doTest("B", "A", 0);
+ }
+
public void testDependantFields() throws Exception {
doTest("B", "A", 0);
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
index 0cf3fc3..83dbbef 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
@@ -149,6 +149,11 @@
doSingleFileTest();
}
+ public void testLastResourceVariableWithFinallyBlock() throws Exception {
+ LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
+ doSingleFileTest();
+ }
+
public void testLastTypeParam() throws Exception {
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
doSingleFileTest();
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java
index 709db99..6d66a43 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java
@@ -140,6 +140,10 @@
"Variable 'arr' is accessed for writing.");
}
+ public void testArrayMethodCallInitialized() throws Exception {
+ doTest(true);
+ }
+
public void testArrayIndex() throws Exception {
doTest(true);
}
@@ -205,6 +209,10 @@
doTest(true);
}
+ public void testResourceVariable() throws Exception {
+ doTest(false);
+ }
+
public void testEnclosingThisExpression() throws Exception {
doTest(true);
}
diff --git a/java/openapi/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java b/java/openapi/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java
index ebefeef..7950e60 100644
--- a/java/openapi/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java
+++ b/java/openapi/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java
@@ -79,7 +79,7 @@
@Override
public boolean contains(VirtualFile file, @NotNull Project project, @Nullable NamedScopesHolder holder) {
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
- return matchesScope(file, holder.getProject(), fileIndex) && (myPattern == null || myPattern.matcher(getPackageName(file, fileIndex)).matches());
+ return matchesScope(file, project, fileIndex) && (myPattern == null || myPattern.matcher(getPackageName(file, fileIndex)).matches());
}
private boolean matchesScope(VirtualFile file, Project project, ProjectFileIndex fileIndex) {
diff --git a/java/openapi/src/com/intellij/psi/util/PsiConcatenationUtil.java b/java/openapi/src/com/intellij/psi/util/PsiConcatenationUtil.java
index 9b60456..08e3443 100644
--- a/java/openapi/src/com/intellij/psi/util/PsiConcatenationUtil.java
+++ b/java/openapi/src/com/intellij/psi/util/PsiConcatenationUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -26,65 +26,61 @@
* User: cdr
*/
public class PsiConcatenationUtil {
- public static void buildFormatString(
- PsiExpression expression, StringBuilder formatString,
- List<PsiExpression> formatParameters, boolean printfFormat) {
- if (expression instanceof PsiLiteralExpression) {
- final PsiLiteralExpression literalExpression =
- (PsiLiteralExpression) expression;
- final String text = String.valueOf(literalExpression.getValue());
- final String formatText;
- if (printfFormat) {
- formatText = StringUtil.escapeStringCharacters(text)
- .replace("%", "%%").replace("\\'", "'");
+
+ public static void buildFormatString(PsiExpression expression, StringBuilder formatString,
+ List<PsiExpression> formatParameters, boolean printfFormat) {
+ if (expression instanceof PsiLiteralExpression) {
+ final PsiLiteralExpression literalExpression = (PsiLiteralExpression) expression;
+ final String text = String.valueOf(literalExpression.getValue());
+ final String formatText;
+ if (printfFormat) {
+ formatText = StringUtil.escapeStringCharacters(text).replace("%", "%%").replace("\\'", "'");
+ }
+ else {
+ formatText = StringUtil.escapeStringCharacters(text).replace("'", "''").replaceAll("((\\{|})+)", "'$1'");
+ }
+ formatString.append(formatText);
+ } else if (expression instanceof PsiPolyadicExpression) {
+ final PsiType type = expression.getType();
+ if (type != null && type.equalsToText("java.lang.String")) {
+ final PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression) expression;
+ PsiExpression[] operands = binaryExpression.getOperands();
+ PsiType left = operands[0].getType();
+ boolean stringStarted = left != null && left.equalsToText("java.lang.String");
+ if (stringStarted) {
+ buildFormatString(operands[0], formatString, formatParameters, printfFormat);
}
- else {
- formatText = StringUtil.escapeStringCharacters(text)
- .replace("'", "''").replace("{", "'{").replace("}", "'}");
- }
- formatString.append(formatText);
- } else if (expression instanceof PsiPolyadicExpression) {
- final PsiType type = expression.getType();
- if (type != null && type.equalsToText("java.lang.String")) {
- final PsiPolyadicExpression binaryExpression =
- (PsiPolyadicExpression) expression;
- PsiExpression[] operands = binaryExpression.getOperands();
- PsiType left = operands[0].getType();
- boolean stringStarted = left != null && left.equalsToText("java.lang.String");
- if (stringStarted) {
- buildFormatString(operands[0], formatString, formatParameters, printfFormat);
+ for (int i = 1; i < operands.length; i++) {
+ PsiExpression op = operands[i];
+ PsiType optype = op.getType();
+ PsiType r = TypeConversionUtil.calcTypeForBinaryExpression(left, optype, binaryExpression.getOperationTokenType(), true);
+ if (r != null && r.equalsToText("java.lang.String") && !stringStarted) {
+ stringStarted = true;
+ PsiElement element = binaryExpression.getTokenBeforeOperand(op);
+ if (element.getPrevSibling() instanceof PsiWhiteSpace) element = element.getPrevSibling();
+ String text = binaryExpression.getText().substring(0, element.getStartOffsetInParent());
+ PsiExpression subExpression = JavaPsiFacade.getInstance(binaryExpression.getProject()).getElementFactory()
+ .createExpressionFromText(text, binaryExpression);
+ addFormatParameter(subExpression, formatString, formatParameters, printfFormat);
+ }
+ if (stringStarted) {
+ if (optype != null && (optype.equalsToText("java.lang.String") || optype == PsiType.CHAR)) {
+ buildFormatString(op, formatString, formatParameters, printfFormat);
}
- for (int i = 1; i < operands.length; i++) {
- PsiExpression op = operands[i];
- PsiType optype = op.getType();
- PsiType r = TypeConversionUtil.calcTypeForBinaryExpression(left, optype, binaryExpression.getOperationTokenType(), true);
- if (r != null && r.equalsToText("java.lang.String") && !stringStarted) {
- stringStarted = true;
- PsiElement element = binaryExpression.getTokenBeforeOperand(op);
- if (element.getPrevSibling() instanceof PsiWhiteSpace) element = element.getPrevSibling();
- String text = binaryExpression.getText().substring(0, element.getStartOffsetInParent());
- PsiExpression subExpression = JavaPsiFacade.getInstance(binaryExpression.getProject()).getElementFactory()
- .createExpressionFromText(text, binaryExpression);
- addFormatParameter(subExpression, formatString, formatParameters, printfFormat);
- }
- if (stringStarted) {
- if (optype != null && (optype.equalsToText("java.lang.String") || optype == PsiType.CHAR)) {
- buildFormatString(op, formatString, formatParameters, printfFormat);
- }
- else {
- addFormatParameter(op, formatString, formatParameters, printfFormat);
- }
- }
- left = r;
+ else {
+ addFormatParameter(op, formatString, formatParameters, printfFormat);
}
}
- else {
- addFormatParameter(expression, formatString, formatParameters, printfFormat);
- }
+ left = r;
+ }
}
else {
addFormatParameter(expression, formatString, formatParameters, printfFormat);
}
+ }
+ else {
+ addFormatParameter(expression, formatString, formatParameters, printfFormat);
+ }
}
private static void addFormatParameter(PsiExpression expression,
@@ -92,13 +88,13 @@
List<PsiExpression> formatParameters, boolean printfFormat) {
final PsiType type = expression.getType();
if (!printfFormat) {
- formatString.append("{" + formatParameters.size() + "}");
+ formatString.append("{").append(formatParameters.size()).append("}");
}
else if (type != null &&
- (type.equalsToText("long") ||
- type.equalsToText("int") ||
- type.equalsToText("java.lang.Long") ||
- type.equalsToText("java.lang.Integer"))) {
+ (type.equalsToText("long") ||
+ type.equalsToText("int") ||
+ type.equalsToText("java.lang.Long") ||
+ type.equalsToText("java.lang.Integer"))) {
formatString.append("%d");
}
else {
diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
index 6d40070..ccaa2cb 100644
--- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
@@ -119,16 +119,17 @@
@Override
@NotNull
- public InspectionTool[] getInspectionTools(PsiElement element) {
+ public InspectionToolWrapper[] getInspectionTools(PsiElement element) {
Collection<InspectionToolWrapper> values = myAvailableTools.values();
- return values.toArray(new InspectionTool[values.size()]);
+ return values.toArray(new InspectionToolWrapper[values.size()]);
}
+ @NotNull
@Override
- public List<ToolsImpl> getAllEnabledInspectionTools(Project project) {
- List<ToolsImpl> result = new ArrayList<ToolsImpl>();
- for (InspectionProfileEntry entry : getInspectionTools(null)) {
- result.add(new ToolsImpl(entry, entry.getDefaultLevel(), true));
+ public List<Tools> getAllEnabledInspectionTools(Project project) {
+ List<Tools> result = new ArrayList<Tools>();
+ for (InspectionToolWrapper toolWrapper : getInspectionTools(null)) {
+ result.add(new ToolsImpl(toolWrapper, toolWrapper.getDefaultLevel(), true));
}
return result;
}
@@ -140,12 +141,12 @@
@Override
public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, PsiElement element) {
- final InspectionProfileEntry localInspectionTool = myAvailableTools.get(key.toString());
+ final InspectionToolWrapper localInspectionTool = myAvailableTools.get(key.toString());
return localInspectionTool != null ? localInspectionTool.getDefaultLevel() : HighlightDisplayLevel.WARNING;
}
@Override
- public InspectionTool getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) {
+ public InspectionToolWrapper getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) {
return myAvailableTools.get(shortName);
}
};
@@ -192,14 +193,9 @@
//((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).assertPointersDisposed();
}
- protected void enableInspectionTool(InspectionProfileEntry tool){
- InspectionToolWrapper wrapper = InspectionToolRegistrar.wrapTool(tool);
- final String shortName = wrapper.getShortName();
- final HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
- if (key == null) {
- HighlightDisplayKey.register(shortName, wrapper.getDisplayName(), ((LocalInspectionToolWrapper)wrapper).getID());
- }
- myAvailableTools.put(shortName, wrapper);
+ protected void enableInspectionTool(@NotNull InspectionProfileEntry tool) {
+ InspectionToolWrapper toolWrapper = InspectionToolRegistrar.wrapTool(tool);
+ LightPlatformTestCase.enableInspectionTool(myAvailableTools, toolWrapper);
}
protected void enableInspectionToolsFromProvider(InspectionToolProvider toolProvider){
diff --git a/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java b/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java
new file mode 100644
index 0000000..e1f9857
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2000-2013 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.debugger;
+
+import com.intellij.debugger.engine.DebugProcessImpl;
+import com.intellij.debugger.engine.RemoteStateState;
+import com.intellij.debugger.engine.SuspendContextImpl;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.intellij.debugger.engine.events.DebuggerCommandImpl;
+import com.intellij.debugger.impl.*;
+import com.intellij.debugger.jdi.StackFrameProxyImpl;
+import com.intellij.debugger.settings.DebuggerSettings;
+import com.intellij.debugger.settings.NodeRendererSettings;
+import com.intellij.debugger.ui.breakpoints.BreakpointManager;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.*;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.ui.UIUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.lang.reflect.InvocationTargetException;
+import java.util.StringTokenizer;
+
+public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCase {
+ protected DebuggerSession myDebuggerSession;
+ private StringBuffer myConsoleBuffer;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void initApplication() throws Exception {
+ super.initApplication();
+ setTestJDK();
+ DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = DebuggerSettings.SOCKET_TRANSPORT;
+ DebuggerSettings.getInstance().SKIP_CONSTRUCTORS = false;
+ DebuggerSettings.getInstance().SKIP_GETTERS = false;
+ NodeRendererSettings.getInstance().getClassRenderer().SHOW_DECLARED_TYPE = true;
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ super.runTest();
+ if(getDebugProcess() != null) {
+ getDebugProcess().getExecutionResult().getProcessHandler().startNotify();
+ waitProcess(getDebugProcess().getExecutionResult().getProcessHandler());
+ waitForCompleted();
+ disposeSession(myDebuggerSession);
+ assertNull(DebuggerManagerEx.getInstanceEx(myProject).getDebugProcess(getDebugProcess().getExecutionResult().getProcessHandler()));
+ myDebuggerSession = null;
+ }
+ if(myConsoleBuffer != null) {
+ //println("", b);
+ //println("Console output:", b);
+ //println(myConsoleBuffer.toString(), b);
+ }
+ checkTestOutput();
+ }
+
+ protected void checkTestOutput() throws Exception {
+ getChecker().checkValid(getTestProjectJdk());
+ }
+
+ protected void disposeSession(final DebuggerSession debuggerSession) throws InterruptedException, InvocationTargetException {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ debuggerSession.dispose();
+ }
+ });
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ myConsoleBuffer = null;
+ }
+
+ protected void createLocalProcess(String className) throws ExecutionException, InterruptedException, InvocationTargetException {
+ LOG.assertTrue(myDebugProcess == null);
+ myDebuggerSession = createLocalProcess(DebuggerSettings.SOCKET_TRANSPORT, createJavaParameters(className));
+ myDebugProcess = myDebuggerSession.getProcess();
+ }
+
+ protected DebuggerSession createLocalSession(final JavaParameters javaParameters, final String sessionName) throws ExecutionException, InterruptedException {
+ createBreakpoints(javaParameters.getMainClass());
+ DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = DebuggerSettings.SOCKET_TRANSPORT;
+
+ GenericDebuggerRunnerSettings debuggerRunnerSettings = new GenericDebuggerRunnerSettings();
+ debuggerRunnerSettings.LOCAL = true;
+
+ final RemoteConnection debugParameters = DebuggerManagerImpl.createDebugParameters(javaParameters, debuggerRunnerSettings, false);
+
+ RunnerSettings<JDOMExternalizable> runnerSettings = new RunnerSettings<JDOMExternalizable>(debuggerRunnerSettings, null);
+
+ final JavaCommandLineState javaCommandLineState = new JavaCommandLineState(new ExecutionEnvironment(new MockConfiguration(), myProject,
+ runnerSettings, null, null)){
+ @Override
+ protected JavaParameters createJavaParameters() {
+ return javaParameters;
+ }
+
+ @Override
+ protected GeneralCommandLine createCommandLine() throws ExecutionException {
+ return CommandLineBuilder.createFromJavaParameters(getJavaParameters());
+ }
+ };
+
+ final GenericDebuggerRunner runner = new GenericDebuggerRunner();
+
+ ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ myDebuggerSession = DebuggerManagerEx.getInstanceEx(myProject).attachVirtualMachine(new DefaultDebugExecutor(),
+ runner, new MockConfiguration(), javaCommandLineState, debugParameters, false);
+ }
+ catch (ExecutionException e) {
+ LOG.error(e);
+ }
+ }
+ }, ModalityState.defaultModalityState());
+ myDebugProcess = myDebuggerSession.getProcess();
+
+ //myConsoleBuffer = new StringBuffer();
+
+ myDebugProcess.addProcessListener(new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ //myConsoleBuffer.append(event.getText());
+ print(event.getText(), outputType);
+ }
+ });
+
+ assertNotNull(myDebuggerSession);
+ assertNotNull(myDebugProcess);
+
+ return myDebuggerSession;
+ }
+
+
+ protected DebuggerSession createLocalProcess(int transport, final JavaParameters javaParameters) throws ExecutionException, InterruptedException, InvocationTargetException {
+ createBreakpoints(javaParameters.getMainClass());
+ final DebuggerSession[] debuggerSession = new DebuggerSession[]{null};
+
+ DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = transport;
+
+ GenericDebuggerRunnerSettings debuggerRunnerSettings = new GenericDebuggerRunnerSettings();
+ debuggerRunnerSettings.LOCAL = true;
+ debuggerRunnerSettings.DEBUG_PORT = "3456";
+
+ RunnerSettings<JDOMExternalizable> runnerSettings = new RunnerSettings<JDOMExternalizable>(debuggerRunnerSettings, null);
+
+ final JavaCommandLineState javaCommandLineState = new JavaCommandLineState(new ExecutionEnvironment(new MockConfiguration(), myProject,
+ runnerSettings, null, null)) {
+ @Override
+ protected JavaParameters createJavaParameters() {
+ return javaParameters;
+ }
+
+ @Override
+ protected GeneralCommandLine createCommandLine() throws ExecutionException {
+ return CommandLineBuilder.createFromJavaParameters(getJavaParameters());
+ }
+ };
+
+ final RemoteConnection debugParameters =
+ DebuggerManagerImpl.createDebugParameters(javaCommandLineState.getJavaParameters(), debuggerRunnerSettings, true);
+
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ debuggerSession[0] = attachVirtualMachine(javaCommandLineState, debugParameters, false);
+ }
+ catch (ExecutionException e) {
+ fail(e.getMessage());
+ }
+ }
+ });
+
+ final ExecutionResult executionResult = debuggerSession[0].getProcess().getExecutionResult();
+ debuggerSession[0].getProcess().addProcessListener(new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ print(event.getText(), outputType);
+ }
+ });
+
+ DebugProcessImpl process =
+ (DebugProcessImpl)DebuggerManagerEx.getInstanceEx(myProject).getDebugProcess(executionResult.getProcessHandler());
+ assertNotNull(process);
+ return debuggerSession[0];
+ }
+
+
+ protected DebuggerSession createRemoteProcess(final int transport, final boolean serverMode, JavaParameters javaParameters)
+ throws ExecutionException, InterruptedException, InvocationTargetException {
+ boolean useSockets = transport == DebuggerSettings.SOCKET_TRANSPORT;
+
+ RemoteConnection remoteConnection = new RemoteConnection(
+ useSockets,
+ "127.0.0.1",
+ "3456",
+ serverMode);
+
+ String launchCommandLine = remoteConnection.getLaunchCommandLine();
+
+ launchCommandLine = StringUtil.replace(launchCommandLine, RemoteConnection.ONTHROW, "");
+ launchCommandLine = StringUtil.replace(launchCommandLine, RemoteConnection.ONUNCAUGHT, "");
+
+ launchCommandLine = StringUtil.replace(launchCommandLine, "suspend=n", "suspend=y");
+
+ println(launchCommandLine, ProcessOutputTypes.SYSTEM);
+
+ JavaParameters parameters = javaParameters;
+
+ for(StringTokenizer tokenizer = new StringTokenizer(launchCommandLine);tokenizer.hasMoreTokens();) {
+ String token = tokenizer.nextToken();
+ parameters.getVMParametersList().add(token);
+ }
+
+ GeneralCommandLine commandLine = CommandLineBuilder.createFromJavaParameters(parameters);
+
+
+ DebuggerSession debuggerSession;
+
+ if(serverMode) {
+ debuggerSession = attachVM(remoteConnection, false);
+ commandLine.createProcess();
+ } else {
+ commandLine.createProcess();
+ debuggerSession = attachVM(remoteConnection, true);
+ }
+
+ ExecutionResult executionResult = debuggerSession.getProcess().getExecutionResult();
+ DebugProcessImpl process = (DebugProcessImpl)DebuggerManagerEx.getInstanceEx(myProject)
+ .getDebugProcess(executionResult.getProcessHandler());
+
+ assertNotNull(process);
+ return debuggerSession;
+ }
+
+ protected DebuggerSession attachVM(final RemoteConnection remoteConnection, final boolean pollConnection)
+ throws InvocationTargetException, InterruptedException {
+ final RunnerSettings<JDOMExternalizable> runnerSettings = new RunnerSettings<JDOMExternalizable>(null, null);
+ final RemoteState remoteState = new RemoteStateState(myProject, remoteConnection, runnerSettings, null);
+
+ final DebuggerSession[] debuggerSession = new DebuggerSession[1];
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ debuggerSession[0] = attachVirtualMachine(remoteState, remoteConnection, pollConnection);
+ }
+ catch (ExecutionException e) {
+ fail(e.getMessage());
+ }
+ }
+ });
+ debuggerSession[0].getProcess().getExecutionResult().getProcessHandler().addProcessListener(new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ print(event.getText(), outputType);
+ }
+ });
+ return debuggerSession[0];
+ }
+
+ protected void createBreakpoints(final String className) {
+ final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
+ @Override
+ public PsiClass compute() {
+ return JavaPsiFacade.getInstance(myProject).findClass(className, GlobalSearchScope.allScope(myProject));
+ }
+ });
+
+ createBreakpoints(psiClass.getContainingFile());
+
+ }
+
+ protected EvaluationContextImpl createEvaluationContext(final SuspendContextImpl suspendContext) {
+ try {
+ return new EvaluationContextImpl(
+ suspendContext,
+ suspendContext.getFrameProxy(),
+ suspendContext.getFrameProxy().thisObject());
+ }
+ catch (EvaluateException e) {
+ error(e);
+ return null;
+ }
+ }
+
+ protected void waitForCompleted() {
+ final SynchronizationBasedSemaphore s = new SynchronizationBasedSemaphore();
+ s.down();
+
+ final InvokeThread.WorkerThreadRequest request = getDebugProcess().getManagerThread().getCurrentRequest();
+ final Thread thread = new Thread("Joining "+request) {
+ @Override
+ public void run() {
+ try {
+ request.join();
+ }
+ catch (Exception e) {
+ }
+ }
+ };
+ thread.start();
+ if(request.isDone()) {
+ thread.interrupt();
+ }
+ waitFor(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ thread.join();
+ }
+ catch (InterruptedException e) {
+ }
+ }
+ });
+
+ invokeRatherLater(new DebuggerCommandImpl() {
+ @Override
+ protected void action() throws Exception {
+ LOG.assertTrue(false);
+ }
+
+ @Override
+ protected void commandCancelled() {
+ //We wait for invokeRatherLater's
+ invokeRatherLater(new DebuggerCommandImpl() {
+ @Override
+ protected void action() throws Exception {
+ LOG.assertTrue(false);
+ }
+
+ @Override
+ protected void commandCancelled() {
+ s.up();
+ }
+ });
+ }
+ });
+
+ waitFor(new Runnable() {
+ @Override
+ public void run() {
+ s.waitFor();
+ }
+ });
+ }
+
+ public DebuggerContextImpl createDebuggerContext(final SuspendContextImpl suspendContext, StackFrameProxyImpl stackFrame) {
+ final DebuggerSession[] session = new DebuggerSession[1];
+
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ session[0] = DebuggerManagerEx.getInstanceEx(myProject).getSession(suspendContext.getDebugProcess());
+ }
+ });
+
+ DebuggerContextImpl debuggerContext = DebuggerContextImpl.createDebuggerContext(
+ session[0],
+ suspendContext,
+ stackFrame != null ? stackFrame.threadProxy() : null,
+ stackFrame);
+ debuggerContext.initCaches();
+ return debuggerContext;
+ }
+
+ public DebuggerContextImpl createDebuggerContext(final SuspendContextImpl suspendContext) {
+ return createDebuggerContext(suspendContext, suspendContext.getFrameProxy());
+ }
+
+ protected void createBreakpointInHelloWorld() {
+ DebuggerInvocationUtil.invokeAndWait(myProject, new Runnable() {
+ @Override
+ public void run() {
+ BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager();
+ PsiClass psiClass = JavaPsiFacade.getInstance(myProject).findClass("HelloWorld", GlobalSearchScope.allScope(myProject));
+ Document document = PsiDocumentManager.getInstance(myProject).getDocument(psiClass.getContainingFile());
+ breakpointManager.addLineBreakpoint(document, 3);
+ }
+ }, ApplicationManager.getApplication().getDefaultModalityState());
+ }
+
+ protected void createHelloWorldProcessWithBreakpoint() throws ExecutionException, InterruptedException, InvocationTargetException {
+ createLocalProcess("HelloWorld");
+
+ createBreakpointInHelloWorld();
+ }
+
+ @Override
+ protected DebugProcessImpl getDebugProcess() {
+ return myDebuggerSession != null ? myDebuggerSession.getProcess() : null;
+ }
+
+ public DebuggerSession getDebuggerSession() {
+ return myDebuggerSession;
+ }
+
+ protected DebuggerSession attachVirtualMachine(RunProfileState state, RemoteConnection remoteConnection, boolean pollConnection) throws ExecutionException {
+ return DebuggerManagerEx.getInstanceEx(myProject).attachVirtualMachine(new DefaultDebugExecutor(), new GenericDebuggerRunner(), new MockConfiguration(), state, remoteConnection, pollConnection);
+ }
+
+ private static class MockConfiguration implements ModuleRunConfiguration {
+ @Override
+ @NotNull
+ public Module[] getModules() {
+ return Module.EMPTY_ARRAY; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Icon getIcon() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public ConfigurationFactory getFactory() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void setName(final String name) {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Project getProject() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ @NotNull
+ public ConfigurationType getType() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public JDOMExternalizable createRunnerSettings(final ConfigurationInfoProvider provider) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public SettingsEditor<JDOMExternalizable> getRunnerSettingsEditor(final ProgramRunner runner) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public RunConfiguration clone() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public int getUniqueID() {
+ return 0;
+ }
+
+ @Override
+ public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public String getName() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void checkConfiguration() throws RuntimeConfigurationException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void readExternal(final Element element) throws InvalidDataException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void writeExternal(final Element element) throws WriteExternalException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ }
+
+}
diff --git a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
new file mode 100644
index 0000000..bccbfe5
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2000-2013 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.debugger;
+
+import com.intellij.debugger.engine.*;
+import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
+import com.intellij.debugger.engine.events.DebuggerCommandImpl;
+import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
+import com.intellij.debugger.impl.DebuggerManagerImpl;
+import com.intellij.debugger.impl.PositionUtil;
+import com.intellij.debugger.impl.PrioritizedTask;
+import com.intellij.debugger.impl.SynchronizationBasedSemaphore;
+import com.intellij.debugger.jdi.StackFrameProxyImpl;
+import com.intellij.debugger.settings.DebuggerSettings;
+import com.intellij.debugger.ui.breakpoints.Breakpoint;
+import com.intellij.debugger.ui.breakpoints.BreakpointManager;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionTestCase;
+import com.intellij.execution.configurations.RemoteConnection;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.projectRoots.ProjectJdkTable;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.ui.classFilter.ClassFilter;
+import com.intellij.util.IJSwingUtilities;
+import com.intellij.util.ui.UIUtil;
+import com.sun.jdi.Method;
+import com.sun.jdi.ThreadReference;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+public abstract class ExecutionWithDebuggerToolsTestCase extends ExecutionTestCase {
+ private DebugProcessListener myPauseScriptListener = null;
+ private final List<SuspendContextRunnable> myScriptRunnables = new ArrayList<SuspendContextRunnable>();
+ private final SynchronizationBasedSemaphore myScriptRunnablesSema = new SynchronizationBasedSemaphore();
+ protected static final int RATHER_LATER_INVOKES_N = 10;
+ public DebugProcessImpl myDebugProcess = null;
+
+
+ private class InvokeRatherLaterRequest {
+ private final DebuggerCommandImpl myDebuggerCommand;
+ private final DebugProcessImpl myDebugProcess;
+ int invokesN = 0;
+
+ public InvokeRatherLaterRequest(DebuggerCommandImpl debuggerCommand, DebugProcessImpl debugProcess) {
+ myDebuggerCommand = debuggerCommand;
+ myDebugProcess = debugProcess;
+ }
+ }
+
+ public List<InvokeRatherLaterRequest> myRatherLaterRequests = new ArrayList<InvokeRatherLaterRequest>();
+
+ protected DebugProcessImpl getDebugProcess() {
+ return myDebugProcess;
+ }
+
+ protected String readValue(String comment, String valueName) {
+ int valueStart = comment.indexOf(valueName);
+ if (valueStart == -1) return null;
+
+ int valueEnd = comment.indexOf(')', valueStart);
+ return comment.substring(valueStart + valueName.length() + 1, valueEnd);
+ }
+
+ protected void resume(SuspendContextImpl context) {
+ DebugProcessImpl debugProcess = context.getDebugProcess();
+ debugProcess.getManagerThread().schedule(debugProcess.createResumeCommand(context, PrioritizedTask.Priority.LOW));
+ }
+
+ protected void waitBreakpoints() {
+ myScriptRunnablesSema.down();
+ waitFor(new Runnable() {
+ @Override
+ public void run() {
+ myScriptRunnablesSema.waitFor();
+ }
+ });
+ }
+
+ protected void onBreakpoint(SuspendContextRunnable runnable) {
+ if (myPauseScriptListener == null) {
+ final DebugProcessImpl debugProcess = getDebugProcess();
+
+ assertTrue("Debug process was not started", debugProcess != null);
+
+ myPauseScriptListener = new DelayedEventsProcessListener(
+ new DebugProcessAdapterImpl() {
+ @Override
+ public void paused(SuspendContextImpl suspendContext) {
+ try {
+ if (myScriptRunnables.isEmpty()) {
+ print("resuming ", ProcessOutputTypes.SYSTEM);
+ printContext(suspendContext);
+ resume(suspendContext);
+ return;
+ }
+ SuspendContextRunnable suspendContextRunnable = myScriptRunnables.remove(0);
+ suspendContextRunnable.run(suspendContext);
+ }
+ catch (Exception e) {
+ error(e);
+ }
+
+ if (myScriptRunnables.isEmpty()) {
+ myScriptRunnablesSema.up();
+ }
+ }
+
+ //executed in manager thread
+ @Override
+ public void resumed(SuspendContextImpl suspendContext) {
+ final SuspendContextImpl pausedContext = debugProcess.getSuspendManager().getPausedContext();
+ if (pausedContext != null) {
+ debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(pausedContext) {
+ @Override
+ public void contextAction() throws Exception {
+ paused(pausedContext);
+ }
+ });
+ }
+ }
+ }
+ );
+ debugProcess.addDebugProcessListener(myPauseScriptListener);
+ }
+ myScriptRunnables.add(runnable);
+ }
+
+ protected void printFrameProxy(StackFrameProxyImpl frameProxy) throws EvaluateException {
+ int frameIndex = frameProxy.getFrameIndex();
+ Method method = frameProxy.location().method();
+
+ println("frameProxy(" + frameIndex + ") = " + method, ProcessOutputTypes.SYSTEM);
+ }
+
+ protected void printContext(final StackFrameContext context) {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ if (context.getFrameProxy() != null) {
+ SourcePosition sourcePosition = PositionUtil.getSourcePosition(context);
+ println(sourcePosition.getFile().getVirtualFile().getName() + ":" + sourcePosition.getLine(), ProcessOutputTypes.SYSTEM);
+ }
+ else {
+ println("Context thread is null", ProcessOutputTypes.SYSTEM);
+ }
+ }
+ });
+ }
+
+ protected void invokeRatherLater(SuspendContextImpl context, final Runnable runnable) {
+ invokeRatherLater(new SuspendContextCommandImpl(context) {
+ @Override
+ public void contextAction() throws Exception {
+ DebuggerInvocationUtil.invokeLater(myProject, runnable);
+ }
+ });
+ }
+
+ protected void pumpSwingThread() {
+ LOG.assertTrue(SwingUtilities.isEventDispatchThread());
+
+ final InvokeRatherLaterRequest request = myRatherLaterRequests.get(0);
+ request.invokesN++;
+
+ if (request.invokesN == RATHER_LATER_INVOKES_N) {
+ myRatherLaterRequests.remove(0);
+ if (!myRatherLaterRequests.isEmpty()) pumpSwingThread();
+ }
+
+ if (request.myDebuggerCommand instanceof SuspendContextCommandImpl) {
+ request.myDebugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(
+ ((SuspendContextCommandImpl)request.myDebuggerCommand).getSuspendContext()) {
+ @Override
+ public void contextAction() throws Exception {
+ pumpDebuggerThread(request);
+ }
+
+ @Override
+ protected void commandCancelled() {
+ pumpDebuggerThread(request);
+ }
+ });
+ }
+ else {
+ request.myDebugProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
+ @Override
+ protected void action() throws Exception {
+ pumpDebuggerThread(request);
+ }
+
+ @Override
+ protected void commandCancelled() {
+ pumpDebuggerThread(request);
+ }
+ });
+ }
+ }
+
+ private void pumpDebuggerThread(final InvokeRatherLaterRequest request) {
+ if (request.invokesN == RATHER_LATER_INVOKES_N) {
+ request.myDebugProcess.getManagerThread().schedule(request.myDebuggerCommand);
+ }
+ else {
+ if (!SwingUtilities.isEventDispatchThread()) {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ pumpSwingThread();
+ }
+ });
+ }
+ else {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ pumpSwingThread();
+ }
+ });
+ }
+ }
+ }
+
+ protected void invokeRatherLater(final DebuggerCommandImpl command) {
+ IJSwingUtilities.invoke(new Runnable() {
+ @Override
+ public void run() {
+ InvokeRatherLaterRequest request = new InvokeRatherLaterRequest(command, getDebugProcess());
+ myRatherLaterRequests.add(request);
+
+ if (myRatherLaterRequests.size() == 1) pumpSwingThread();
+ }
+ });
+ }
+
+
+ protected void error(Throwable th) {
+ fail(StringUtil.getThrowableText(th));
+ }
+
+ public void createBreakpoints(final PsiFile file) {
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ BreakpointManager breakpointManager = DebuggerManagerImpl.getInstanceEx(myProject).getBreakpointManager();
+ Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
+ int offset = -1;
+ for (; ;) {
+ offset = document.getText().indexOf("Breakpoint!", offset + 1);
+ if (offset == -1) break;
+
+ int commentLine = document.getLineNumber(offset);
+
+ String comment = document.getText().substring(document.getLineStartOffset(commentLine), document.getLineEndOffset(commentLine));
+
+ Breakpoint breakpoint;
+
+ if (comment.indexOf("Method") != -1) {
+ breakpoint = breakpointManager.addMethodBreakpoint(document, commentLine + 1);
+ println("MethodBreakpoint created at " + file.getVirtualFile().getName() + ":" + (commentLine + 2), ProcessOutputTypes.SYSTEM);
+ }
+ else if (comment.indexOf("Field") != -1) {
+ breakpoint = breakpointManager.addFieldBreakpoint(document, commentLine + 1, readValue(comment, "Field"));
+ println("FieldBreakpoint created at " + file.getVirtualFile().getName() + ":" + (commentLine + 2), ProcessOutputTypes.SYSTEM);
+ }
+ else if (comment.indexOf("Exception") != -1) {
+ breakpoint = breakpointManager.addExceptionBreakpoint(readValue(comment, "Exception"), "");
+ println("ExceptionBreakpoint created at " + file.getVirtualFile().getName() + ":" + (commentLine + 2), ProcessOutputTypes.SYSTEM);
+ }
+ else {
+ breakpoint = breakpointManager.addLineBreakpoint(document, commentLine + 1);
+ println("LineBreakpoint created at " + file.getVirtualFile().getName() + ":" + (commentLine + 2), ProcessOutputTypes.SYSTEM);
+ }
+
+ String suspendPolicy = readValue(comment, "suspendPolicy");
+ if (suspendPolicy != null) {
+ breakpoint.SUSPEND = !DebuggerSettings.SUSPEND_NONE.equals(suspendPolicy);
+ breakpoint.SUSPEND_POLICY = suspendPolicy;
+ println("SUSPEND_POLICY = " + suspendPolicy, ProcessOutputTypes.SYSTEM);
+ }
+ String condition = readValue(comment, "Condition");
+ if (condition != null) {
+ breakpoint.CONDITION_ENABLED = true;
+ breakpoint.setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, condition));
+ println("Condition = " + condition, ProcessOutputTypes.SYSTEM);
+ }
+ String passCount = readValue(comment, "Pass count");
+ if (passCount != null) {
+ breakpoint.COUNT_FILTER_ENABLED = true;
+ breakpoint.COUNT_FILTER = Integer.parseInt(passCount);
+ println("Pass count = " + passCount, ProcessOutputTypes.SYSTEM);
+ }
+
+ String classFilters = readValue(comment, "Class filters");
+ if (classFilters != null) {
+ breakpoint.CLASS_FILTERS_ENABLED = true;
+ StringTokenizer tokenizer = new StringTokenizer(classFilters, " ,");
+ ArrayList<ClassFilter> lst = new ArrayList<ClassFilter>();
+
+ while (tokenizer.hasMoreTokens()) {
+ ClassFilter filter = new ClassFilter();
+ filter.setEnabled(true);
+ filter.setPattern(tokenizer.nextToken());
+ lst.add(filter);
+ }
+
+ breakpoint.setClassFilters(lst.toArray(new ClassFilter[lst.size()]));
+ println("Class filters = " + classFilters, ProcessOutputTypes.SYSTEM);
+ }
+ }
+ }
+ };
+ if (!SwingUtilities.isEventDispatchThread()) {
+ DebuggerInvocationUtil.invokeAndWait(myProject, runnable, ModalityState.defaultModalityState());
+ }
+ else {
+ runnable.run();
+ }
+ }
+
+ private Sdk getTestJdk() {
+ try {
+ ProjectJdkImpl jdk = (ProjectJdkImpl)JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk().clone();
+ jdk.setName("JDK");
+ return jdk;
+ }
+ catch (CloneNotSupportedException e) {
+ LOG.error(e);
+ return null;
+ }
+ }
+
+ protected void setTestJDK() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ Sdk jdk = ProjectJdkTable.getInstance().findJdk("JDK");
+ if (jdk != null) {
+ ProjectJdkTable.getInstance().removeJdk(jdk);
+ }
+
+ ProjectJdkTable.getInstance().addJdk(getTestJdk());
+ }
+ });
+ }
+
+ private class DelayedEventsProcessListener implements DebugProcessListener {
+ private final DebugProcessAdapterImpl myTarget;
+
+ public DelayedEventsProcessListener(DebugProcessAdapterImpl target) {
+ myTarget = target;
+ }
+
+ @Override
+ public void threadStarted(DebugProcess proc, ThreadReference thread) {
+ }
+
+ @Override
+ public void threadStopped(DebugProcess proc, ThreadReference thread) {
+ }
+
+ @Override
+ public void paused(final SuspendContext suspendContext) {
+ pauseExecution();
+ myTarget.paused(suspendContext);
+ }
+
+ @Override
+ public void resumed(final SuspendContext suspendContext) {
+ pauseExecution();
+ myTarget.resumed(suspendContext);
+ }
+
+ @Override
+ public void processDetached(final DebugProcess process, final boolean closedByUser) {
+ myTarget.processDetached(process, closedByUser);
+ }
+
+ @Override
+ public void processAttached(final DebugProcess process) {
+ myTarget.processAttached(process);
+ }
+
+ @Override
+ public void connectorIsReady() {
+ myTarget.connectorIsReady();
+ }
+
+ @Override
+ public void attachException(final RunProfileState state, final ExecutionException exception, final RemoteConnection remoteConnection) {
+ myTarget.attachException(state, exception, remoteConnection);
+ }
+
+ private void pauseExecution() {
+ try {
+ Thread.sleep(10);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+ }
+}
diff --git a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
new file mode 100644
index 0000000..0d6624d
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2000-2013 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.debugger.impl;
+
+import com.intellij.debugger.DebuggerTestCase;
+import com.intellij.debugger.engine.DebugProcessImpl;
+import com.intellij.debugger.engine.SuspendContextImpl;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
+import com.intellij.debugger.engine.jdi.StackFrameProxy;
+import com.intellij.debugger.settings.NodeRendererSettings;
+import com.intellij.debugger.ui.impl.watch.DebuggerTree;
+import com.intellij.debugger.ui.impl.watch.LocalVariableDescriptorImpl;
+import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
+import com.intellij.debugger.ui.tree.DebuggerTreeNode;
+import com.intellij.debugger.ui.tree.NodeDescriptor;
+import com.intellij.debugger.ui.tree.ValueDescriptor;
+import com.intellij.debugger.ui.tree.render.NodeRenderer;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.util.Pair;
+import com.sun.jdi.Value;
+
+import java.util.*;
+
+public abstract class DescriptorTestCase extends DebuggerTestCase {
+ private final List<Pair<NodeDescriptorImpl,List<String>>> myDescriptorLog = new ArrayList<Pair<NodeDescriptorImpl, List<String>>>();
+
+ public DescriptorTestCase() {
+ super();
+ }
+
+ protected NodeRenderer getToStringRenderer() {
+ return NodeRendererSettings.getInstance().getToStringRenderer();
+ }
+
+ protected NodeRenderer getMapRenderer() {
+ return getAlternateCollectionRenderer("Map");
+ }
+
+ private NodeRenderer getAlternateCollectionRenderer(final String name) {
+ final NodeRenderer[] renderers = NodeRendererSettings.getInstance().getAlternateCollectionRenderers();
+ for (int idx = 0; idx < renderers.length; idx++) {
+ NodeRenderer renderer = renderers[idx];
+ if (name.equals(renderer.getName())) {
+ return renderer;
+ }
+ }
+ return null;
+ }
+
+ protected NodeRenderer getMapEntryRenderer() {
+ return getAlternateCollectionRenderer("Map.Entry");
+ }
+
+ protected NodeRenderer getHexRenderer() {
+ return NodeRendererSettings.getInstance().getHexRenderer();
+ }
+
+ protected NodeRenderer getCollectionRenderer() {
+ return getAlternateCollectionRenderer("Collection");
+ }
+
+ @Override
+ protected void resume(final SuspendContextImpl suspendContext) {
+ final DebugProcessImpl localProcess = suspendContext.getDebugProcess();
+ invokeRatherLater(new SuspendContextCommandImpl(suspendContext) {
+ @Override
+ public void contextAction() throws Exception {
+ flushDescriptors();
+ localProcess.getManagerThread().schedule(localProcess.createResumeCommand(suspendContext, Priority.LOW));
+ }
+ });
+ }
+
+ protected void logDescriptor(final NodeDescriptorImpl descriptor, String text) {
+ Pair<NodeDescriptorImpl, List<String>> descriptorText = findDescriptorLog(descriptor);
+
+ if(descriptorText == null) {
+ ArrayList<String> allText = new ArrayList<String>();
+ allText.add(text);
+ descriptorText = new Pair<NodeDescriptorImpl, List<String>>(descriptor, allText);
+ myDescriptorLog.add(descriptorText);
+ }
+ else {
+ List<String> allText = descriptorText.getSecond();
+ if(!allText.get(allText.size() - 1).equals(text)) {
+ allText.add(text);
+ }
+ }
+ }
+
+ private Pair<NodeDescriptorImpl, List<String>> findDescriptorLog(final NodeDescriptorImpl descriptor) {
+ Pair<NodeDescriptorImpl, List<String>> descriptorText = null;
+ for (Iterator<Pair<NodeDescriptorImpl, List<String>>> iterator = myDescriptorLog.iterator(); iterator.hasNext();) {
+ Pair<NodeDescriptorImpl, List<String>> pair = iterator.next();
+ if(pair.getFirst() == descriptor) {
+ descriptorText = pair;
+ break;
+ }
+ }
+ return descriptorText;
+ }
+
+ protected void flushDescriptor(final NodeDescriptorImpl descriptor) {
+ Pair<NodeDescriptorImpl, List<String>> descriptorLog = findDescriptorLog(descriptor);
+ if(descriptorLog != null) {
+ printDescriptorLog(descriptorLog);
+ myDescriptorLog.remove(descriptorLog);
+ }
+ }
+
+ protected void flushDescriptors() {
+ for (Iterator<Pair<NodeDescriptorImpl, List<String>>> iterator = myDescriptorLog.iterator(); iterator.hasNext();) {
+ printDescriptorLog(iterator.next());
+ }
+ myDescriptorLog.clear();
+ }
+
+ private void printDescriptorLog(Pair<NodeDescriptorImpl, List<String>> pair) {
+ for (Iterator<String> it = pair.getSecond().iterator(); it.hasNext();) {
+ String text = it.next();
+ print(text, ProcessOutputTypes.SYSTEM);
+ }
+ }
+
+ protected void disableRenderer(NodeRenderer renderer) {
+ renderer.setEnabled(false);
+ }
+
+ protected void enableRenderer(NodeRenderer renderer) {
+ renderer.setEnabled(true);
+ }
+
+ protected LocalVariableDescriptorImpl localVar(DebuggerTree frameTree,
+ EvaluationContextImpl evaluationContext,
+ String name) {
+ try {
+ StackFrameProxy frameProxy = evaluationContext.getFrameProxy();
+ LocalVariableDescriptorImpl local = frameTree.getNodeFactory().getLocalVariableDescriptor(null, frameProxy.visibleVariableByName(name));
+ local.setContext(evaluationContext);
+ return local;
+ } catch (EvaluateException e) {
+ error(e);
+ return null;
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ flushDescriptors();
+ super.tearDown();
+ }
+
+ protected void expandAll(final DebuggerTree tree, final Runnable runnable) {
+ doExpandAll(tree, runnable, new HashSet<Value>(), null);
+ }
+
+ protected static interface NodeFilter {
+ boolean shouldExpand(DebuggerTreeNode node);
+ }
+
+ protected void expandAll(final DebuggerTree tree, final Runnable runnable, NodeFilter filter) {
+ doExpandAll(tree, runnable, new HashSet<Value>(), filter);
+ }
+
+ private void doExpandAll(final DebuggerTree tree, final Runnable runnable, final Set<Value> alreadyExpanded, final NodeFilter filter) {
+ invokeRatherLater(tree.getDebuggerContext().getSuspendContext(), new Runnable() {
+ @Override
+ public void run() {
+ boolean anyCollapsed = false;
+ for(int i = 0; i < tree.getRowCount(); i++) {
+ final DebuggerTreeNode treeNode = (DebuggerTreeNode)tree.getPathForRow(i).getLastPathComponent();
+ if(tree.isCollapsed(i) && !treeNode.isLeaf()) {
+ final NodeDescriptor nodeDescriptor = treeNode.getDescriptor();
+ boolean shouldExpand = filter == null? true : filter.shouldExpand(treeNode);
+ if (shouldExpand) {
+ // additional checks to prevent infinite expand
+ if (nodeDescriptor instanceof ValueDescriptor) {
+ final Value value = ((ValueDescriptor)nodeDescriptor).getValue();
+ shouldExpand = !alreadyExpanded.contains(value);
+ if (shouldExpand) {
+ alreadyExpanded.add(value);
+ }
+ }
+ }
+ if (shouldExpand) {
+ anyCollapsed = true;
+ tree.expandRow(i);
+ }
+ }
+ }
+
+ if (anyCollapsed) {
+ doExpandAll(tree, runnable, alreadyExpanded, filter);
+ }
+ else {
+ runnable.run();
+ }
+ }
+ });
+ }
+}
diff --git a/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java b/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java
new file mode 100644
index 0000000..9c48ade
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2000-2013 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.debugger.impl;
+
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.idea.IdeaLogger;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.HashMap;
+import junit.framework.Assert;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class OutputChecker {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.OutputChecker");
+
+ protected final String myAppPath;
+
+ public static final Key[] OUTPUT_ORDER = new Key[] {
+ ProcessOutputTypes.SYSTEM, ProcessOutputTypes.STDOUT, ProcessOutputTypes.STDERR
+ };
+ private Map<Key, StringBuffer> myBuffers;
+ protected String myTestName;
+
+
+ //ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2
+ private static final Pattern JDI_BUG_OUTPUT_PATTERN_1 =
+ Pattern.compile("ERROR\\:\\s+JDWP\\s+Unable\\s+to\\s+get\\s+JNI\\s+1\\.2\\s+environment,\\s+jvm-\\>GetEnv\\(\\)\\s+return\\s+code\\s+=\\s+-2\n");
+ //JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [../../../src/share/back/util.c:820]
+ private static final Pattern JDI_BUG_OUTPUT_PATTERN_2 =
+ Pattern.compile("JDWP\\s+exit\\s+error\\s+AGENT_ERROR_NO_JNI_ENV.*\\]\n");
+
+ public OutputChecker(String appPath) {
+ myAppPath = appPath;
+ }
+
+ public void init(String testName) {
+ IdeaLogger.ourErrorsOccurred = null;
+
+ testName = Character.toLowerCase(testName.charAt(0)) + testName.substring(1);
+ myTestName = testName;
+ synchronized (this) {
+ myBuffers = new HashMap<Key, StringBuffer>();
+ }
+ }
+
+ public void print(String s, Key outputType) {
+ synchronized (this) {
+ if (myBuffers != null) {
+ StringBuffer buffer = myBuffers.get(outputType);
+ if (buffer == null) {
+ myBuffers.put(outputType, buffer = new StringBuffer());
+ }
+ buffer.append(s);
+ }
+ }
+ }
+
+ public void println(String s, Key outputType) {
+ print(s + "\n", outputType);
+ }
+
+ public void checkValid(Sdk jdk) throws Exception {
+ checkValid(jdk, false);
+ }
+
+ public void checkValid(Sdk jdk, boolean sortClassPath) throws Exception {
+ if (IdeaLogger.ourErrorsOccurred != null) {
+ throw IdeaLogger.ourErrorsOccurred;
+ }
+
+ String actual = preprocessBuffer(jdk, buildOutputString(), sortClassPath);
+
+ File outs = new File(myAppPath + File.separator + "outs");
+ assert outs.exists() || outs.mkdirs() : outs;
+
+ File outFile = new File(outs, myTestName + ".out");
+ if (!outFile.exists()) {
+ if (SystemInfo.isWindows) {
+ final File winOut = new File(outs, myTestName + ".win.out");
+ if (winOut.exists()) {
+ outFile = winOut;
+ }
+ }
+ else if (SystemInfo.isUnix) {
+ final File unixOut = new File(outs, myTestName + ".unx.out");
+ if (unixOut.exists()) {
+ outFile = unixOut;
+ }
+ }
+ }
+
+ if (!outFile.exists()) {
+ FileOutputStream fos = new FileOutputStream(outFile, false);
+ try {
+ fos.write(actual.getBytes());
+ }
+ finally {
+ fos.close();
+ }
+ LOG.error("Test file created " + outFile.getPath() + "\n" + "**************** Don't forget to put it into VCS! *******************");
+ }
+ else {
+ String originalText = FileUtil.loadFile(outFile);
+ String expected = originalText;
+
+ expected = StringUtil.replace(expected, "\r\n", "\n");
+ expected = StringUtil.replace(expected, "\r", "\n");
+
+ if (!expected.equals(actual)) {
+ System.out.println("expected:");
+ System.out.println(originalText);
+ System.out.println("actual:");
+ System.out.println(actual);
+
+ Assert.assertEquals(originalText, actual);
+ }
+ }
+ }
+
+ private synchronized String buildOutputString() {
+ final StringBuilder result = new StringBuilder();
+ for (Key key : OUTPUT_ORDER) {
+ final StringBuffer buffer = myBuffers.get(key);
+ if (buffer != null) {
+ result.append(buffer.toString());
+ }
+ }
+ return result.toString();
+ }
+
+ private String preprocessBuffer(final Sdk testJdk, final String buffer, final boolean sortClassPath) throws Exception {
+ Application application = ApplicationManager.getApplication();
+
+ if (application == null) return buffer;
+
+ final Exception[] ex = new Exception[]{null};
+
+ String actual = application.runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ try {
+ String internalJdkHome = JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk().getHomeDirectory().getPath();
+ //System.out.println("internalJdkHome = " + internalJdkHome);
+
+ String result = buffer;
+ //System.out.println("Original Output = " + result);
+ final boolean shouldIgnoreCase = !SystemInfo.isFileSystemCaseSensitive;
+
+ result = StringUtil.replace(result, "\r\n", "\n");
+ result = StringUtil.replace(result, "\r", "\n");
+ result = StringUtil.replace(result, testJdk.getHomePath(), "!TEST_JDK!", shouldIgnoreCase);
+ result = StringUtil.replace(result, myAppPath, "!APP_PATH!", shouldIgnoreCase);
+ result = StringUtil.replace(result, myAppPath.replace(File.separatorChar, '/'), "!APP_PATH!", shouldIgnoreCase);
+ result = StringUtil.replace(result, JavaSdkUtil.getIdeaRtJarPath(), "!RT_JAR!", shouldIgnoreCase);
+ result = StringUtil.replace(result, JavaSdkUtil.getJunit4JarPath(), "!JUNIT4_JAR!", shouldIgnoreCase);
+ result = StringUtil.replace(result, InetAddress.getLocalHost().getCanonicalHostName(), "!HOST_NAME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, InetAddress.getLocalHost().getHostName(), "!HOST_NAME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, "127.0.0.1", "!HOST_NAME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, JavaSdkUtil.getIdeaRtJarPath().replace('/', File.separatorChar), "!RT_JAR!", shouldIgnoreCase);
+ result = StringUtil.replace(result, internalJdkHome.replace('/', File.separatorChar), "!JDK_HOME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, internalJdkHome, "!JDK_HOME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, PathManager.getHomePath(), "!IDEA_HOME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, "Process finished with exit code 255", "Process finished with exit code -1");
+
+ result = replaceAdditionalInOutput(result);
+
+// result = result.replaceAll(" +\n", "\n");
+ result = result.replaceAll("!HOST_NAME!:\\d*", "!HOST_NAME!:!HOST_PORT!");
+ result = result.replaceAll("at \\'.*?\\'", "at '!HOST_NAME!:PORT_NAME!'");
+ result = result.replaceAll("address: \\'.*?\\'", "address: '!HOST_NAME!:PORT_NAME!'");
+ result = result.replaceAll("file.*AppletPage.*\\.html", "file:/!APPLET_HTML!");
+ result = result.replaceAll("\"(!JDK_HOME!.*?)\"", "$1");
+ result = result.replaceAll("\"(!APP_PATH!.*?)\"", "$1");
+
+ result = result.replaceAll("-Didea.launcher.port=\\d*", "-Didea.launcher.port=!IDEA_LAUNCHER_PORT!");
+ result = result.replaceAll("-Dfile.encoding=[\\w\\d-]*", "-Dfile.encoding=!FILE_ENCODING!");
+ result = result.replaceAll("\\((.*)\\:\\d+\\)", "($1:!LINE_NUMBER!)");
+
+ int commandLineStart = result.indexOf("!JDK_HOME!");
+ while (commandLineStart != -1) {
+ final StringBuilder builder = new StringBuilder(result);
+ int i = commandLineStart + 1;
+ while (i < builder.length()) {
+ char c = builder.charAt(i);
+ if (c == '\n') break;
+ else if (c == File.separatorChar) builder.setCharAt(i, '\\');
+ i++;
+ }
+ result = builder.toString();
+ commandLineStart = result.indexOf("!JDK_HOME!", commandLineStart + 1);
+ }
+
+ result = stripQuotesAroundClasspath(result);
+
+ final Matcher matcher = Pattern.compile("-classpath\\s+(\\S+)\\s+").matcher(result);
+ while (matcher.find()) {
+ final String classPath = matcher.group(1);
+ final String[] classPathElements = classPath.split(File.pathSeparator);
+ if (sortClassPath) {
+ Arrays.sort(classPathElements);
+ }
+ final String sortedPath = StringUtil.join(classPathElements, ";");
+ result = StringUtil.replace(result, classPath, sortedPath);
+ }
+
+ result = JDI_BUG_OUTPUT_PATTERN_1.matcher(result).replaceAll("");
+ result = JDI_BUG_OUTPUT_PATTERN_2.matcher(result).replaceAll("");
+
+ return result;
+ }
+ catch (Exception exception) {
+ ex[0] = exception;
+ return null;
+ }
+ }
+ });
+
+
+ if (ex[0] != null) throw ex[0];
+
+ return actual;
+ }
+
+ protected String replaceAdditionalInOutput(String str) {
+ return str;
+ }
+
+ //do not depend on spaces in jdk path
+ private static String stripQuotesAroundClasspath(String result) {
+ final String clsp = "-classpath ";
+ int clspIdx = 0;
+ while (true) {
+ clspIdx = result.indexOf(clsp, clspIdx);
+ if (clspIdx <= -1) {
+ break;
+ }
+
+ final int spaceIdx = result.indexOf(" ", clspIdx + clsp.length());
+ if (spaceIdx > -1) {
+ result = result.substring(0, clspIdx) +
+ clsp +
+ StringUtil.stripQuotesAroundValue(result.substring(clspIdx + clsp.length(), spaceIdx)) +
+ result.substring(spaceIdx);
+ clspIdx += clsp.length();
+ } else {
+ break;
+ }
+ }
+ return result;
+ }
+}
diff --git a/java/testFramework/src/com/intellij/debugger/impl/SynchronizationBasedSemaphore.java b/java/testFramework/src/com/intellij/debugger/impl/SynchronizationBasedSemaphore.java
new file mode 100644
index 0000000..8c57cd3
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/impl/SynchronizationBasedSemaphore.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2013 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.debugger.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: Nov 17, 2009
+ */
+public class SynchronizationBasedSemaphore {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.Semaphore");
+ private int mySemaphore = 0;
+
+ public synchronized void down() {
+ mySemaphore++;
+ if (mySemaphore == 0) {
+ notifyAll();
+ }
+ }
+
+ public synchronized void up() {
+ mySemaphore--;
+ if (mySemaphore == 0) {
+ notifyAll();
+ }
+ }
+
+ public synchronized void waitFor() {
+ try {
+ while (mySemaphore > 0) {
+ wait();
+ }
+ }
+ catch (InterruptedException e) {
+ LOG.debug(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ public synchronized boolean waitFor(final long timeout) {
+ try {
+ if (mySemaphore == 0) return true;
+ final long startTime = System.currentTimeMillis();
+ long waitTime = timeout;
+ while (mySemaphore > 0) {
+ wait(waitTime);
+ final long elapsed = System.currentTimeMillis() - startTime;
+ if (elapsed < timeout) {
+ waitTime = timeout - elapsed;
+ }
+ else {
+ break;
+ }
+ }
+ return mySemaphore == 0;
+ }
+ catch (InterruptedException e) {
+ LOG.debug(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java b/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java
new file mode 100644
index 0000000..075c681
--- /dev/null
+++ b/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.execution;
+
+import com.intellij.debugger.impl.OutputChecker;
+import com.intellij.execution.configurations.JavaParameters;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.IdeaTestCase;
+import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.util.Alarm;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ui.UIUtil;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import org.jetbrains.annotations.NonNls;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class ExecutionTestCase extends IdeaTestCase {
+ private OutputChecker myChecker;
+
+ private int myTimeout;
+
+ private static AssertionFailedError ourAssertion;
+ private static final String CLASSES = "classes";
+ private static final String SRC = "src";
+
+ public ExecutionTestCase() {
+ setTimeout(300000); //30 seconds
+ }
+
+ public void setTimeout(int timeout) {
+ myTimeout = timeout;
+ }
+
+ protected abstract OutputChecker initOutputChecker();
+
+ protected abstract String getTestAppPath();
+
+ @Override
+ protected void setUp() throws Exception {
+ ourAssertion = null;
+ ensureCompiledAppExists();
+ myChecker = initOutputChecker();
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ExecutionTestCase.super.setUp();
+ }
+ catch (Throwable e) {
+ e.printStackTrace();
+ assertTrue(false);
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void setUpModule() {
+ super.setUpModule();
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ final String modulePath = getTestAppPath();
+ final String srcPath = modulePath + File.separator + "src";
+ VirtualFile moduleDir = LocalFileSystem.getInstance().findFileByPath(modulePath.replace(File.separatorChar, '/'));
+ VirtualFile srcDir = LocalFileSystem.getInstance().findFileByPath(srcPath.replace(File.separatorChar, '/'));
+
+ final ModuleRootManager rootManager = ModuleRootManager.getInstance(myModule);
+ PsiTestUtil.removeAllRoots(myModule, rootManager.getSdk());
+ PsiTestUtil.addContentRoot(myModule, moduleDir);
+ PsiTestUtil.addSourceRoot(myModule, srcDir);
+ PsiTestUtil.setCompilerOutputPath(myModule, VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(getAppClassesPath())), false);
+ }
+ });
+ }
+
+ public void println(@NonNls String s, Key outputType) {
+ myChecker.println(s, outputType);
+ }
+
+ public void print(String s, Key outputType) {
+ myChecker.print(s, outputType);
+ }
+
+ @Override
+ protected void runBareRunnable(Runnable runnable) throws Throwable {
+ runnable.run();
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ myChecker.init(getTestName(true));
+ super.runTest();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ExecutionTestCase.super.tearDown();
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ }
+ }
+ });
+ if (ourAssertion != null) {
+ throw ourAssertion;
+ }
+ //myChecker.checkValid(getTestProjectJdk());
+ //probably some thread is destroyed right now because of log exception
+ //wait a little bit
+ synchronized (this) {
+ wait(300);
+ }
+ }
+
+ protected JavaParameters createJavaParameters(String mainClass) {
+ JavaParameters parameters = new JavaParameters();
+ parameters.getClassPath().add(getAppClassesPath());
+ parameters.setMainClass(mainClass);
+ parameters.setJdk(JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk());
+ return parameters;
+ }
+
+ protected OutputChecker getChecker() {
+ return myChecker;
+ }
+
+ protected String getAppDataPath() {
+ return getTestAppPath() + File.separator + "data";
+ }
+
+ protected String getAppOptionsPath() {
+ return getTestAppPath() + File.separator + "config" + File.separator + "options";
+ }
+
+ protected String getAppClassesPath() {
+ return getTestAppPath() + File.separator + "classes";
+ }
+
+ public void waitProcess(final ProcessHandler processHandler) {
+ Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, getTestRootDisposable());
+
+ final boolean[] isRunning = {true};
+ alarm.addRequest(new Runnable() {
+ @Override
+ public void run() {
+ boolean b;
+ synchronized (isRunning) {
+ b = isRunning[0];
+ }
+ if (b) {
+ processHandler.destroyProcess();
+ LOG.error("process was running over " + myTimeout / 1000 + " seconds. Interrupted. ");
+ }
+ }
+ }, myTimeout);
+ processHandler.waitFor();
+ synchronized (isRunning) {
+ isRunning[0] = false;
+ }
+ alarm.dispose();
+ }
+
+ public void waitFor(Runnable r) {
+ Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, getTestRootDisposable());
+ final Thread thread = Thread.currentThread();
+
+ final boolean[] isRunning = {true};
+ alarm.addRequest(new Runnable() {
+ @Override
+ public void run() {
+ boolean b;
+ synchronized (isRunning) {
+ b = isRunning[0];
+ }
+ if (b) {
+ thread.interrupt();
+ LOG.error("test was running over " + myTimeout / 1000 + " seconds. Interrupted. ");
+ }
+ }
+ }, myTimeout);
+ r.run();
+ synchronized (isRunning) {
+ isRunning[0] = false;
+ }
+ Thread.interrupted();
+ }
+
+// public static void fail(String message) {
+// ourAssertion = new AssertionFailedError(message);
+// }
+//
+// static public void assertTrue(String message, boolean condition) {
+// if (!condition)
+// fail(message);
+// }
+//
+// static public void assertTrue(boolean condition) {
+// assertTrue(null, condition);
+// }
+
+ private static final int CURRENT_VERSION = 6;
+ private static final String VERSION_FILE_NAME = "version-" + CURRENT_VERSION;
+ protected void ensureCompiledAppExists() throws Exception {
+ final String appPath = getTestAppPath();
+ final File classesDir = new File(appPath, CLASSES);
+ final File versionFile = new File(classesDir, VERSION_FILE_NAME);
+ if (!classesDir.exists() || !versionFile.exists() || !hasCompiledClasses(classesDir)) {
+ FileUtil.delete(classesDir);
+ classesDir.mkdirs();
+ if (compileTinyApp(appPath) != 0) {
+ throw new Exception("Failed to compile debugger test application.\nIt must be compiled in order to run debugger tests.\n" + appPath);
+ }
+ versionFile.createNewFile();
+ }
+ }
+
+ private int compileTinyApp(String appPath) {
+ final List<String> args = new ArrayList<String>();
+ args.add("-g");
+ args.add("-d");
+ args.add(new File(appPath, CLASSES).getPath());
+
+ final Class<TestCase> testCaseClass = TestCase.class;
+ final String junitLibRoot = PathManager.getResourceRoot(testCaseClass, "/" + testCaseClass.getName().replace('.', '/') + ".class");
+ if (junitLibRoot != null) {
+ args.add("-cp");
+ args.add(junitLibRoot);
+ }
+
+ final File[] files = new File(appPath, SRC).listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".java");
+ }
+ });
+ if (files == null) return 0; // Nothing to compile
+
+ for (File file : files) {
+ args.add(file.getPath());
+ }
+ return com.sun.tools.javac.Main.compile(ArrayUtil.toStringArray(args));
+ }
+
+ private boolean hasCompiledClasses(final File classesDir) {
+ for (File file : classesDir.listFiles()) {
+ if (file.isFile() && file.getName().endsWith(".class")) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java b/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java
index a93ea6b..bfeac04 100644
--- a/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java
+++ b/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java
@@ -76,11 +76,11 @@
doTest(folderName, new GlobalInspectionToolWrapper(tool), "java 1.4", checkRange, runDeadCodeFirst);
}
- public void doTest(@NonNls String folderName, InspectionTool tool) {
+ public void doTest(@NonNls String folderName, InspectionToolWrapper tool) {
doTest(folderName, tool, "java 1.4");
}
- public void doTest(@NonNls String folderName, InspectionTool tool, final boolean checkRange) {
+ public void doTest(@NonNls String folderName, InspectionToolWrapper tool, final boolean checkRange) {
doTest(folderName, tool, "java 1.4", checkRange);
}
@@ -88,35 +88,35 @@
doTest(folderName, new LocalInspectionToolWrapper(tool), jdkName);
}
- public void doTest(@NonNls String folderName, InspectionTool tool, @NonNls final String jdkName) {
+ public void doTest(@NonNls String folderName, InspectionToolWrapper tool, @NonNls final String jdkName) {
doTest(folderName, tool, jdkName, false);
}
- public void doTest(@NonNls String folderName, InspectionTool tool, @NonNls final String jdkName, boolean checkRange) {
+ public void doTest(@NonNls String folderName, InspectionToolWrapper tool, @NonNls final String jdkName, boolean checkRange) {
doTest(folderName, tool, jdkName, checkRange, false);
}
public void doTest(@NonNls String folderName,
- InspectionTool tool,
+ InspectionToolWrapper toolWrapper,
@NonNls final String jdkName,
boolean checkRange,
boolean runDeadCodeFirst,
- InspectionTool... additional) {
+ InspectionToolWrapper... additional) {
final String testDir = getTestDataPath() + "/" + folderName;
- runTool(testDir, jdkName, runDeadCodeFirst, tool, additional);
+ runTool(testDir, jdkName, runDeadCodeFirst, toolWrapper, additional);
- InspectionTestUtil.compareToolResults(tool, checkRange, testDir);
+ InspectionTestUtil.compareToolResults(toolWrapper, checkRange, testDir);
}
- protected void runTool(@NonNls final String testDir, @NonNls final String jdkName, final InspectionTool tool) {
+ protected void runTool(@NonNls final String testDir, @NonNls final String jdkName, final InspectionToolWrapper tool) {
runTool(testDir, jdkName, false, tool);
}
protected void runTool(final String testDir,
final String jdkName,
boolean runDeadCodeFirst,
- final InspectionTool tool,
- InspectionTool... additional) {
+ @NotNull InspectionToolWrapper toolWrapper,
+ @NotNull InspectionToolWrapper... additional) {
final VirtualFile[] sourceDir = new VirtualFile[1];
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
@@ -132,14 +132,15 @@
AnalysisScope scope = createAnalysisScope(sourceDir[0].getParent());
InspectionManagerEx inspectionManager = (InspectionManagerEx)InspectionManager.getInstance(getProject());
- InspectionTool[] tools = runDeadCodeFirst ? new InspectionTool[]{new UnusedDeclarationInspection(), tool} : new InspectionTool[]{tool};
- tools = ArrayUtil.mergeArrays(tools, additional);
+ InspectionToolWrapper[] toolWrappers = runDeadCodeFirst ? new InspectionToolWrapper []{new GlobalInspectionToolWrapper(new UnusedDeclarationInspection()), toolWrapper} : new InspectionToolWrapper []{toolWrapper};
+ toolWrappers = ArrayUtil.mergeArrays(toolWrappers, additional);
final GlobalInspectionContextImpl globalContext =
- CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, getProject(), inspectionManager, tools);
+ CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, getProject(), inspectionManager, toolWrappers);
- InspectionTestUtil.runTool(tool, scope, globalContext, inspectionManager);
+ InspectionTestUtil.runTool(toolWrapper, scope, globalContext, inspectionManager);
}
+ @NotNull
protected AnalysisScope createAnalysisScope(VirtualFile sourceDir) {
PsiManager psiManager = PsiManager.getInstance(myProject);
return new AnalysisScope(psiManager.findDirectory(sourceDir));
diff --git a/java/testFramework/testFramework-java.iml b/java/testFramework/testFramework-java.iml
index 9d48d3d..ed67da5 100644
--- a/java/testFramework/testFramework-java.iml
+++ b/java/testFramework/testFramework-java.iml
@@ -22,6 +22,8 @@
<orderEntry type="module" module-name="relaxng" exported="" scope="TEST" />
<orderEntry type="module" module-name="idea-ui" exported="" />
<orderEntry type="module" module-name="external-system-impl" exported="" scope="TEST" />
+ <orderEntry type="module" module-name="debugger-impl" exported="" />
+ <orderEntry type="module" module-name="execution-openapi" exported="" />
</component>
<component name="copyright">
<Base>