diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerEncodingService.java b/java/compiler/impl/src/com/intellij/compiler/CompilerEncodingService.java new file mode 100644 index 000000000000..9c88df815466 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerEncodingService.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2012 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.compiler; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.util.Chunk; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.nio.charset.Charset; +import java.util.Collection; + +/** + * @author nik + */ +public abstract class CompilerEncodingService { + public static CompilerEncodingService getInstance(@NotNull Project project) { + return ServiceManager.getService(project, CompilerEncodingService.class); + } + + @Nullable + public static Charset getPreferredModuleEncoding(Chunk chunk) { + CompilerEncodingService service = null; + for (Module module : chunk.getNodes()) { + if (service == null) { + service = getInstance(module.getProject()); + } + final Charset charset = service.getPreferredModuleEncoding(module); + if (charset != null) { + return charset; + } + } + return null; + } + + @Nullable + public abstract Charset getPreferredModuleEncoding(@NotNull Module module); + + @NotNull + public abstract Collection getAllModuleEncodings(@NotNull Module module); +} diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompilerEncodingServiceImpl.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompilerEncodingServiceImpl.java new file mode 100644 index 000000000000..db458420d1cc --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompilerEncodingServiceImpl.java @@ -0,0 +1,118 @@ +/* + * Copyright 2000-2012 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.compiler.impl; + +import com.intellij.compiler.CompilerEncodingService; +import com.intellij.openapi.compiler.CompilerManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.encoding.EncodingProjectManager; +import com.intellij.openapi.vfs.encoding.EncodingProjectManagerImpl; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author nik + */ +public class CompilerEncodingServiceImpl extends CompilerEncodingService { + @NotNull private final Project myProject; + private final CachedValue>> myModuleFileEncodings; + + public CompilerEncodingServiceImpl(@NotNull Project project) { + myProject = project; + myModuleFileEncodings = CachedValuesManager.getManager(project).createCachedValue(new CachedValueProvider>>() { + @Override + public Result>> compute() { + Map> result = computeModuleCharsetMap(); + return Result.create(result, ProjectRootManager.getInstance(myProject), + ((EncodingProjectManagerImpl)EncodingProjectManager.getInstance(myProject)).getModificationTracker()); + } + }, false); + } + + private Map> computeModuleCharsetMap() { + final Map> map = new THashMap>(); + final Map mappings = EncodingProjectManager.getInstance(myProject).getAllMappings(); + ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex(); + final CompilerManager compilerManager = CompilerManager.getInstance(myProject); + for (Map.Entry entry : mappings.entrySet()) { + final VirtualFile file = entry.getKey(); + final Charset charset = entry.getValue(); + if (file == null || charset == null || (!file.isDirectory() && !compilerManager.isCompilableFileType(file.getFileType())) + || !index.isInSourceContent(file)) continue; + + final Module module = index.getModuleForFile(file); + if (module == null) continue; + + Set set = map.get(module); + if (set == null) { + set = new LinkedHashSet(); + map.put(module, set); + + final VirtualFile sourceRoot = index.getSourceRootForFile(file); + VirtualFile current = file.getParent(); + Charset parentCharset = null; + while (current != null) { + final Charset currentCharset = mappings.get(current); + if (currentCharset != null) { + parentCharset = currentCharset; + } + if (current.equals(sourceRoot)) { + break; + } + current = current.getParent(); + } + if (parentCharset != null) { + set.add(parentCharset); + } + } + set.add(charset); + } + + return map; + } + + @Override + @Nullable + public Charset getPreferredModuleEncoding(@NotNull Module module) { + final Set encodings = myModuleFileEncodings.getValue().get(module); + return ContainerUtil.getFirstItem(encodings, EncodingProjectManager.getInstance(myProject).getDefaultCharset()); + } + + @NotNull + @Override + public Collection getAllModuleEncodings(@NotNull Module module) { + final Set encodings = myModuleFileEncodings.getValue().get(module); + if (encodings != null) { + return encodings; + } + return ContainerUtil.createMaybeSingletonList(EncodingProjectManager.getInstance(myProject).getDefaultCharset()); + } +} diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java index 4851b0d2b548..6ada45f6853f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java @@ -48,10 +48,7 @@ import com.intellij.openapi.projectRoots.JavaSdkType; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.*; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -72,6 +69,7 @@ import org.objectweb.asm.ClassWriter; import java.io.File; import java.io.IOException; +import java.nio.charset.Charset; import java.util.*; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -186,9 +184,16 @@ public class BackendCompilerWrapper { } private void compileChunk(ModuleChunk chunk) throws IOException { + final String chunkPresentableName = getPresentableNameFor(chunk); + myModuleName = chunkPresentableName; + + // validate encodings + if (chunk.getModuleCount() > 1) { + validateEncoding(chunk, chunkPresentableName); + } + runTransformingCompilers(chunk); - setPresentableNameFor(chunk); final List outs = new ArrayList(); File fileToDelete = getOutputDirsToCompileTo(chunk, outs); @@ -206,10 +211,39 @@ public class BackendCompilerWrapper { } } + private void validateEncoding(ModuleChunk chunk, String chunkPresentableName) { + final CompilerEncodingService es = CompilerEncodingService.getInstance(myProject); + Charset charset = null; + for (Module module : chunk.getModules()) { + final Charset moduleCharset = es.getPreferredModuleEncoding(module); + if (charset == null) { + charset = moduleCharset; + } + else { + if (!Comparing.equal(charset, moduleCharset)) { + // warn user + final Charset chunkEncoding = CompilerEncodingService.getPreferredModuleEncoding(chunk); + final StringBuilder message = new StringBuilder(); + message.append("Modules in chunk ["); + message.append(chunkPresentableName); + message.append("] configured to use different encodings.\n"); + if (chunkEncoding != null) { + message.append("\"").append(chunkEncoding.name()).append("\" encoding will be used to compile the chunk"); + } + else { + message.append("Default compiler encoding will be used to compile the chunk"); + } + myCompileContext.addMessage(CompilerMessageCategory.INFORMATION, message.toString(), null, -1, -1); + break; + } + } + } + } - private void setPresentableNameFor(final ModuleChunk chunk) { - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { + + private static String getPresentableNameFor(final ModuleChunk chunk) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + public String compute() { final Module[] modules = chunk.getModules(); StringBuilder moduleName = new StringBuilder(Math.min(128, modules.length * 8)); for (int idx = 0; idx < modules.length; idx++) { @@ -223,7 +257,7 @@ public class BackendCompilerWrapper { break; } } - myModuleName = moduleName.toString(); + return moduleName.toString(); } }); } @@ -845,7 +879,9 @@ public class BackendCompilerWrapper { while (true) { FileObject path = myPaths.take(); - if (path == myStopThreadToken) break; + if (path == myStopThreadToken) { + break; + } processPath(path, myProject); } } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ModuleChunk.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ModuleChunk.java index b45aef2894c0..50d0e5dbe8e5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ModuleChunk.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ModuleChunk.java @@ -305,7 +305,11 @@ public class ModuleChunk extends Chunk { //the check for equal language levels is done elsewhere public LanguageLevel getLanguageLevel() { - return LanguageLevelUtil.getEffectiveLanguageLevel(getModules()[0]); + return LanguageLevelUtil.getEffectiveLanguageLevel(getNodes().iterator().next()); + } + + public Project getProject() { + return myContext.getProject(); } private static class BeforeJdkOrderEntryCondition implements Condition { diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java index e26b8de22f37..651651272032 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java @@ -109,7 +109,7 @@ public class CompilerAPICompiler implements BackendCompiler { List commandLine = new ArrayList(); JavacSettings javacSettings = CompilerAPIConfiguration.getSettings(myProject, CompilerAPIConfiguration.class); final List additionalOptions = - JavacCompiler.addAdditionalSettings(commandLine, javacSettings, false, JavaSdkVersion.JDK_1_6, myProject, compileContext.isAnnotationProcessorsEnabled()); + JavacCompiler.addAdditionalSettings(commandLine, javacSettings, false, JavaSdkVersion.JDK_1_6, chunk, compileContext.isAnnotationProcessorsEnabled()); JavacCompiler.addCommandLineOptions(chunk, commandLine, outputDir, chunk.getJdk(), false,false, null, false, false, false); commandLine.addAll(additionalOptions); diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompiler.java index 5944df90ada9..5cd786eecd78 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompiler.java @@ -184,7 +184,7 @@ public class EclipseCompiler extends ExternalCompiler { commandLine.add(outputPath.replace('/', File.separatorChar)); commandLine.add("-verbose"); - StringTokenizer tokenizer = new StringTokenizer(compilerSettings.getOptionsString(myProject), " "); + StringTokenizer tokenizer = new StringTokenizer(compilerSettings.getOptionsString(chunk), " "); while (tokenizer.hasMoreTokens()) { commandLine.add(tokenizer.nextToken()); } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacCompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacCompiler.java index ab6d143ed41f..724dcdd01fc4 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacCompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacCompiler.java @@ -214,7 +214,7 @@ public class JavacCompiler extends ExternalCompiler { } final List additionalOptions = - addAdditionalSettings(commandLine, javacSettings, myAnnotationProcessorMode, version, myProject, annotationProcessorsEnabled); + addAdditionalSettings(commandLine, javacSettings, myAnnotationProcessorMode, version, chunk, annotationProcessorsEnabled); CompilerUtil.addLocaleOptions(commandLine, false); @@ -275,15 +275,15 @@ public class JavacCompiler extends ExternalCompiler { } public static List addAdditionalSettings(List commandLine, JavacSettings javacSettings, boolean isAnnotationProcessing, - JavaSdkVersion version, Project project, boolean annotationProcessorsEnabled) { + JavaSdkVersion version, ModuleChunk chunk, boolean annotationProcessorsEnabled) { final List additionalOptions = new ArrayList(); - StringTokenizer tokenizer = new StringTokenizer(javacSettings.getOptionsString(project), " "); + StringTokenizer tokenizer = new StringTokenizer(javacSettings.getOptionsString(chunk), " "); if (!version.isAtLeast(JavaSdkVersion.JDK_1_6)) { isAnnotationProcessing = false; // makes no sense for these versions annotationProcessorsEnabled = false; } if (isAnnotationProcessing) { - final CompilerConfiguration config = CompilerConfiguration.getInstance(project); + final CompilerConfiguration config = CompilerConfiguration.getInstance(chunk.getProject()); additionalOptions.add("-Xprefer:source"); additionalOptions.add("-implicit:none"); additionalOptions.add("-proc:only"); diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacSettings.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacSettings.java index 9759426bacc1..97106f0fe19b 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacSettings.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacSettings.java @@ -15,11 +15,12 @@ */ package com.intellij.compiler.impl.javaCompiler.javac; +import com.intellij.compiler.CompilerEncodingService; +import com.intellij.compiler.impl.javaCompiler.ModuleChunk; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.openapi.vfs.encoding.EncodingProjectManager; +import com.intellij.util.Chunk; import org.jetbrains.annotations.TestOnly; import java.nio.charset.Charset; @@ -37,7 +38,7 @@ public class JavacSettings { private boolean myTestsUseExternalCompiler = false; - public Collection getOptions(Project project) { + public Collection getOptions(Chunk chunk) { List options = new ArrayList(); if (DEBUGGING_INFO) { options.add("-g"); @@ -61,10 +62,10 @@ public class JavacSettings { } } if (!isEncodingSet && acceptEncoding()) { - final Charset ideCharset = EncodingProjectManager.getInstance(project).getDefaultCharset(); - if (ideCharset != null && !Comparing.equal(CharsetToolkit.getDefaultSystemCharset(), ideCharset)) { + final Charset charset = CompilerEncodingService.getPreferredModuleEncoding(chunk); + if (charset != null) { options.add("-encoding"); - options.add(ideCharset.name()); + options.add(charset.name()); } } return options; @@ -78,9 +79,9 @@ public class JavacSettings { return true; } - public String getOptionsString(final Project project) { + public String getOptionsString(final ModuleChunk chunk) { final StringBuilder options = new StringBuilder(); - for (String option : getOptions(project)) { + for (String option : getOptions(chunk)) { if (options.length() > 0) { options.append(" "); } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/jikes/JikesCompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/jikes/JikesCompiler.java index 9ea3047b8f22..10c7be635bf5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/jikes/JikesCompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/jikes/JikesCompiler.java @@ -202,7 +202,7 @@ public class JikesCompiler extends ExternalCompiler { commandLine.add(outputPath.replace('/', File.separatorChar)); JikesSettings jikesSettings = JikesConfiguration.getSettings(myProject); - StringTokenizer tokenizer = new StringTokenizer(jikesSettings.getOptionsString(myProject), " "); + StringTokenizer tokenizer = new StringTokenizer(jikesSettings.getOptionsString(chunk), " "); while (tokenizer.hasMoreTokens()) { commandLine.add(tokenizer.nextToken()); } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/jikes/JikesSettings.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/jikes/JikesSettings.java index cf91f52487ab..1e05c57b7fad 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/jikes/JikesSettings.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/jikes/JikesSettings.java @@ -19,7 +19,8 @@ import com.intellij.compiler.impl.javaCompiler.javac.JavacSettings; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StorageScheme; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.module.Module; +import com.intellij.util.Chunk; import java.util.Collection; @@ -34,8 +35,8 @@ public class JikesSettings extends JavacSettings { public String JIKES_PATH = ""; public boolean IS_EMACS_ERRORS_MODE = true; - public Collection getOptions(Project project) { - final Collection options = super.getOptions(project); + public Collection getOptions(Chunk chunk) { + final Collection options = super.getOptions(chunk); if(IS_EMACS_ERRORS_MODE) { options.add("+E"); } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/rmiCompiler/RmicCompiler.java b/java/compiler/impl/src/com/intellij/compiler/impl/rmiCompiler/RmicCompiler.java index 20d2c6cab0b9..4292432fc325 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/rmiCompiler/RmicCompiler.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/rmiCompiler/RmicCompiler.java @@ -42,6 +42,7 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; +import com.intellij.util.Chunk; import com.intellij.util.PathsList; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; @@ -276,7 +277,6 @@ public class RmicCompiler implements ClassPostProcessingCompiler{ return successfullyCompiledItems.toArray(new RmicProcessingItem[successfullyCompiledItems.size()]); } - // todo: Module -> ModuleChunk private static String[] createStartupCommand(final Module module, final String outputPath, final RmicProcessingItem[] items) { final Sdk jdk = ModuleRootManager.getInstance(module).getSdk(); @@ -296,7 +296,7 @@ public class RmicCompiler implements ClassPostProcessingCompiler{ commandLine.add("-verbose"); final Project project = module.getProject(); - ContainerUtil.addAll(commandLine, RmicConfiguration.getSettings(project).getOptions(project)); + ContainerUtil.addAll(commandLine, RmicConfiguration.getSettings(project).getOptions(new Chunk(module))); commandLine.add("-classpath"); diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/rmiCompiler/RmicSettings.java b/java/compiler/impl/src/com/intellij/compiler/impl/rmiCompiler/RmicSettings.java index 98eea78a2df5..d619ec9eca15 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/rmiCompiler/RmicSettings.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/rmiCompiler/RmicSettings.java @@ -19,7 +19,8 @@ import com.intellij.compiler.impl.javaCompiler.javac.JavacSettings; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StorageScheme; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.module.Module; +import com.intellij.util.Chunk; import java.util.Collection; @@ -38,8 +39,8 @@ public class RmicSettings extends JavacSettings { DEPRECATION = false; // in this configuration deprecation is false by default } - public Collection getOptions(Project project) { - final Collection options = super.getOptions(project); + public Collection getOptions(Chunk chunk) { + final Collection options = super.getOptions(chunk); if(GENERATE_IIOP_STUBS) { options.add("-iiop"); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java index 41546503f757..4fc52aea677a 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java @@ -770,10 +770,16 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple return null; } }; + + Collection actionsFromExtensions = new ArrayList(); for (final ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) { - result.addAll(extension.createAddActions(selectedNodeRetriever, TREE_UPDATER, myProject, myRoot)); + actionsFromExtensions.addAll(extension.createAddActions(selectedNodeRetriever, TREE_UPDATER, myProject, myRoot)); } + if (!actionsFromExtensions.isEmpty() && !result.isEmpty()) { + result.add(new Separator()); + } + result.addAll(actionsFromExtensions); return result.toArray(new AnAction[result.size()]); } }; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index b68572f1c4af..6cc5e983fc69 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -27,6 +27,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -35,7 +36,7 @@ import java.util.List; /** * @author peter */ -class ConstructorInsertHandler implements InsertHandler> { +public class ConstructorInsertHandler implements InsertHandler> { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.ConstructorInsertHandler"); public static final ConstructorInsertHandler SMART_INSTANCE = new ConstructorInsertHandler(true); public static final ConstructorInsertHandler BASIC_INSTANCE = new ConstructorInsertHandler(false); @@ -169,6 +170,7 @@ class ConstructorInsertHandler implements InsertHandler List insertMembersBeforeAnchor(PsiClass aClass, PsiElement anchor, @NotNull List memberPrototypes) throws IncorrectOperationException { + public static List insertMembersBeforeAnchor(PsiClass aClass, @Nullable PsiElement anchor, @NotNull List memberPrototypes) throws IncorrectOperationException { boolean before = true; for (T memberPrototype : memberPrototypes) { memberPrototype.insert(aClass, anchor, before); @@ -280,7 +280,7 @@ public class GenerateMembersUtil { if (paramName == null) paramName = "p" + i; PsiParameter newParameter = factory.createParameter(paramName, substituted); - if (parameter.getLanguage() == StdLanguages.JAVA) { + if (parameter.getLanguage() == JavaLanguage.INSTANCE) { PsiModifierList modifierList = newParameter.getModifierList(); modifierList = (PsiModifierList)modifierList.replace(parameter.getModifierList()); processAnnotations(project, modifierList); diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java index ec028e11c50e..06583b409c77 100644 --- a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java @@ -26,6 +26,7 @@ import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.BaseLocalInspectionTool; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.text.StringUtil; @@ -60,6 +61,8 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { @Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NOT_ANNOTATED_SETTER_PARAMETER = true; @Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = true; // remains for test @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD = true; + + private static final Logger LOG = Logger.getInstance("#" + NullableStuffInspection.class.getName()); @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { @@ -144,10 +147,10 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { final PsiParameter[] parameters = setter.getParameterList().getParameters(); assert parameters.length == 1 : setter.getText(); final PsiParameter parameter = parameters[0]; - assert parameter != null : setter.getText(); + LOG.assertTrue(parameter != null, setter.getText()); if (REPORT_NOT_ANNOTATED_GETTER && !AnnotationUtil.isAnnotated(parameter, manager.getAllAnnotations()) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) { final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); - assert nameIdentifier1 != null : parameter; + assertValidElement(setter, parameter, nameIdentifier1); holder.registerProblem(nameIdentifier1, InspectionsBundle.message("inspection.nullable.problems.annotated.field.setter.parameter.not.annotated", StringUtil.getShortName(anno)), @@ -157,7 +160,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { if (PropertyUtils.isSimpleSetter(setter)) { if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false)) { final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); - assert nameIdentifier1 != null : parameter; + assertValidElement(setter, parameter, nameIdentifier1); holder.registerProblem(nameIdentifier1, InspectionsBundle.message( "inspection.nullable.problems.annotated.field.setter.parameter.conflict", StringUtil.getShortName(anno), nullableSimpleName), @@ -166,7 +169,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { } else if (annotated.isDeclaredNullable && manager.isNotNull(parameter, false)) { final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); - assert nameIdentifier1 != null : parameter; + assertValidElement(setter, parameter, nameIdentifier1); holder.registerProblem(nameIdentifier1, InspectionsBundle.message( "inspection.nullable.problems.annotated.field.setter.parameter.conflict", StringUtil.getShortName(anno), notNullSimpleName), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, @@ -241,6 +244,11 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { } } + private void assertValidElement(PsiMethod setter, PsiParameter parameter, PsiIdentifier nameIdentifier1) { + LOG.assertTrue(nameIdentifier1 != null, setter.getText()); + LOG.assertTrue(parameter.isPhysical(), setter.getText()); + } + public PsiAssignmentExpression getAssignmentExpressionIfOnAssignmentLefthand(PsiExpression expression) { PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class); if (!(parent instanceof PsiAssignmentExpression)) { diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveDirectoryWithClassesHelper.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveDirectoryWithClassesHelper.java index 9d8b77c145fa..ca4a899167a0 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveDirectoryWithClassesHelper.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveDirectoryWithClassesHelper.java @@ -74,6 +74,10 @@ public class JavaMoveDirectoryWithClassesHelper extends MoveDirectoryWithClasses if (!(file instanceof PsiClassOwner)) { return false; } + + if (!JspPsiUtil.isInJspFile(file)) { + return false; + } for (PsiClass psiClass : ((PsiClassOwner)file).getClasses()) { final PsiClass newClass = MoveClassesOrPackagesUtil.doMoveClass(psiClass, moveDestination); diff --git a/java/java-psi-api/src/com/intellij/psi/ClsFileDecompiledPsiFileProvider.java b/java/java-psi-api/src/com/intellij/psi/ClsFileDecompiledPsiFileProvider.java new file mode 100644 index 000000000000..c5ca74428224 --- /dev/null +++ b/java/java-psi-api/src/com/intellij/psi/ClsFileDecompiledPsiFileProvider.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi; + +import com.intellij.openapi.extensions.ExtensionPointName; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Evgeny Gerashchenko + * @since 3/20/12 + */ +public interface ClsFileDecompiledPsiFileProvider { + ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.psi.clsDecompiledFileProvider"); + + /** + * Returns decompiled PSI associated with this classfile + * + * @param clsFile instance of ClsFile + * @return decompiled PSI file + */ + @Nullable + PsiFile getDecompiledPsiFile(@NotNull PsiJavaFile clsFile); +} diff --git a/java/java-psi-impl/java-psi-impl.iml b/java/java-psi-impl/java-psi-impl.iml index 6c15172b7e3d..ccd2d51410f9 100644 --- a/java/java-psi-impl/java-psi-impl.iml +++ b/java/java-psi-impl/java-psi-impl.iml @@ -12,7 +12,6 @@ - diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index bedf04e6c3e5..2569d397f3d3 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -26,8 +26,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; -import com.intellij.openapi.fileTypes.ContentBasedFileSubstitutor; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.progress.NonCancelableSection; import com.intellij.openapi.progress.ProgressIndicatorProvider; @@ -327,12 +325,10 @@ public class ClsFileImpl extends ClsRepositoryPsiElement @Override public PsiFile getDecompiledPsiFile() { - for (ContentBasedFileSubstitutor processor : Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME)) { - if (processor instanceof ContentBasedClassFileProcessor && processor.isApplicable(getProject(), getVirtualFile())) { - PsiFile decompiledPsiFile = ((ContentBasedClassFileProcessor)processor).getDecompiledPsiFile(this); - if (decompiledPsiFile != null) { - return decompiledPsiFile; - } + for (ClsFileDecompiledPsiFileProvider provider : Extensions.getExtensions(ClsFileDecompiledPsiFileProvider.EP_NAME)) { + PsiFile decompiledPsiFile = provider.getDecompiledPsiFile(this); + if (decompiledPsiFile != null) { + return decompiledPsiFile; } } return (PsiFile) getMirror(); diff --git a/java/openapi/src/com/intellij/psi/JavaCodeFragmentFactory.java b/java/openapi/src/com/intellij/psi/JavaCodeFragmentFactory.java index a942f8cad9de..fc91555bb674 100644 --- a/java/openapi/src/com/intellij/psi/JavaCodeFragmentFactory.java +++ b/java/openapi/src/com/intellij/psi/JavaCodeFragmentFactory.java @@ -19,6 +19,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class JavaCodeFragmentFactory { public static JavaCodeFragmentFactory getInstance(Project project) { @@ -49,7 +50,7 @@ public abstract class JavaCodeFragmentFactory { * @return the created code fragment. */ @NotNull - public abstract JavaCodeFragment createCodeBlockCodeFragment(@NotNull String text, PsiElement context, boolean isPhysical); + public abstract JavaCodeFragment createCodeBlockCodeFragment(@NotNull String text, @Nullable PsiElement context, boolean isPhysical); /** * Flag for {@linkplain #createTypeCodeFragment(String, PsiElement, boolean, int)} - allows void type. diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java index 54ab504d2a94..bdf9b68045fc 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java @@ -65,7 +65,7 @@ public abstract class IntervalTreeImpl extends RedBla private final IntervalTreeImpl myIntervalTree; - public IntervalNode(IntervalTreeImpl intervalTree, @NotNull E key, int start, int end) { + public IntervalNode(@NotNull IntervalTreeImpl intervalTree, @NotNull E key, int start, int end) { // maxEnd == 0 so to not disrupt existing maxes myIntervalTree = intervalTree; myStart = start; diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java index 72180cd2ec84..7d1343e5ad70 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java @@ -28,7 +28,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.RangeMarkerImpl"); protected final DocumentEx myDocument; - protected RangeMarkerTree.RMNode myNode; + protected RangeMarkerTree.RMNode myNode; private final long myId; private static final StripedIDGenerator counter = new StripedIDGenerator(); @@ -91,7 +91,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx public void invalidate(final DocumentEvent e) { setValid(false); - RangeMarkerTree.RMNode node = myNode; + RangeMarkerTree.RMNode node = myNode; if (node != null) { node.processAliveKeys(new Processor() { diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java index bd320dfc7462..6fc5bb1d8830 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java @@ -88,10 +88,10 @@ public class RangeMarkerTree extends IntervalTreeImpl.RMNode addInterval(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { + public RMNode addInterval(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { RangeMarkerImpl marker = (RangeMarkerImpl)interval; marker.setValid(true); - RangeMarkerTree.RMNode node = (RMNode)super.addInterval(interval, start, end, greedyToLeft, greedyToRight, layer); + RMNode node = (RMNode)super.addInterval(interval, start, end, greedyToLeft, greedyToRight, layer); if (DEBUG && node.intervals.size() > DUPLICATE_LIMIT) { l.readLock().lock(); @@ -113,7 +113,7 @@ public class RangeMarkerTree extends IntervalTreeImpl node) { @NonNls final StringBuilder msg = new StringBuilder(); final AtomicInteger alive = new AtomicInteger(); node.processAliveKeys(new Processor() { @@ -135,8 +135,8 @@ public class RangeMarkerTree extends IntervalTreeImpl createNewNode(@NotNull T key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { + return new RMNode(this, key, start, end, greedyToLeft, greedyToRight); } @Override @@ -146,21 +146,26 @@ public class RangeMarkerTree extends IntervalTreeImpl.RMNode lookupNode(@NotNull T key) { - return (RMNode)((RangeMarkerImpl)key).myNode; + protected RMNode lookupNode(@NotNull T key) { + return (RMNode)((RangeMarkerImpl)key).myNode; } @Override protected void setNode(@NotNull T key, IntervalNode intervalNode) { - ((RangeMarkerImpl)key).myNode = (RangeMarkerTree.RMNode)intervalNode; + ((RangeMarkerImpl)key).myNode = (RMNode)intervalNode; } - public class RMNode extends IntervalTreeImpl.IntervalNode { + static class RMNode extends IntervalTreeImpl.IntervalNode { private final boolean isExpandToLeft; private final boolean isExpandToRight; - public RMNode(@NotNull T key, int start, int end, boolean greedyToLeft, boolean greedyToRight) { - super(RangeMarkerTree.this, key, start, end); + public RMNode(@NotNull RangeMarkerTree rangeMarkerTree, + @NotNull T key, + int start, + int end, + boolean greedyToLeft, + boolean greedyToRight) { + super(rangeMarkerTree, key, start, end); isExpandToLeft = greedyToLeft; isExpandToRight = greedyToRight; } @@ -227,7 +232,7 @@ public class RangeMarkerTree extends IntervalTreeImpl insertedNode = (RMNode)findOrInsert(node); // can change if two range become the one if (insertedNode != node) { // merge happened diff --git a/platform/lang-api/src/com/intellij/profile/DefaultProjectProfileManager.java b/platform/lang-api/src/com/intellij/profile/DefaultProjectProfileManager.java index ba8ea7eeaa7b..9aae48874161 100644 --- a/platform/lang-api/src/com/intellij/profile/DefaultProjectProfileManager.java +++ b/platform/lang-api/src/com/intellij/profile/DefaultProjectProfileManager.java @@ -15,6 +15,7 @@ */ package com.intellij.profile; +import com.intellij.openapi.Disposable; import com.intellij.openapi.components.StateSplitter; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -204,8 +205,14 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager return profile; } - public void addProfilesListener(ProfileChangeAdapter profilesListener) { + public void addProfilesListener(final ProfileChangeAdapter profilesListener, Disposable parent) { myProfilesListener.add(profilesListener); + Disposer.register(parent, new Disposable() { + @Override + public void dispose() { + myProfilesListener.remove(profilesListener); + } + }); } public void removeProfilesListener(ProfileChangeAdapter profilesListener) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java index bf7b2ba624b5..60d25f3665ed 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java @@ -63,6 +63,7 @@ import com.intellij.openapi.vfs.VirtualFilePropertyEvent; import com.intellij.profile.Profile; import com.intellij.profile.ProfileChangeAdapter; import com.intellij.profile.codeInspection.InspectionProfileManager; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; import com.intellij.psi.impl.PsiDocumentManagerImpl; import com.intellij.psi.search.scope.packageSet.NamedScopesHolder; @@ -229,8 +230,9 @@ class DaemonListeners implements Disposable { CommandProcessor.getInstance().addCommandListener(new MyCommandListener(), this); ApplicationListener applicationListener = new MyApplicationListener(); ApplicationManager.getApplication().addApplicationListener(applicationListener, this); - EditorColorsManager.getInstance().addEditorColorsListener(new MyEditorColorsListener(),this); + EditorColorsManager.getInstance().addEditorColorsListener(new MyEditorColorsListener(), this); InspectionProfileManager.getInstance().addProfileChangeListener(new MyProfileChangeListener(), this); + InspectionProjectProfileManager.getInstance(project).addProfilesListener(new MyProfileChangeListener(), this); TodoConfiguration.getInstance().addPropertyChangeListener(new MyTodoListener(), this); ActionManagerEx.getInstanceEx().addAnActionListener(new MyAnActionListener(), this); VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index 5126b9042f6c..a044b8ae00dd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -54,7 +54,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator ourRendererColors = new THashMap(); @NonNls private static final String COLOR = "color"; - private final TObjectIntHashMap myOrder = new TObjectIntHashMap(); + private final OrderMap myOrder = new OrderMap(); private JDOMExternalizableStringList myReadOrder; private static final Map STANDARD_SEVERITIES = new THashMap(); @@ -301,13 +301,15 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator order = getOrder(); - return order.get(s1) - order.get(s2); + OrderMap order = getOrder(); + int o1 = order.getOrder(s1, -1); + int o2 = order.getOrder(s2, -1); + return o1 - o2; } @NotNull - private TObjectIntHashMap getOrder() { + private OrderMap getOrder() { if (myOrder.isEmpty()) { List order = getDefaultOrder(); setFromList(order); @@ -414,4 +416,11 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator { + private int getOrder(@NotNull HighlightSeverity severity, int defaultOrder) { + int index = index(severity); + return index < 0 ? defaultOrder : _values[index]; + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java index 7b4d26419477..2723b8940e36 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java @@ -80,11 +80,10 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone myFileTools.clear(); } }; - myProfileManager.addProfilesListener(myProfilesListener); + myProfileManager.addProfilesListener(myProfilesListener, myProject); Disposer.register(myProject, new Disposable() { @Override public void dispose() { - myProfileManager.removeProfilesListener(myProfilesListener); myFileTools.clear(); } }); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java index ff171fa13760..e80cbf8e61b8 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java @@ -87,7 +87,11 @@ public class ProblemDescriptorImpl extends CommonProblemDescriptorImpl implement assertPhysical(startElement); if (startElement != endElement) assertPhysical(endElement); - if (startElement.getTextRange().getStartOffset() >= endElement.getTextRange().getEndOffset()) { + final TextRange startElementRange = startElement.getTextRange(); + LOG.assertTrue(startElementRange != null, startElement); + final TextRange endElementRange = endElement.getTextRange(); + LOG.assertTrue(endElementRange != null, endElement); + if (startElementRange.getStartOffset() >= endElementRange.getEndOffset()) { if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) { LOG.error("Empty PSI elements should not be passed to createDescriptor. Start: " + startElement + ", end: " + endElement); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsViewComparator.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsViewComparator.java index b0b76948bf27..7fac178a6060 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsViewComparator.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsViewComparator.java @@ -141,7 +141,11 @@ public class InspectionResultsViewComparator implements Comparator { private static int compareEntity(final RefEntity entity, final PsiElement element) { if (entity instanceof RefElement) { - return PsiUtilCore.compareElementsByPosition(((RefElement)entity).getElement(), element); + final PsiElement psiElement = ((RefElement)entity).getElement(); + if (psiElement != null && element != null) { + return PsiUtilCore.compareElementsByPosition(psiElement, element); + } + if (element == null) return psiElement == null ? 0 : 1; } if (element instanceof PsiQualifiedNamedElement) { return StringUtil.compare(entity.getQualifiedName(), ((PsiQualifiedNamedElement)element).getQualifiedName(), true); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderRootsCache.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderRootsCache.java index be2c92e84dd9..de76638132e9 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderRootsCache.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderRootsCache.java @@ -49,7 +49,7 @@ public class OrderRootsCache { @Nullable public VirtualFile[] getCachedRoots(OrderRootType rootType, int flags) { final VirtualFilePointerContainer cached = myRoots.get(new CacheKey(rootType, flags)); - return cached != null ? cached.getFiles() : null; + return cached == null ? null : cached.getFiles(); } @Nullable @@ -67,7 +67,7 @@ public class OrderRootsCache { private static final class CacheKey { private final OrderRootType myRootType; - private int myFlags; + private final int myFlags; private CacheKey(OrderRootType rootType, int flags) { myRootType = rootType; diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/BeforeCheckinHandlerUtil.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/BeforeCheckinHandlerUtil.java index 5a2c3d785530..6c88ae099f46 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/BeforeCheckinHandlerUtil.java +++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/BeforeCheckinHandlerUtil.java @@ -16,6 +16,7 @@ package com.intellij.openapi.vcs.checkin; import com.intellij.openapi.components.StorageScheme; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.roots.ProjectFileIndex; @@ -70,6 +71,10 @@ public class BeforeCheckinHandlerUtil { private static boolean isFileUnderSourceRoot(@NotNull Project project, @NotNull VirtualFile file) { ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex(); - return index.isInSource(file) && !index.isInLibrarySource(file); + if (StdFileTypes.JAVA == file.getFileType()) { + return index.isInSource(file) && !index.isInLibrarySource(file); + } else { + return index.isInContent(file) && !index.isInLibrarySource(file) ; + } } } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java index 600ee089edc0..c29801d58402 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java @@ -356,7 +356,7 @@ public class InspectionProfileManager extends ApplicationProfileManager implemen return mySchemesManager; } - public void onProfilesChanged() { + public static void onProfilesChanged() { //cleanup caches blindly for all projects in case ide profile was modified for (Project project : ProjectManager.getInstance().getOpenProjects()) { HighlightingSettingsPerFile.getInstance(project).cleanProfileSettings(); diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ProjectInspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ProjectInspectionToolsConfigurable.java index a37ffe08cf08..56d9e859ffed 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ProjectInspectionToolsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ProjectInspectionToolsConfigurable.java @@ -53,6 +53,7 @@ public class ProjectInspectionToolsConfigurable extends InspectionToolsConfigura myProfileManager.setRootProfile(profileName); myProjectProfileManager.setProjectProfile(null); } + InspectionProfileManager.onProfilesChanged(); } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index 8ffa8b89fd4e..db88fb00b106 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -31,6 +31,7 @@ import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; import com.intellij.pom.PomManager; @@ -407,6 +408,12 @@ public class DocumentCommitThread implements Runnable, Disposable { catch (Exception e) { s += e; } + try { + Disposer.dispose(project); + } + catch (Throwable ignored) { + // do not fill log with endless exceptions + } throw new RuntimeException(s); } diff --git a/platform/platform-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java b/platform/platform-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java index 595f3dc87d10..dee22ce81b6a 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java +++ b/platform/platform-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java @@ -34,13 +34,4 @@ public interface ContentBasedClassFileProcessor extends ContentBasedFileSubstitu */ @NotNull SyntaxHighlighter createHighlighter(Project project, VirtualFile vFile); - - /** - * Returns decompiled PSI associated with this classfile - * - * @param clsFile instance of ClsFile - * @return decompiled PSI file - */ - @Nullable - PsiFile getDecompiledPsiFile(PsiFile clsFile); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index 607b043b00b8..b297fd94ce71 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -110,7 +110,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, DocumentBulkUpdateListener bulkUpdateListener = new DocumentBulkUpdateListener() { @Override public void updateStarted(@NotNull Document doc) { - if (doc != myEditor.getDocument() && myOffset >= doc.getTextLength()) return; + if (doc != myEditor.getDocument() && myOffset >= doc.getTextLength() || savedBeforeBulkCaretMarker != null) return; savedBeforeBulkCaretMarker = doc.createRangeMarker(myOffset, myOffset); } @Override @@ -237,7 +237,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, } public void setIgnoreWrongMoves(boolean ignoreWrongMoves) { - this.myIgnoreWrongMoves = ignoreWrongMoves; + myIgnoreWrongMoves = ignoreWrongMoves; } @Override @@ -695,9 +695,8 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, moveToOffset(newLength, performSoftWrapAdjustment); } else { - final int line; try { - line = event.translateLineViaDiff(myLogicalCaret.line); + final int line = event.translateLineViaDiff(myLogicalCaret.line); moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment, null, false); } catch (FilesTooBigForDiffException e1) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java index 8a191e1b86bd..cd0947bc871f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java @@ -44,19 +44,20 @@ public class RangeHighlighterTree extends RangeMarkerTree { @NotNull @Override protected RHNode createNewNode(@NotNull RangeHighlighterEx key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { - return new RHNode(key, start, end, greedyToLeft, greedyToRight,layer); + return new RHNode(this, key, start, end, greedyToLeft, greedyToRight,layer); } - class RHNode extends RangeMarkerTree.RMNode { + static class RHNode extends RMNode { final int myLayer; - public RHNode(@NotNull final RangeHighlighterEx key, + public RHNode(@NotNull RangeHighlighterTree rangeMarkerTree, + @NotNull final RangeHighlighterEx key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { - super(key, start, end, greedyToLeft, greedyToRight); + super(rangeMarkerTree, key, start, end, greedyToLeft, greedyToRight); myLayer = layer; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingProjectManagerImpl.java index 5e6b834c77ed..0d27f0cebe4e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingProjectManagerImpl.java @@ -36,6 +36,7 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.vfs.*; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -65,6 +66,13 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { private boolean myUseUTFGuessing = true; private boolean myNative2AsciiForPropertiesFiles; private Charset myDefaultCharsetForPropertiesFiles; + private long myModificationCount; + private final ModificationTracker myModificationTracker = new ModificationTracker() { + @Override + public long getModificationCount() { + return myModificationCount; + } + }; public EncodingProjectManagerImpl(Project project, GeneralSettings generalSettings, EditorSettingsExternalizable editorSettings, PsiDocumentManager documentManager) { myProject = project; @@ -138,6 +146,7 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { myEditorSettings.migrateCharsetSettingsTo(defaultManager); } } + myModificationCount++; } @Override @@ -180,6 +189,10 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { return null; } + public ModificationTracker getModificationTracker() { + return myModificationTracker; + } + @Override public void setEncoding(@Nullable VirtualFile virtualFileOrDir, @Nullable Charset charset) { if (charset == null) { @@ -188,6 +201,7 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { else { myMapping.put(virtualFileOrDir, charset); } + myModificationCount++; setAndSaveOrReload(virtualFileOrDir, charset); } @@ -252,6 +266,7 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { } } } + myModificationCount++; } //retrieves encoding for the Project node diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java index 2c4fe1c3ac34..9048428ee33a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java @@ -25,6 +25,7 @@ import com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer; import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.ContainerUtilRt; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -39,10 +40,10 @@ import java.util.List; */ public class VirtualFilePointerContainerImpl implements VirtualFilePointerContainer, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer"); - @NotNull private final List myList = new ArrayList(); + @NotNull private final List myList = ContainerUtilRt.createEmptyCOWList(); private final List myReadOnlyList = Collections.unmodifiableList(myList); - private final VirtualFilePointerManagerImpl myVirtualFilePointerManager; - private final Disposable myParent; + @NotNull private final VirtualFilePointerManagerImpl myVirtualFilePointerManager; + @NotNull private final Disposable myParent; private final VirtualFilePointerListener myListener; private VirtualFile[] myCachedDirectories; @NonNls private static final String URL_ATTR = "url"; @@ -91,7 +92,7 @@ public class VirtualFilePointerContainerImpl implements VirtualFilePointerContai ContainerUtil.swapElements(myList, index, index + 1); } - private int indexOf(final String url) { + private int indexOf(@NotNull final String url) { for (int i = 0; i < myList.size(); i++) { final VirtualFilePointer pointer = myList.get(i); if (url.equals(pointer.getUrl())) { @@ -134,7 +135,7 @@ public class VirtualFilePointerContainerImpl implements VirtualFilePointerContai @Override @NotNull public List getList() { - assert !myDisposed; + assert !myDisposed; return myReadOnlyList; } @@ -166,6 +167,7 @@ public class VirtualFilePointerContainerImpl implements VirtualFilePointerContai return myCachedUrls; } + @NotNull private String[] calcUrls() { if (myList.isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY; final ArrayList result = new ArrayList(myList.size()); @@ -186,6 +188,7 @@ public class VirtualFilePointerContainerImpl implements VirtualFilePointerContai return myCachedFiles; } + @NotNull private VirtualFile[] calcFiles() { if (myList.isEmpty()) return VirtualFile.EMPTY_ARRAY; final ArrayList result = new ArrayList(myList.size()); @@ -272,6 +275,7 @@ public class VirtualFilePointerContainerImpl implements VirtualFilePointerContai return myVirtualFilePointerManager.duplicate(virtualFilePointer, myParent, myListener); } + @NotNull @NonNls @Override public String toString() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/TabContentLayout.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/TabContentLayout.java index a4f917cc315b..92e05d962b6c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/TabContentLayout.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/TabContentLayout.java @@ -318,7 +318,7 @@ class TabContentLayout extends ContentLayout { @Nullable private static BufferedImage drawToBuffer(Rectangle r, boolean selected, boolean last, boolean prevSelected, boolean active) { - if (r.width == 0 || r.height == 0) return null; + if (r.width <= 0 || r.height <= 0) return null; BufferedImage image = new BufferedImage(r.width, r.height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = image.createGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 04707cc5ddfa..8c33091ef480 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -532,6 +532,8 @@ + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index d71221af0aed..8479f1c58c85 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -540,6 +540,7 @@ + diff --git a/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java b/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java index 693d948b22d6..9b2365e0dd22 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java @@ -41,6 +41,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.plaf.TreeUI; import javax.swing.tree.*; import java.awt.datatransfer.StringSelection; +import java.util.ArrayList; +import java.util.List; public abstract class TestTreeView extends Tree implements DataProvider, CopyProvider { private TestFrameworkRunningModel myModel; @@ -88,13 +90,14 @@ public abstract class TestTreeView extends Tree implements DataProvider, CopyPro if (LangDataKeys.PSI_ELEMENT_ARRAY.is(dataId)) { TreePath[] paths = getSelectionPaths(); if (paths != null && paths.length > 1) { - final PsiElement[] els = new PsiElement[paths.length]; - int i = 0; + final List els = new ArrayList(paths.length); for (TreePath path : paths) { AbstractTestProxy test = getSelectedTest(path); - els[i++] = test != null ? (PsiElement)TestsUIUtil.getData(test, LangDataKeys.PSI_ELEMENT.getName(), myModel) : null; + if (test != null) { + els.add((PsiElement)TestsUIUtil.getData(test, LangDataKeys.PSI_ELEMENT.getName(), myModel)); + } } - return els; + return els.isEmpty() ? null : els.toArray(new PsiElement[els.size()]); } } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java index eee08caf705e..2e92cd784037 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java @@ -429,6 +429,32 @@ public abstract class VcsVFSListener implements Disposable { } } + // If a file is scheduled for deletion, and at the same time for copying or addition, don't delete it. + // It happens during Overwrite command or undo of overwrite. + private void dontDeleteAddedCopiedOrMovedFiles() { + Collection copiedAddedMoved = new ArrayList(); + for (VirtualFile file : myCopyFromMap.keySet()) { + copiedAddedMoved.add(file.getPath()); + } + for (VirtualFile file : myAddedFiles) { + copiedAddedMoved.add(file.getPath()); + } + for (MovedFileInfo movedFileInfo : myMovedFiles) { + copiedAddedMoved.add(movedFileInfo.myNewPath); + } + + for (Iterator iter = myDeletedFiles.iterator(); iter.hasNext(); ) { + if (copiedAddedMoved.contains(iter.next().getPath())) { + iter.remove(); + } + } + for (Iterator iter = myDeletedWithoutConfirmFiles.iterator(); iter.hasNext(); ) { + if (copiedAddedMoved.contains(iter.next().getPath())) { + iter.remove(); + } + } + } + public void commandFinished(final CommandEvent event) { if (myProject != event.getProject()) return; myCommandLevel--; @@ -444,6 +470,7 @@ public abstract class VcsVFSListener implements Disposable { finally { myCommandLevel--; } + dontDeleteAddedCopiedOrMovedFiles(); checkMovedAddedSourceBack(); if (!myAddedFiles.isEmpty()) { executeAdd(); @@ -479,5 +506,6 @@ public abstract class VcsVFSListener implements Disposable { } } } + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java index c46fc1dd7ae6..9f20c24c356a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -138,6 +138,15 @@ public class DirDiffElement { return mySourceLength < 0 ? null : String.valueOf(mySourceLength); } + public DirDiffOperation getDefaultOperation() { + return myDefaultOperation; + //if (myType == DType.SOURCE) return COPY_TO; + //if (myType == DType.TARGET) return COPY_FROM; + //if (myType == DType.CHANGED) return MERGE; + //if (myType == DType.EQUAL) return EQUAL; + //return NONE; + } + @Nullable public String getTargetName() { return myType == DType.CHANGED || myType == DType.TARGET || myType == DType.EQUAL diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToLeft.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToLeft.java index 92839c69c867..2f6b19a91763 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToLeft.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToLeft.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.diff.impl.dir.actions.popup; +import com.intellij.openapi.diff.impl.dir.DirDiffElement; import com.intellij.openapi.diff.impl.dir.DirDiffOperation; import org.jetbrains.annotations.NotNull; @@ -27,4 +28,9 @@ public class SetCopyToLeft extends SetOperationToBase { protected DirDiffOperation getOperation() { return DirDiffOperation.COPY_FROM; } + + @Override + protected boolean isEnabledFor(DirDiffElement element) { + return element.getTarget() != null; + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToRight.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToRight.java index 80d982d8ec28..0a648ec5caaf 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToRight.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToRight.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.diff.impl.dir.actions.popup; +import com.intellij.openapi.diff.impl.dir.DirDiffElement; import com.intellij.openapi.diff.impl.dir.DirDiffOperation; import org.jetbrains.annotations.NotNull; @@ -27,4 +28,9 @@ public class SetCopyToRight extends SetOperationToBase { protected DirDiffOperation getOperation() { return DirDiffOperation.COPY_TO; } + + @Override + protected boolean isEnabledFor(DirDiffElement element) { + return element.getSource() != null; + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDefault.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDefault.java new file mode 100644 index 000000000000..674978005c4f --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDefault.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2012 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.openapi.diff.impl.dir.actions.popup; + +import com.intellij.openapi.diff.impl.dir.DirDiffElement; +import com.intellij.openapi.diff.impl.dir.DirDiffOperation; +import org.jetbrains.annotations.NotNull; + +/** + * @author Konstantin Bulenkov + */ +public class SetDefault extends SetOperationToBase { + @NotNull + @Override + protected DirDiffOperation getOperation() { + return DirDiffOperation.NONE; + } + + @Override + protected boolean isEnabledFor(DirDiffElement element) { + return true; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDelete.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDelete.java index 3a8038108a61..8dd1cbf05b39 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDelete.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDelete.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.diff.impl.dir.actions.popup; +import com.intellij.openapi.diff.impl.dir.DirDiffElement; import com.intellij.openapi.diff.impl.dir.DirDiffOperation; import org.jetbrains.annotations.NotNull; @@ -27,4 +28,9 @@ public class SetDelete extends SetOperationToBase { protected DirDiffOperation getOperation() { return DirDiffOperation.DELETE; } + + @Override + protected boolean isEnabledFor(DirDiffElement element) { + return element.getSource() == null || element.getTarget() == null; + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetOperationToBase.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetOperationToBase.java index 264757c85ea2..27aca25a9961 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetOperationToBase.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetOperationToBase.java @@ -33,11 +33,16 @@ public abstract class SetOperationToBase extends AnAction { @Override public void actionPerformed(AnActionEvent e) { DirDiffOperation operation = getOperation(); + boolean setToDefault = operation == DirDiffOperation.NONE; final DirDiffTableModel model = getModel(e); final JTable table = getTable(e); assert model != null && table != null; for (DirDiffElement element : model.getSelectedElements()) { - element.setOperation(operation); + if (isEnabledFor(element)) { + element.setOperation(setToDefault ? element.getDefaultOperation() : operation); + } else { + element.setOperation(DirDiffOperation.NONE); + } } table.repaint(); } @@ -46,14 +51,22 @@ public abstract class SetOperationToBase extends AnAction { protected abstract DirDiffOperation getOperation(); @Override - public void update(AnActionEvent e) { + public final void update(AnActionEvent e) { final DirDiffTableModel model = getModel(e); final JTable table = getTable(e); - e.getPresentation().setEnabled(table != null - && model != null - && !model.getSelectedElements().isEmpty()); + if (table != null && model != null) { + for (DirDiffElement element : model.getSelectedElements()) { + if (isEnabledFor(element)) { + e.getPresentation().setEnabled(true); + return; + } + } + } + e.getPresentation().setEnabled(false); } + protected abstract boolean isEnabledFor(DirDiffElement element); + @Nullable private static JTable getTable(AnActionEvent e) { return e.getData(DirDiffPanel.DIR_DIFF_TABLE); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java index 92ab2a6c428d..9afdb600452b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java @@ -299,6 +299,7 @@ public abstract class ChangesTreeList extends JPanel { } }); + final Set wasSelected = new HashSet(Arrays.asList(myList.getSelectedValues())); myList.setModel(new AbstractListModel() { @Override public int getSize() { @@ -310,6 +311,12 @@ public abstract class ChangesTreeList extends JPanel { return sortedChanges.get(index); } }); + for (int i = 0; i < sortedChanges.size(); i++) { + T t = sortedChanges.get(i); + if (wasSelected.contains(t)) { + myList.setSelectedIndex(i); + } + } final DefaultTreeModel model = buildTreeModel(changes, myChangeDecorator); TreeState state = null; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java index 91f31c4a3886..866eb1a4bee9 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java @@ -92,7 +92,6 @@ public class XFramesView extends XDebugViewBase { CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_COLOR, 0, 0, 1, 0); myThreadsPanel.setBorder(border); myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.EAST); - myThreadsPanel.add(myThreadComboBox, BorderLayout.CENTER); myMainPanel.add(myThreadsPanel, BorderLayout.NORTH); rebuildView(SessionEvent.RESUMED); @@ -155,12 +154,10 @@ public class XFramesView extends XDebugViewBase { } XExecutionStack activeExecutionStack = suspendContext.getActiveExecutionStack(); myThreadComboBox.setSelectedItem(activeExecutionStack); - final boolean invisible = executionStacks.length == 1 && StringUtil.isEmpty(executionStacks[0].getDisplayName()); myThreadsPanel.removeAll(); - if (invisible) { - myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.WEST); - } else { - myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.EAST); + myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.EAST); + final boolean invisible = executionStacks.length == 1 && StringUtil.isEmpty(executionStacks[0].getDisplayName()); + if (!invisible) { myThreadsPanel.add(myThreadComboBox, BorderLayout.CENTER); } myToolbar.setAddSeparatorFirst(!invisible); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java index e89e21c45978..0de37c8ed3df 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2011 Bas Leijdekkers + * Copyright 2006-201@ Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,6 +73,10 @@ public class UnqualifiedFieldAccessInspection extends BaseInspection { if (field.hasModifierProperty(PsiModifier.STATIC)) { return; } + final PsiClass containingClass = field.getContainingClass(); + if (containingClass instanceof PsiAnonymousClass) { + return; + } registerError(expression); } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedMethodAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedMethodAccessInspection.java index 12ceb5425306..2d54bc48f77f 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedMethodAccessInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedMethodAccessInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2011 Bas Leijdekkers + * Copyright 2006-2012 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -68,6 +68,10 @@ public class UnqualifiedMethodAccessInspection extends BaseInspection { if (method.isConstructor() || method.hasModifierProperty(PsiModifier.STATIC)) { return; } + final PsiClass containingClass = method.getContainingClass(); + if (containingClass instanceof PsiAnonymousClass) { + return; + } registerError(expression); } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_field_access/UnqualifiedFieldAccess.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_field_access/UnqualifiedFieldAccess.java index c74a6852d584..6c7518d8d83b 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_field_access/UnqualifiedFieldAccess.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_field_access/UnqualifiedFieldAccess.java @@ -9,4 +9,17 @@ public class UnqualifiedFieldAccess { final String s = String.valueOf(field.hashCode()); System.out.println(s); } + + void foo() { + new Object() { + int i; + void foo() { + new Object() { + void foo() { + i = 0; + } + }; + } + }; + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_method_access/UnqualifiedMethodAccess.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_method_access/UnqualifiedMethodAccess.java index 0e3b456c86c5..0e626f3fe31d 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_method_access/UnqualifiedMethodAccess.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_method_access/UnqualifiedMethodAccess.java @@ -15,4 +15,16 @@ public class UnqualifiedMethodAccess extends JPanel { void foo(String s) { this.foo(); } + + void anonymous() { + new Object() { + void bar() { + new Object() { + void foo() { + bar(); + } + }; + } + }; + } } diff --git a/plugins/git4idea/src/git4idea/GitBranch.java b/plugins/git4idea/src/git4idea/GitBranch.java index e04e9cc1677b..90b63fbb28dd 100644 --- a/plugins/git4idea/src/git4idea/GitBranch.java +++ b/plugins/git4idea/src/git4idea/GitBranch.java @@ -52,7 +52,7 @@ public class GitBranch extends GitReference { super(name); myRemote = remote; myActive = active; - myHash = new String(hash); + myHash = new String(hash.trim()); } @Deprecated diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java index ca92d7cefef3..6917cec47765 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java @@ -23,6 +23,7 @@ import com.intellij.util.Processor; import com.intellij.vcsUtil.VcsUtil; import git4idea.GitBranch; import git4idea.branch.GitBranchesCollection; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,11 +55,9 @@ class GitRepositoryReader { // this format shouldn't appear, but we don't want to fail because of a space private static Pattern BRANCH_WEAK_PATTERN = Pattern.compile(" *(ref:)? */?refs/heads/(\\S+)"); private static Pattern COMMIT_PATTERN = Pattern.compile("[0-9a-fA-F]+"); // commit hash - private static Pattern PACKED_REFS_BRANCH_LINE = Pattern.compile("([0-9a-fA-F]+) (\\S+)"); // branch reference in .git/packed-refs - private static Pattern PACKED_REFS_TAGREF_LINE = Pattern.compile("\\^[0-9a-fA-F]+"); // tag reference in .git/packed-refs - private static final String REFS_HEADS_PREFIX = "refs/heads/"; - private static final String REFS_REMOTES_PREFIX = "refs/remotes/"; + @NonNls private static final String REFS_HEADS_PREFIX = "refs/heads/"; + @NonNls private static final String REFS_REMOTES_PREFIX = "refs/remotes/"; private static final int IO_RETRIES = 3; // number of retries before fail if an IOException happens during file read. private final File myGitDir; // .git/ @@ -146,7 +145,7 @@ class GitRepositoryReader { * and returns the {@link GitBranch} for the branch name written there, or null if these files don't exist. */ @Nullable - private GitBranch readRebaseBranch(String rebaseDirName) { + private GitBranch readRebaseBranch(@NonNls String rebaseDirName) { File rebaseDir = new File(myGitDir, rebaseDirName); if (!rebaseDir.exists()) { return null; @@ -197,7 +196,8 @@ class GitRepositoryReader { while ((line = reader.readLine()) != null) { final AtomicReference hashRef = new AtomicReference(); parsePackedRefsLine(line, new PackedRefsLineResultHandler() { - @Override public void handleResult(String hash, String branchName) { + @Override + public void handleResult(String hash, String branchName) { if (hash == null || branchName == null) { return; } @@ -436,26 +436,47 @@ class GitRepositoryReader { * Using a special handler may seem to be an overhead, but it is to avoid code duplication in two methods that parse packed-refs. */ private static void parsePackedRefsLine(String line, PackedRefsLineResultHandler resultHandler) { - line = line.trim(); - if (line.startsWith("#")) { // ignoring comments - resultHandler.handleResult(null, null); - return; + try { + line = line.trim(); + char firstChar = line.isEmpty() ? 0 : line.charAt(0); + if (firstChar == '#') { // ignoring comments + return; + } + if (firstChar == '^') { + // ignoring the hash which an annotated tag above points to + return; + } + String hash = null; + int i; + for (i = 0; i < line.length(); i++) { + char c = line.charAt(i); + if (!Character.isLetterOrDigit(c)) { + hash = line.substring(0, i); + break; + } + } + String branch = null; + int start = i; + if (hash != null && start < line.length() && line.charAt(start++) == ' ') { + for (i = start; i < line.length(); i++) { + char c = line.charAt(i); + if (Character.isWhitespace(c)) { + break; + } + } + branch = line.substring(start, i); + } + + if (hash != null && branch != null) { + resultHandler.handleResult(hash, branch); + } + else { + LOG.info("Ignoring invalid packed-refs line: [" + line + "]"); + } } - if (PACKED_REFS_TAGREF_LINE.matcher(line).matches()) { // ignoring the hash which an annotated tag above points to + finally { resultHandler.handleResult(null, null); - return; } - Matcher matcher = PACKED_REFS_BRANCH_LINE.matcher(line); - if (matcher.matches()) { - String hash = matcher.group(1); - String branch = matcher.group(2); - resultHandler.handleResult(hash, branch); - } else { - LOG.info("Ignoring invalid packed-refs line: [" + line + "]"); - resultHandler.handleResult(null, null); - return; - } - resultHandler.handleResult(null, null); } private interface PackedRefsLineResultHandler { diff --git a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java index a0cc84ab6fe2..6a46c760a964 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java @@ -151,8 +151,8 @@ public class GitRepositoryReaderTest extends LightIdeaTestCase { private final String myHash; private GitTestBranch(String name, String hash) { - myName = name; - myHash = hash; + myName = name.trim(); + myHash = hash.trim(); } String getName() { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java index 9f4acf10fec4..88e0f0ea79ed 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java @@ -75,7 +75,9 @@ public class GradleTaskManager extends AbstractProjectComponent implements Gradl } finally { myAlarm.cancelAllRequests(); - myAlarm.addRequest(this, DETECT_HANGED_TASKS_FREQUENCY_MILLIS); + if (!myProject.isDisposed()) { + myAlarm.addRequest(this, DETECT_HANGED_TASKS_FREQUENCY_MILLIS); + } } } }, DETECT_HANGED_TASKS_FREQUENCY_MILLIS); @@ -84,6 +86,7 @@ public class GradleTaskManager extends AbstractProjectComponent implements Gradl @Override public void disposeComponent() { myProgressNotificationManager.removeNotificationListener(this); + myAlarm.cancelAllRequests(); } /** diff --git a/plugins/groovy/resources/inspectionDescriptions/GrDeprecatedAPIUsage.html b/plugins/groovy/resources/inspectionDescriptions/GrDeprecatedAPIUsage.html new file mode 100644 index 000000000000..f946eea6ddee --- /dev/null +++ b/plugins/groovy/resources/inspectionDescriptions/GrDeprecatedAPIUsage.html @@ -0,0 +1,5 @@ + + +This inspection reports usages of deprecated code in Groovy + + \ No newline at end of file diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 956a30ddf366..6226695b0628 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -599,6 +599,9 @@ + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index 57c820df5558..af9e9170000a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -304,3 +304,4 @@ primitive.bound.types.are.not.allowed=Primitive bound types are not allowed ellipsis.type.is.not.allowed.here=Ellipsis type is not allowed here method.0.is.too.complex.too.analyze=Method ''{0}'' is too complex to analyze.\nTypes of local variables are not inferred. closure.is.too.complex.to.analyze=Closure is complex to analyze.\nTypes of local variables are not inferred. +0.is.deprecated=''{0}'' is deprecated diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties index 28f439a39a95..a2b7cb92f819 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties @@ -83,3 +83,4 @@ unused.0=Unused {0} remove.0=Remove {0} replace.postfix.0.with.prefix.0=Replace postfix {0} with prefix {0} replace.0.with.1=Replace {0} with binary {1} +gr.deprecated.api.usage=Deprecated API inspection diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java new file mode 100644 index 000000000000..a70da482cccb --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java @@ -0,0 +1,104 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.codeInspection.confusing; + +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.psi.PsiDocCommentOwner; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiModifierListOwner; +import com.intellij.psi.impl.PsiImplUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.GroovyBundle; +import org.jetbrains.plugins.groovy.codeInspection.BaseInspection; +import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor; +import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; +import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; + +/** + * @author Max Medvedev + */ +public class GrDeprecatedAPIUsageInspection extends BaseInspection { + @Override + public boolean isEnabledByDefault() { + return true; + } + + @Nls + @NotNull + public String getGroupDisplayName() { + return CONFUSING_CODE_CONSTRUCTS; + } + + @Nls + @NotNull + public String getDisplayName() { + return GroovyInspectionBundle.message("gr.deprecated.api.usage"); + } + + @NonNls + @NotNull + public String getShortName() { + return "GrDeprecatedAPIUsage"; + } + + @Override + protected BaseInspectionVisitor buildVisitor() { + return new BaseInspectionVisitor() { + @Override + public void visitReferenceExpression(GrReferenceExpression ref) { + super.visitReferenceExpression(ref); + checkRef(ref); + } + + @Override + public void visitCodeReferenceElement(GrCodeReferenceElement ref) { + super.visitCodeReferenceElement(ref); + checkRef(ref); + } + + private void checkRef(GrReferenceElement ref) { + PsiElement resolved = ref.resolve(); + if (isDeprecated(resolved)) { + PsiElement toHighlight = getElementToHighlight(ref); + registerError(toHighlight, GroovyBundle.message("0.is.deprecated", ref.getReferenceName()), LocalQuickFix.EMPTY_ARRAY, + ProblemHighlightType.LIKE_DEPRECATED); + } + } + + @NotNull + public PsiElement getElementToHighlight(@NotNull GrReferenceElement refElement) { + final PsiElement refNameElement = refElement.getReferenceNameElement(); + return refNameElement != null ? refNameElement : refElement; + } + + + private boolean isDeprecated(PsiElement resolved) { + if (resolved instanceof PsiDocCommentOwner && PsiImplUtil.isDeprecatedByDocTag((PsiDocCommentOwner)resolved)) { + return true; + } + if (resolved instanceof PsiModifierListOwner && PsiImplUtil.isDeprecatedByAnnotation((PsiModifierListOwner)resolved)) { + return true; + } + return false; + } + }; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java index b29f0906545b..d357105345c6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java @@ -21,6 +21,8 @@ import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.impl.*; +import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction; +import com.intellij.codeInsight.daemon.impl.quickfix.SafeDeleteFix; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.ProblemHighlightType; @@ -122,20 +124,24 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) { String name = ((GrNamedElement)element).getName(); if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) { - unusedDeclarations.add( - PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL)); + HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL); + QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element)); + unusedDeclarations.add(highlightInfo); } else if (element instanceof GrMethod) { GrMethod method = (GrMethod)element; - if (!GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(method.getName()) && - !PostHighlightingPass.isMethodReferenced(method, progress, usageHelper)) { - unusedDeclarations.add( - PostHighlightingPass.createUnusedSymbolInfo(nameId, (method.isConstructor() ? "Constructor" : "Method") +" " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL)); + if (!GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(method.getName()) && !PostHighlightingPass.isMethodReferenced(method, progress, usageHelper)) { + String message = (method.isConstructor() ? "Constructor" : "Method") + " " + name + " is unused"; + HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, message, HighlightInfoType.UNUSED_SYMBOL); + QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method)); + unusedDeclarations.add(highlightInfo); } } else if (element instanceof GrField && PostHighlightingPass.isFieldUnused((GrField)element, progress, usageHelper)) { - unusedDeclarations.add( - PostHighlightingPass.createUnusedSymbolInfo(nameId, "Property " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL)); + HighlightInfo highlightInfo = + PostHighlightingPass.createUnusedSymbolInfo(nameId, "Property " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL); + QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element)); + unusedDeclarations.add(highlightInfo); } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java index 17c9260260f6..533a835ac1a2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java @@ -294,8 +294,10 @@ public class GroovyCodeFragmentFactory extends CodeFragmentFactory { PsiElement parent = context; while (parent != null) { if (parent instanceof PsiModifierListOwner && ((PsiModifierListOwner)parent).hasModifierProperty(PsiModifier.STATIC)) return true; - if (parent instanceof GrTypeDefinition || parent instanceof GroovyFile) return false; - parent = parent.getParent(); + if (parent instanceof GroovyFile && parent.isPhysical()) return false; + if (parent instanceof GrTypeDefinition) return false; + + parent = parent.getContext(); } return false; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppExpectedTypesContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppExpectedTypesContributor.java index 58896deb7d7b..67dd997c81db 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppExpectedTypesContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppExpectedTypesContributor.java @@ -18,7 +18,10 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; /** * @author peter @@ -65,7 +68,7 @@ public class GppExpectedTypesContributor extends GroovyExpectedTypesContributor final PsiElement method = resolveResult.getElement(); if (method instanceof PsiMethod && ((PsiMethod)method).isConstructor()) { final Map> map = GrClosureSignatureUtil - .mapArgumentsToParameters(resolveResult, list, false, GrNamedArgument.EMPTY_ARRAY, args, GrClosableBlock.EMPTY_ARRAY); + .mapArgumentsToParameters(resolveResult, list, false, true, GrNamedArgument.EMPTY_ARRAY, args, GrClosableBlock.EMPTY_ARRAY); if (map != null) { final Pair pair = map.get(arg); if (pair != null) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java index 8d57380907ab..eefcae38a423 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java @@ -47,22 +47,16 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; */ public class IntentionUtils { - public static void replaceExpression(@NotNull String newExpression, - @NotNull GrExpression expression) - throws IncorrectOperationException { + public static void replaceExpression(@NotNull String newExpression, @NotNull GrExpression expression) throws IncorrectOperationException { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(expression.getProject()); - final GrExpression newCall = - factory.createExpressionFromText(newExpression); - final PsiElement insertedElement = expression.replaceWithExpression(newCall, true); + final GrExpression newCall = factory.createExpressionFromText(newExpression); + expression.replaceWithExpression(newCall, true); } - public static GrStatement replaceStatement( - @NonNls @NotNull String newStatement, - @NonNls @NotNull GrStatement statement) - throws IncorrectOperationException { + public static GrStatement replaceStatement(@NonNls @NotNull String newStatement, @NonNls @NotNull GrStatement statement) + throws IncorrectOperationException { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(statement.getProject()); - final GrStatement newCall = - (GrStatement) factory.createTopElementFromText(newStatement); + final GrStatement newCall = (GrStatement)factory.createTopElementFromText(newStatement); return statement.replaceWithStatement(newCall); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertMapToClassIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertMapToClassIntention.java index f9c42d5f16fa..dfe33a2b2a5d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertMapToClassIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertMapToClassIntention.java @@ -196,7 +196,7 @@ public class ConvertMapToClassIntention extends Intention { GrClosableBlock[] closures = methodCall.getClosureArguments(); final Map> mapToParams = GrClosureSignatureUtil - .mapArgumentsToParameters(resolveResult, arg, false, argList.getNamedArguments(), argList.getExpressionArguments(), closures); + .mapArgumentsToParameters(resolveResult, arg, false, false, argList.getNamedArguments(), argList.getExpressionArguments(), closures); if (mapToParams == null) return null; final Pair parameterPair = mapToParams.get(arg); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java index 90e0725872a8..711886e11677 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java @@ -16,25 +16,26 @@ package org.jetbrains.plugins.groovy.intentions.style; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiManager; import com.intellij.psi.PsiMethod; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.intentions.base.Intention; -import org.jetbrains.plugins.groovy.intentions.base.IntentionUtils; import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; -import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; +import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*; @@ -42,6 +43,8 @@ import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*; * @author ilyas */ public class JavaStylePropertiesInvocationIntention extends Intention { + private static final Logger LOG = Logger.getInstance(JavaStylePropertiesInvocationIntention.class); + @Override protected boolean isStopElement(PsiElement element) { return super.isStopElement(element) || element instanceof GrClosableBlock; @@ -51,35 +54,35 @@ public class JavaStylePropertiesInvocationIntention extends Intention { assert element instanceof GrMethodCall; GrMethodCall call = ((GrMethodCall)element); GrExpression invoked = call.getInvokedExpression(); + String accessorName = ((GrReferenceExpression)invoked).getName(); if (isGetterInvocation(call) && invoked instanceof GrReferenceExpression) { - String name = ((GrReferenceExpression)invoked).getName(); - assert name != null; - name = StringUtil.trimStart(name, GET_PREFIX); - name = StringUtil.decapitalize(name); - replaceWithGetter(call, name); + final GrExpression newCall = genRefForGetter(call, accessorName); + call.replaceWithExpression(newCall, true); } else if (isSetterInvocation(call) && invoked instanceof GrReferenceExpression) { - String name = ((GrReferenceExpression)invoked).getName(); - assert name != null; - name = StringUtil.trimStart(name, SET_PREFIX); - name = StringUtil.decapitalize(name); - GrExpression value = call.getExpressionArguments()[0]; - replaceWithSetter(call, name, value); + final GrStatement newCall = genRefForSetter(call, accessorName); + call.replaceWithStatement(newCall); } } - private static void replaceWithSetter(GrMethodCall call, String name, GrExpression value) throws IncorrectOperationException { - GrReferenceExpression refExpr = (GrReferenceExpression) call.getInvokedExpression(); + private static GrAssignmentExpression genRefForSetter(GrMethodCall call, String accessorName) { + String name = getPropertyNameBySetterName(accessorName); + GrExpression value = call.getExpressionArguments()[0]; + GrReferenceExpression refExpr = (GrReferenceExpression)call.getInvokedExpression(); String oldNameStr = refExpr.getReferenceNameElement().getText(); String newRefExpr = StringUtil.trimEnd(refExpr.getText(), oldNameStr) + name; - IntentionUtils.replaceStatement(newRefExpr + " = " + value.getText(), call); + final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(call.getProject()); + return (GrAssignmentExpression)factory.createStatementFromText(newRefExpr + " = " + value.getText(), call); } - private static void replaceWithGetter(GrMethodCall call, String name) throws IncorrectOperationException { - GrReferenceExpression refExpr = (GrReferenceExpression) call.getInvokedExpression(); + private static GrExpression genRefForGetter(GrMethodCall call, String accessorName) { + String name = getPropertyNameByGetterName(accessorName, true); + GrReferenceExpression refExpr = (GrReferenceExpression)call.getInvokedExpression(); String oldNameStr = refExpr.getReferenceNameElement().getText(); String newRefExpr = StringUtil.trimEnd(refExpr.getText(), oldNameStr) + name; - IntentionUtils.replaceExpression(newRefExpr, call); + + final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(call.getProject()); + return factory.createExpressionFromText(newRefExpr, call); } @NotNull @@ -100,60 +103,86 @@ public class JavaStylePropertiesInvocationIntention extends Intention { GrExpression expr = call.getInvokedExpression(); if (!(expr instanceof GrReferenceExpression)) return false; + GrReferenceExpression refExpr = (GrReferenceExpression)expr; - GrReferenceExpression refExpr = (GrReferenceExpression) expr; - String name = refExpr.getName(); - if (name == null || !name.startsWith(SET_PREFIX)) return false; - - name = name.substring(SET_PREFIX.length()); - String propName = StringUtil.decapitalize(name); - if (propName.length() == 0 || name.equals(propName)) return false; - + PsiMethod method; if (call instanceof GrApplicationStatement) { PsiElement element = refExpr.resolve(); - if (!(element instanceof PsiMethod) || !GroovyPropertyUtils.isSimplePropertySetter(((PsiMethod)element))) return false; - } else { - PsiMethod method = call.resolveMethod(); - if (!GroovyPropertyUtils.isSimplePropertySetter(method)) return false; + if (!(element instanceof PsiMethod) || !isSimplePropertySetter(((PsiMethod)element))) return false; + method = (PsiMethod)element; + } + else { + method = call.resolveMethod(); + if (!isSimplePropertySetter(method)) return false; } - if (call instanceof GrMethodCallExpression) { - GrArgumentList args = call.getArgumentList(); - return args != null && - args.getExpressionArguments().length == 1 && - args.getNamedArguments().length == 0; + if (!GroovyNamesUtil.isValidReference(getPropertyNameByGetterName(method.getName(), true), + ((GrReferenceExpression)expr).getQualifier() != null, + call.getProject())) { + return false; } GrArgumentList args = call.getArgumentList(); - return args != null && - args.getExpressionArguments().length == 1 && - args.getNamedArguments().length == 0; + if (args == null || args.getExpressionArguments().length != 1 || args.getNamedArguments().length > 0) { + return false; + } + GrAssignmentExpression assignment = genRefForSetter(call, refExpr.getName()); + GrExpression value = assignment.getLValue(); + if (value instanceof GrReferenceExpression && + call.getManager().areElementsEquivalent(((GrReferenceExpression)value).resolve(), method)) { + return true; + } + + return false; } private static boolean isGetterInvocation(GrMethodCall call) { GrExpression expr = call.getInvokedExpression(); if (!(expr instanceof GrReferenceExpression)) return false; - GrReferenceExpression refExpr = (GrReferenceExpression) expr; - String name = refExpr.getName(); - if (name == null || !name.startsWith(GET_PREFIX)) return false; - - name = name.substring(GET_PREFIX.length()); - String propName = StringUtil.decapitalize(name); - if (propName.length() == 0 || name.equals(propName)) return false; - PsiMethod method = call.resolveMethod(); - if (!GroovyPropertyUtils.isSimplePropertyGetter(method)) return false; + if (!isSimplePropertyGetter(method)) return false; + + if (!GroovyNamesUtil.isValidReference(getPropertyNameByGetterName(method.getName(), true), + ((GrReferenceExpression)expr).getQualifier() != null, + call.getProject())) { + return false; + } GrArgumentList args = call.getArgumentList(); - return args != null && args.getExpressionArguments().length == 0; + if (args == null || args.getAllArguments().length != 0) { + return false; + } + + GrExpression ref = genRefForGetter(call, ((GrReferenceExpression)expr).getName()); + if (ref instanceof GrReferenceExpression) { + PsiElement resolved = ((GrReferenceExpression)ref).resolve(); + PsiManager manager = call.getManager(); + if (manager.areElementsEquivalent(resolved, method) || areEquivalentAccessors(method, resolved, manager)) { + return true; + } + } + + return false; + } + + private static boolean areEquivalentAccessors(PsiMethod method, PsiElement resolved, PsiManager manager) { + if (!(resolved instanceof GrAccessorMethod) || !(method instanceof GrAccessorMethod)) { + return false; + } + + if (((GrAccessorMethod)resolved).isSetter() != ((GrAccessorMethod)method).isSetter()) return false; + + GrField p1 = ((GrAccessorMethod)resolved).getProperty(); + GrField p2 = ((GrAccessorMethod)method).getProperty(); + return manager.areElementsEquivalent(p1, p2); } private static class JavaPropertyInvocationPredicate implements PsiElementPredicate { public boolean satisfiedBy(PsiElement element) { if (!(element instanceof GrMethodCall)) return false; - return isPropertyAccessor((GrMethodCall) element); + return isPropertyAccessor((GrMethodCall)element); } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java index 4b217ac7d149..004d38cb7cfa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java @@ -280,7 +280,7 @@ public class GroovySmartCompletionContributor extends CompletionContributor { final PsiClass psiClass = com.intellij.psi.util.PsiUtil.resolveClassInType(type); if (psiClass == null) return null; - if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) return null; + //if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) return null; if (!checkForInnerClass(psiClass, place)) return null; final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), place); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/handlers/AfterNewClassInsertHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/handlers/AfterNewClassInsertHandler.java index 9662dc517e77..470950fea483 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/handlers/AfterNewClassInsertHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/handlers/AfterNewClassInsertHandler.java @@ -17,15 +17,19 @@ package org.jetbrains.plugins.groovy.lang.completion.handlers; import com.intellij.codeInsight.AutoPopupController; +import com.intellij.codeInsight.completion.ConstructorInsertHandler; import com.intellij.codeInsight.completion.InsertHandler; import com.intellij.codeInsight.completion.InsertionContext; import com.intellij.codeInsight.completion.JavaCompletionFeatures; import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler; import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassType; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; @@ -33,6 +37,8 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; * @author Maxim.Medvedev */ public class AfterNewClassInsertHandler implements InsertHandler> { + private static final Logger LOG = Logger.getInstance(AfterNewClassInsertHandler.class); + private final PsiClassType myClassType; private final boolean myTriggerFeature; @@ -41,14 +47,15 @@ public class AfterNewClassInsertHandler implements InsertHandler item) { + public void handleInsert(final InsertionContext context, LookupItem item) { final PsiClassType.ClassResolveResult resolveResult = myClassType.resolveGenerics(); final PsiClass psiClass = resolveResult.getElement(); if (psiClass == null || !psiClass.isValid()) { return; } - GroovyPsiElement place = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), GroovyPsiElement.class, false); + GroovyPsiElement place = + PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), GroovyPsiElement.class, false); boolean hasParams = place != null && GroovyCompletionUtil.hasConstructorParameters(psiClass, place); if (myTriggerFeature) { FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW); @@ -60,9 +67,36 @@ public class AfterNewClassInsertHandler implements InsertHandler 0) { + if (!ResolveUtil.processElement(processor, synth[0], state)) return false; + } + } + return true; + } + + private boolean processOwner(PsiScopeProcessor processor, ResolveState state) { if (processor instanceof PropertyResolverProcessor && OWNER_NAME.equals(((PropertyResolverProcessor)processor).getName())) { processor.handleEvent(ResolveUtil.DECLARATION_SCOPE_PASSED, this); } @@ -108,22 +135,21 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock if (nameHint == null || nameHint.equals(OWNER_NAME)) { if (!processor.execute(getOwner(), state)) return false; } - - final PsiClass closureClass = GroovyPsiManager.getInstance(getProject()).findClassWithCache(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, getResolveScope()); - if (closureClass != null) { - if (!closureClass.processDeclarations(processor, state, lastParent, place)) return false; - - if (place instanceof GroovyPsiElement && - !ResolveUtil - .processNonCodeMembers(GrClosureType.create(this, false /*if it is 'true' need-to-prevent-recursion triggers*/), processor, - (GroovyPsiElement)place, state)) { - return false; - } - } - return true; } + private boolean isItAlreadyDeclared(PsiElement place) { + while (place != this && place != null) { + if (place instanceof GrClosableBlock && + !((GrClosableBlock)place).hasParametersSection() && + !(place.getParent() instanceof GrStringInjection)) { + return true; + } + place = place.getParent(); + } + return false; + } + public String toString() { return "Closable block"; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java index d39783bf74ae..b0bea6e761d6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java @@ -140,6 +140,29 @@ public class GrClosureSignatureUtil { }; } + public static GrClosureSignature createSignatureWithErasedParameterTypes(final GrClosableBlock closure) { + final PsiParameter[] params = closure.getParameterList().getParameters(); + final GrClosureParameter[] closureParams = new GrClosureParameter[params.length]; + for (int i = 0; i < params.length; i++) { + PsiParameter param = params[i]; + PsiType type = TypeConversionUtil.erasure(param.getType()); + closureParams[i] = new GrClosureParameterImpl(type, GrClosureParameterImpl.isParameterOptional(param), + GrClosureParameterImpl.getDefaultInitializer(param)); + } + return new GrClosureSignatureImpl(closureParams, null, GrClosureParameterImpl.isVararg(closureParams)) { + @Override + public PsiType getReturnType() { + return closure.getReturnType(); + } + + @Override + public boolean isValid() { + return closure.isValid(); + } + }; + } + + public static GrClosureSignature createSignature(PsiParameter[] parameters, @Nullable PsiType returnType) { return new GrClosureSignatureImpl(parameters, returnType); } @@ -449,6 +472,7 @@ public class GrClosureSignatureUtil { public static Map> mapArgumentsToParameters(@NotNull GroovyResolveResult resolveResult, @NotNull GroovyPsiElement context, final boolean partial, + final boolean eraseArgs, @NotNull final GrNamedArgument[] namedArgs, @NotNull final GrExpression[] expressionArgs, @NotNull GrClosableBlock[] closureArguments) { @@ -457,18 +481,20 @@ public class GrClosureSignatureUtil { final PsiElement element = resolveResult.getElement(); final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); if (element instanceof PsiMethod) { - signature = createSignature((PsiMethod)element, substitutor); + signature = + eraseArgs ? createSignatureWithErasedParameterTypes((PsiMethod)element) : createSignature((PsiMethod)element, substitutor); parameters = ((PsiMethod)element).getParameterList().getParameters(); } else if (element instanceof GrClosableBlock) { - signature = createSignature((GrClosableBlock)element); + signature = + eraseArgs ? createSignatureWithErasedParameterTypes((GrClosableBlock)element) : createSignature(((GrClosableBlock)element)); parameters = ((GrClosableBlock)element).getAllParameters(); } else { return null; } - final ArgInfo[] argInfos = mapParametersToArguments(signature, namedArgs, expressionArgs, context, closureArguments, partial); + final ArgInfo[] argInfos = mapParametersToArguments(signature, namedArgs, expressionArgs, context, closureArguments, partial, eraseArgs); if (argInfos == null) { return null; } @@ -498,17 +524,17 @@ public class GrClosureSignatureUtil { @Nullable GrArgumentList list, @NotNull GroovyPsiElement context, @NotNull GrClosableBlock[] closureArguments) { - return mapParametersToArguments(signature, list, context, closureArguments, false); + return mapParametersToArguments(signature, list, context, closureArguments, false, false); } @Nullable public static ArgInfo[] mapParametersToArguments(@NotNull GrClosureSignature signature, @Nullable GrArgumentList list, @NotNull GroovyPsiElement context, - @NotNull GrClosableBlock[] closureArguments, final boolean partial) { + @NotNull GrClosableBlock[] closureArguments, final boolean partial, final boolean eraseArgs) { final GrNamedArgument[] namedArgs = list == null ? GrNamedArgument.EMPTY_ARRAY : list.getNamedArguments(); final GrExpression[] expressionArgs = list == null ? GrExpression.EMPTY_ARRAY : list.getExpressionArguments(); - return mapParametersToArguments(signature, namedArgs, expressionArgs, context, closureArguments, partial); + return mapParametersToArguments(signature, namedArgs, expressionArgs, context, closureArguments, partial, eraseArgs); } @Nullable @@ -517,7 +543,7 @@ public class GrClosureSignatureUtil { @NotNull GrExpression[] expressionArgs, @NotNull GroovyPsiElement context, @NotNull GrClosableBlock[] closureArguments, - final boolean partial) { + final boolean partial, boolean eraseArgs) { List innerArgs = new ArrayList(); boolean hasNamedArgs = namedArgs.length > 0; @@ -539,7 +565,9 @@ public class GrClosureSignatureUtil { if (expression instanceof GrNewExpression && com.intellij.psi.util.PsiUtil.resolveClassInType(type) == null) { type = null; } - type = TypeConversionUtil.erasure(type); + if (eraseArgs) { + type = TypeConversionUtil.erasure(type); + } innerArgs.add(new InnerArg(type, expression)); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java index c756a12a4a77..8f82f8bf9280 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.resolve.processors; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiField; import com.intellij.psi.PsiType; import com.intellij.psi.ResolveState; import org.jetbrains.annotations.NotNull; @@ -36,10 +37,10 @@ public class PropertyResolverProcessor extends ResolverProcessor { @Override public boolean execute(PsiElement element, ResolveState state) { - if (element instanceof GrReferenceExpression && ((GrReferenceExpression)element).getQualifier()!=null) { + if (element instanceof GrReferenceExpression && ((GrReferenceExpression)element).getQualifier() != null) { return true; } - return super.execute(element, state); + return super.execute(element, state) || state.get(RESOLVE_CONTEXT) != null; } @NotNull @@ -50,10 +51,21 @@ public class PropertyResolverProcessor extends ResolverProcessor { final int size = candidates.size(); if (size == 0) return GroovyResolveResult.EMPTY_ARRAY; final GroovyResolveResult last = candidates.get(size - 1); - if (last.isAccessible() && last.isStaticsOK()) return candidates.toArray(new GroovyResolveResult[candidates.size()]); + if (isCorrectLocalVarOrParam(last)) { + return new GroovyResolveResult[]{last}; + } for (GroovyResolveResult candidate : candidates) { - if (candidate.isStaticsOK()) return new GroovyResolveResult[]{candidate}; + if (candidate.isStaticsOK()) { + return new GroovyResolveResult[]{candidate}; + } } return candidates.toArray(new GroovyResolveResult[candidates.size()]); } + + private static boolean isCorrectLocalVarOrParam(GroovyResolveResult last) { + return !(last.getElement() instanceof PsiField) && + last.isAccessible() && + last.isStaticsOK() && + last.getCurrentFileResolveContext() == null; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java index 0767cedcaf18..d725c411e807 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java @@ -30,6 +30,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; @@ -133,9 +134,11 @@ public class GroovyOverrideImplementUtil { for (int i = 0; i < parameters.length; i++) { if (i > 0) buffer.append(", "); PsiParameter parameter = parameters[i]; - final PsiType parameterType = substitutor.substitute(parameter.getType()); - buffer.append(parameterType.getCanonicalText()); - buffer.append(" "); + if (!(parameter instanceof GrParameter && parameter.getTypeElement() == null)) { + final PsiType parameterType = substitutor.substitute(parameter.getType()); + buffer.append(parameterType.getCanonicalText()); + buffer.append(" "); + } final String paramName = parameter.getName(); if (paramName != null) { buffer.append(paramName); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNamesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNamesUtil.java index c59dee306da4..93912e2da292 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNamesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNamesUtil.java @@ -17,12 +17,13 @@ package org.jetbrains.plugins.groovy.refactoring; import com.intellij.lexer.Lexer; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; -import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import java.util.ArrayList; import java.util.regex.Matcher; @@ -48,6 +49,18 @@ public class GroovyNamesUtil { return lexer.getTokenType() == null; } + public static boolean isValidReference(@Nullable String text, boolean afterDot, Project project) { + if (text == null) return false; + + try { + GroovyPsiElementFactory.getInstance(project).createReferenceExpressionFromText(afterDot ? "foo." + text : text); + return true; + } + catch (Exception e) { + return false; + } + } + public static ArrayList camelizeString(String str) { ArrayList res = new ArrayList(); StringBuilder sb = new StringBuilder(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java index af6985f51938..560f2dbdf212 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java @@ -83,7 +83,7 @@ public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrec else { myMapToArguments = GrClosureSignatureUtil .mapParametersToArguments(signature, call.getNamedArguments(), call.getExpressionArguments(), call, call.getClosureArguments(), - false); + false, false); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java index 86faa6ce8300..f62cde5b3726 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java @@ -56,10 +56,10 @@ class ArgumentListGenerator { GrClosableBlock[] clArgs, GroovyPsiElement context) { GrClosureSignatureUtil.ArgInfo[] argInfos = - signature == null ? null : GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, context, clArgs, false); + signature == null ? null : GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, context, clArgs, false, false); if (argInfos == null && signature != null) { - argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, context, clArgs, true); + argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, context, clArgs, true, true); } final PsiSubstitutor substitutor = signature == null ? PsiSubstitutor.EMPTY : signature.getSubstitutor(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java index a0d21ba0581b..322e4c2a55fe 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java @@ -376,6 +376,12 @@ public class StubGenerator implements ClassItemGenerator { private static String getVariableInitializer(GrVariable variable, PsiType declaredType) { if (declaredType instanceof PsiPrimitiveType) { Object eval = GroovyConstantExpressionEvaluator.evaluate(variable.getInitializerGroovy()); + if (eval instanceof Float) { + return eval.toString() + "f"; + } + else if (eval instanceof Character) { + return "'" + ((Character)eval).charValue() + "'"; + } if (eval instanceof Number || eval instanceof Boolean) { return eval.toString(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java index 1242a49ebc85..94e1e6780310 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java @@ -397,7 +397,7 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess if (signature == null) signature = GrClosureSignatureUtil.createSignature(toReplaceIn); final GrClosureSignatureUtil.ArgInfo[] actualArgs = - GrClosureSignatureUtil.mapParametersToArguments(signature, argList, callExpression, callExpression.getClosureArguments(), true); + GrClosureSignatureUtil.mapParametersToArguments(signature, argList, callExpression, callExpression.getClosureArguments(), true, true); if (PsiTreeUtil.isAncestor(toReplaceIn, callExpression, false)) { argList.addAfter(factory.createExpressionFromText(settings.getName()), anchor); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java index 1cf0992694ef..c27c632706a5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java @@ -102,7 +102,7 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP if (signature == null) signature = GrClosureSignatureUtil.createSignature(data.getMethodToSearchFor(), PsiSubstitutor.EMPTY); final GrClosureSignatureUtil.ArgInfo[] actualArgs = - GrClosureSignatureUtil.mapParametersToArguments(signature, argList, callExpression, callExpression.getClosureArguments(), true); + GrClosureSignatureUtil.mapParametersToArguments(signature, argList, callExpression, callExpression.getClosureArguments(), true, true); final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(data.getProject()); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy index 3a1bcf6f4038..8e9fab456631 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy @@ -36,12 +36,8 @@ public class GroovySmartCompletionTest extends GroovyCompletionTestBase { assertOrderedEquals(myFixture.lookupElementStrings, "Bar", "Foo"); } - public void testSmartCompletionAfterNewInDeclarationWithInterface() throws Throwable { doSmartTest(); } - public void testCaretAfterSmartCompletionAfterNewInDeclaration() throws Throwable { doSmartTest(); } - public void testSmartCompletionAfterNewInDeclarationWithAbstractClass() throws Throwable { doSmartTest(); } - public void testSmartCompletionAfterNewInDeclarationWithArray() throws Throwable { doSmartTest(); } public void testSmartCompletionAfterNewInDeclarationWithIntArray() throws Throwable { doSmartTest(); } @@ -128,4 +124,19 @@ throw new RuntimeException() void testInnerClassReferenceWithoutQualifier() { doSmartTest() } + + void testAnonymousClassCompletion() { + myFixture.configureByText('_a.groovy', '''\ +Runnable r = new Run +''') + myFixture.complete(CompletionType.SMART) + myFixture.checkResult('''\ +Runnable r = new Runnable() { + @Override + void run() { + //To change body of implemented methods use File | Settings | File Templates. + } +} +''') + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy index e0ba3cd80dad..575ad2e4d3c1 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy @@ -36,10 +36,6 @@ import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspec import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyResultOfAssignmentUsedInspection import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyUncheckedAssignmentOfMemberOfRawTypeInspection -import org.jetbrains.plugins.groovy.codeInspection.confusing.ClashingGettersInspection -import org.jetbrains.plugins.groovy.codeInspection.confusing.GrUnusedIncDecInspection -import org.jetbrains.plugins.groovy.codeInspection.confusing.GroovyOctalIntegerInspection -import org.jetbrains.plugins.groovy.codeInspection.confusing.GroovyResultOfIncrementOrDecrementUsedInspection import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialConditionalInspection import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialIfInspection import org.jetbrains.plugins.groovy.codeInspection.control.GroovyUnnecessaryReturnInspection @@ -50,6 +46,7 @@ import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.Groov import org.jetbrains.plugins.groovy.codeInspection.unusedDef.UnusedDefInspection import org.jetbrains.plugins.groovy.util.TestUtils import org.jetbrains.plugins.groovy.codeInspection.bugs.* +import org.jetbrains.plugins.groovy.codeInspection.confusing.* /** * @author peter @@ -710,4 +707,22 @@ public class CorrectImplementor implements ActionListener { public void testReassignedHighlighting() { myFixture.testHighlighting(true, true, true, getTestName(false) + ".groovy"); } + + public void testDeprecated() { + myFixture.configureByText('_a.groovy', '''\ +/** + @deprecated +*/ +class X { + @Deprecated + def foo(){} + + public static void main() { + new X().foo() + } +}''') + + myFixture.enableInspections(GrDeprecatedAPIUsageInspection) + myFixture.testHighlighting(true, false, false) + } } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy index 98565ef793cc..1691b1b6f0c7 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy @@ -722,7 +722,7 @@ print map.class''') public void testResolveInsideWith0() { def resolved = resolve('a.groovy') - assertInstanceOf( resolved , GrAccessorMethod) + assertInstanceOf(resolved, GrAccessorMethod) assertEquals(resolved.containingClass.name, 'A') } @@ -733,4 +733,19 @@ print map.class''') assertEquals(resolved.containingClass.name, 'B') } + + void testLocalVarVsFieldInWithClosure() { + def ref = configureByText('''\ +class Test { + def var +} + +int var = 4 +new Test().with() { + print var +} +''') + assertFalse ref.resolve() instanceof GrField + assertTrue ref.resolve() instanceof GrVariable + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index 8dbbccc2e871..bfb0c781db9f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -233,6 +233,10 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase { doTest(new SimpleInfo("lucky", -1, "defValue", "defInit", String.class.getName(), true)); } + public void testParamsWithGenerics() { + doTest(new SimpleInfo(0)); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } diff --git a/plugins/groovy/testdata/groovy/completion/smart/InnerClassReferenceWithoutQualifier.groovy b/plugins/groovy/testdata/groovy/completion/smart/InnerClassReferenceWithoutQualifier.groovy index c915cfa25dd4..3b01d5120a54 100644 --- a/plugins/groovy/testdata/groovy/completion/smart/InnerClassReferenceWithoutQualifier.groovy +++ b/plugins/groovy/testdata/groovy/completion/smart/InnerClassReferenceWithoutQualifier.groovy @@ -1,6 +1,6 @@ class Foo { static class Bar {} { - List l = new AL + List l = new ArrL } } \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithAbstractClass.groovy b/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithAbstractClass.groovy deleted file mode 100644 index 655fb441ba77..000000000000 --- a/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithAbstractClass.groovy +++ /dev/null @@ -1,9 +0,0 @@ -abstract class Foo { -} -class Bar extends Foo { -} - -abstract class Foo2 extends Foo { -} - -Foo f = new \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithAbstractClass_after.groovy b/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithAbstractClass_after.groovy deleted file mode 100644 index 4a73ed826356..000000000000 --- a/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithAbstractClass_after.groovy +++ /dev/null @@ -1,9 +0,0 @@ -abstract class Foo { -} -class Bar extends Foo { -} - -abstract class Foo2 extends Foo { -} - -Foo f = new Bar() \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithInterface.groovy b/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithInterface.groovy deleted file mode 100644 index 1b0a220f446c..000000000000 --- a/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithInterface.groovy +++ /dev/null @@ -1,6 +0,0 @@ -interface Foo { -} -class Bar implements Foo { -} - -Foo f = new \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithInterface_after.groovy b/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithInterface_after.groovy deleted file mode 100644 index 1ac83aa458bf..000000000000 --- a/plugins/groovy/testdata/groovy/completion/smart/SmartCompletionAfterNewInDeclarationWithInterface_after.groovy +++ /dev/null @@ -1,6 +0,0 @@ -interface Foo { -} -class Bar implements Foo { -} - -Foo f = new Bar() \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ParamsWithGenerics.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ParamsWithGenerics.groovy new file mode 100644 index 000000000000..85e056508d55 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ParamsWithGenerics.groovy @@ -0,0 +1,5 @@ +class Foo { + def bar (int x, List list) {} +} + +new Foo().bar(1, []) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ParamsWithGenerics_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ParamsWithGenerics_after.groovy new file mode 100644 index 000000000000..94ac6e7334c0 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ParamsWithGenerics_after.groovy @@ -0,0 +1,5 @@ +class Foo { + def bar (int x) {} +} + +new Foo().bar(1) \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java index 8dc80a92e6f5..66d35185a88e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java @@ -35,7 +35,7 @@ public class MavenAddArchetypeDialog extends DialogWrapper { public MavenAddArchetypeDialog(Component parent) { super(parent, false); - setTitle("Add archetype"); + setTitle("Add Archetype"); init(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 3e25901512c5..50f35abf515b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -556,17 +556,22 @@ public class SvnVcs extends AbstractVcs { } private void createPool() { + if (myPool != null) return; final String property = System.getProperty(KEEP_CONNECTIONS_KEY); final boolean keep; if (StringUtil.isEmptyOrSpaces(property)) { - keep = ! ApplicationManager.getApplication().isUnitTestMode(); // default + keep = !ApplicationManager.getApplication().isUnitTestMode(); // default } else { keep = Boolean.getBoolean(KEEP_CONNECTIONS_KEY); } myPool = new DefaultSVNRepositoryPool(myConfiguration.getAuthenticationManager(this), myConfiguration.getOptions(myProject), 60*1000, keep); } + @NotNull private ISVNRepositoryPool getPool() { + if (myPool == null) { + createPool(); + } return myPool; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java index 1255ace19796..fd7c1b22761f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java @@ -86,18 +86,22 @@ public class CopiesPanel { myCurrentInfoList = null; final Runnable focus = new Runnable() { + @Override public void run() { IdeFocusManager.getInstance(myProject).requestFocus(myRefreshLabel, true); } }; final Runnable refreshView = new Runnable() { + @Override public void run() { final List infoList = myVcs.getAllWcInfos(); Runnable runnable = new Runnable() { + @Override public void run() { if (myCurrentInfoList != null) { final List> newList = ObjectsConvertor.convert(infoList, new Convertor>() { + @Override public OverrideEqualsWrapper convert(WCInfo o) { return new OverrideEqualsWrapper(InfoEqualityPolicy.getInstance(), o); } @@ -119,8 +123,14 @@ public class CopiesPanel { } }; final Runnable refreshOnPooled = new Runnable() { + @Override public void run() { - ApplicationManager.getApplication().executeOnPooledThread(refreshView); + if (ApplicationManager.getApplication().isUnitTestMode()) { + refreshView.run(); + } + else { + ApplicationManager.getApplication().executeOnPooledThread(refreshView); + } } }; myConnection.subscribe(SvnVcs.ROOTS_RELOADED, refreshOnPooled); @@ -133,6 +143,7 @@ public class CopiesPanel { panel.add(myPanel, BorderLayout.NORTH); holderPanel.add(panel, BorderLayout.WEST); myRefreshLabel = new MyLinkLabel(myTextHeight, "Refresh", new LinkListener() { + @Override public void linkSelected(LinkLabel aSource, Object aLinkData) { if (myRefreshLabel.isEnabled()) { myVcs.invokeRefreshSvnRoots(true); @@ -280,6 +291,7 @@ public class CopiesPanel { private void mergeFrom(final WCInfo wcInfo, final VirtualFile root, final Component mergeLabel) { SelectBranchPopup.showForBranchRoot(myProject, root, new SelectBranchPopup.BranchSelectedCallback() { + @Override public void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision) { new QuickMerge(project, url, wcInfo, SVNPathUtil.tail(url), root).execute(); } @@ -393,6 +405,7 @@ public class CopiesPanel { } } + @Override public int getHashCode(WCInfo value) { final HashCodeBuilder builder = new HashCodeBuilder(); builder.append(value.getPath()); @@ -404,6 +417,7 @@ public class CopiesPanel { return builder.getCode(); } + @Override public boolean isEqual(WCInfo val1, WCInfo val2) { if (val1 == val2) return true; if (val1 == null || val2 == null || val1.getClass() != val2.getClass()) return false; @@ -425,6 +439,7 @@ public class CopiesPanel { return ourComparator; } + @Override public int compare(WCInfo o1, WCInfo o2) { return o1.getPath().compareTo(o2.getPath()); } diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java index 314b5729fa97..8a64a074f259 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java @@ -246,9 +246,10 @@ public class TestNGRunnableState extends JavaCommandLineState { LOG.info("Language level is " + effectiveLanguageLevel.toString()); LOG.info("is15 is " + is15); final String pathToBundledJar = PathUtil.getJarPathForClass(AfterClass.class); - final String incompatibilityMessage = TestNGVersionChecker - .getVersionIncompatibilityMessage(project, config.getPersistantData().getScope().getSourceScope(config).getLibrariesScope(), - pathToBundledJar); + final SourceScope sourceScope = config.getPersistantData().getScope().getSourceScope(config); + final String incompatibilityMessage = sourceScope != null ? + TestNGVersionChecker.getVersionIncompatibilityMessage(project, sourceScope.getLibrariesScope(), pathToBundledJar) : + null; if (incompatibilityMessage != null) { javaParameters.getClassPath().add(pathToBundledJar); } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java index 58d3f25a2fe3..f3e351146b67 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java @@ -904,8 +904,8 @@ public final class PropertyTable extends JBTable implements ComponentSelectionLi } }; - myExpandIcon = IconLoader.getIcon("/com/intellij/uiDesigner/icons/expandNode.png"); - myCollapseIcon = IconLoader.getIcon("/com/intellij/uiDesigner/icons/collapseNode.png"); + myExpandIcon = IconLoader.getIcon("/com/intellij/designer/icons/expandNode.png"); + myCollapseIcon = IconLoader.getIcon("/com/intellij/designer/icons/collapseNode.png"); for (int i = 0; i < myIndentIcons.length; i++) { myIndentIcons[i] = new EmptyIcon(9 + 11 * i, 9); } diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml index 7ebbc00918b9..950b924e7452 100644 --- a/resources/src/idea/RichPlatformPlugin.xml +++ b/resources/src/idea/RichPlatformPlugin.xml @@ -187,6 +187,8 @@ serviceImplementation="com.intellij.openapi.roots.impl.CompilerProjectExtensionImpl"/> + diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdReferenceProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdReferenceProvider.java index b479f565cb56..7446b7c0c42c 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdReferenceProvider.java +++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/IdReferenceProvider.java @@ -17,8 +17,10 @@ package com.intellij.psi.impl.source.resolve.reference.impl.providers; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; +import com.intellij.psi.PsiReferenceProvider; import com.intellij.psi.filters.ElementFilter; import com.intellij.psi.impl.source.resolve.reference.PsiReferenceProviderBase; +import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlTag; @@ -33,7 +35,7 @@ import org.jetbrains.annotations.NotNull; /** * @author peter */ -public class IdReferenceProvider extends PsiReferenceProviderBase { +public class IdReferenceProvider extends PsiReferenceProvider { @NonNls public static final String FOR_ATTR_NAME = "for"; @NonNls public static final String ID_ATTR_NAME = "id"; @NonNls public static final String STYLE_ID_ATTR_NAME = "styleId"; @@ -112,6 +114,8 @@ public class IdReferenceProvider extends PsiReferenceProviderBase { if (jsfNs) { attributeValueSelfReference = new AttributeValueSelfReference(element); } else { + if (hasOuterLanguageElement(element)) return PsiReference.EMPTY_ARRAY; + attributeValueSelfReference = new GlobalAttributeValueSelfReference(element, true); } return new PsiReference[]{attributeValueSelfReference}; @@ -121,6 +125,16 @@ public class IdReferenceProvider extends PsiReferenceProviderBase { return PsiReference.EMPTY_ARRAY; } + private static boolean hasOuterLanguageElement(@NotNull PsiElement element) { + for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) { + if (child instanceof OuterLanguageElement) { + return true; + } + } + + return false; + } + public static class GlobalAttributeValueSelfReference extends AttributeValueSelfReference { private final boolean mySoft;