diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index e866606c5852..c32d10a8ced1 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -664,8 +664,9 @@ def setPluginVersionAndSince(String moduleName, String version) { if (file.isFile()) { def text = file.text if (!text.contains("")) { - def nextMajorVersion = Integer.parseInt(version.substring(0, version.indexOf('.'))) + 1 - file.text = text.replace("", "\n ${version}\n \n") + def dotIndex = version.indexOf('.') + def untilBuild = dotIndex > 0 ? (Integer.parseInt(version.substring(0, dotIndex)) + 1).toString() + ".0" : version + file.text = text.replace("", "\n ${version}\n \n") } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index f563f316422b..5448aff23bb9 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -740,7 +740,7 @@ public class GenericsHighlightUtil { if (type instanceof PsiClassType && ((PsiClassType)type).resolve() == aClass) return null; } - if (PsiUtil.isCompileTimeConstant(field)) return null; + if (PsiUtil.isCompileTimeConstant((PsiVariable)field)) return null; String description = JavaErrorMessages.message( "illegal.to.access.static.member.from.enum.constructor.or.instance.initializer", diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index 830678b58b1e..0dbd868f5144 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -292,7 +292,7 @@ public class HighlightClassUtil { } PsiField field = (PsiField)keyword.getParent().getParent(); - if (PsiUtilCore.hasErrorElementChild(field) || PsiUtil.isCompileTimeConstant(field)) { + if (PsiUtilCore.hasErrorElementChild(field) || PsiUtil.isCompileTimeConstant((PsiVariable)field)) { return null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 905bba345c72..bd39b5f96f47 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -21,7 +21,7 @@ import com.intellij.codeInsight.ExternalAnnotationsManager; import com.intellij.codeInsight.InferredAnnotationsManager; import com.intellij.codeInsight.documentation.DocumentationManagerProtocol; import com.intellij.codeInsight.documentation.DocumentationManagerUtil; -import com.intellij.javadoc.JavadocConfiguration; +import com.intellij.javadoc.JavadocGeneratorRunProfile; import com.intellij.lang.ASTNode; import com.intellij.lang.LangBundle; import com.intellij.openapi.diagnostic.Logger; @@ -233,7 +233,7 @@ public class JavaDocInfoGenerator { myProject = project; myElement = element; - Sdk jdk = JavadocConfiguration.getSdk(myProject); + Sdk jdk = JavadocGeneratorRunProfile.getSdk(myProject); mySdkVersion = jdk == null ? null : JavaSdk.getInstance().getVersion(jdk); } diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocConfigurable.java b/java/java-impl/src/com/intellij/javadoc/JavadocConfigurable.java index d0d6ad8ff11b..0f51d477408c 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavadocConfigurable.java +++ b/java/java-impl/src/com/intellij/javadoc/JavadocConfigurable.java @@ -16,6 +16,9 @@ package com.intellij.javadoc; import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.JavadocOrderRootType; import com.intellij.psi.PsiKeyword; import javax.swing.*; @@ -24,14 +27,21 @@ import java.io.File; public final class JavadocConfigurable implements Configurable { private JavadocGenerationPanel myPanel; private final JavadocConfiguration myConfiguration; + private final Project myProject; - public JavadocConfigurable(JavadocConfiguration configuration) { + public JavadocConfigurable(JavadocConfiguration configuration, Project project) { myConfiguration = configuration; + myProject = project; + } + + public static boolean sdkHasJavadocUrls(Project project) { + Sdk sdk = JavadocGeneratorRunProfile.getSdk(project); + return sdk != null && sdk.getRootProvider().getFiles(JavadocOrderRootType.getInstance()).length > 0; } public JComponent createComponent() { myPanel = new JavadocGenerationPanel(); - myPanel.myLinkToJdkDocs.setEnabled(myConfiguration.sdkHasJavadocUrls()); + myPanel.myLinkToJdkDocs.setEnabled(sdkHasJavadocUrls(myProject)); return myPanel.myPanel; } diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java index ae35f7e616d5..5ac31e88f656 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java +++ b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java @@ -15,57 +15,21 @@ */ package com.intellij.javadoc; -import com.intellij.analysis.AnalysisScope; -import com.intellij.execution.CantRunException; -import com.intellij.execution.ExecutionException; -import com.intellij.execution.Executor; -import com.intellij.execution.configurations.*; -import com.intellij.execution.filters.RegexpFilter; -import com.intellij.execution.process.OSProcessHandler; -import com.intellij.execution.process.ProcessAdapter; -import com.intellij.execution.process.ProcessEvent; -import com.intellij.execution.process.ProcessTerminatedListener; -import com.intellij.execution.runners.ExecutionEnvironment; -import com.intellij.ide.BrowserUtil; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.projectRoots.JavaSdk; -import com.intellij.openapi.projectRoots.JavaSdkType; -import com.intellij.openapi.projectRoots.JavaSdkVersion; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.ex.PathUtilEx; -import com.intellij.openapi.roots.*; -import com.intellij.openapi.util.*; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; -import com.intellij.util.PathsList; -import com.intellij.util.containers.HashSet; +import com.intellij.openapi.util.DefaultJDOMExternalizer; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.psi.PsiKeyword; import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; -import javax.swing.*; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; +import java.lang.reflect.Field; /** * @author Eugene Zhuravlev * Date: Apr 24, 2004 */ -public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizable{ +public class JavadocConfiguration implements JDOMExternalizable { public String OUTPUT_DIRECTORY; public String OPTION_SCOPE = PsiKeyword.PROTECTED; public boolean OPTION_HIERARCHY = true; @@ -81,46 +45,10 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl public String HEAP_SIZE; public String LOCALE; public boolean OPEN_IN_BROWSER = true; - - private final Project myProject; - private AnalysisScope myGenerationScope; - private static final Logger LOGGER = Logger.getInstance("#" + JavadocConfiguration.class.getName()); public boolean OPTION_INCLUDE_LIBS = false; public boolean OPTION_LINK_TO_JDK_DOCS = false; - public void setGenerationScope(AnalysisScope generationScope) { - myGenerationScope = generationScope; - } - - public JavadocConfiguration(Project project) { - myProject = project; - } - - public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException { - return new MyJavaCommandLineState(myProject, myGenerationScope, env); - } - - public String getName() { - return JavadocBundle.message("javadoc.settings.title"); - } - - public void checkConfiguration() throws RuntimeConfigurationException { - if (myGenerationScope == null) { - throw new RuntimeConfigurationError(JavadocBundle.message("javadoc.settings.not.specified")); - } - } - - public JavadocConfigurable createConfigurable() { - return new JavadocConfigurable(this); - } - - public Icon getIcon() { - return null; - } - - @NotNull - public Module[] getModules() { - return Module.EMPTY_ARRAY; + public JavadocConfiguration() { } public void readExternal(Element element) throws InvalidDataException { @@ -128,280 +56,12 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl } public void writeExternal(Element element) throws WriteExternalException { - DefaultJDOMExternalizer.writeExternal(this, element); - } - - public boolean sdkHasJavadocUrls() { - Sdk sdk = getSdk(myProject); - return sdk != null && sdk.getRootProvider().getFiles(JavadocOrderRootType.getInstance()).length > 0; - } - - public static Sdk getSdk(@NotNull Project project) { - return PathUtilEx.getAnyJdk(project); - } - - private class MyJavaCommandLineState extends CommandLineState { - private final AnalysisScope myGenerationOptions; - private final Project myProject; - @NonNls private static final String INDEX_HTML = "index.html"; - - public MyJavaCommandLineState(Project project, AnalysisScope generationOptions, ExecutionEnvironment env) { - super(env); - myGenerationOptions = generationOptions; - myProject = project; - addConsoleFilters(new RegexpFilter(project, "$FILE_PATH$:$LINE$:[^\\^]+\\^"), - new RegexpFilter(project, "$FILE_PATH$:$LINE$: warning - .+$")); - } - - protected GeneralCommandLine createCommandLine() throws ExecutionException { - final GeneralCommandLine cmdLine = new GeneralCommandLine(); - final Sdk jdk = getSdk(myProject); - setupExeParams(jdk, cmdLine); - setupProgramParameters(jdk, cmdLine); - return cmdLine; - } - - private void setupExeParams(final Sdk jdk, GeneralCommandLine cmdLine) throws ExecutionException { - final String jdkPath = jdk != null && jdk.getSdkType() instanceof JavaSdkType ? ((JavaSdkType)jdk.getSdkType()).getBinPath(jdk) : null; - if (jdkPath == null) { - throw new CantRunException(JavadocBundle.message("javadoc.generate.no.jdk.path")); + DefaultJDOMExternalizer.writeExternal(this, element, new DefaultJDOMExternalizer.JDOMFilter() { + @Override + public boolean isAccept(@NotNull Field field) { + return !field.getName().equals("OPTION_LINK_TO_JDK_DOCS") || OPTION_LINK_TO_JDK_DOCS; } - JavaSdkVersion version = JavaSdk.getInstance().getVersion(jdk); - if (HEAP_SIZE != null && HEAP_SIZE.trim().length() != 0) { - if (version == null || version.isAtLeast(JavaSdkVersion.JDK_1_2)) { - cmdLine.getParametersList().prepend("-J-Xmx" + HEAP_SIZE + "m"); - } - else { - cmdLine.getParametersList().prepend("-J-mx" + HEAP_SIZE + "m"); - } - } - cmdLine.setWorkDirectory((File)null); - @NonNls final String javadocExecutableName = File.separator + (SystemInfo.isWindows ? "javadoc.exe" : "javadoc"); - @NonNls String exePath = jdkPath.replace('/', File.separatorChar) + javadocExecutableName; - if (new File(exePath).exists()) { - cmdLine.setExePath(exePath); - } else { //try to use wrapper jdk - exePath = new File(jdkPath).getParent().replace('/', File.separatorChar) + javadocExecutableName; - if (!new File(exePath).exists()){ - final File parent = new File(System.getProperty("java.home")).getParentFile(); //try system jre - exePath = parent.getPath() + File.separator + "bin" + javadocExecutableName; - if (!new File(exePath).exists()){ - throw new CantRunException(JavadocBundle.message("javadoc.generate.no.jdk.path")); - } - } - cmdLine.setExePath(exePath); - } - } - - private void setupProgramParameters(final Sdk jdk, final GeneralCommandLine cmdLine) throws CantRunException { - @NonNls final ParametersList parameters = cmdLine.getParametersList(); - - if (LOCALE != null && LOCALE.length() > 0) { - parameters.add("-locale"); - parameters.add(LOCALE); - } - - if (OPTION_SCOPE != null) { - parameters.add("-" + OPTION_SCOPE); - } - - if (!OPTION_HIERARCHY) { - parameters.add("-notree"); - } - - if (!OPTION_NAVIGATOR) { - parameters.add("-nonavbar"); - } - - if (!OPTION_INDEX) { - parameters.add("-noindex"); - } - else if (OPTION_SEPARATE_INDEX) { - parameters.add("-splitindex"); - } - - if (OPTION_DOCUMENT_TAG_USE) { - parameters.add("-use"); - } - - if (OPTION_DOCUMENT_TAG_AUTHOR) { - parameters.add("-author"); - } - - if (OPTION_DOCUMENT_TAG_VERSION) { - parameters.add("-version"); - } - - if (!OPTION_DOCUMENT_TAG_DEPRECATED) { - parameters.add("-nodeprecated"); - } - else if (!OPTION_DEPRECATED_LIST) { - parameters.add("-nodeprecatedlist"); - } - - parameters.addParametersString(OTHER_OPTIONS); - - final Set modules = new LinkedHashSet(); - try { - final File sourcePathTempFile = FileUtil.createTempFile("javadoc", "args.txt", true); - parameters.add("@" + sourcePathTempFile.getCanonicalPath()); - final PrintWriter writer = new PrintWriter(new FileWriter(sourcePathTempFile)); - try { - final Collection packages = new HashSet(); - final Collection sources = new HashSet(); - final Runnable findRunnable = new Runnable() { - public void run() { - final int scopeType = myGenerationOptions.getScopeType(); - final boolean usePackageNotation = scopeType == AnalysisScope.MODULE || - scopeType == AnalysisScope.MODULES || - scopeType == AnalysisScope.PROJECT || - scopeType == AnalysisScope.DIRECTORY; - myGenerationOptions.accept(new MyContentIterator(myProject, packages, sources, modules, usePackageNotation)); - } - }; - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(findRunnable, "Search for sources to generate javadoc in...", true, myProject)) { - return; - } - if (packages.size() + sources.size() == 0) { - throw new CantRunException(JavadocBundle.message("javadoc.generate.no.classes.in.selected.packages.error")); - } - for (String aPackage : packages) { - writer.println(aPackage); - } - //http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#runningjavadoc - for (String source : sources) { - writer.println(StringUtil.wrapWithDoubleQuote(source)); - } - writer.println("-sourcepath"); - OrderEnumerator enumerator = OrderEnumerator.orderEntries(myProject); - if (!OPTION_INCLUDE_LIBS) { - enumerator = enumerator.withoutSdk().withoutLibraries(); - } - final PathsList pathsList = enumerator.getSourcePathsList(); - final List files = pathsList.getRootDirs(); - final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); - final StringBuilder sourcePath = new StringBuilder(); - boolean start = true; - for (VirtualFile file : files) { - if (!myGenerationOptions.isIncludeTestSource() && fileIndex.isInTestSourceContent(file)) continue; - if (start) { - start = false; - } - else { - sourcePath.append(File.pathSeparator); - } - sourcePath.append(file.getPath()); - } - writer.println(StringUtil.wrapWithDoubleQuote(sourcePath.toString())); - } - finally { - writer.close(); - } - } - catch (IOException e) { - LOGGER.error(e); - } - - if (OPTION_LINK_TO_JDK_DOCS) { - VirtualFile[] docUrls = jdk.getRootProvider().getFiles(JavadocOrderRootType.getInstance()); - for (VirtualFile docUrl : docUrls) { - parameters.add("-link"); - parameters.add(VfsUtil.toUri(docUrl).toString()); - } - } - - final PathsList classPath; - final OrderEnumerator orderEnumerator = ProjectRootManager.getInstance(myProject).orderEntries(modules); - if (jdk.getSdkType() instanceof JavaSdk) { - classPath = orderEnumerator.withoutSdk().withoutModuleSourceEntries().getPathsList(); - } - else { - //libraries are included into jdk - classPath = orderEnumerator.withoutModuleSourceEntries().getPathsList(); - } - final String classPathString = classPath.getPathsString(); - if (classPathString.length() > 0) { - parameters.add("-classpath"); - parameters.add(classPathString); - } - - if (OUTPUT_DIRECTORY != null) { - parameters.add("-d"); - parameters.add(OUTPUT_DIRECTORY.replace('/', File.separatorChar)); - } - - } - - @NotNull - protected OSProcessHandler startProcess() throws ExecutionException { - final OSProcessHandler handler = JavaCommandLineStateUtil.startProcess(createCommandLine()); - ProcessTerminatedListener.attach(handler, myProject, JavadocBundle.message("javadoc.generate.exited")); - handler.addProcessListener(new ProcessAdapter() { - public void processTerminated(ProcessEvent event) { - if (OPEN_IN_BROWSER) { - File url = new File(OUTPUT_DIRECTORY, INDEX_HTML); - if (url.exists() && event.getExitCode() == 0) { - BrowserUtil.browse(url); - } - } - } - }); - return handler; - } - } - - private static class MyContentIterator extends PsiRecursiveElementWalkingVisitor { - private final PsiManager myPsiManager; - private final Collection myPackages; - private final Collection mySourceFiles; - private final Set myModules; - private final boolean myUsePackageNotation; - - public MyContentIterator(Project project, - Collection packages, - Collection sources, - Set modules, - boolean canUsePackageNotation) { - myModules = modules; - myUsePackageNotation = canUsePackageNotation; - myPsiManager = PsiManager.getInstance(project); - myPackages = packages; - mySourceFiles = sources; - } - - @Override - public void visitFile(PsiFile file) { - final VirtualFile fileOrDir = file.getVirtualFile(); - if (fileOrDir == null) return; - if (!fileOrDir.isInLocalFileSystem()) return; - final Module module = ModuleUtilCore.findModuleForFile(fileOrDir, myPsiManager.getProject()); - if (module != null) { - myModules.add(module); - } - if (file instanceof PsiJavaFile) { - final PsiJavaFile javaFile = (PsiJavaFile)file; - final String packageName = javaFile.getPackageName(); - if (containsPackagePrefix(module, packageName) || (packageName.length() == 0 && !(javaFile instanceof ServerPageFile)) || !myUsePackageNotation) { - mySourceFiles.add(FileUtil.toSystemIndependentName(fileOrDir.getPath())); - } - else { - myPackages.add(packageName); - } - } - } - - private static boolean containsPackagePrefix(Module module, String packageFQName) { - if (module == null) return false; - for (ContentEntry contentEntry : ModuleRootManager.getInstance(module).getContentEntries()) { - for (SourceFolder sourceFolder : contentEntry.getSourceFolders(JavaModuleSourceRootTypes.SOURCES)) { - final String packagePrefix = sourceFolder.getPackagePrefix(); - final int prefixLength = packagePrefix.length(); - if (prefixLength > 0 && packageFQName.startsWith(packagePrefix)) { - return true; - } - } - } - return false; - } + }); } } + diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java index 3589918fe4a1..b1a5ef4984ef 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java +++ b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java @@ -20,7 +20,6 @@ import com.intellij.analysis.AnalysisScope; import com.intellij.execution.ExecutionException; import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.execution.runners.ExecutionEnvironmentBuilder; -import com.intellij.execution.runners.ExecutionUtil; import com.intellij.execution.util.ExecutionErrorDialog; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; @@ -48,7 +47,7 @@ public final class JavadocGenerationManager implements PersistentStateComponent< JavadocGenerationManager(Project project) { myProject = project; - myConfiguration = new JavadocConfiguration(project); + myConfiguration = new JavadocConfiguration(); } @Override @@ -78,9 +77,9 @@ public final class JavadocGenerationManager implements PersistentStateComponent< } public void generateJavadoc(AnalysisScope scope) { - myConfiguration.setGenerationScope(scope); try { - ExecutionEnvironmentBuilder.create(myProject, DefaultRunExecutor.getRunExecutorInstance(), myConfiguration).buildAndExecute(); + JavadocGeneratorRunProfile profile = new JavadocGeneratorRunProfile(myProject, scope, myConfiguration); + ExecutionEnvironmentBuilder.create(myProject, DefaultRunExecutor.getRunExecutorInstance(), profile).buildAndExecute(); } catch (ExecutionException e) { ExecutionErrorDialog.show(e, CommonBundle.getErrorTitle(), myProject); diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGeneratorRunProfile.java b/java/java-impl/src/com/intellij/javadoc/JavadocGeneratorRunProfile.java new file mode 100644 index 000000000000..b18a5b38ef6f --- /dev/null +++ b/java/java-impl/src/com/intellij/javadoc/JavadocGeneratorRunProfile.java @@ -0,0 +1,373 @@ +/* + * Copyright 2000-2015 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.javadoc; + +import com.intellij.analysis.AnalysisScope; +import com.intellij.execution.CantRunException; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.Executor; +import com.intellij.execution.configurations.*; +import com.intellij.execution.filters.RegexpFilter; +import com.intellij.execution.process.OSProcessHandler; +import com.intellij.execution.process.ProcessAdapter; +import com.intellij.execution.process.ProcessEvent; +import com.intellij.execution.process.ProcessTerminatedListener; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.JavaSdk; +import com.intellij.openapi.projectRoots.JavaSdkType; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.ex.PathUtilEx; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.util.PathsList; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; + +import javax.swing.*; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** + * @author nik + */ +public class JavadocGeneratorRunProfile implements ModuleRunProfile { + private static final Logger LOGGER = Logger.getInstance("#" + JavadocConfiguration.class.getName()); + private final Project myProject; + private final AnalysisScope myGenerationScope; + private final JavadocConfiguration myConfiguration; + + public JavadocGeneratorRunProfile(Project project, AnalysisScope generationScope, JavadocConfiguration configuration) { + myProject = project; + myGenerationScope = generationScope; + myConfiguration = configuration; + } + + public static Sdk getSdk(@NotNull Project project) { + return PathUtilEx.getAnyJdk(project); + } + + public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException { + return new MyJavaCommandLineState(myConfiguration, myProject, myGenerationScope, env); + } + + public String getName() { + return JavadocBundle.message("javadoc.settings.title"); + } + + public Icon getIcon() { + return null; + } + + @NotNull + public Module[] getModules() { + return Module.EMPTY_ARRAY; + } + + private static class MyJavaCommandLineState extends CommandLineState { + private final AnalysisScope myGenerationOptions; + private final Project myProject; + @NonNls private static final String INDEX_HTML = "index.html"; + private JavadocConfiguration myConfiguration; + + public MyJavaCommandLineState(final JavadocConfiguration configuration, + Project project, + AnalysisScope generationOptions, + ExecutionEnvironment env) { + super(env); + myGenerationOptions = generationOptions; + myProject = project; + addConsoleFilters(new RegexpFilter(project, "$FILE_PATH$:$LINE$:[^\\^]+\\^"), + new RegexpFilter(project, "$FILE_PATH$:$LINE$: warning - .+$")); + this.myConfiguration = configuration; + } + + protected GeneralCommandLine createCommandLine() throws ExecutionException { + final GeneralCommandLine cmdLine = new GeneralCommandLine(); + final Sdk jdk = getSdk(myProject); + setupExeParams(jdk, cmdLine); + setupProgramParameters(jdk, cmdLine); + return cmdLine; + } + + private void setupExeParams(final Sdk jdk, GeneralCommandLine cmdLine) throws ExecutionException { + final String jdkPath = + jdk != null && jdk.getSdkType() instanceof JavaSdkType ? ((JavaSdkType)jdk.getSdkType()).getBinPath(jdk) : null; + if (jdkPath == null) { + throw new CantRunException(JavadocBundle.message("javadoc.generate.no.jdk.path")); + } + JavaSdkVersion version = JavaSdk.getInstance().getVersion(jdk); + if (myConfiguration.HEAP_SIZE != null && myConfiguration.HEAP_SIZE.trim().length() != 0) { + if (version == null || version.isAtLeast(JavaSdkVersion.JDK_1_2)) { + cmdLine.getParametersList().prepend("-J-Xmx" + myConfiguration.HEAP_SIZE + "m"); + } + else { + cmdLine.getParametersList().prepend("-J-mx" + myConfiguration.HEAP_SIZE + "m"); + } + } + cmdLine.setWorkDirectory((File)null); + @NonNls final String javadocExecutableName = File.separator + (SystemInfo.isWindows ? "javadoc.exe" : "javadoc"); + @NonNls String exePath = jdkPath.replace('/', File.separatorChar) + javadocExecutableName; + if (new File(exePath).exists()) { + cmdLine.setExePath(exePath); + } + else { //try to use wrapper jdk + exePath = new File(jdkPath).getParent().replace('/', File.separatorChar) + javadocExecutableName; + if (!new File(exePath).exists()) { + final File parent = new File(System.getProperty("java.home")).getParentFile(); //try system jre + exePath = parent.getPath() + File.separator + "bin" + javadocExecutableName; + if (!new File(exePath).exists()) { + throw new CantRunException(JavadocBundle.message("javadoc.generate.no.jdk.path")); + } + } + cmdLine.setExePath(exePath); + } + } + + private void setupProgramParameters(final Sdk jdk, final GeneralCommandLine cmdLine) throws CantRunException { + @NonNls final ParametersList parameters = cmdLine.getParametersList(); + + if (myConfiguration.LOCALE != null && myConfiguration.LOCALE.length() > 0) { + parameters.add("-locale"); + parameters.add(myConfiguration.LOCALE); + } + + if (myConfiguration.OPTION_SCOPE != null) { + parameters.add("-" + myConfiguration.OPTION_SCOPE); + } + + if (!myConfiguration.OPTION_HIERARCHY) { + parameters.add("-notree"); + } + + if (!myConfiguration.OPTION_NAVIGATOR) { + parameters.add("-nonavbar"); + } + + if (!myConfiguration.OPTION_INDEX) { + parameters.add("-noindex"); + } + else if (myConfiguration.OPTION_SEPARATE_INDEX) { + parameters.add("-splitindex"); + } + + if (myConfiguration.OPTION_DOCUMENT_TAG_USE) { + parameters.add("-use"); + } + + if (myConfiguration.OPTION_DOCUMENT_TAG_AUTHOR) { + parameters.add("-author"); + } + + if (myConfiguration.OPTION_DOCUMENT_TAG_VERSION) { + parameters.add("-version"); + } + + if (!myConfiguration.OPTION_DOCUMENT_TAG_DEPRECATED) { + parameters.add("-nodeprecated"); + } + else if (!myConfiguration.OPTION_DEPRECATED_LIST) { + parameters.add("-nodeprecatedlist"); + } + + parameters.addParametersString(myConfiguration.OTHER_OPTIONS); + + final Set modules = new LinkedHashSet(); + try { + final File sourcePathTempFile = FileUtil.createTempFile("javadoc", "args.txt", true); + parameters.add("@" + sourcePathTempFile.getCanonicalPath()); + final PrintWriter writer = new PrintWriter(new FileWriter(sourcePathTempFile)); + try { + final Collection packages = new HashSet(); + final Collection sources = new HashSet(); + final Runnable findRunnable = new Runnable() { + public void run() { + final int scopeType = myGenerationOptions.getScopeType(); + final boolean usePackageNotation = scopeType == AnalysisScope.MODULE || + scopeType == AnalysisScope.MODULES || + scopeType == AnalysisScope.PROJECT || + scopeType == AnalysisScope.DIRECTORY; + myGenerationOptions.accept(new MyContentIterator(myProject, packages, sources, modules, usePackageNotation)); + } + }; + if (!ProgressManager + .getInstance() + .runProcessWithProgressSynchronously(findRunnable, "Search for sources to generate javadoc in...", true, myProject)) { + return; + } + if (packages.size() + sources.size() == 0) { + throw new CantRunException(JavadocBundle.message("javadoc.generate.no.classes.in.selected.packages.error")); + } + for (String aPackage : packages) { + writer.println(aPackage); + } + //http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#runningjavadoc + for (String source : sources) { + writer.println(StringUtil.wrapWithDoubleQuote(source)); + } + writer.println("-sourcepath"); + OrderEnumerator enumerator = OrderEnumerator.orderEntries(myProject); + if (!myConfiguration.OPTION_INCLUDE_LIBS) { + enumerator = enumerator.withoutSdk().withoutLibraries(); + } + final PathsList pathsList = enumerator.getSourcePathsList(); + final List files = pathsList.getRootDirs(); + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); + final StringBuilder sourcePath = new StringBuilder(); + boolean start = true; + for (VirtualFile file : files) { + if (!myGenerationOptions.isIncludeTestSource() && fileIndex.isInTestSourceContent(file)) continue; + if (start) { + start = false; + } + else { + sourcePath.append(File.pathSeparator); + } + sourcePath.append(file.getPath()); + } + writer.println(StringUtil.wrapWithDoubleQuote(sourcePath.toString())); + } + finally { + writer.close(); + } + } + catch (IOException e) { + LOGGER.error(e); + } + + if (myConfiguration.OPTION_LINK_TO_JDK_DOCS) { + VirtualFile[] docUrls = jdk.getRootProvider().getFiles(JavadocOrderRootType.getInstance()); + for (VirtualFile docUrl : docUrls) { + parameters.add("-link"); + parameters.add(VfsUtil.toUri(docUrl).toString()); + } + } + + final PathsList classPath; + final OrderEnumerator orderEnumerator = ProjectRootManager.getInstance(myProject).orderEntries(modules); + if (jdk.getSdkType() instanceof JavaSdk) { + classPath = orderEnumerator.withoutSdk().withoutModuleSourceEntries().getPathsList(); + } + else { + //libraries are included into jdk + classPath = orderEnumerator.withoutModuleSourceEntries().getPathsList(); + } + final String classPathString = classPath.getPathsString(); + if (classPathString.length() > 0) { + parameters.add("-classpath"); + parameters.add(classPathString); + } + + if (myConfiguration.OUTPUT_DIRECTORY != null) { + parameters.add("-d"); + parameters.add(myConfiguration.OUTPUT_DIRECTORY.replace('/', File.separatorChar)); + } + } + + @NotNull + protected OSProcessHandler startProcess() throws ExecutionException { + final OSProcessHandler handler = JavaCommandLineStateUtil.startProcess(createCommandLine()); + ProcessTerminatedListener.attach(handler, myProject, JavadocBundle.message("javadoc.generate.exited")); + handler.addProcessListener(new ProcessAdapter() { + public void processTerminated(ProcessEvent event) { + if (myConfiguration.OPEN_IN_BROWSER) { + File url = new File(myConfiguration.OUTPUT_DIRECTORY, INDEX_HTML); + if (url.exists() && event.getExitCode() == 0) { + BrowserUtil.browse(url); + } + } + } + }); + return handler; + } + } + + private static class MyContentIterator extends PsiRecursiveElementWalkingVisitor { + private final PsiManager myPsiManager; + private final Collection myPackages; + private final Collection mySourceFiles; + private final Set myModules; + private final boolean myUsePackageNotation; + + public MyContentIterator(Project project, + Collection packages, + Collection sources, + Set modules, + boolean canUsePackageNotation) { + myModules = modules; + myUsePackageNotation = canUsePackageNotation; + myPsiManager = PsiManager.getInstance(project); + myPackages = packages; + mySourceFiles = sources; + } + + @Override + public void visitFile(PsiFile file) { + final VirtualFile fileOrDir = file.getVirtualFile(); + if (fileOrDir == null) return; + if (!fileOrDir.isInLocalFileSystem()) return; + final Module module = ModuleUtilCore.findModuleForFile(fileOrDir, myPsiManager.getProject()); + if (module != null) { + myModules.add(module); + } + if (file instanceof PsiJavaFile) { + final PsiJavaFile javaFile = (PsiJavaFile)file; + final String packageName = javaFile.getPackageName(); + if (containsPackagePrefix(module, packageName) || + (packageName.length() == 0 && !(javaFile instanceof ServerPageFile)) || + !myUsePackageNotation) { + mySourceFiles.add(FileUtil.toSystemIndependentName(fileOrDir.getPath())); + } + else { + myPackages.add(packageName); + } + } + } + + private static boolean containsPackagePrefix(Module module, String packageFQName) { + if (module == null) return false; + for (ContentEntry contentEntry : ModuleRootManager.getInstance(module).getContentEntries()) { + for (SourceFolder sourceFolder : contentEntry.getSourceFolders(JavaModuleSourceRootTypes.SOURCES)) { + final String packagePrefix = sourceFolder.getPackagePrefix(); + final int prefixLength = packagePrefix.length(); + if (prefixLength > 0 && packageFQName.startsWith(packagePrefix)) { + return true; + } + } + } + return false; + } + } +} diff --git a/java/java-impl/src/com/intellij/javadoc/actions/GenerateJavadocAction.java b/java/java-impl/src/com/intellij/javadoc/actions/GenerateJavadocAction.java index 068f527c0170..9f097a117c4b 100644 --- a/java/java-impl/src/com/intellij/javadoc/actions/GenerateJavadocAction.java +++ b/java/java-impl/src/com/intellij/javadoc/actions/GenerateJavadocAction.java @@ -44,7 +44,7 @@ public final class GenerateJavadocAction extends BaseAnalysisAction{ @Override protected JComponent getAdditionalActionSettings(Project project, final BaseAnalysisActionDialog dialog) { - myConfigurable = JavadocGenerationManager.getInstance(project).getConfiguration().createConfigurable(); + myConfigurable = new JavadocConfigurable(JavadocGenerationManager.getInstance(project).getConfiguration(), project); final JComponent component = myConfigurable.createComponent(); myConfigurable.reset(); myConfigurable.getOutputDirField().getDocument().addDocumentListener(new DocumentAdapter() { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java index 6f1cd002c9c5..e71e6c3317ae 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,6 +16,7 @@ package com.intellij.refactoring.introduceField; import com.intellij.codeInsight.completion.JavaCompletionUtil; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -32,6 +33,8 @@ import com.intellij.refactoring.ui.*; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.RefactoringMessageUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.ui.update.Activatable; +import com.intellij.util.ui.update.UiNotifyConnector; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -147,7 +150,7 @@ class IntroduceFieldDialog extends DialogWrapper { gbConstraints.gridx = 0; gbConstraints.gridy = 0; - JLabel type = new JLabel(getTypeLabel()); + final JLabel type = new JLabel(getTypeLabel()); panel.add(type, gbConstraints); @@ -163,7 +166,7 @@ class IntroduceFieldDialog extends DialogWrapper { gbConstraints.weighty = 1; gbConstraints.gridx = 0; gbConstraints.gridy = 1; - JLabel namePrompt = new JLabel(RefactoringBundle.message("name.prompt")); + final JLabel namePrompt = new JLabel(RefactoringBundle.message("name.prompt")); panel.add(namePrompt, gbConstraints); gbConstraints.insets = new Insets(4, 0, 4, 4); @@ -180,10 +183,24 @@ class IntroduceFieldDialog extends DialogWrapper { }); namePrompt.setLabelFor(myNameField.getFocusableComponent()); - myNameSuggestionsManager = new NameSuggestionsManager(myTypeSelector, myNameField, - createGenerator(myWillBeDeclaredStatic, myLocalVariable, myInitializerExpression, myIsInvokedOnDeclaration, myEnteredName, - myParentClass, myProject)); - myNameSuggestionsManager.setLabelsFor(type, namePrompt); + // We delay initialization of name field till dialog is shown, so that it will be executed in a different command and won't + // be tied to any document changes performed in current command (and won't prevent undo for them later) + new UiNotifyConnector.Once(panel, new Activatable.Adapter() { + @Override + public void showNotify() { + myNameSuggestionsManager = new NameSuggestionsManager(myTypeSelector, myNameField, + createGenerator(myWillBeDeclaredStatic, myLocalVariable, + myInitializerExpression, myIsInvokedOnDeclaration, + myEnteredName, myParentClass, myProject)); + myNameSuggestionsManager.setLabelsFor(type, namePrompt); + + Editor editor = myNameField.getEditor(); + if (editor != null) { + editor.getSelectionModel().setSelection(0, editor.getDocument().getTextLength()); + } + } + }); + return panel; } diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java index 0611af494c47..15d7b115352e 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java @@ -39,17 +39,17 @@ public class TypeMigrationReplacementUtil { private TypeMigrationReplacementUtil() { } - public static void replaceExpression(PsiExpression expression, final Project project, Object conversion) { + public static PsiElement replaceExpression(PsiExpression expression, final Project project, Object conversion) { if (conversion instanceof TypeConversionDescriptorBase) { try { - ((TypeConversionDescriptorBase)conversion).replace(expression); + return ((TypeConversionDescriptorBase)conversion).replace(expression); } catch (IncorrectOperationException e) { LOG.error(e); } } else if (conversion instanceof String) { String replacement = (String)conversion; try { - expression.replace( + return expression.replace( JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(replacement, expression)); } catch (IncorrectOperationException e) { @@ -66,7 +66,7 @@ public class TypeMigrationReplacementUtil { if (conversion instanceof PsiMethod) { if (resolved instanceof PsiMethod) { try { - expression.replace( + return expression.replace( JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(newref, expression)); } catch (IncorrectOperationException e) { @@ -75,7 +75,7 @@ public class TypeMigrationReplacementUtil { } else { try { - expression.replace(JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText( + return expression.replace(JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText( newref + "()", expression)); } catch (IncorrectOperationException e) { @@ -86,7 +86,7 @@ public class TypeMigrationReplacementUtil { else if (conversion instanceof PsiField) { if (resolved instanceof PsiField) { try { - expression.replace( + return expression.replace( JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(newref, expression)); } catch (IncorrectOperationException e) { @@ -98,7 +98,7 @@ public class TypeMigrationReplacementUtil { if (parent instanceof PsiMethodCallExpression) { try { - parent.replace( + return parent.replace( JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(newref, expression)); } catch (IncorrectOperationException e) { @@ -108,6 +108,7 @@ public class TypeMigrationReplacementUtil { } } } + return expression; } static void migratePsiMemberType(final PsiElement element, final Project project, PsiType migratedType) { diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java index 306c43e5b15c..54cade32e37a 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java @@ -636,13 +636,16 @@ public final class PsiUtil extends PsiUtilCore { return containingClass1 == null && containingClass2 == null; } + /** + * @deprecated use more generic {@link #isCompileTimeConstant(PsiVariable)} instead + */ public static boolean isCompileTimeConstant(@NotNull final PsiField field) { return isCompileTimeConstant((PsiVariable)field); } - /** - * JLS 15.28 - */ + /** + * JLS 15.28 + */ public static boolean isCompileTimeConstant(@NotNull final PsiVariable field) { return field.hasModifierProperty(PsiModifier.FINAL) && (TypeConversionUtil.isPrimitiveAndNotNull(field.getType()) || field.getType().equalsToText(JAVA_LANG_STRING)) diff --git a/java/typeMigration/src/META-INF/TypeMigration.xml b/java/typeMigration/src/META-INF/TypeMigration.xml index 9a0c0e187dfa..082c3ba802d5 100644 --- a/java/typeMigration/src/META-INF/TypeMigration.xml +++ b/java/typeMigration/src/META-INF/TypeMigration.xml @@ -12,6 +12,7 @@ + com.intellij.refactoring.typeMigration.intentions.ConvertFieldToAtomicIntention Java/Concurrency diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java index 7a31db0f2d95..914a17cb6bf0 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/inspections/GuavaInspection.java @@ -15,21 +15,31 @@ */ package com.intellij.refactoring.typeMigration.inspections; +import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.impl.quickfix.VariableTypeFix; import com.intellij.codeInspection.*; +import com.intellij.openapi.command.undo.UndoUtil; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.AtomicNotNullLazyValue; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.refactoring.typeMigration.TypeMigrationVariableTypeFixProvider; +import com.intellij.refactoring.typeMigration.*; import com.intellij.refactoring.typeMigration.rules.TypeConversionRule; import com.intellij.refactoring.typeMigration.rules.guava.BaseGuavaTypeConversionRule; +import com.intellij.refactoring.typeMigration.rules.guava.GuavaFluentIterableConversionRule; import com.intellij.refactoring.typeMigration.rules.guava.GuavaFunctionConversionRule; +import com.intellij.refactoring.typeMigration.rules.guava.GuavaOptionalConversionRule; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.hash.HashMap; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -43,6 +53,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool { private final static Logger LOG = Logger.getInstance(GuavaInspection.class); private final static String PROBLEM_DESCRIPTION_FOR_VARIABLE = "Guava's functional primitives can be replaced by Java API"; + private final static String PROBLEM_DESCRIPTION_FOR_METHOD_CHAIN = "Guava's FluentIterable method chain can be replaced by Java API"; @NotNull @Override @@ -93,6 +104,54 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool { } } + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + if (!isFluentIterableFromCall(expression)) return; + + final PsiMethodCallExpression chain = findGuavaMethodChain(expression); + + PsiClassType initialType = (PsiClassType)expression.getType(); + LOG.assertTrue(initialType != null); + PsiClass resolvedClass = initialType.resolve(); + PsiClass target; + if (resolvedClass == null || (target = myGuavaClassConversions.getValue().get(resolvedClass.getQualifiedName())) == null) { + return; + } + PsiClassType targetType = addTypeParameters(initialType, initialType.resolveGenerics(), target); + + holder.registerProblem(chain, PROBLEM_DESCRIPTION_FOR_METHOD_CHAIN, new MigrateFluentIterableChainQuickFix(chain, initialType, targetType)); + } + + private boolean isFluentIterableFromCall(PsiMethodCallExpression expression) { + PsiMethod method = expression.resolveMethod(); + if (method == null || !"from".equals(method.getName())) { + return false; + } + PsiClass aClass = method.getContainingClass(); + return aClass != null && GuavaFluentIterableConversionRule.FLUENT_ITERABLE.equals(aClass.getQualifiedName()); + } + + private PsiMethodCallExpression findGuavaMethodChain(PsiMethodCallExpression expression) { + PsiMethodCallExpression chain = expression; + while (true) { + final PsiMethodCallExpression current = PsiTreeUtil.getParentOfType(chain, PsiMethodCallExpression.class); + if (current != null && current.getMethodExpression().getQualifierExpression() == chain) { + final PsiMethod method = current.resolveMethod(); + if (method == null) { + return chain; + } + final PsiClass containingClass = method.getContainingClass(); + if (containingClass == null || ! (GuavaFluentIterableConversionRule.FLUENT_ITERABLE.equals(containingClass.getQualifiedName()) + || GuavaOptionalConversionRule.GUAVA_OPTIONAL.equals(containingClass.getQualifiedName()))) { + return chain; + } + } else { + return chain; + } + chain = current; + } + } + private PsiClassType addTypeParameters(PsiType currentType, PsiClassType.ClassResolveResult currentTypeResolveResult, PsiClass targetClass) { final Map substitutionMap = currentTypeResolveResult.getSubstitutor().getSubstitutionMap(); final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(holder.getProject()); @@ -110,4 +169,58 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool { } }; } + + public static class MigrateFluentIterableChainQuickFix extends LocalQuickFixAndIntentionActionOnPsiElement { + private final PsiClassType myInitialType; + private final PsiClassType myTargetType; + + private MigrateFluentIterableChainQuickFix(@Nullable PsiElement element, PsiClassType initialType, PsiClassType targetType) { + super(element); + myInitialType = initialType; + myTargetType = targetType; + } + + @Override + public void invoke(@NotNull Project project, + @NotNull PsiFile file, + @Nullable("is null when called from inspection") Editor editor, + @NotNull PsiElement startElement, + @NotNull PsiElement endElement) { + + if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; + try { + final PsiMethodCallExpression expr = (PsiMethodCallExpression)startElement; + final TypeMigrationRules rules = new TypeMigrationRules(myInitialType); + rules.setMigrationRootType(myTargetType); + rules.setBoundScope(GlobalSearchScope.fileScope(file)); + final TypeConversionDescriptorBase conversion = + rules.findConversion(myInitialType, myTargetType, expr.resolveMethod(), expr, new TypeMigrationLabeler(rules)); + LOG.assertTrue(conversion != null); + final PsiElement replacedExpression = TypeMigrationReplacementUtil.replaceExpression(expr, project, conversion); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(replacedExpression); + UndoUtil.markPsiFileForUndo(file); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + + @Override + public boolean startInWriteAction() { + return true; + } + + @NotNull + @Override + public String getText() { + return getFamilyName(); + } + + @Nls + @NotNull + @Override + public String getFamilyName() { + return "Replace FluentIterable method chain by Java API"; + } + } } \ No newline at end of file diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java index 8daec6de5c7d..8984ccc0f4a4 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/BaseGuavaTypeConversionRule.java @@ -45,10 +45,10 @@ public abstract class BaseGuavaTypeConversionRule extends TypeConversionRule { protected void fillSimpleDescriptors(Map descriptorsMap) {}; @Nullable - protected TypeConversionDescriptorBase findConversionForMethod(@NotNull PsiType from, - @NotNull PsiType to, + protected TypeConversionDescriptorBase findConversionForMethod(PsiType from, + PsiType to, @NotNull PsiMethod method, - String methodName, + @NotNull String methodName, PsiExpression context, TypeMigrationLabeler labeler) { return null; @@ -62,12 +62,12 @@ public abstract class BaseGuavaTypeConversionRule extends TypeConversionRule { @Nullable @Override - public final TypeConversionDescriptorBase findConversion(PsiType from, - PsiType to, - PsiMember member, - PsiExpression context, - TypeMigrationLabeler labeler) { - if (!canConvert(from, to)) { + public final TypeConversionDescriptorBase findConversion(@Nullable PsiType from, + @Nullable PsiType to, + PsiMember member, + PsiExpression context, + TypeMigrationLabeler labeler) { + if (from != null && to != null && !canConvert(from, to)) { return null; } if (member instanceof PsiMethod) { diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java index 3a75c0202116..386c6ebcfe6b 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java @@ -16,10 +16,12 @@ package com.intellij.refactoring.typeMigration.rules.guava; import com.intellij.codeInspection.java18StreamApi.StreamApiConstants; +import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.psi.*; import com.intellij.refactoring.typeMigration.TypeConversionDescriptor; import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase; import com.intellij.refactoring.typeMigration.TypeMigrationLabeler; +import com.intellij.refactoring.typeMigration.rules.TypeConversionRule; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SmartList; import com.intellij.util.containers.hash.HashMap; @@ -27,7 +29,6 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -106,11 +107,11 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu protected TypeConversionDescriptorBase findConversionForMethod(@NotNull PsiType from, @NotNull PsiType to, @NotNull PsiMethod method, - String methodName, + @NotNull String methodName, PsiExpression context, TypeMigrationLabeler labeler) { if (context instanceof PsiMethodCallExpression) { - return buildCompoundDescriptor((PsiMethodCallExpression)context, to); + return buildCompoundDescriptor((PsiMethodCallExpression)context, to, labeler); } final TypeConversionDescriptorFactory base = DESCRIPTORS_MAP.get(methodName); if (base != null) { @@ -126,8 +127,23 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu } @Nullable - private GuavaChainedConversionDescriptor buildCompoundDescriptor(PsiMethodCallExpression expression, PsiType to) { - List methodDescriptors = new SmartList(); + private static GuavaChainedConversionDescriptor buildCompoundDescriptor(PsiMethodCallExpression expression, + PsiType to, + TypeMigrationLabeler labeler) { + List methodDescriptors = new SmartList(); + + NotNullLazyValue optionalDescriptor = new NotNullLazyValue() { + @NotNull + @Override + protected TypeConversionRule compute() { + for (TypeConversionRule rule : TypeConversionRule.EP_NAME.getExtensions()) { + if (rule instanceof GuavaOptionalConversionRule) { + return rule; + } + } + throw new RuntimeException("GuavaOptionalConversionRule extension is not found"); + } + }; PsiMethodCallExpression current = expression; while (true) { @@ -137,15 +153,26 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu } final String methodName = method.getName(); final PsiClass containingClass = method.getContainingClass(); - //TODO for optional too - if (containingClass == null || !FLUENT_ITERABLE.equals(containingClass.getQualifiedName())) { + if (containingClass == null) { break; } - final TypeConversionDescriptorFactory descriptorFactory = DESCRIPTORS_MAP.get(methodName); - if (descriptorFactory == null) { - return null; + TypeConversionDescriptorBase descriptor; + if (FLUENT_ITERABLE.equals(containingClass.getQualifiedName())) { + final TypeConversionDescriptorFactory descriptorFactory = DESCRIPTORS_MAP.get(methodName); + if (descriptorFactory == null) { + return null; + } + descriptor = descriptorFactory.create(); } - methodDescriptors.add(descriptorFactory.create()); + else if (GuavaOptionalConversionRule.GUAVA_OPTIONAL.equals(containingClass.getQualifiedName())) { + descriptor = optionalDescriptor.getValue().findConversion(null, null, method, current.getMethodExpression(), labeler); + if (descriptor == null) { + return null; + } + } else { + break; + } + methodDescriptors.add(descriptor); final PsiExpression qualifier = current.getMethodExpression().getQualifierExpression(); if (qualifier instanceof PsiMethodCallExpression) { current = (PsiMethodCallExpression)qualifier; @@ -172,10 +199,10 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu } private static class GuavaChainedConversionDescriptor extends TypeConversionDescriptorBase { - private final List myMethodDescriptors; + private final List myMethodDescriptors; private final PsiType myToType; - private GuavaChainedConversionDescriptor(List descriptors, PsiType to) { + private GuavaChainedConversionDescriptor(List descriptors, PsiType to) { myMethodDescriptors = descriptors; myToType = to; } @@ -184,15 +211,21 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu public PsiExpression replace(PsiExpression expression) throws IncorrectOperationException { PsiMethodCallExpression toReturn = null; PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) expression; - for (TypeConversionDescriptor descriptor : myMethodDescriptors) { + final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(expression.getProject()); + + for (TypeConversionDescriptorBase descriptor : myMethodDescriptors) { + final PsiExpression oldQualifier = methodCallExpression.getMethodExpression().getQualifierExpression(); + final SmartPsiElementPointer qualifierRef = oldQualifier == null + ? null + : smartPointerManager.createSmartPsiElementPointer(oldQualifier); final PsiMethodCallExpression replaced = (PsiMethodCallExpression)descriptor.replace(methodCallExpression); if (toReturn == null) { toReturn = replaced; } - final PsiExpression qualifier = replaced.getMethodExpression().getQualifierExpression(); - if (qualifier instanceof PsiMethodCallExpression) { - methodCallExpression = (PsiMethodCallExpression)qualifier; + final PsiExpression newQualifier = qualifierRef == null ? null : qualifierRef.getElement(); + if (newQualifier instanceof PsiMethodCallExpression) { + methodCallExpression = (PsiMethodCallExpression)newQualifier; } else { return toReturn; } diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java index cc8968f8f51e..9363797e757d 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java @@ -36,10 +36,10 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule { @Nullable @Override - protected TypeConversionDescriptorBase findConversionForMethod(@NotNull PsiType from, - @NotNull PsiType to, + protected TypeConversionDescriptorBase findConversionForMethod(@Nullable PsiType from, + @Nullable PsiType to, @NotNull PsiMethod method, - String methodName, + @NotNull String methodName, PsiExpression context, TypeMigrationLabeler labeler) { if ("or".equals(methodName)) { @@ -53,9 +53,7 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule { if (aClass != null) { final String qName = aClass.getQualifiedName(); String pattern = - GUAVA_OPTIONAL.equals(qName) ? "java.util.Optional.ofNullable($expr$.get())" : "com.google.common.bas.Supplier".equals(qName) - ? "java.util.Optional.ofNullable($expr$)" - : "java.util.Optional.ofNullable($expr$)"; + GUAVA_OPTIONAL.equals(qName) ? "java.util.Optional.ofNullable($expr$.get())" : "java.util.Optional.ofNullable($expr$)"; return new TypeConversionDescriptor("$expr$", pattern); } return null; @@ -73,10 +71,15 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule { if (aClass != null) { final String qName = aClass.getQualifiedName(); if (GUAVA_OPTIONAL.equals(qName)) { - return new TypeConversionDescriptor("$val$.or($other$)", "java.util.Optional.ofNullable($val$.orElseGet($other$::get))", to); + TypeConversionDescriptor descriptor = + new TypeConversionDescriptor("$val$.or($other$)", "java.util.Optional.ofNullable($val$.orElseGet($other$::get))"); + if (to != null) { + descriptor.withConversionType(to); + } + return descriptor; } - String pattern = "com.google.common.bas.Supplier".equals(qName) ? "$val$.orElseGet($other$::get)" : "$val$.orElse($other$)"; - return new TypeConversionDescriptor("$val$.or($other$)", pattern); + String pattern = GuavaSupplierConversionRule.GUAVA_SUPPLIER.equals(qName) ? "$val$.orElseGet($other$)" : "$val$.orElse($other$)"; + return new LambdaParametersTypeConversionDescription("$val$.or($other$)", pattern); } return null; } diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaSupplierConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaSupplierConversionRule.java new file mode 100644 index 000000000000..dc9df00e3250 --- /dev/null +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaSupplierConversionRule.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2015 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.refactoring.typeMigration.rules.guava; + +import com.intellij.refactoring.typeMigration.TypeConversionDescriptor; +import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +/** + * @author Dmitry Batkovich + */ +public class GuavaSupplierConversionRule extends BaseGuavaTypeConversionRule { + public final static String GUAVA_SUPPLIER = "com.google.common.base.Supplier"; + + @Override + protected void fillSimpleDescriptors(Map descriptorsMap) { + descriptorsMap.put("get", new TypeConversionDescriptor("$val$.get()", "$val$.get()")); + } + + @NotNull + @Override + public String ruleFromClass() { + return GUAVA_SUPPLIER; + } + + @NotNull + @Override + public String ruleToClass() { + return "java.util.function.Supplier"; + } +} diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescription.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescription.java index c70598eeb77d..c64472df85a3 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescription.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/LambdaParametersTypeConversionDescription.java @@ -27,10 +27,6 @@ import org.jetbrains.annotations.NonNls; public class LambdaParametersTypeConversionDescription extends TypeConversionDescriptor { private static final Logger LOG = Logger.getInstance(LambdaParametersTypeConversionDescription.class); - public LambdaParametersTypeConversionDescription(@NonNls String stringToReplace, @NonNls String replaceByString, PsiType conversionType) { - super(stringToReplace, replaceByString, conversionType); - } - public LambdaParametersTypeConversionDescription(@NonNls String stringToReplace, @NonNls String replaceByString) { super(stringToReplace, replaceByString); } @@ -52,7 +48,16 @@ public class LambdaParametersTypeConversionDescription extends TypeConversionDes } private static PsiExpression addApplyReference(final PsiExpression expression) { - return (PsiExpression)expression.replace(JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(expression.getText() + "::apply", null)); + boolean isSupplier = false; + PsiType type = expression.getType(); + if (type instanceof PsiClassType) { + PsiClass resolvedClass = ((PsiClassType)type).resolve(); + if (resolvedClass != null && GuavaSupplierConversionRule.GUAVA_SUPPLIER.equals(resolvedClass.getQualifiedName())) { + isSupplier = true; + } + } + return (PsiExpression)expression.replace( + JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(expression.getText() + "::" + (isSupplier ? "get" : "apply"), null)); } public static PsiExpression convertParameter(PsiExpression expression) { diff --git a/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java b/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java index 8afd272fb25a..886a3c356356 100644 --- a/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java +++ b/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java @@ -63,7 +63,7 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase { doTest(); } - public void _testFluentIterableChainWithoutVariable() { + public void testFluentIterableChainWithoutVariable() { doTest(); } @@ -71,19 +71,23 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase { doTest(); } + public void testFluentIterableChainWithOptional() { + doTest(); + } + private void doTest() { myFixture.configureByFile(getTestName(true) + ".java"); myFixture.enableInspections(new GuavaInspection()); boolean actionFound = false; myFixture.doHighlighting(); for (IntentionAction action : myFixture.getAvailableIntentions()) { - if (action instanceof VariableTypeFix) { + if (action instanceof VariableTypeFix || action instanceof GuavaInspection.MigrateFluentIterableChainQuickFix) { myFixture.launchAction(action); actionFound = true; break; } } - assertTrue(actionFound); + assertTrue("Quick fix isn't found", actionFound); myFixture.checkResultByFile(getTestName(true) + "_after.java"); } } diff --git a/java/typeMigration/testData/inspections/guava/fluentIterableChainWithOptional.java b/java/typeMigration/testData/inspections/guava/fluentIterableChainWithOptional.java new file mode 100644 index 000000000000..5bc29c381651 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/fluentIterableChainWithOptional.java @@ -0,0 +1,10 @@ +import java.util.*; +import com.google.common.collect.FluentIterable; + +class A { + void m1() { + ArrayList strings = new ArrayList(); + String str = FluentIterable.from(strings).transform(s -> s + s).limit(10).firstMatch(s -> s.isEmpty()).orNull(); + System.out.println("s: " + str); + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/fluentIterableChainWithOptional_after.java b/java/typeMigration/testData/inspections/guava/fluentIterableChainWithOptional_after.java new file mode 100644 index 000000000000..e55604989080 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/fluentIterableChainWithOptional_after.java @@ -0,0 +1,10 @@ +import java.util.*; +import com.google.common.collect.FluentIterable; + +class A { + void m1() { + ArrayList strings = new ArrayList(); + String str = strings.stream().map(s -> s + s).limit(10).filter(s -> s.isEmpty()).findFirst().orElse(null); + System.out.println("s: " + str); + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/fluentIterableChainWithoutVariable.java b/java/typeMigration/testData/inspections/guava/fluentIterableChainWithoutVariable.java new file mode 100644 index 000000000000..a66738c7885d --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/fluentIterableChainWithoutVariable.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2015 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. + */ +import java.util.*; +import com.google.common.collect.FluentIterable; + +class A { + int m1() { + ArrayList strings = new ArrayList(); + int size = FluentIterable.from(strings).transform(s -> s + s).limit(10).size(); + return size + } +} \ No newline at end of file diff --git a/java/typeMigration/testData/inspections/guava/fluentIterableChainWithoutVariable_after.java b/java/typeMigration/testData/inspections/guava/fluentIterableChainWithoutVariable_after.java new file mode 100644 index 000000000000..fd41604f6a9f --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/fluentIterableChainWithoutVariable_after.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2015 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. + */ +import java.util.*; +import java.util.stream.Collectors; + +import com.google.common.collect.FluentIterable; + +class A { + int m1() { + ArrayList strings = new ArrayList(); + int size = strings.stream().map(s -> s + s).limit(10).collect(Collectors.toList()).size(); + return size + } +} \ No newline at end of file diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index b0470155ff36..c4fa71e86864 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,6 +22,7 @@ import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.concurrency.Semaphore; import com.intellij.util.concurrency.SequentialTaskExecutor; import com.intellij.util.io.DataOutputStream; import io.netty.channel.Channel; @@ -49,7 +50,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope; @@ -64,7 +64,7 @@ final class BuildSession implements Runnable, CanceledStatus { private final Channel myChannel; @Nullable private final PreloadedData myPreloadedData; - private volatile boolean myCanceled = false; + private volatile boolean myCanceled; private final String myProjectPath; @Nullable private CmdlineRemoteProto.Message.ControllerMessage.FSEvent myInitialFSDelta; @@ -345,7 +345,7 @@ final class BuildSession implements Runnable, CanceledStatus { } public void processFSEvent(final CmdlineRemoteProto.Message.ControllerMessage.FSEvent event) { - myEventsProcessor.submit(new Runnable() { + myEventsProcessor.execute(new Runnable() { @Override public void run() { try { @@ -646,23 +646,21 @@ final class BuildSession implements Runnable, CanceledStatus { } private static class EventsProcessor extends SequentialTaskExecutor { - private final AtomicBoolean myProcessingEnabled = new AtomicBoolean(false); + private final Semaphore myProcessingEnabled = new Semaphore(); - EventsProcessor() { + private EventsProcessor() { super(SharedThreadPool.getInstance()); + myProcessingEnabled.down(); + execute(new Runnable() { + @Override + public void run() { + myProcessingEnabled.waitFor(); + } + }); } - public void startProcessing() { - if (!myProcessingEnabled.getAndSet(true)) { - super.processQueue(); - } - } - - @Override - protected void processQueue() { - if (myProcessingEnabled.get()) { - super.processQueue(); - } + private void startProcessing() { + myProcessingEnabled.up(); } } diff --git a/platform/built-in-server/testSrc/RestApiTest.kt b/platform/built-in-server/testSrc/RestApiTest.kt index f399816c1be9..5116c6425b47 100644 --- a/platform/built-in-server/testSrc/RestApiTest.kt +++ b/platform/built-in-server/testSrc/RestApiTest.kt @@ -1,13 +1,10 @@ package org.jetbrains.ide import com.google.gson.stream.JsonWriter -import com.intellij.openapi.vfs.CharsetToolkit import io.netty.handler.codec.http.HttpResponseStatus import org.assertj.core.api.Assertions.assertThat import org.jetbrains.ide.TestManager.TestDescriptor import org.junit.Test -import java.io.BufferedOutputStream -import java.io.OutputStreamWriter import java.net.HttpURLConnection import java.net.URL @@ -72,13 +69,13 @@ private class RestApiTest : BuiltInServerTestCase() { connection = URL("$serviceUrl").openConnection() as HttpURLConnection connection.requestMethod = "POST" connection.doOutput = true - val writer = JsonWriter(OutputStreamWriter(BufferedOutputStream(connection.outputStream), CharsetToolkit.UTF8_CHARSET)) - writer.beginObject() - writer.name("file").value(manager.filePath) - writer.name("line").value(line) - writer.name("column").value(column) - writer.endObject() - writer.close() + JsonWriter(connection.outputStream.bufferedWriter()).use { + it.beginObject() + it.name("file").value(manager.filePath) + it.name("line").value(line) + it.name("column").value(column) + it.endObject() + } assertThat(HttpResponseStatus.valueOf(connection.responseCode)).isEqualTo(expectedStatus) } } diff --git a/platform/configuration-store-impl/src/StateMap.kt b/platform/configuration-store-impl/src/StateMap.kt index 1ea0b98b8097..403e0f4ef31c 100644 --- a/platform/configuration-store-impl/src/StateMap.kt +++ b/platform/configuration-store-impl/src/StateMap.kt @@ -32,6 +32,9 @@ import java.util.* import java.util.concurrent.atomic.AtomicReferenceArray class StateMap private constructor(private val names: Array, private val states: AtomicReferenceArray) { + override fun toString(): String = + if (this == EMPTY) "EMPTY" else states.toString(); + companion object { private val XML_FORMAT = Format.getRawFormat().setTextMode(Format.TextMode.TRIM).setOmitEncoding(true).setOmitDeclaration(true) diff --git a/platform/core-api/src/com/intellij/openapi/components/PersistentStateComponent.java b/platform/core-api/src/com/intellij/openapi/components/PersistentStateComponent.java index 64d3cfaf8a32..df8eed4d1255 100644 --- a/platform/core-api/src/com/intellij/openapi/components/PersistentStateComponent.java +++ b/platform/core-api/src/com/intellij/openapi/components/PersistentStateComponent.java @@ -24,7 +24,8 @@ import org.jetbrains.annotations.Nullable; * See IntelliJ Platform SDK DevGuide * for detailed description. * - * Implementation must be thread-safe - a component should expect these methods to be called at any moment of its lifecycle. + * In general, implementation should be thread-safe, because "loadState" is called from the same thread where component is initialized. + * If component used only from one thread (e.g. EDT), thread-safe implementation is not required. */ public interface PersistentStateComponent { /** diff --git a/platform/core-impl/src/com/intellij/codeInsight/CodeInsightUtilCore.java b/platform/core-impl/src/com/intellij/codeInsight/CodeInsightUtilCore.java index fef3b5703a43..2181e43f96f6 100644 --- a/platform/core-impl/src/com/intellij/codeInsight/CodeInsightUtilCore.java +++ b/platform/core-impl/src/com/intellij/codeInsight/CodeInsightUtilCore.java @@ -28,6 +28,9 @@ import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; +import java.util.List; + public abstract class CodeInsightUtilCore extends FileModificationService { public static T findElementInRange(@NotNull PsiFile file, int startOffset, @@ -78,7 +81,12 @@ public abstract class CodeInsightUtilCore extends FileModificationService { } public static boolean parseStringCharacters(@NotNull String chars, @NotNull StringBuilder outChars, @Nullable int[] sourceOffsets) { + return parseStringCharacters(chars, outChars, sourceOffsets, '"', '\''); + } + + public static boolean parseStringCharacters(@NotNull String chars, @NotNull StringBuilder outChars, @Nullable int[] sourceOffsets, Character... endChars) { assert sourceOffsets == null || sourceOffsets.length == chars.length()+1; + List endCharList = Arrays.asList(endChars); if (chars.indexOf('\\') < 0) { outChars.append(chars); if (sourceOffsets != null) { @@ -123,14 +131,6 @@ public abstract class CodeInsightUtilCore extends FileModificationService { outChars.append('\r'); break; - case'"': - outChars.append('"'); - break; - - case'\'': - outChars.append('\''); - break; - case'\\': outChars.append('\\'); break; @@ -193,7 +193,11 @@ public abstract class CodeInsightUtilCore extends FileModificationService { break; default: - return false; + if (endCharList.contains(c)) { + outChars.append(c); + } else { + return false; + } } if (sourceOffsets != null) { sourceOffsets[outChars.length()-outOffset] = index; diff --git a/platform/icons/src/xml/browsers/edge16.png b/platform/icons/src/xml/browsers/edge16.png new file mode 100644 index 000000000000..80ea90842c97 Binary files /dev/null and b/platform/icons/src/xml/browsers/edge16.png differ diff --git a/platform/icons/src/xml/browsers/edge16@2x.png b/platform/icons/src/xml/browsers/edge16@2x.png new file mode 100644 index 000000000000..de81b85536d4 Binary files /dev/null and b/platform/icons/src/xml/browsers/edge16@2x.png differ diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java index 7c3240ac26db..3511604c6631 100755 --- a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java +++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java @@ -367,7 +367,7 @@ public class SheetController { } private static String handleBreaks(final String message) { - return message.replaceAll("(\r\n|\n)", "
"); + return message == null ? "" : message.replaceAll("(\r\n|\n)", "
"); } private void shiftButtonsToTheBottom(int shiftDistance) { diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index c33f9ef75e3d..b7ce21f6e5cf 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -11,9 +11,9 @@ - - com.intellij.javaee.DefaultHtmlDoctypeInitialConfigurator - + + + com.intellij.codeInsight.editorActions.XmlTagNameSynchronizer diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java index 46fb5fab897d..1eb40d1b1c2b 100644 --- a/platform/util/src/com/intellij/icons/AllIcons.java +++ b/platform/util/src/com/intellij/icons/AllIcons.java @@ -1224,6 +1224,7 @@ public class AllIcons { public static final Icon Canary16 = IconLoader.getIcon("/xml/browsers/canary16.png"); // 16x16 public static final Icon Chrome16 = IconLoader.getIcon("/xml/browsers/chrome16.png"); // 16x16 public static final Icon Chromium16 = IconLoader.getIcon("/xml/browsers/chromium16.png"); // 16x16 + public static final Icon Edge16 = IconLoader.getIcon("/xml/browsers/edge16.png"); // 16x16 public static final Icon Explorer16 = IconLoader.getIcon("/xml/browsers/explorer16.png"); // 16x16 public static final Icon Firefox16 = IconLoader.getIcon("/xml/browsers/firefox16.png"); // 16x16 public static final Icon Nwjs16 = IconLoader.getIcon("/xml/browsers/nwjs16.png"); // 16x16 diff --git a/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java b/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java index f2e3e0bebfaa..c5690842a29d 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java @@ -41,7 +41,7 @@ public class BuildNumberTest { assertTrue(BuildNumber.fromString("90.SNAPSHOT").compareTo(BuildNumber.fromString("90.12345")) > 0); assertTrue(BuildNumber.fromString("IU-90.SNAPSHOT").compareTo(BuildNumber.fromString("RM-90.12345")) > 0); assertTrue(BuildNumber.fromString("IU-90.SNAPSHOT").compareTo(BuildNumber.fromString("RM-100.12345")) < 0); - assertTrue(BuildNumber.fromString("IU-90.SNAPSHOT").compareTo(BuildNumber.fromString("RM-100.SNAPSHOT")) == 0); + assertTrue(BuildNumber.fromString("IU-90.SNAPSHOT").compareTo(BuildNumber.fromString("RM-100.SNAPSHOT")) < 0); assertTrue(BuildNumber.fromString("IU-90.SNAPSHOT").compareTo(BuildNumber.fromString("RM-90.SNAPSHOT")) == 0); } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/MagicNumberInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/MagicNumberInspectionBase.java index a664d01a92dc..222c5715c602 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/MagicNumberInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/MagicNumberInspectionBase.java @@ -93,7 +93,7 @@ public class MagicNumberInspectionBase extends BaseInspection { return; } final PsiField field = PsiTreeUtil.getParentOfType(expression, PsiField.class); - if (field != null && PsiUtil.isCompileTimeConstant(field)) { + if (field != null && PsiUtil.isCompileTimeConstant((PsiVariable)field)) { return; } final PsiElement parent = expression.getParent(); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IteratorHasNextCallsIteratorNextInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IteratorHasNextCallsIteratorNextInspection.java index ea55c8778593..ba62d217d304 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IteratorHasNextCallsIteratorNextInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IteratorHasNextCallsIteratorNextInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.IteratorUtils; import com.siyeh.ig.psiutils.MethodUtils; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; public class IteratorHasNextCallsIteratorNextInspection @@ -48,15 +47,12 @@ public class IteratorHasNextCallsIteratorNextInspection return new IteratorHasNextCallsIteratorNext(); } - private static class IteratorHasNextCallsIteratorNext - extends BaseInspectionVisitor { + private static class IteratorHasNextCallsIteratorNext extends BaseInspectionVisitor { @Override public void visitMethod(@NotNull PsiMethod method) { // note: no call to super - @NonNls final String name = method.getName(); - if (!MethodUtils.methodMatches(method, CommonClassNames.JAVA_UTIL_ITERATOR, null, - HardcodedMethodConstants.HAS_NEXT)) { + if (!MethodUtils.methodMatches(method, CommonClassNames.JAVA_UTIL_ITERATOR, null, HardcodedMethodConstants.HAS_NEXT)) { return; } if (!IteratorUtils.containsCallToIteratorNext(method, null, true)) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java index f75617403e5c..04724eb4d929 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2012 Bas Leijdekkers + * Copyright 2008-2015 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -190,6 +190,9 @@ public class IfMayBeConditionalInspection extends BaseInspection { @Override public void visitIfStatement(PsiIfStatement statement) { super.visitIfStatement(statement); + if (ControlFlowUtils.isElseIf(statement)) { + return; + } final PsiStatement thenBranch = statement.getThenBranch(); final PsiStatement elseBranch = statement.getElseBranch(); final PsiStatement thenStatement = ControlFlowUtils.stripBraces(thenBranch); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/FieldMayBeStaticInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/FieldMayBeStaticInspection.java index 40b06c127967..fcdcdbfa22fe 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/FieldMayBeStaticInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/FieldMayBeStaticInspection.java @@ -77,11 +77,11 @@ public class FieldMayBeStaticInspection extends BaseInspection { if (containingClass != null && !containingClass.hasModifierProperty(PsiModifier.STATIC) && containingClass.getContainingClass() != null - && !PsiUtil.isCompileTimeConstant(field)) { + && !PsiUtil.isCompileTimeConstant((PsiVariable)field)) { // inner class cannot have static declarations return; } - if (containingClass instanceof PsiAnonymousClass && !PsiUtil.isCompileTimeConstant(field)) { + if (containingClass instanceof PsiAnonymousClass && !PsiUtil.isCompileTimeConstant((PsiVariable)field)) { return; } if (!canBeStatic(initializer)) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/IteratorUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/IteratorUtils.java index 4f4cb93b62e2..f2e1e9ab5e15 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/IteratorUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/IteratorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2011 Bas Leijdekkers + * Copyright 2003-2015 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -96,9 +96,8 @@ public class IteratorUtils { } } else { - if (!MethodCallUtils.isCallToMethod(expression, - CommonClassNames.JAVA_UTIL_ITERATOR, null, - HardcodedMethodConstants.NEXT)) { + if (!MethodCallUtils.isCallToMethod(expression, CommonClassNames.JAVA_UTIL_ITERATOR, null, HardcodedMethodConstants.NEXT) + && !MethodCallUtils.isCallToMethod(expression, "java.util.ListIterator", null, "previous")) { return; } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_may_be_conditional/IfMayBeConditional.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_may_be_conditional/IfMayBeConditional.java index 1109243d24a2..4f8524d2600a 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_may_be_conditional/IfMayBeConditional.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_may_be_conditional/IfMayBeConditional.java @@ -9,11 +9,11 @@ public class IfMayBeConditional { void foo2(int a, int b) { int c = 0; - if (a < b) { c += a - b; } else { c += b; } + if (a < b) { c += a - b; } else { c += b; } } void foo3(int i, StringBuilder sb) { - if (i == 0) { + if (i == 0) { sb.append("type.getConstructor()", 0, 1); } else { @@ -22,7 +22,7 @@ public class IfMayBeConditional { } int foo4(int a, int b) { - if (a < b) return a; + if (a < b) return a; else return b; } @@ -42,4 +42,17 @@ public class IfMayBeConditional { i = b < c ? b : c; } } + + void largeIf(boolean a, boolean b, boolean c) { + final String value; + if (a) { + value = "a"; + } else if (b) { + value = "b"; + } else if (c) { + value = "c"; + } else { + value = "d"; + } + } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_may_be_conditional/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_may_be_conditional/expected.xml deleted file mode 100644 index 3ecb05a6e414..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_may_be_conditional/expected.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - IfMayBeConditional.java - 12 - If statement could be replaced with simple conditional expression - <code>if</code> could be replaced with simple conditional expression #loc - - - - IfMayBeConditional.java - 16 - 'if' statement could be replaced with simple conditional expression - <code>if</code> could be replaced with simple conditional expression #loc - - - - IfMayBeConditional.java - 25 - 'if' statement could be replaced with conditional expression - <code>if</code> could be replaced with conditional expression #loc - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IteratorHasNextCallsIteratorNextInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IteratorHasNextCallsIteratorNextInspectionTest.java new file mode 100644 index 000000000000..bd09bdcc14bb --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IteratorHasNextCallsIteratorNextInspectionTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2000-2015 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.siyeh.ig.bugs; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class IteratorHasNextCallsIteratorNextInspectionTest extends LightInspectionTestCase { + + public void testHasNextCallsNext() { + doTest("import java.util.*;" + + "class MyIterator implements Iterator {" + + " private Iterator iterator;" + + " public MyIterator(Iterator iterator) {" + + " this.iterator = iterator;" + + " }" + + " public boolean /*'Iterator.hasNext()' contains call to 'next()'*/hasNext/**/() {" + + " return next() != null;" + + " }" + + " public T next() {" + + " return iterator.next();" + + " }" + + " public void remove() {" + + " iterator.remove();" + + " }" + + "}"); + } + + public void testHasNextCallsPrevious() { + doTest("import java.util.*;" + + "abstract class MyIterator implements ListIterator {" + + " private ListIterator iterator;" + + " public MyIterator(ListIterator iterator) {" + + " this.iterator = iterator;" + + " }" + + " public boolean /*'Iterator.hasNext()' contains call to 'next()'*/hasNext/**/() {" + + " return previous() != null;" + + " }" + + " public T next() {" + + " return iterator.next();" + + " }" + + " public T previous() {" + + " return iterator.previous();" + + " }" + + "}"); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new IteratorHasNextCallsIteratorNextInspection(); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IteratorNextDoesNotThrowNoSuchElementExceptionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IteratorNextDoesNotThrowNoSuchElementExceptionInspectionTest.java new file mode 100644 index 000000000000..f5fad269994d --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IteratorNextDoesNotThrowNoSuchElementExceptionInspectionTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2015 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.siyeh.ig.bugs; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import junit.framework.TestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class IteratorNextDoesNotThrowNoSuchElementExceptionInspectionTest extends LightInspectionTestCase { + + public void testPrevious() { + doTest("import java.util.*;" + + "class ReverseListIterator implements Iterator {" + + " private ListIterator iterator;" + + " public ReverseListIterator(List list) {" + + " this.iterator = list.listIterator(list.size());" + + " }" + + " public boolean hasNext() {" + + " return iterator.hasPrevious();" + + " }" + + " public T next() {" + + " return iterator.previous();" + + " }" + + " public void remove() {" + + " iterator.remove();" + + " }" + + "}"); + } + + public void testEmpty() { + doTest("import java.util.*;" + + "class EmptyIterator implements Iterator {" + + " public boolean hasNext() {" + + " return false;" + + " }" + + " public T /*'Iterator.next()' which can't throw 'NoSuchElementException'*/next/**/() {" + + " return null;" + + " }" + + " public void remove() {" + + " }" + + "}"); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new IteratorNextDoesNotThrowNoSuchElementExceptionInspection(); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/IfMayBeConditionalInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/IfMayBeConditionalInspectionTest.java index 2a3ff34b7677..1f5b254068a5 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/IfMayBeConditionalInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/IfMayBeConditionalInspectionTest.java @@ -1,12 +1,20 @@ package com.siyeh.ig.controlflow; -import com.siyeh.ig.IGInspectionTestCase; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; -public class IfMayBeConditionalInspectionTest extends IGInspectionTestCase { +public class IfMayBeConditionalInspectionTest extends LightInspectionTestCase { - public void test() throws Exception { - final IfMayBeConditionalInspection tool = new IfMayBeConditionalInspection(); - tool.reportMethodCalls = true; - doTest("com/siyeh/igtest/controlflow/if_may_be_conditional", tool); + public void testIfMayBeConditional() throws Exception { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + final IfMayBeConditionalInspection inspection = new IfMayBeConditionalInspection(); + inspection.reportMethodCalls = true; + return inspection; } } \ No newline at end of file diff --git a/plugins/devkit/testSources/PluginProjectWizardTest.java b/plugins/devkit/testSources/PluginProjectWizardTest.java index 99ba3f4cbb9c..af96140257ce 100644 --- a/plugins/devkit/testSources/PluginProjectWizardTest.java +++ b/plugins/devkit/testSources/PluginProjectWizardTest.java @@ -36,7 +36,7 @@ public class PluginProjectWizardTest extends NewProjectWizardTestCase { createSdk("devkit", IdeaJdk.getInstance()); Project project = createProjectFromTemplate(PluginModuleType.getInstance().getName(), null, null); VirtualFile baseDir = project.getBaseDir(); - VirtualFile virtualFile = VfsUtilCore.findRelativeFile("META-INF/plugin.xml", baseDir); + VirtualFile virtualFile = VfsUtilCore.findRelativeFile("resources/META-INF/plugin.xml", baseDir); assertNotNull(virtualFile); RunnerAndConfigurationSettings configuration = RunManager.getInstance(project).getSelectedConfiguration(); diff --git a/plugins/maven/maven3-server-common/maven3-server-common.iml b/plugins/maven/maven3-server-common/maven3-server-common.iml index c48f45961ae9..585533b9a91d 100644 --- a/plugins/maven/maven3-server-common/maven3-server-common.iml +++ b/plugins/maven/maven3-server-common/maven3-server-common.iml @@ -4,7 +4,6 @@ - diff --git a/plugins/maven/maven30-server-impl/maven30-server-impl.iml b/plugins/maven/maven30-server-impl/maven30-server-impl.iml index 953e3dc5d7c4..61fd91b52dfa 100644 --- a/plugins/maven/maven30-server-impl/maven30-server-impl.iml +++ b/plugins/maven/maven30-server-impl/maven30-server-impl.iml @@ -4,7 +4,6 @@ - diff --git a/plugins/maven/maven32-server-impl/maven32-server-impl.iml b/plugins/maven/maven32-server-impl/maven32-server-impl.iml index b002fe636334..7d11ef040a60 100644 --- a/plugins/maven/maven32-server-impl/maven32-server-impl.iml +++ b/plugins/maven/maven32-server-impl/maven32-server-impl.iml @@ -4,7 +4,6 @@ -