diff --git a/.idea/libraries/Netty.xml b/.idea/libraries/Netty.xml index bc6600b3242d..c79ce3e2cbe0 100644 --- a/.idea/libraries/Netty.xml +++ b/.idea/libraries/Netty.xml @@ -1,11 +1,11 @@ - + - + \ No newline at end of file diff --git a/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java b/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java index e9586776531d..6c052461c5b8 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -61,7 +61,7 @@ public class CheckRegExpIntentionAction extends QuickEditAction implements Icona final Project project = file.getProject(); final Document document = PsiDocumentManager.getInstance(project).getDocument(file); if (document != null) { - return new CheckRegExpForm(new Pair>(file, ref)).getRootPanel(); + return new CheckRegExpForm(Pair.create(file, ref)).getRootPanel(); } return null; } diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index 435720ffcab7..225113a63393 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -251,7 +251,7 @@ libraryLicense(name: "XML-RPC", libraryName: "XmlRPC", version: "2.0", license: libraryLicense(name: "XStream", version: "1.4.3", license: "BSD", url: "http://xstream.codehaus.org/", licenseUrl: "http://xstream.codehaus.org/license.html") libraryLicense(name: "YourKit Java Profiler", libraryName: "yjp-controller-api-redist.jar", version: "8.0.x", license: "link (commercial license)", url: "http://yourkit.com/", licenseUrl: "http://www.yourkit.com/purchase/license.html") libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "http://code.google.com/p/protobuf/source/browse/trunk/COPYING.txt?r=367") -libraryLicense(name: "Netty", libraryName: "Netty", version: "5.0.0.Alpha1", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") +libraryLicense(name: "Netty", libraryName: "Netty", version: "4.1.0.Alpha2", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Kryo", libraryName: "Kryo", version: "2.22", license: "New BSD License", url: "https://github.com/EsotericSoftware/kryo", licenseUrl: "https://github.com/EsotericSoftware/kryo/blob/master/license.txt") libraryLicense(name: "Snappy-Java", libraryName: "Snappy-Java", version: "0.3", license: "Apache 2.0", url: "https://github.com/dain/snappy", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Cucumber-Java", libraryName: "cucumber-java", version: "1.0.14", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerManagerImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerManagerImpl.java index 46a090da8a92..64356bf491b2 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerManagerImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerManagerImpl.java @@ -397,12 +397,17 @@ public class CompilerManagerImpl extends CompilerManager { @NotNull public CompileScope createModuleCompileScope(@NotNull final Module module, final boolean includeDependentModules) { - return new ModuleCompileScope(module, includeDependentModules); + return createModulesCompileScope(new Module[] {module}, includeDependentModules); } @NotNull public CompileScope createModulesCompileScope(@NotNull final Module[] modules, final boolean includeDependentModules) { - return new ModuleCompileScope(myProject, modules, includeDependentModules); + return createModulesCompileScope(modules, includeDependentModules, false); + } + + @NotNull + public CompileScope createModulesCompileScope(@NotNull Module[] modules, boolean includeDependentModules, boolean includeRuntimeDependencies) { + return new ModuleCompileScope(myProject, modules, includeDependentModules, includeRuntimeDependencies); } @NotNull diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/PropertyFileGeneratorImpl.java b/java/compiler/impl/src/com/intellij/compiler/ant/PropertyFileGeneratorImpl.java index f7ee1bcbfb14..b6c74bf3dd6e 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/PropertyFileGeneratorImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/PropertyFileGeneratorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -85,7 +85,7 @@ public class PropertyFileGeneratorImpl extends PropertyFileGenerator { } public void addProperty(String name, String value) { - myProperties.add(new Pair(name, value)); + myProperties.add(Pair.create(name, value)); } @Override diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java index f58d9efd9482..51343b9e5d7e 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -17,17 +17,20 @@ package com.intellij.compiler.classFilesIndex.chainsSearch; import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext; import com.intellij.compiler.classFilesIndex.chainsSearch.context.TargetType; +import com.intellij.compiler.classFilesIndex.impl.MethodIncompleteSignature; import com.intellij.compiler.classFilesIndex.impl.MethodsUsageIndexReader; import com.intellij.compiler.classFilesIndex.impl.UsageIndexValue; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Pair; -import com.intellij.psi.*; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.intellij.compiler.classFilesIndex.impl.MethodIncompleteSignature; import java.util.*; @@ -93,7 +96,7 @@ public final class ChainsSearcher { final WeightAware methodIncompleteSignatureWeightAware) { final MethodIncompleteSignature underlying = methodIncompleteSignatureWeightAware.getUnderlying(); return new WeightAware>( - new Pair( + Pair.create( underlying, new MethodsChain(context.resolveNotDeprecated(underlying), methodIncompleteSignatureWeightAware.getWeight(), @@ -173,7 +176,7 @@ public final class ChainsSearcher { final MethodsChain methodsChain = currentVertexUnderlying.second.addEdge(resolved, sign.getUnderlying().getOwner(), sign.getWeight()); q.add(new WeightAware>( - new Pair(sign.getUnderlying(), methodsChain), sign.getWeight())); + Pair.create(sign.getUnderlying(), methodsChain), sign.getWeight())); continue; } } @@ -184,7 +187,7 @@ public final class ChainsSearcher { if (parametersMatchResult.noUnmatchedAndHasMatched() && parametersMatchResult.hasTarget()) { updated = true; q.addFirst(new WeightAware>( - new Pair(sign.getUnderlying(), methodsChain), sign.getWeight())); + Pair.create(sign.getUnderlying(), methodsChain), sign.getWeight())); } isBreak = true; } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileContextImpl.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileContextImpl.java index f4c372a86d62..764bf1dbc042 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileContextImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -348,7 +348,7 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon myGeneratedTestRoots.add(root); } if (compiler instanceof SourceGeneratingCompiler) { - myOutputRootToSourceGeneratorMap.put(root, new Pair((SourceGeneratingCompiler)compiler, module)); + myOutputRootToSourceGeneratorMap.put(root, Pair.create((SourceGeneratingCompiler)compiler, module)); } } finally { diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index 38fe261235b0..39b052f5c82a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -182,8 +182,8 @@ public class CompileDriver { for (IntermediateOutputCompiler compiler : generatingCompilers) { final VirtualFile productionOutput = lookupVFile(lfs, CompilerPaths.getGenerationOutputPath(compiler, module, false)); final VirtualFile testOutput = lookupVFile(lfs, CompilerPaths.getGenerationOutputPath(compiler, module, true)); - final Pair pair = new Pair(compiler, module); - final Pair outputs = new Pair(productionOutput, testOutput); + final Pair pair = Pair.create(compiler, module); + final Pair outputs = Pair.create(productionOutput, testOutput); myGenerationCompilerModuleToOutputDirMap.put(pair, outputs); } if (config.getAnnotationProcessingConfiguration(module).isEnabled()) { @@ -1882,7 +1882,7 @@ public class CompileDriver { private VirtualFile getGenerationOutputDir(final IntermediateOutputCompiler compiler, final Module module, final boolean forTestSources) { final Pair outputs = - myGenerationCompilerModuleToOutputDirMap.get(new Pair(compiler, module)); + myGenerationCompilerModuleToOutputDirMap.get(Pair.create(compiler, module)); return forTestSources? outputs.getSecond() : outputs.getFirst(); } @@ -2730,7 +2730,7 @@ public class CompileDriver { list = new ArrayList>(); myData.put(file, list); } - list.add(new Pair(cache, item)); + list.add(Pair.create(cache, item)); } public void doUpdate() throws IOException { @@ -2896,7 +2896,7 @@ public class CompileDriver { final Set depFiles = new HashSet(deps.getSecond()); depFiles.removeAll(myProcessedFiles); myProcessedFiles.addAll(deps.getSecond()); - return new Pair>(currentDeps.toArray(), depFiles); + return Pair.create(currentDeps.toArray(), depFiles); } } } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/ModuleCompileScope.java b/java/compiler/impl/src/com/intellij/compiler/impl/ModuleCompileScope.java index b2485e8d8ea8..63bb747e9462 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/ModuleCompileScope.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/ModuleCompileScope.java @@ -25,10 +25,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.FileIndex; -import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.ProjectFileIndex; -import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.*; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -36,10 +33,7 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.CommonProcessors; import org.jetbrains.annotations.NotNull; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; public class ModuleCompileScope extends FileIndexCompileScope { private final Project myProject; @@ -47,18 +41,18 @@ public class ModuleCompileScope extends FileIndexCompileScope { private final Module[] myModules; public ModuleCompileScope(final Module module, boolean includeDependentModules) { - myProject = module.getProject(); - myScopeModules = new HashSet(); - if (includeDependentModules) { - buildScopeModulesSet(module); - } - else { - myScopeModules.add(module); - } - myModules = ModuleManager.getInstance(myProject).getModules(); + this(module.getProject(), Collections.singleton(module), includeDependentModules, false); } public ModuleCompileScope(Project project, final Module[] modules, boolean includeDependentModules) { + this(project, modules, includeDependentModules, false); + } + + public ModuleCompileScope(Project project, final Module[] modules, boolean includeDependentModules, boolean includeRuntimeDependencies) { + this(project, Arrays.asList(modules), includeDependentModules, includeRuntimeDependencies); + } + + private ModuleCompileScope(Project project, final Collection modules, boolean includeDependentModules, boolean includeRuntimeDeps) { myProject = project; myScopeModules = new HashSet(); for (Module module : modules) { @@ -66,7 +60,11 @@ public class ModuleCompileScope extends FileIndexCompileScope { continue; // prevent NPE } if (includeDependentModules) { - buildScopeModulesSet(module); + OrderEnumerator enumerator = ModuleRootManager.getInstance(module).orderEntries().recursively(); + if (!includeRuntimeDeps) { + enumerator = enumerator.compileOnly(); + } + enumerator.forEachModule(new CommonProcessors.CollectProcessor(myScopeModules)); } else { myScopeModules.add(module); @@ -75,10 +73,6 @@ public class ModuleCompileScope extends FileIndexCompileScope { myModules = ModuleManager.getInstance(myProject).getModules(); } - private void buildScopeModulesSet(Module module) { - ModuleRootManager.getInstance(module).orderEntries().recursively().compileOnly().forEachModule(new CommonProcessors.CollectProcessor(myScopeModules)); - } - @NotNull public Module[] getAffectedModules() { return myScopeModules.toArray(new Module[myScopeModules.size()]); 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 a4c2fbeeed05..cfc34412e727 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -768,7 +768,7 @@ public class BackendCompilerWrapper { LOG.info(message); myCompileContext.addMessage(CompilerMessageCategory.WARNING, message, sourceFile.getUrl(), -1, -1); // do not move: looks like source file has been invalidated, need recompilation - return new Pair(tempOutputDir, pathToClass); + return Pair.create(tempOutputDir, pathToClass); } final String realOutputDir; if (myCompileContext.isInTestSourceContent(sourceFile)) { @@ -782,7 +782,7 @@ public class BackendCompilerWrapper { if (FileUtil.pathsEqual(tempOutputDir, realOutputDir)) { // no need to move filesToRefresh.add(new File(pathToClass)); - return new Pair(realOutputDir, pathToClass); + return Pair.create(realOutputDir, pathToClass); } final String realPathToClass = realOutputDir + pathToClass.substring(tempOutputDir.length()); @@ -809,7 +809,7 @@ public class BackendCompilerWrapper { } if (success) { filesToRefresh.add(toFile); - return new Pair(realOutputDir, realPathToClass); + return Pair.create(realOutputDir, realPathToClass); } return null; } 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 ae0f0b716399..142b6e694d0a 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -155,7 +155,7 @@ public class RmicCompiler implements ClassPostProcessingCompiler{ final Map, List> sortedByModuleAndOutputPath = new HashMap, List>(); for (ProcessingItem item1 : items) { final RmicProcessingItem item = (RmicProcessingItem)item1; - final Pair moduleOutputPair = new Pair(item.getModule(), item.getOutputDir()); + final Pair moduleOutputPair = Pair.create(item.getModule(), item.getOutputDir()); List dirItems = sortedByModuleAndOutputPath.get(moduleOutputPair); if (dirItems == null) { dirItems = new ArrayList(); diff --git a/java/compiler/impl/src/com/intellij/compiler/make/CachingSearcher.java b/java/compiler/impl/src/com/intellij/compiler/make/CachingSearcher.java index 8ac89b3b5f77..b232c2ee9485 100644 --- a/java/compiler/impl/src/com/intellij/compiler/make/CachingSearcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/make/CachingSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -42,7 +42,7 @@ public class CachingSearcher { } public Collection findReferences(PsiElement element, final boolean ignoreAccessScope) { - final Pair key = new Pair(element, ignoreAccessScope? Boolean.TRUE : Boolean.FALSE); + final Pair key = Pair.create(element, ignoreAccessScope ? Boolean.TRUE : Boolean.FALSE); Collection psiReferences = myElementToReferencersMap.get(key); if (psiReferences == null) { GlobalSearchScope searchScope = GlobalSearchScope.projectScope(myProject); diff --git a/java/compiler/impl/src/com/intellij/compiler/make/DependencyCache.java b/java/compiler/impl/src/com/intellij/compiler/make/DependencyCache.java index 92f3285bf8ef..722f9faa8be5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/make/DependencyCache.java +++ b/java/compiler/impl/src/com/intellij/compiler/make/DependencyCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -395,7 +395,7 @@ public class DependencyCache { throws CacheCorruptedException, ExitException { markDependencies(context, project, compiledWithErrors); - return new Pair>(myMarkedInfos.toArray(), Collections.unmodifiableSet(myMarkedFiles)); + return Pair.create(myMarkedInfos.toArray(), Collections.unmodifiableSet(myMarkedFiles)); } private void markDependencies(CompileContext context, Project project, final Set compiledWithErrors) diff --git a/java/compiler/impl/src/com/intellij/compiler/options/ProcessedModulesTable.java b/java/compiler/impl/src/com/intellij/compiler/options/ProcessedModulesTable.java index f95025b448f9..787391c405a7 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/ProcessedModulesTable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/ProcessedModulesTable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -220,7 +220,7 @@ public class ProcessedModulesTable extends JPanel { List> elements = new ArrayList>(); for (int idx = 0; idx < count; idx++) { final Module module = myTableModel.getModuleAt(idx); - elements.add(new Pair(module, myTableModel.getGenDirName(module))); + elements.add(Pair.create(module, myTableModel.getGenDirName(module))); } return elements; } diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java index a6ba4a38190a..d324a620155b 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java @@ -20,9 +20,9 @@ import com.intellij.util.containers.ConcurrentHashSet; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.util.AttributeKey; import org.jetbrains.annotations.Nullable; +import org.jetbrains.io.SimpleChannelInboundHandlerAdapter; import org.jetbrains.jps.api.CmdlineProtoUtil; import org.jetbrains.jps.api.CmdlineRemoteProto; @@ -36,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap; * Date: 4/25/12 */ @ChannelHandler.Sharable -class BuildMessageDispatcher extends SimpleChannelInboundHandler { +class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter { private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.server.BuildMessageDispatcher"); private static final AttributeKey SESSION_DATA = AttributeKey.valueOf("BuildMessageDispatcher.sessionData"); diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerStateSplitter.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerStateSplitter.java index 90ee240c0a04..14fecb85dbdc 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerStateSplitter.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerStateSplitter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -37,7 +37,7 @@ public class ArtifactManagerStateSplitter implements StateSplitter { for (Element element : JDOMUtil.getElements(e)) { final String name = generator.generateUniqueName(FileUtil.sanitizeFileName(element.getAttributeValue(ArtifactState.NAME_ATTRIBUTE))) + ".xml"; - result.add(new Pair(element, name)); + result.add(Pair.create(element, name)); } return result; diff --git a/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java b/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java index 5900ea2d6097..ee88a678cabc 100644 --- a/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java +++ b/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java @@ -171,15 +171,15 @@ public abstract class BaseCompilerTestCase extends ModuleTestCase { } protected CompilationLog make(Module... modules) { - return make(false, modules); + return make(false, false, modules); } - protected CompilationLog makeWithDependencies(Module... modules) { - return make(true, modules); + protected CompilationLog makeWithDependencies(final boolean includeRuntimeDependencies, Module... modules) { + return make(true, includeRuntimeDependencies, modules); } - private CompilationLog make(boolean includeDependentModules, Module... modules) { - return make(getCompilerManager().createModulesCompileScope(modules, includeDependentModules), CompilerFilter.ALL); + private CompilationLog make(boolean includeDependentModules, final boolean includeRuntimeDependencies, Module... modules) { + return make(getCompilerManager().createModulesCompileScope(modules, includeDependentModules, includeRuntimeDependencies), CompilerFilter.ALL); } protected CompilationLog recompile(Module... modules) { diff --git a/java/compiler/openapi/src/com/intellij/compiler/ModuleCompilerUtil.java b/java/compiler/openapi/src/com/intellij/compiler/ModuleCompilerUtil.java index 44b7b2a03fc6..1a5a202569df 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ModuleCompilerUtil.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ModuleCompilerUtil.java @@ -27,6 +27,7 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.util.Pair; import com.intellij.util.Chunk; +import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.graph.*; import org.jetbrains.annotations.Nullable; @@ -115,14 +116,17 @@ public final class ModuleCompilerUtil { } public Iterator getIn(final ModuleRootModel model) { - final Module[] modules = model.getModuleDependencies(); final List dependencies = new ArrayList(); - for (Module module : modules) { - T depModel = models.get(module); - if (depModel != null) { - dependencies.add(depModel); + model.orderEntries().compileOnly().forEachModule(new Processor() { + @Override + public boolean process(Module module) { + T depModel = models.get(module); + if (depModel != null) { + dependencies.add(depModel); + } + return true; } - } + }); return dependencies.iterator(); } })); diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/CompositeGenerator.java b/java/compiler/openapi/src/com/intellij/compiler/ant/CompositeGenerator.java index 884e125945b0..a6146ac35860 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/CompositeGenerator.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/CompositeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -83,7 +83,7 @@ public class CompositeGenerator extends Generator { * @param emptyLinesCount amount of empty lines */ public final void add(Generator generator, int emptyLinesCount) { - myGenerators.add(new Pair(generator, new Integer(emptyLinesCount))); + myGenerators.add(Pair.create(generator, new Integer(emptyLinesCount))); } /** diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/Tag.java b/java/compiler/openapi/src/com/intellij/compiler/ant/Tag.java index aa08438d4509..4811a94b75a3 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/Tag.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/Tag.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -82,6 +82,6 @@ public class Tag extends CompositeGenerator { if (v2 == null) { return null; } - return new Pair(v1, v2); + return Pair.create(v1, v2); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/AntCall.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/AntCall.java index 4768d5fbb347..d2a8ef900b75 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/AntCall.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/AntCall.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -27,6 +27,6 @@ import com.intellij.openapi.util.Pair; public class AntCall extends Tag{ public AntCall(final String target) { - super("antcall", new Pair[] {new Pair("target", target)}); + super("antcall", new Pair[] {Pair.create("target", target)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/AntProject.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/AntProject.java index 3aa3eee935f7..911f880800ec 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/AntProject.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/AntProject.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -27,6 +27,6 @@ import org.jetbrains.annotations.NonNls; public class AntProject extends Tag { public AntProject(@NonNls String name, @NonNls String defaultTarget) { //noinspection HardCodedStringLiteral - super("project", new Pair[]{new Pair("name", name), new Pair("default", defaultTarget)}); + super("project", new Pair[]{Pair.create("name", name), Pair.create("default", defaultTarget)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Copy.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Copy.java index c95348b66367..e10f81c6980e 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Copy.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Copy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -27,10 +27,10 @@ import org.jetbrains.annotations.NonNls; public class Copy extends Tag { public Copy(@NonNls String toDir) { //noinspection HardCodedStringLiteral - super("copy", new Pair[] {new Pair("todir", toDir)}); + super("copy", new Pair[] {Pair.create("todir", toDir)}); } public Copy(@NonNls String file, @NonNls String toFile) { //noinspection HardCodedStringLiteral - super("copy", new Pair[] {new Pair("file", file), new Pair("tofile", toFile)}); + super("copy", new Pair[] {Pair.create("file", file), Pair.create("tofile", toFile)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/DirSet.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/DirSet.java index b4cba0848d26..1476f8b8f7e4 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/DirSet.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/DirSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -28,6 +28,6 @@ public class DirSet extends Tag{ public DirSet(@NonNls final String dir) { //noinspection HardCodedStringLiteral - super("dirset", new Pair[] {new Pair("dir", dir)}); + super("dirset", new Pair[] {Pair.create("dir", dir)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Dirname.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Dirname.java index f833f585014b..7be6755361bd 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Dirname.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Dirname.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -27,6 +27,6 @@ import org.jetbrains.annotations.NonNls; public class Dirname extends Tag{ public Dirname(@NonNls String property, @NonNls String file) { //noinspection HardCodedStringLiteral - super("dirname", new Pair[] {new Pair("property", property), new Pair("file", file)}); + super("dirname", new Pair[] {Pair.create("property", property), Pair.create("file", file)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Exclude.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Exclude.java index 42e7a6aec854..6b9e1ff16ae7 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Exclude.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Exclude.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -28,7 +28,7 @@ public class Exclude extends Tag { public Exclude(@NonNls final String name) { //noinspection HardCodedStringLiteral - super("exclude", new Pair[] {new Pair("name", name)}); + super("exclude", new Pair[] {Pair.create("name", name)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Import.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Import.java index 2c6e23c7d271..611b6344cf16 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Import.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Import.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -27,11 +27,11 @@ import org.jetbrains.annotations.NonNls; public class Import extends Tag{ public Import(@NonNls String file, boolean optional) { //noinspection HardCodedStringLiteral - super("import", new Pair[] {new Pair("file", file), new Pair("optional", optional? "true" : "false")}); + super("import", new Pair[] {Pair.create("file", file), Pair.create("optional", optional ? "true" : "false")}); } public Import(@NonNls String file) { //noinspection HardCodedStringLiteral - super("import", new Pair[] {new Pair("file", file)}); + super("import", new Pair[] {Pair.create("file", file)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Mkdir.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Mkdir.java index ef15e5c3274b..4c2bff8aafeb 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Mkdir.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Mkdir.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -27,6 +27,6 @@ import org.jetbrains.annotations.NonNls; public class Mkdir extends Tag { public Mkdir(@NonNls String directory) { //noinspection HardCodedStringLiteral - super("mkdir", new Pair[] {new Pair("dir", directory)}); + super("mkdir", new Pair[] {Pair.create("dir", directory)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Param.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Param.java index 19649e04699f..5eaa4856b669 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Param.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Param.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -28,8 +28,8 @@ public class Param extends Tag { public Param(@NonNls final String name, final String value) { //noinspection HardCodedStringLiteral super("param", new Pair[] { - new Pair("name", name), - new Pair("value", value) + Pair.create("name", name), + Pair.create("value", value) }); } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/PatternSetRef.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/PatternSetRef.java index 1055016894b8..6a30765b48ad 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/PatternSetRef.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/PatternSetRef.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -27,6 +27,6 @@ import org.jetbrains.annotations.NonNls; public class PatternSetRef extends Tag{ public PatternSetRef(@NonNls final String refid) { //noinspection HardCodedStringLiteral - super("patternset", new Pair[] {new Pair("refid", refid)}); + super("patternset", new Pair[] {Pair.create("refid", refid)}); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Property.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Property.java index f28d12747e11..2c2f16ad8095 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Property.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Property.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -29,15 +29,15 @@ public class Property extends Tag { public Property(@NonNls final String name, final String value) { //noinspection HardCodedStringLiteral super("property", new Pair[] { - new Pair("name", name), - new Pair("value", value) + Pair.create("name", name), + Pair.create("value", value) }); } public Property(@NonNls final String filePath) { //noinspection HardCodedStringLiteral super("property", new Pair[] { - new Pair("file", filePath), + Pair.create("file", filePath), }); } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Target.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Target.java index fa845a85fb0f..2b17c0b1959b 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Target.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Target.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -41,7 +41,7 @@ public class Target extends Tag{ @SuppressWarnings({"HardCodedStringLiteral"}) private static Pair[] getOptions(@NonNls String... names) { final List options = new ArrayList(); - options.add(new Pair("name", names[0])); + options.add(Pair.create("name", names[0])); appendIfNonEmpty(options, "depends", names[1]); appendIfNonEmpty(options, "description", names[2]); appendIfNonEmpty(options, "unless", names[3]); @@ -53,7 +53,7 @@ public class Target extends Tag{ private static void appendIfNonEmpty(List options, final String paramName, String value) { if (!StringUtil.isEmptyOrSpaces(value)) { - options.add(new Pair(paramName, value)); + options.add(Pair.create(paramName, value)); } } } diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerManager.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerManager.java index f9d8bce65258..1f0106c11fa4 100644 --- a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerManager.java +++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerManager.java @@ -285,11 +285,13 @@ public abstract class CompilerManager { @NotNull public abstract CompileScope createFilesCompileScope(@NotNull VirtualFile[] files); @NotNull - public abstract CompileScope createModuleCompileScope(@NotNull Module module, final boolean includeDependentModules); + public abstract CompileScope createModuleCompileScope(@NotNull Module module, boolean includeDependentModules); @NotNull - public abstract CompileScope createModulesCompileScope(@NotNull Module[] modules, final boolean includeDependentModules); + public abstract CompileScope createModulesCompileScope(@NotNull Module[] modules, boolean includeDependentModules); @NotNull - public abstract CompileScope createModuleGroupCompileScope(@NotNull Project project, @NotNull Module[] modules, final boolean includeDependentModules); + public abstract CompileScope createModulesCompileScope(@NotNull Module[] modules, boolean includeDependentModules, boolean includeRuntimeDependencies); + @NotNull + public abstract CompileScope createModuleGroupCompileScope(@NotNull Project project, @NotNull Module[] modules, boolean includeDependentModules); @NotNull public abstract CompileScope createProjectCompileScope(@NotNull Project project); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java index 5d29954164f9..2f41cb2288f1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -79,7 +79,7 @@ public class DebugProcessEvents extends DebugProcessImpl { if(requestor instanceof Breakpoint) { breakpoint = (Breakpoint)requestor; } - String text = debugProcess.getEventText(new Pair(breakpoint, event)); + String text = debugProcess.getEventText(Pair.create(breakpoint, event)); debugProcess.showStatusText(text); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 39451f7122e0..d924822bf9ef 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -189,7 +189,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb if (method == null) { return null; } - return new Pair(method, watcher.getLastMethodReturnValue()); + return Pair.create(method, watcher.getLastMethodReturnValue()); } public void setWatchMethodReturnValuesEnabled(boolean enabled) { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactoryContextWrapper.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactoryContextWrapper.java index 4249138bdf29..805fd8b8a91d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactoryContextWrapper.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactoryContextWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,9 +18,7 @@ package com.intellij.debugger.engine.evaluation; import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder; -import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl; import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; -import com.intellij.xdebugger.impl.ui.tree.ValueMarkup; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -31,6 +29,7 @@ import com.intellij.psi.JavaRecursiveElementVisitor; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLocalVariable; import com.intellij.util.StringBuilderSpinAllocator; +import com.intellij.xdebugger.impl.ui.tree.ValueMarkup; import com.sun.jdi.ObjectCollectedException; import com.sun.jdi.ObjectReference; import com.sun.jdi.Value; @@ -126,7 +125,7 @@ public class CodeFragmentFactoryContextWrapper extends CodeFragmentFactory { } } buffer.append(" "); - return new Pair>(buffer.toString(), reverseMap); + return Pair.create(buffer.toString(), reverseMap); } finally { StringBuilderSpinAllocator.dispose(buffer); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/UnBoxingEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/UnBoxingEvaluator.java index cb4505bb3506..0f3bb4b9bdf4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/UnBoxingEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/UnBoxingEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -38,14 +38,14 @@ public class UnBoxingEvaluator implements Evaluator{ private final Evaluator myOperand; private static final Map> TYPES_TO_CONVERSION_METHOD_MAP = new HashMap>(); static { - TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Boolean", new Pair("booleanValue", "()Z")); - TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Byte", new Pair("byteValue", "()B")); - TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Character", new Pair("charValue", "()C")); - TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Short", new Pair("shortValue", "()S")); - TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Integer", new Pair("intValue", "()I")); - TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Long", new Pair("longValue", "()J")); - TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Float", new Pair("floatValue", "()F")); - TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Double", new Pair("doubleValue", "()D")); + TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Boolean", Pair.create("booleanValue", "()Z")); + TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Byte", Pair.create("byteValue", "()B")); + TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Character", Pair.create("charValue", "()C")); + TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Short", Pair.create("shortValue", "()S")); + TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Integer", Pair.create("intValue", "()I")); + TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Long", Pair.create("longValue", "()J")); + TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Float", Pair.create("floatValue", "()F")); + TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Double", Pair.create("doubleValue", "()D")); } public static boolean isTypeUnboxable(String typeName) { diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java index 1419a2853e84..2c81eae90f72 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -360,7 +360,7 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils { for (final Event event : events) { final Requestor requestor = requestManager.findRequestor(event.request()); if (requestor instanceof Breakpoint) { - eventDescriptors.add(new Pair((Breakpoint)requestor, event)); + eventDescriptors.add(Pair.create((Breakpoint)requestor, event)); } } return eventDescriptors; diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/MultiProcessCommand.java b/java/debugger/impl/src/com/intellij/debugger/impl/MultiProcessCommand.java index 9fe6b8c390ff..8abcd6d4e687 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/MultiProcessCommand.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/MultiProcessCommand.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -52,6 +52,6 @@ public class MultiProcessCommand implements Runnable{ } public void addCommand(DebugProcessImpl debugProcess, DebuggerCommandImpl command) { - myCommands.add(new Pair(debugProcess, command)); + myCommands.add(Pair.create(debugProcess, command)); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java index ea54ac255023..0f813d0bf167 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -497,7 +497,7 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable { public List> getExpressions() { final ArrayList> pairs = new ArrayList>(myData.size()); for (final Row row : myData) { - pairs.add(new Pair(row.name, row.value)); + pairs.add(Pair.create(row.name, row.value)); } return pairs; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java index 5694eb1cba67..a3f95f8ea983 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -323,17 +323,17 @@ public class FrameVariablesTree extends DebuggerTree { EvaluationContextImpl evalContext) { final int line = position.getLine(); if (line < 0) { - return new Pair, Set>(Collections.emptySet(), Collections.emptySet()); + return Pair.create(Collections.emptySet(), Collections.emptySet()); } final PsiFile positionFile = position.getFile(); if (!positionFile.getLanguage().isKindOf(JavaLanguage.INSTANCE)) { - return new Pair, Set>(visibleVars, Collections.emptySet()); + return Pair.create(visibleVars, Collections.emptySet()); } final VirtualFile vFile = positionFile.getVirtualFile(); final Document doc = vFile != null? FileDocumentManager.getInstance().getDocument(vFile) : null; if (doc == null || doc.getLineCount() == 0 || line > (doc.getLineCount() - 1)) { - return new Pair, Set>(Collections.emptySet(), Collections.emptySet()); + return Pair.create(Collections.emptySet(), Collections.emptySet()); } final TextRange limit = calculateLimitRange(positionFile, doc, line); @@ -375,7 +375,7 @@ public class FrameVariablesTree extends DebuggerTree { //noinspection unchecked if (element instanceof PsiCompiledElement) { - return new Pair, Set>(visibleVars, Collections.emptySet()); + return Pair.create(visibleVars, Collections.emptySet()); } else { final Set vars = new HashSet(); @@ -383,11 +383,11 @@ public class FrameVariablesTree extends DebuggerTree { final PsiElementVisitor variablesCollector = new VariablesCollector(visibleVars, adjustRange(element, lineRange), expressions, vars, position, evalContext); element.accept(variablesCollector); - return new Pair, Set>(vars, expressions); + return Pair.create(vars, expressions); } } } - return new Pair, Set>(Collections.emptySet(), Collections.emptySet()); + return Pair.create(Collections.emptySet(), Collections.emptySet()); } private static TextRange calculateLimitRange(final PsiFile file, final Document doc, final int line) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/EnumerationChildrenRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/EnumerationChildrenRenderer.java index 36878a21dfd0..2baefd798965 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/EnumerationChildrenRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/EnumerationChildrenRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -76,7 +76,7 @@ public final class EnumerationChildrenRenderer extends com.intellij.debugger.ui. String name = item.getAttributeValue(CHILD_NAME); TextWithImports text = DebuggerUtils.getInstance().readTextWithImports((Element) item.getChildren().get(0)); - myChildren.add(new Pair(name, text)); + myChildren.add(Pair.create(name, text)); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/configurables/NamedChildrenConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/configurables/NamedChildrenConfigurable.java index 7e1515f4d170..fe4861de14eb 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/configurables/NamedChildrenConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/configurables/NamedChildrenConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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,7 +138,7 @@ public class NamedChildrenConfigurable implements UnnamedConfigurable{ java.util.List> result = new ArrayList>(); for (int idx = 0; idx < size; idx++) { - result.add(new Pair((String)model.getValueAt(idx, 0), (TextWithImports)model.getValueAt(idx, 1))); + result.add(Pair.create((String)model.getValueAt(idx, 0), (TextWithImports)model.getValueAt(idx, 1))); } myRenderer.setChildren(result); } diff --git a/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java b/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java index 57efc543da2d..124220d75966 100644 --- a/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java +++ b/java/execution/impl/src/com/intellij/compiler/options/CompileStepBeforeRun.java @@ -143,7 +143,7 @@ public class CompileStepBeforeRun extends BeforeRunTaskProvider(radioButton, comboBox)); + myButtons.put(ri, Pair.create(radioButton, comboBox)); myButtonGroup.add(radioButton); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index e6de88efc4e0..59024a8d89c2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -540,6 +540,11 @@ public class GenericsHighlightUtil { return null; } + if (superMethod.hasModifierProperty(PsiModifier.STATIC) && superContainingClass != null && + superContainingClass.isInterface() && PsiUtil.isLanguageLevel8OrHigher(superContainingClass)) { + return null; + } + final PsiType retErasure1 = TypeConversionUtil.erasure(checkMethod.getReturnType()); final PsiType retErasure2 = TypeConversionUtil.erasure(superMethod.getReturnType()); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index ee07cf92bbcc..247c03005a92 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -1142,6 +1142,7 @@ public class HighlightMethodUtil { } if (isMethodStatic) { + if (superClass.isInterface()) return null; int accessLevel = PsiUtil.getAccessLevel(modifierList); String accessModifier = PsiUtil.getAccessModifier(accessLevel); HighlightInfo info = isWeaker(method, modifierList, accessModifier, accessLevel, superMethod, true); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/accessStaticViaInstance/AccessStaticViaInstanceBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/accessStaticViaInstance/AccessStaticViaInstanceBase.java index 6c75f8be8e7d..00c66668638f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/accessStaticViaInstance/AccessStaticViaInstanceBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/accessStaticViaInstance/AccessStaticViaInstanceBase.java @@ -19,17 +19,14 @@ import com.intellij.codeInsight.daemon.JavaErrorMessages; import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil; import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil; import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableUtil; -import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool; -import com.intellij.codeInspection.InspectionsBundle; -import com.intellij.codeInspection.LocalQuickFix; -import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.codeInspection.*; import com.intellij.psi.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -public class AccessStaticViaInstanceBase extends BaseJavaBatchLocalInspectionTool { +public class AccessStaticViaInstanceBase extends BaseJavaBatchLocalInspectionTool implements CleanupLocalInspectionTool { @NonNls public static final String ACCESS_STATIC_VIA_INSTANCE = "AccessStaticViaInstance"; @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/duplicateThrows/DuplicateThrowsInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/duplicateThrows/DuplicateThrowsInspection.java index b95c3c9c4b63..c40f4385f3e4 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/duplicateThrows/DuplicateThrowsInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/duplicateThrows/DuplicateThrowsInspection.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; -public class DuplicateThrowsInspection extends BaseJavaBatchLocalInspectionTool { +public class DuplicateThrowsInspection extends BaseJavaBatchLocalInspectionTool implements CleanupLocalInspectionTool { @SuppressWarnings("PublicField") public boolean ignoreSubclassing = false; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/GenericsInspectionToolBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/GenericsInspectionToolBase.java index 80d11cbb2471..cd8d804d16d1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/GenericsInspectionToolBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/GenericsInspectionToolBase.java @@ -15,10 +15,7 @@ */ package com.intellij.codeInspection.miscGenerics; -import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool; -import com.intellij.codeInspection.InspectionManager; -import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.codeInspection.*; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import com.intellij.util.containers.ContainerUtil; @@ -31,7 +28,7 @@ import java.util.List; /** * @author ven */ -public abstract class GenericsInspectionToolBase extends BaseJavaBatchLocalInspectionTool { +public abstract class GenericsInspectionToolBase extends BaseJavaBatchLocalInspectionTool implements CleanupLocalInspectionTool { @Override public boolean isEnabledByDefault() { return true; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrowsDeclaration.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrowsDeclaration.java index 61b501c78ec9..424c707706e5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrowsDeclaration.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrowsDeclaration.java @@ -33,7 +33,7 @@ import java.util.Set; * @author anna * @since 15-Nov-2005 */ -public class RedundantThrowsDeclaration extends BaseJavaBatchLocalInspectionTool { +public class RedundantThrowsDeclaration extends BaseJavaBatchLocalInspectionTool implements CleanupLocalInspectionTool { @Override @NotNull public String getGroupDisplayName() { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddDeprecationAnnotationIntention.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddDeprecationAnnotationIntention.java index bcc4e4c1cb5d..35c6d09d1fe3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddDeprecationAnnotationIntention.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddDeprecationAnnotationIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -31,6 +31,6 @@ public class AddDeprecationAnnotationIntention extends AddAnnotationIntention { @NotNull @Override public Pair getAnnotations(@NotNull Project project) { - return new Pair("java.lang.annotation.Deprecated", ArrayUtil.EMPTY_STRING_ARRAY); + return Pair.create("java.lang.annotation.Deprecated", ArrayUtil.EMPTY_STRING_ARRAY); } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddNotNullAnnotationIntention.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddNotNullAnnotationIntention.java index b5e322503b4c..b44de1d4c7e4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddNotNullAnnotationIntention.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddNotNullAnnotationIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -34,7 +34,7 @@ public class AddNotNullAnnotationIntention extends AddAnnotationIntention { @NotNull @Override public Pair getAnnotations(@NotNull Project project) { - return new Pair(NullableNotNullManager.getInstance(project).getDefaultNotNull(), getNullables(project)); + return Pair.create(NullableNotNullManager.getInstance(project).getDefaultNotNull(), getNullables(project)); } @NotNull diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddNullableAnnotationIntention.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddNullableAnnotationIntention.java index 3979218b069a..d0e0602bd0d8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddNullableAnnotationIntention.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddNullableAnnotationIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -34,7 +34,7 @@ public class AddNullableAnnotationIntention extends AddAnnotationIntention { @NotNull @Override public Pair getAnnotations(@NotNull Project project) { - return new Pair(NullableNotNullManager.getInstance(project).getDefaultNullable(), getNotNulls(project)); + return Pair.create(NullableNotNullManager.getInstance(project).getDefaultNullable(), getNotNulls(project)); } @NotNull diff --git a/java/java-impl/src/com/intellij/codeInsight/template/impl/ShortenToStaticImportProcessor.java b/java/java-impl/src/com/intellij/codeInsight/template/impl/ShortenToStaticImportProcessor.java index cf2f8c1176ba..41424cf2b526 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/impl/ShortenToStaticImportProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/impl/ShortenToStaticImportProcessor.java @@ -67,7 +67,7 @@ public class ShortenToStaticImportProcessor implements TemplateOptionalProcessor { for (StaticImporter importer : IMPORTERS) { if (importer.canPerform(element)) { - staticImportTargets.add(new Pair(element, importer)); + staticImportTargets.add(Pair.create(element, importer)); break; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplate.java index c48ef1b97ba1..90812945f7e6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplate.java @@ -15,18 +15,20 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Editor; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -public class AssertStatementPostfixTemplate extends BooleanPostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class AssertStatementPostfixTemplate extends JavaStatementWrapPostfixTemplate { + public AssertStatementPostfixTemplate() { - super("assert", "assert expr;"); + super("assert", "assert expr;", JAVA_PSI_INFO, IS_BOOLEAN); } + @NotNull @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PostfixTemplatesUtils.createSimpleStatement(context, editor, "assert"); + protected String getHead() { + return "assert "; } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java index 7c56047fe059..4cb9bbc5eb0e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java @@ -16,7 +16,6 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.generation.surroundWith.JavaWithCastSurrounder; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiExpression; import org.jetbrains.annotations.NotNull; @@ -28,6 +27,6 @@ public class CastExpressionPostfixTemplate extends ExpressionPostfixTemplateWith @Override protected void doIt(@NotNull final Editor editor, @NotNull final PsiExpression expression) { - PostfixTemplatesUtils.apply(new JavaWithCastSurrounder(), expression.getProject(), editor, expression); + PostfixTemplatesUtils.surround(new JavaWithCastSurrounder(), editor, expression); } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java index f92f4c81f71b..b9b6c3437123 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java @@ -15,27 +15,21 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.CodeInsightServicesUtil; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; +import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder; +import com.intellij.lang.surroundWith.Surrounder; import org.jetbrains.annotations.NotNull; -public class ElseStatementPostfixTemplate extends BooleanPostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class ElseStatementPostfixTemplate extends ElseExpressionPostfixTemplateBase { public ElseStatementPostfixTemplate() { - super("else", "if (!expr)"); + super(JAVA_PSI_INFO, IS_BOOLEAN); } + @NotNull @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); - assert expression != null; - PsiExpression invertedExpression = (PsiExpression)expression.replace(CodeInsightServicesUtil.invertCondition(expression)); - TextRange range = PostfixTemplatesUtils.ifStatement(invertedExpression.getProject(), editor, invertedExpression); - if (range != null) { - editor.getCaretModel().moveToOffset(range.getStartOffset()); - } + protected Surrounder getSurrounder() { + return new JavaWithIfExpressionSurrounder(); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java index 69df4ccd40a7..25bd61f00b7d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java @@ -15,7 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.codeInsight.unwrap.ScopeHighlighter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -108,7 +108,7 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla @NotNull private static List maybeTopmostExpression(@NotNull PsiElement context) { - PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); + PsiExpression expression = JavaPostfixTemplatesUtils.getTopmostExpression(context); PsiType type = expression != null ? expression.getType() : null; if (type == null || PsiType.VOID.equals(type)) return ContainerUtil.emptyList(); return ContainerUtil.createMaybeSingletonList(expression); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplate.java index b55405b01e3c..6b70cd2db844 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplate.java @@ -15,7 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiExpression; import org.jetbrains.annotations.NotNull; @@ -35,7 +35,7 @@ public class ForDescendingPostfixTemplate extends ForIndexedPostfixTemplate { @NotNull @Override protected String getComparativeSign(@NotNull PsiExpression expr) { - return PostfixTemplatesUtils.isNumber(expr.getType()) ? ">" : ">="; + return JavaPostfixTemplatesUtils.isNumber(expr.getType()) ? ">" : ">="; } @Nullable @@ -45,7 +45,7 @@ public class ForDescendingPostfixTemplate extends ForIndexedPostfixTemplate { if (bound == null) { return null; } - return PostfixTemplatesUtils.isNumber(expression.getType()) + return JavaPostfixTemplatesUtils.isNumber(expression.getType()) ? Pair.create(bound, "0") : Pair.create(bound + " - 1", "0"); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java index 4fd22ed5e67d..745d76ff61a5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java @@ -19,7 +19,7 @@ import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateManager; import com.intellij.codeInsight.template.impl.MacroCallNode; import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -37,15 +37,15 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); - return expr != null && (PostfixTemplatesUtils.isNumber(expr.getType()) || - PostfixTemplatesUtils.isArray(expr.getType()) || - PostfixTemplatesUtils.isIterable(expr.getType())); + PsiExpression expr = JavaPostfixTemplatesUtils.getTopmostExpression(context); + return expr != null && (JavaPostfixTemplatesUtils.isNumber(expr.getType()) || + JavaPostfixTemplatesUtils.isArray(expr.getType()) || + JavaPostfixTemplatesUtils.isIterable(expr.getType())); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); + PsiExpression expr = JavaPostfixTemplatesUtils.getTopmostExpression(context); if (expr == null) { PostfixTemplatesUtils.showErrorHint(context.getProject(), editor); return; @@ -94,13 +94,13 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate { @Nullable protected static String getExpressionBound(@NotNull PsiExpression expr) { PsiType type = expr.getType(); - if (PostfixTemplatesUtils.isNumber(type)) { + if (JavaPostfixTemplatesUtils.isNumber(type)) { return expr.getText(); } - else if (PostfixTemplatesUtils.isArray(type)) { + else if (JavaPostfixTemplatesUtils.isArray(type)) { return expr.getText() + ".length"; } - else if (PostfixTemplatesUtils.isIterable(type)) { + else if (JavaPostfixTemplatesUtils.isIterable(type)) { return expr.getText() + ".size()"; } return null; @@ -109,7 +109,7 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate { @NotNull private static String suggestIndexType(@NotNull PsiExpression expr) { PsiType type = expr.getType(); - if (PostfixTemplatesUtils.isNumber(type)) { + if (JavaPostfixTemplatesUtils.isNumber(type)) { return type.getCanonicalText(); } return "int"; diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java index 88f07dca85ce..aefafaebc235 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java @@ -22,7 +22,7 @@ import com.intellij.codeInsight.template.impl.TextExpression; import com.intellij.codeInsight.template.impl.VariableNode; import com.intellij.codeInsight.template.macro.IterableComponentTypeMacro; import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -37,13 +37,13 @@ public class ForeachPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); - return expr != null && (PostfixTemplatesUtils.isArray(expr.getType()) || PostfixTemplatesUtils.isIterable(expr.getType())); + PsiExpression expr = JavaPostfixTemplatesUtils.getTopmostExpression(context); + return expr != null && (JavaPostfixTemplatesUtils.isArray(expr.getType()) || JavaPostfixTemplatesUtils.isIterable(expr.getType())); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); + PsiExpression expr = JavaPostfixTemplatesUtils.getTopmostExpression(context); if (expr == null) return; Project project = context.getProject(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java index 288df0770259..f312d44d1d7c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java @@ -15,29 +15,48 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; -public class FormatPostfixTemplate extends PostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class FormatPostfixTemplate extends JavaStatementWrapPostfixTemplate { + private static final Condition IS_STRING = new Condition() { + @Override + public boolean value(PsiElement expr) { + if (!(expr instanceof PsiExpression)) { + return false; + } + PsiType type = ((PsiExpression)expr).getType(); + return type != null && CommonClassNames.JAVA_LANG_STRING.equals(type.getCanonicalText()); + } + }; + + public FormatPostfixTemplate() { - super("format", "String.format(expr);"); + super("format", "String.format(expr);", JAVA_PSI_INFO, IS_STRING); } @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PostfixTemplatesUtils.createStatement(context, editor, "String.format(", ", )", -2); + protected void afterExpand(@NotNull PsiElement newElement, @NotNull Editor editor) { + editor.getCaretModel().moveToOffset(newElement.getTextRange().getEndOffset() - 2); + JavaPostfixTemplateProvider.doNotDeleteSemicolon(newElement.getContainingFile()); } + @NotNull @Override - public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); - PsiType type = expr != null ? expr.getType() : null; - return expr != null && type != null && CommonClassNames.JAVA_LANG_STRING.equals(type.getCanonicalText()); + protected String getHead() { + return "String.format("; + } + + @NotNull + @Override + protected String getTail() { + return ", );"; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java index 231a7a2cf10f..ff0ace20ab2b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java @@ -15,26 +15,22 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; +import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder; +import com.intellij.lang.surroundWith.Surrounder; import org.jetbrains.annotations.NotNull; -public class IfStatementPostfixTemplate extends BooleanPostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class IfStatementPostfixTemplate extends IfPostfixTemplateBase { public IfStatementPostfixTemplate() { - super("if", "if (expr)"); + super(JAVA_PSI_INFO, IS_BOOLEAN); } + @NotNull @Override - public void expand(@NotNull PsiElement context, @NotNull final Editor editor) { - PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); - assert expression != null; - TextRange range = PostfixTemplatesUtils.ifStatement(expression.getProject(), editor, expression); - if (range != null) { - editor.getCaretModel().moveToOffset(range.getStartOffset()); - } + protected Surrounder getSurrounder() { + return new JavaWithIfExpressionSurrounder(); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java index 1bb19448b1ea..2b00a06b5a0f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java @@ -19,7 +19,7 @@ import com.intellij.codeInsight.guess.GuessManager; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.PsiTypeLookupItem; import com.intellij.codeInsight.template.*; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; @@ -46,13 +46,13 @@ public class InstanceofExpressionPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(PostfixTemplatesUtils.getTopmostExpression(context)); + return JavaPostfixTemplatesUtils.isNotPrimitiveTypeExpression(JavaPostfixTemplatesUtils.getTopmostExpression(context)); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); - if (!PostfixTemplatesUtils.isNotPrimitiveTypeExpression(expression)) return; + PsiExpression expression = JavaPostfixTemplatesUtils.getTopmostExpression(context); + if (!JavaPostfixTemplatesUtils.isNotPrimitiveTypeExpression(expression)) return; surroundExpression(context.getProject(), editor, expression); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IsNullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IsNullCheckPostfixTemplate.java index 428935a7870b..26c510405b97 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IsNullCheckPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IsNullCheckPostfixTemplate.java @@ -15,11 +15,16 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder; +import com.intellij.lang.surroundWith.Surrounder; import org.jetbrains.annotations.NotNull; -public class IsNullCheckPostfixTemplate extends NullCheckPostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NOT_PRIMITIVE; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class IsNullCheckPostfixTemplate extends SurroundPostfixTemplateBase { public IsNullCheckPostfixTemplate() { - super("null", "if (expr == null)"); + super("null", "if (expr == null)", JAVA_PSI_INFO, IS_NOT_PRIMITIVE); } @NotNull @@ -27,4 +32,10 @@ public class IsNullCheckPostfixTemplate extends NullCheckPostfixTemplate { protected String getTail() { return "== null"; } + + @NotNull + @Override + protected Surrounder getSurrounder() { + return new JavaWithIfExpressionSurrounder(); + } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaStatementWrapPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaStatementWrapPostfixTemplate.java new file mode 100644 index 000000000000..b88a702fe31b --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaStatementWrapPostfixTemplate.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +public abstract class JavaStatementWrapPostfixTemplate extends StatementWrapPostfixTemplate { + + protected JavaStatementWrapPostfixTemplate(@NotNull String name, + @NotNull String descr, + @NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull Condition typeChecker) { + super(name, descr, psiInfo, typeChecker); + } + + @Override + protected void afterExpand(@NotNull PsiElement newElement, @NotNull Editor editor) { + super.afterExpand(newElement, editor); + JavaPostfixTemplateProvider.doNotDeleteSemicolon(newElement.getContainingFile()); + } + + @NotNull + @Override + protected String getTail() { + return ";"; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java index 29cfb22c02fa..55e53fe4126c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java @@ -16,7 +16,7 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.CodeInsightServicesUtil; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiExpression; @@ -26,7 +26,7 @@ public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithC private static final Condition BOOLEAN_TYPE_CONDITION = new Condition() { @Override public boolean value(PsiExpression expression) { - return PostfixTemplatesUtils.isBoolean(expression.getType()); + return JavaPostfixTemplatesUtils.isBoolean(expression.getType()); } }; diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java index 58a9ebf7a484..47a794518289 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java @@ -15,16 +15,21 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder; +import com.intellij.lang.surroundWith.Surrounder; import org.jetbrains.annotations.NotNull; -public class NotNullCheckPostfixTemplate extends NullCheckPostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NOT_PRIMITIVE; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class NotNullCheckPostfixTemplate extends SurroundPostfixTemplateBase { public NotNullCheckPostfixTemplate() { this("notnull"); } public NotNullCheckPostfixTemplate(String alias) { - super(alias, "if (expr != null)"); + super(alias, "if (expr != null)", JAVA_PSI_INFO, IS_NOT_PRIMITIVE); } @NotNull @@ -32,4 +37,10 @@ public class NotNullCheckPostfixTemplate extends NullCheckPostfixTemplate { protected String getTail() { return "!= null"; } + + @NotNull + @Override + protected Surrounder getSurrounder() { + return new JavaWithIfExpressionSurrounder(); + } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java deleted file mode 100644 index c77b2d527b54..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.codeInsight.template.postfix.templates; - -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementFactory; -import com.intellij.psi.PsiExpression; -import org.jetbrains.annotations.NotNull; - -/** - * @author ignatov - */ -public abstract class NullCheckPostfixTemplate extends PostfixTemplate { - protected NullCheckPostfixTemplate(@NotNull String name, @NotNull String example) { - super(name, example); - } - - @NotNull - abstract String getTail(); - - @Override - public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(PostfixTemplatesUtils.getTopmostExpression(context)); - } - - @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); - if (!PostfixTemplatesUtils.isNotPrimitiveTypeExpression(expr)) return; - - Project project = expr.getProject(); - PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); - PsiExpression condition = factory.createExpressionFromText(expr.getText() + getTail(), context); - - PsiElement replace = expr.replace(condition); - assert replace instanceof PsiExpression; - - TextRange range = PostfixTemplatesUtils.ifStatement(project, editor, (PsiExpression)replace); - if (range != null) { - editor.getCaretModel().moveToOffset(range.getStartOffset()); - } - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java index 21707353d31f..4f60680e788e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java @@ -15,18 +15,19 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Editor; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -public class ReturnStatementPostfixTemplate extends NonVoidPostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class ReturnStatementPostfixTemplate extends JavaStatementWrapPostfixTemplate { public ReturnStatementPostfixTemplate() { - super("return", "return expr;"); + super("return", "return expr;", JAVA_PSI_INFO, IS_NON_VOID); } + @NotNull @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PostfixTemplatesUtils.createSimpleStatement(context, editor, "return"); + protected String getHead() { + return "return "; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SoutPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SoutPostfixTemplate.java index b04d001402c9..149141840f5f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SoutPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SoutPostfixTemplate.java @@ -15,18 +15,25 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Editor; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -public class SoutPostfixTemplate extends NonVoidPostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class SoutPostfixTemplate extends JavaStatementWrapPostfixTemplate { public SoutPostfixTemplate() { - super("sout", "System.out.println(expr);"); + super("sout", "System.out.println(expr);", JAVA_PSI_INFO, IS_NON_VOID); } + @NotNull @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PostfixTemplatesUtils.createStatement(context, editor, "System.out.println(", ")"); + protected String getHead() { + return "System.out.println("; + } + + @NotNull + @Override + protected String getTail() { + return ");"; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java deleted file mode 100644 index 593e45f930d5..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.codeInsight.template.postfix.templates; - -import com.intellij.codeInsight.CodeInsightUtilCore; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.psi.util.PsiTreeUtil; - -/** - * @author ignatov - */ -public abstract class StatementPostfixTemplateBase extends PostfixTemplate { - protected StatementPostfixTemplateBase(String name, String example) { - super(name, example); - } - - protected void surroundWith(PsiElement context, Editor editor, String text) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); - PsiElement parent = expr != null ? expr.getParent() : null; - if (!(parent instanceof PsiExpressionStatement)) return; - - Project project = context.getProject(); - PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); - CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); - PsiElement statement = codeStyleManager.reformat(factory.createStatementFromText(text + " (" + expr.getText() + ") {\nst;\n}", context)); - statement = parent.replace(statement); - - //noinspection ConstantConditions - PsiCodeBlock block = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(PsiTreeUtil.getChildOfType(statement, PsiCodeBlock.class)); - TextRange range = block.getStatements()[0].getTextRange(); - editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset()); - - editor.getCaretModel().moveToOffset(range.getStartOffset()); - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java index e84aa8ed38fd..21122d0f0128 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java @@ -15,49 +15,65 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -public class SwitchStatementPostfixTemplate extends StatementPostfixTemplateBase { - public SwitchStatementPostfixTemplate() { - super("switch", "switch (expr)"); - } +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; - private static boolean isSwitchCompatibleType(@Nullable PsiType type, @NotNull PsiElement context) { - if (type == null) return false; - if (PsiType.INT.isAssignableFrom(type)) return true; - - if (type instanceof PsiClassType) { - PsiClass psiClass = ((PsiClassType)type).resolve(); - if (psiClass != null && psiClass.isEnum()) return true; - } - - if (type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) { - if (ApplicationManager.getApplication().isUnitTestMode()) return true; // todo: mock jdk 6 and 7 - PsiFile containingFile = context.getContainingFile(); - if (containingFile instanceof PsiJavaFile) { - LanguageLevel level = ((PsiJavaFile)containingFile).getLanguageLevel(); - if (level.isAtLeast(LanguageLevel.JDK_1_7)) return true; +public class SwitchStatementPostfixTemplate extends JavaStatementWrapPostfixTemplate { + private static final Condition SWITCH_TYPE = new Condition() { + @Override + public boolean value(PsiElement expression) { + if (!(expression instanceof PsiExpression)) { + return false; } + + PsiType type = ((PsiExpression)expression).getType(); + + if (type == null) return false; + if (PsiType.INT.isAssignableFrom(type)) return true; + + if (type instanceof PsiClassType) { + PsiClass psiClass = ((PsiClassType)type).resolve(); + if (psiClass != null && psiClass.isEnum()) return true; + } + + if (type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) { + if (ApplicationManager.getApplication().isUnitTestMode()) return true; // todo: mock jdk 6 and 7 + PsiFile containingFile = expression.getContainingFile(); + if (containingFile instanceof PsiJavaFile) { + LanguageLevel level = ((PsiJavaFile)containingFile).getLanguageLevel(); + if (level.isAtLeast(LanguageLevel.JDK_1_7)) return true; + } + } + + return false; } + }; - return false; + public SwitchStatementPostfixTemplate() { + super("switch", "switch (expr)", JAVA_PSI_INFO, SWITCH_TYPE); } @Override - public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); - return expr != null && isSwitchCompatibleType(expr.getType(), context); + protected void afterExpand(@NotNull PsiElement newStatement, @NotNull Editor editor) { + JavaPostfixTemplatesUtils.formatPsiCodeBlock(newStatement, editor); } + @NotNull @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - surroundWith(context, editor, "switch"); + protected String getHead() { + return "switch ("; + } + + @NotNull + @Override + protected String getTail() { + return ") {\nst;\n}"; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java index 2bf17b5fad5f..b2f6fd25ffe3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java @@ -15,29 +15,34 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Document; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiPrimitiveType; -import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; -public class SynchronizedStatementPostfixTemplate extends StatementPostfixTemplateBase { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NOT_PRIMITIVE; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class SynchronizedStatementPostfixTemplate extends JavaStatementWrapPostfixTemplate { public SynchronizedStatementPostfixTemplate() { - super("synchronized", "synchronized (expr)"); + super("synchronized", "synchronized (expr)", JAVA_PSI_INFO, IS_NOT_PRIMITIVE); } @Override - public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); - PsiType type = expression != null ? expression.getType() : null; - return type != null && !(type instanceof PsiPrimitiveType); + protected void afterExpand(@NotNull PsiElement newStatement, @NotNull Editor editor) { + JavaPostfixTemplatesUtils.formatPsiCodeBlock(newStatement, editor); } + @NotNull @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - surroundWith(context, editor, "synchronized"); + protected String getHead() { + return "synchronized ("; } + + @NotNull + @Override + protected String getTail() { + return ") {\nst;\n}"; + } + } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java index 98762cd5c0f7..b8dbd640d246 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java @@ -15,26 +15,17 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import org.jetbrains.annotations.NotNull; -public class ThrowExceptionPostfixTemplate extends PostfixTemplate { +public class ThrowExceptionPostfixTemplate extends JavaStatementWrapPostfixTemplate { public ThrowExceptionPostfixTemplate() { - super("throw", "throw expr;"); + super("throw", "throw expr;", JavaPostfixTemplatesUtils.JAVA_PSI_INFO, JavaPostfixTemplatesUtils.IS_THROWABLE); } + @NotNull @Override - public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); - return expression != null && PostfixTemplatesUtils.isThrowable(expression.getType()); - } - - @Override - public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PostfixTemplatesUtils.createSimpleStatement(context, editor, "throw"); + protected String getHead() { + return "throw "; } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryStatementPostfixTemplate.java index 9b890d6e473f..0c58e42e7430 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryStatementPostfixTemplate.java @@ -16,7 +16,6 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.generation.surroundWith.JavaWithTryCatchSurrounder; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java index 74a56c8da21a..b112eecc0457 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java @@ -22,7 +22,7 @@ import com.intellij.codeInsight.template.TemplateManager; import com.intellij.codeInsight.template.impl.MacroCallNode; import com.intellij.codeInsight.template.impl.TextExpression; import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -45,7 +45,7 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate { public boolean isApplicable(@NotNull PsiElement element, @NotNull Document copyDocument, int newOffset) { if (!PsiUtil.isLanguageLevel7OrHigher(element)) return false; - PsiExpression initializer = PostfixTemplatesUtils.getTopmostExpression(element); + PsiExpression initializer = JavaPostfixTemplatesUtils.getTopmostExpression(element); if (initializer == null) return false; @@ -62,7 +62,7 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); + PsiExpression expression = JavaPostfixTemplatesUtils.getTopmostExpression(context); assert expression != null; Project project = context.getProject(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java index 7ec46518e9f7..ba301df53591 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java @@ -15,19 +15,21 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; -public class WhileStatementPostfixTemplate extends BooleanPostfixTemplate { +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN; +import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; + +public class WhileStatementPostfixTemplate extends TypedPostfixTemplate { public WhileStatementPostfixTemplate() { - super("while", "while (expr)"); + super("while", "while (expr)", JAVA_PSI_INFO, IS_BOOLEAN); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); + PsiElement expression = myPsiInfo.getTopmostExpression(context); assert expression != null; PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject()); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java new file mode 100644 index 000000000000..3c035eced952 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java @@ -0,0 +1,177 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.util; + +import com.intellij.codeInsight.CodeInsightServicesUtil; +import com.intellij.codeInsight.CodeInsightUtilCore; +import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfo; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class JavaPostfixTemplatesUtils { + private JavaPostfixTemplatesUtils() { + } + + public static PostfixTemplatePsiInfo JAVA_PSI_INFO = new PostfixTemplatePsiInfo() { + + @NotNull + @Override + public PsiElement createStatement(@NotNull PsiElement context, + @NotNull String prefix, + @NotNull String suffix) { + return JavaPostfixTemplatesUtils.createStatement(context, prefix, suffix); + } + + @NotNull + @Override + public PsiElement createExpression(@NotNull PsiElement context, + @NotNull String prefix, + @NotNull String suffix) { + return JavaPostfixTemplatesUtils.createExpression(context, prefix, suffix); + } + + @Nullable + @Override + public PsiExpression getTopmostExpression(@NotNull PsiElement element) { + return JavaPostfixTemplatesUtils.getTopmostExpression(element); + } + + @NotNull + @Override + public PsiExpression getNegatedExpression(@NotNull PsiElement element) { + return CodeInsightServicesUtil.invertCondition((PsiExpression)element); + } + }; + + public static Condition IS_BOOLEAN = new Condition() { + @Override + public boolean value(PsiElement element) { + return element instanceof PsiExpression && isBoolean(((PsiExpression)element).getType()); + } + }; + + public static Condition IS_THROWABLE = new Condition() { + @Override + public boolean value(PsiElement element) { + return element instanceof PsiExpression && isThrowable((((PsiExpression)element).getType())); + } + }; + + public static Condition IS_NON_VOID = new Condition() { + @Override + public boolean value(PsiElement element) { + return element instanceof PsiExpression && isNonVoid((((PsiExpression)element).getType())); + } + }; + + public static Condition IS_NOT_PRIMITIVE = new Condition() { + @Override + public boolean value(PsiElement element) { + return element instanceof PsiExpression && isNotPrimitiveTypeExpression(((PsiExpression)element)); + } + }; + + public static PsiElement createStatement(@NotNull PsiElement context, + @NotNull String prefix, + @NotNull String suffix) { + PsiExpression expr = getTopmostExpression(context); + PsiElement parent = expr != null ? expr.getParent() : null; + assert parent instanceof PsiStatement; + PsiElementFactory factory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory(); + return factory.createStatementFromText(prefix + expr.getText() + suffix, expr); + } + + public static PsiElement createExpression(@NotNull PsiElement context, + @NotNull String prefix, + @NotNull String suffix) { + PsiExpression expr = getTopmostExpression(context); + PsiElement parent = expr != null ? expr.getParent() : null; + assert parent instanceof PsiStatement; + PsiElementFactory factory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory(); + return factory.createExpressionFromText(prefix + expr.getText() + suffix, expr); + } + + @Contract("null -> false") + public static boolean isNotPrimitiveTypeExpression(@Nullable PsiExpression expression) { + return expression != null && !(expression.getType() instanceof PsiPrimitiveType); + } + + @Contract("null -> false") + public static boolean isIterable(@Nullable PsiType type) { + return type != null && InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ITERABLE); + } + + @Contract("null -> false") + public static boolean isThrowable(@Nullable PsiType type) { + return type != null && InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_THROWABLE); + } + + @Contract("null -> false") + public static boolean isArray(@Nullable PsiType type) { + return type != null && type instanceof PsiArrayType; + } + + @Contract("null -> false") + public static boolean isBoolean(@Nullable PsiType type) { + return type != null && (PsiType.BOOLEAN.equals(type) || PsiType.BOOLEAN.equals(PsiPrimitiveType.getUnboxedType(type))); + } + + @Contract("null -> false") + public static boolean isNonVoid(@Nullable PsiType type) { + return type != null && !PsiType.VOID.equals(type); + } + + @Contract("null -> false") + public static boolean isNumber(@Nullable PsiType type) { + if (type == null) { + return false; + } + if (PsiType.INT.equals(type) || PsiType.BYTE.equals(type) || PsiType.LONG.equals(type)) { + return true; + } + + PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type); + return PsiType.INT.equals(unboxedType) || PsiType.BYTE.equals(unboxedType) || PsiType.LONG.equals(unboxedType); + } + + @Nullable + public static PsiExpression getTopmostExpression(PsiElement context) { + PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class); + return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null; + } + + public static void formatPsiCodeBlock(PsiElement newStatement, Editor editor) { + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(newStatement.getProject()); + PsiElement statement = newStatement.replace(codeStyleManager.reformat(newStatement)); + + PsiCodeBlock type = PsiTreeUtil.getChildOfType(statement, PsiCodeBlock.class); + assert type != null; + PsiCodeBlock block = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(type); + TextRange range = block.getStatements()[0].getTextRange(); + editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset()); + + editor.getCaretModel().moveToOffset(range.getStartOffset()); + } +} + diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java deleted file mode 100644 index 62c10fee29a3..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.codeInsight.template.postfix.util; - -import com.intellij.codeInsight.generation.surroundWith.JavaExpressionSurrounder; -import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder; -import com.intellij.codeInsight.template.postfix.templates.JavaPostfixTemplateProvider; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; -import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public abstract class PostfixTemplatesUtils { - private PostfixTemplatesUtils() { - } - - public static void showErrorHint(Project project, Editor editor) { - CommonRefactoringUtil.showErrorHint(project, editor, "Can't expand postfix template", "Can't expand postfix template", ""); - } - - public static void createSimpleStatement(@NotNull PsiElement context, @NotNull Editor editor, @NotNull String text) { - createStatement(context, editor, text + " ", ""); - } - - public static void createStatement(@NotNull PsiElement context, @NotNull Editor editor, @NotNull String prefix, @NotNull String suffix) { - createStatement(context, editor, prefix, suffix, 0); - } - - public static void createStatement(@NotNull PsiElement context, @NotNull Editor editor, @NotNull String prefix, @NotNull String suffix, int offset) { - PsiExpression expr = getTopmostExpression(context); - PsiElement parent = expr != null ? expr.getParent() : null; - assert parent instanceof PsiStatement; - PsiElementFactory factory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory(); - PsiStatement statement = factory.createStatementFromText(prefix + expr.getText() + suffix + ";", parent); - PsiElement replace = parent.replace(statement); - editor.getCaretModel().moveToOffset(replace.getTextRange().getEndOffset() + offset); - JavaPostfixTemplateProvider.doNotDeleteSemicolon(replace.getContainingFile()); - } - - @Contract("null -> false") - public static boolean isNotPrimitiveTypeExpression(@Nullable PsiExpression expression) { - return expression != null && !(expression.getType() instanceof PsiPrimitiveType); - } - - @Contract("null -> false") - public static boolean isIterable(@Nullable PsiType type) { - return type != null && InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ITERABLE); - } - - @Contract("null -> false") - public static boolean isThrowable(@Nullable PsiType type) { - return type != null && InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_THROWABLE); - } - - @Contract("null -> false") - public static boolean isArray(@Nullable PsiType type) { - return type != null && type instanceof PsiArrayType; - } - - @Contract("null -> false") - public static boolean isBoolean(@Nullable PsiType type) { - return type != null && (PsiType.BOOLEAN.equals(type) || PsiType.BOOLEAN.equals(PsiPrimitiveType.getUnboxedType(type))); - } - - @Contract("null -> false") - public static boolean isNonVoid(@Nullable PsiType type) { - return type != null && !PsiType.VOID.equals(type); - } - - @Contract("null -> false") - public static boolean isNumber(@Nullable PsiType type) { - if (type == null) { - return false; - } - if (PsiType.INT.equals(type) || PsiType.BYTE.equals(type) || PsiType.LONG.equals(type)) { - return true; - } - - PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type); - return PsiType.INT.equals(unboxedType) || PsiType.BYTE.equals(unboxedType) || PsiType.LONG.equals(unboxedType); - } - - @Nullable - public static TextRange ifStatement(@NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) { - JavaExpressionSurrounder surrounder = new JavaWithIfExpressionSurrounder(); - PsiElement[] elements = {expr}; - if (surrounder.isApplicable(elements)) { - return surrounder.surroundElements(project, editor, elements); - } - else { - showErrorHint(project, editor); - } - return null; - } - - @Nullable - public static TextRange apply(@NotNull JavaExpressionSurrounder surrounder, @NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) { - PsiElement[] elements = {expr}; - if (surrounder.isApplicable(elements)) { - return surrounder.surroundElements(project, editor, elements); - } - else { - showErrorHint(project, editor); - } - return null; - } - - @Nullable - public static PsiExpression getTopmostExpression(PsiElement context) { - PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class); - return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null; - } -} - diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocHelper.java b/java/java-impl/src/com/intellij/javadoc/JavadocHelper.java index 38a51e1f10f0..88cda8ed89ef 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavadocHelper.java +++ b/java/java-impl/src/com/intellij/javadoc/JavadocHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -17,7 +17,10 @@ package com.intellij.javadoc; import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.CaretModel; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; @@ -183,7 +186,7 @@ public class JavadocHelper { result.add(info); } - return new Pair>(anchorInfo, result); + return Pair.create(anchorInfo, result); } @Nullable diff --git a/java/java-impl/src/com/intellij/packageDependencies/ui/TreeModelBuilder.java b/java/java-impl/src/com/intellij/packageDependencies/ui/TreeModelBuilder.java index 4b1de571c01d..7b5ebd05393f 100644 --- a/java/java-impl/src/com/intellij/packageDependencies/ui/TreeModelBuilder.java +++ b/java/java-impl/src/com/intellij/packageDependencies/ui/TreeModelBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -339,7 +339,7 @@ public class TreeModelBuilder { return getModuleDirNode(aPackage, null, ScopeType.LIB); } - Pair descriptor = new Pair(myShowIndividualLibs ? libraryOrJdk : null, aPackage); + Pair descriptor = Pair.create(myShowIndividualLibs ? libraryOrJdk : null, aPackage); PackageNode node = getMap(myLibraryPackageNodes, ScopeType.LIB).get(descriptor); if (node != null) return node; @@ -361,7 +361,7 @@ public class TreeModelBuilder { return getModuleNode(module, scopeType); } - Pair descriptor = new Pair(myShowModules ? module : null, aPackage); + Pair descriptor = Pair.create(myShowModules ? module : null, aPackage); PackageNode node = getMap(myModulePackageNodes, scopeType).get(descriptor); if (node != null) return node; diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 391a8fd86d8c..b76aeaa4b3fd 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -1649,7 +1649,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { IElementType type1 = token1.getElementType(); IElementType type2 = token2.getElementType(); - Pair pair = new Pair(type1, type2); + Pair pair = Pair.create(type1, type2); Boolean res = myCanStickJavaTokensMatrix.get(pair); if (res == null) { if (!checkToken(token1) || !checkToken(token2)) return true; diff --git a/java/java-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java deleted file mode 100644 index ca9d77d0f6b0..000000000000 --- a/java/java-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2000-2011 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.intellij.psi.impl.file.impl; - -import com.intellij.ide.startup.StartupManagerEx; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.startup.StartupManager; -import com.intellij.psi.impl.PsiManagerEx; -import com.intellij.util.messages.MessageBus; - -/** - * @author max - */ -public class JavaFileManagerImpl extends JavaFileManagerBase { - - public JavaFileManagerImpl(final PsiManagerEx manager, final ProjectRootManager projectRootManager, MessageBus bus, - final StartupManager startupManager) { - super(manager, projectRootManager, bus); - - if (!((StartupManagerEx)startupManager).startupActivityPassed() && - !ApplicationManager.getApplication().isUnitTestMode() && - !manager.getProject().isDefault()) { - Logger.getInstance("#com.intellij.psi.impl.file.impl.JavaFileManagerImpl") - .error("Access to psi files should be performed only after startup activity"); - } - } -} diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java index 05e359137e72..b424af918851 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -302,7 +302,7 @@ public class JDParser { result.add(new Pair(sb.toString(), false)); sb.setLength(0); } - result.add(new Pair(s1, marks[i])); + result.add(Pair.create(s1, marks[i])); } else { if (s1.isEmpty()) { @@ -310,10 +310,10 @@ public class JDParser { result.add(new Pair(sb.toString(), false)); sb.setLength(0); } - result.add(new Pair("", marks[i])); + result.add(Pair.create("", marks[i])); } else if (mySettings.JD_PRESERVE_LINE_FEEDS) { - result.add(new Pair(s1, marks[i])); + result.add(Pair.create(s1, marks[i])); } else { if (sb.length() != 0) sb.append(' '); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/CompletionParameterTypeInferencePolicy.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/CompletionParameterTypeInferencePolicy.java index 7be5fdd38805..f06f2082d3be 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/CompletionParameterTypeInferencePolicy.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/CompletionParameterTypeInferencePolicy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -44,7 +44,7 @@ public class CompletionParameterTypeInferencePolicy extends ProcessCandidatePara return new Pair(PsiWildcardType.createExtends(psiManager, superType), ConstraintType.EQUALS); } else { - return new Pair(superType, ConstraintType.SUBTYPE); + return Pair.create(superType, ConstraintType.SUBTYPE); } } diff --git a/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceHandler.java b/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceHandler.java index e14173504618..1de742dbd55f 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceHandler.java @@ -142,8 +142,8 @@ public class ExtractInterfaceHandler implements RefactoringActionHandler, Elemen DocCommentPolicy javaDocPolicy) throws IncorrectOperationException { aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringStarted(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createBeforeData(aClass, selectedMembers)); + final PsiClass anInterface = JavaDirectoryService.getInstance().createInterface(targetDir, interfaceName); try { - PsiClass anInterface = JavaDirectoryService.getInstance().createInterface(targetDir, interfaceName); PsiJavaCodeReferenceElement ref = ExtractSuperClassUtil.createExtendingReference(anInterface, aClass, selectedMembers); final PsiReferenceList referenceList = aClass.isInterface() ? aClass.getExtendsList() : aClass.getImplementsList(); assert referenceList != null; @@ -154,7 +154,7 @@ public class ExtractInterfaceHandler implements RefactoringActionHandler, Elemen } finally { aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) - .refactoringDone(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createAfterData(aClass)); + .refactoringDone(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createAfterData(anInterface)); } } diff --git a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperClassUtil.java b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperClassUtil.java index 11815b222c82..8812398b4f75 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperClassUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperClassUtil.java @@ -70,8 +70,8 @@ public class ExtractSuperClassUtil { project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringStarted(REFACTORING_EXTRACT_SUPER_ID, createBeforeData(subclass, selectedMemberInfos)); + final PsiClass superclass = JavaDirectoryService.getInstance().createClass(targetDirectory, superclassName); try { - PsiClass superclass = JavaDirectoryService.getInstance().createClass(targetDirectory, superclassName); final PsiModifierList superClassModifierList = superclass.getModifierList(); assert superClassModifierList != null; superClassModifierList.setModifierProperty(PsiModifier.FINAL, false); @@ -115,7 +115,7 @@ public class ExtractSuperClassUtil { return superclass; } finally { - project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_EXTRACT_SUPER_ID, createAfterData(subclass)); + project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_EXTRACT_SUPER_ID, createAfterData(superclass)); } } diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousConstructorProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousConstructorProcessor.java index 97ce0591f8ed..3be6e594b5e0 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousConstructorProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousConstructorProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -365,7 +365,7 @@ class InlineToAnonymousConstructorProcessor { super.visitReferenceExpression(expression); final PsiElement psiElement = expression.resolve(); if (psiElement instanceof PsiParameter) { - parameterReferences.add(new Pair(expression, (PsiParameter) psiElement)); + parameterReferences.add(Pair.create(expression, (PsiParameter)psiElement)); } else if ((psiElement instanceof PsiField || psiElement instanceof PsiMethod) && ((PsiMember) psiElement).getContainingClass() == myClass.getSuperClass()) { diff --git a/java/java-impl/src/com/intellij/refactoring/move/MoveInstanceMembersUtil.java b/java/java-impl/src/com/intellij/refactoring/move/MoveInstanceMembersUtil.java index f74c8c79f2d1..571710723547 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/MoveInstanceMembersUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/move/MoveInstanceMembersUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -102,7 +102,7 @@ public class MoveInstanceMembersUtil { final PsiElement resolved = ((PsiReferenceExpression)expression).resolve(); if (resolved instanceof PsiMember && !((PsiMember)resolved).hasModifierProperty(PsiModifier.STATIC)) { PsiClass referencedClass = getReferencedClass((PsiMember)resolved, qualifier, expression); - return new Pair((PsiMember)resolved, referencedClass); + return Pair.create((PsiMember)resolved, referencedClass); } } } else if (expression instanceof PsiNewExpression) { diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaClassProcessor.java index 3a4526101285..e8590261677a 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaClassProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaClassProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -141,7 +141,7 @@ public class RenameJavaClassProcessor extends RenamePsiElementProcessor { final String dollaredStringToSearch = ClassUtil.getJVMClassName(aClass); final String dollaredStringToReplace = dollaredStringToSearch == null ? null : RefactoringUtil.getNewInnerClassName(aClass, dollaredStringToSearch, newName); if (dollaredStringToReplace != null) { - return new Pair(dollaredStringToSearch, dollaredStringToReplace); + return Pair.create(dollaredStringToSearch, dollaredStringToReplace); } } } diff --git a/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/BindingFactory.java b/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/BindingFactory.java index 14f334e829f2..49525a67de44 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/BindingFactory.java +++ b/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/BindingFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -1022,7 +1022,7 @@ public class BindingFactory { return; } - list.addFirst(new Pair(risen.apply(x), risen)); + list.addFirst(Pair.create(risen.apply(x), risen)); } else { final PsiClass[] descendants = getGreatestLowerClasses(xClass, yClass); @@ -1097,11 +1097,11 @@ public class BindingFactory { if (risen == null) { final PsiElementFactory factory = JavaPsiFacade.getInstance(xClass.getProject()).getElementFactory(); - list.addFirst(new Pair(Util.banalize(factory.createType(xClass, factory.createRawSubstitutor(xClass))), - create())); + list.addFirst(Pair.create(Util.banalize(factory.createType(xClass, factory.createRawSubstitutor(xClass))), + create())); } else { - list.addFirst(new Pair(risen.apply(x), risen)); + list.addFirst(Pair.create(risen.apply(x), risen)); } } else { diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeEvaluator.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeEvaluator.java index 105c383f478c..1435dc1f2271 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeEvaluator.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -379,7 +379,7 @@ public class TypeEvaluator { final LinkedList types = myTypeMap.get(usageInfo); final PsiElement element = usageInfo.getElement(); if (element instanceof PsiVariable || element instanceof PsiMethod) { - list.addLast(new Pair(usageInfo, types.getFirst())); + list.addLast(Pair.create(usageInfo, types.getFirst())); } } diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java index 0542ff298dc6..274fbd52f621 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -236,7 +236,7 @@ public class TypeMigrationLabeler { isCovariantPosition, this); if (conversion == null) { - markFailedConversion(new Pair(fromType, toType), expr); + markFailedConversion(Pair.create(fromType, toType), expr); } else { setConversionMapping(expr, conversion); @@ -250,7 +250,7 @@ public class TypeMigrationLabeler { if (originalType.equals(PsiType.NULL)) { if (migrationType instanceof PsiPrimitiveType) { - markFailedConversion(new Pair(originalType, migrationType), expr); + markFailedConversion(Pair.create(originalType, migrationType), expr); } return; } @@ -259,7 +259,7 @@ public class TypeMigrationLabeler { } else if (expr instanceof PsiClassObjectAccessExpression) { if (!TypeConversionUtil.isAssignable(migrationType, expr.getType())) { - markFailedConversion(new Pair(expr.getType(), migrationType), expr); + markFailedConversion(Pair.create(expr.getType(), migrationType), expr); return; } } else if (expr instanceof PsiArrayInitializerExpression && migrationType instanceof PsiArrayType) { @@ -306,7 +306,7 @@ public class TypeMigrationLabeler { } if (isGenericsArrayType(elemenType)){ - markFailedConversion(new Pair(originalType, migrationType), expr); + markFailedConversion(Pair.create(originalType, migrationType), expr); return; } @@ -502,7 +502,7 @@ public class TypeMigrationLabeler { alreadyProcessed = true; } - if (!alreadyProcessed) myMigrationRoots.addFirst(new Pair(usageInfo, type)); + if (!alreadyProcessed) myMigrationRoots.addFirst(Pair.create(usageInfo, type)); return alreadyProcessed; } @@ -544,7 +544,7 @@ public class TypeMigrationLabeler { void markFailedConversion(final Pair typePair, final PsiExpression expression) { LOG.assertTrue(typePair.getSecond() != null); - myFailedConversions.add(new Pair(PsiAnchor.create(expression), typePair.getSecond())); + myFailedConversions.add(Pair.create(PsiAnchor.create(expression), typePair.getSecond())); } void setConversionMapping(final PsiExpression expression, final Object obj) { @@ -657,7 +657,7 @@ public class TypeMigrationLabeler { if (argumentList != null) { final PsiExpression[] expressions = argumentList.getExpressions(); if (checkNumberOfArguments && parametersCount != expressions.length) { - markFailedConversion(new Pair(param.getType(), migrationType), (PsiCallExpression)parent); + markFailedConversion(Pair.create(param.getType(), migrationType), (PsiCallExpression)parent); } if (index > -1 && index < expressions.length) { for (int idx = index; idx < (param.isVarArgs() ? expressions.length : index + 1); idx++) { diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java index d151bf324b71..f3574536c2eb 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -146,7 +146,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { final PsiType migrationType = myTypeEvaluator.evaluateType(consideredExpression); final PsiType fixedType = typeElement.getType(); if (migrationType != null && !TypeConversionUtil.isAssignable(migrationType, fixedType)) { - myLabeler.markFailedConversion(new Pair(fixedType, migrationType), consideredExpression); + myLabeler.markFailedConversion(Pair.create(fixedType, migrationType), consideredExpression); } } } @@ -159,7 +159,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { final PsiType fixedType = typeElement.getType(); final PsiType migrationType = myTypeEvaluator.evaluateType(expression.getOperand()); if (migrationType != null && !TypeConversionUtil.areTypesConvertible(migrationType, fixedType)) { - myLabeler.markFailedConversion(new Pair(fixedType, migrationType), expression); + myLabeler.markFailedConversion(Pair.create(fixedType, migrationType), expression); } } } @@ -189,7 +189,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { if (returnType != null && valueType != null) { if (!myLabeler.addMigrationRoot(method, valueType, myStatement, TypeConversionUtil.isAssignable(returnType, valueType), true) && TypeMigrationLabeler.typeContainsTypeParameters(returnType)) { - myLabeler.markFailedConversion(new Pair(returnType, valueType), value); + myLabeler.markFailedConversion(Pair.create(returnType, valueType), value); } } } @@ -393,7 +393,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { final PsiType type = typeView.getType(); if (migrationType == null || !TypeConversionUtil.isAssignable(migrationType, type)) { if (migrationType != null && !TypeConversionUtil.isAssignable(type, migrationType)) { - myLabeler.markFailedConversion(new Pair(parentExpression.getType(), type), parentExpression); + myLabeler.markFailedConversion(Pair.create(parentExpression.getType(), type), parentExpression); return; } migrationType = type; @@ -410,7 +410,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { private void checkIndexExpression(final PsiExpression indexExpression) { final PsiType indexType = myTypeEvaluator.evaluateType(indexExpression); if (indexType != null && !TypeConversionUtil.isAssignable(PsiType.INT, indexType)) { - myLabeler.markFailedConversion(new Pair(indexExpression.getType(), indexType), indexExpression); + myLabeler.markFailedConversion(Pair.create(indexExpression.getType(), indexType), indexExpression); } } @@ -535,7 +535,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { } public Pair getTypePair() { - return new Pair(myOriginType, myType); + return Pair.create(myOriginType, myType); } } diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java index 5fb9e504c1bf..888c05d932a5 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -1069,7 +1069,7 @@ public class RefactoringUtil { if (!found) { for (PsiDocTag paramTag : paramTags) { final String paramName = getNameOfReferencedParameter(paramTag); - if (eqCondition.value(new Pair(parameter, paramName))) { + if (eqCondition.value(Pair.create(parameter, paramName))) { tagForParam.put(parameter, paramTag); found = true; break; diff --git a/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java b/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java index f7051258941c..5bf07904d7fe 100644 --- a/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java +++ b/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -60,7 +60,7 @@ public class JavaTestFinder implements TestFinder { for (Pair eachNameWithWeight : TestFinderHelper.collectPossibleClassNamesWithWeights(klass.getName())) { for (PsiClass eachClass : cache.getClassesByName(eachNameWithWeight.first, scope)) { if (isTestSubjectClass(eachClass)) { - classesWithWeights.add(new Pair(eachClass, eachNameWithWeight.second)); + classesWithWeights.add(Pair.create(eachClass, eachNameWithWeight.second)); } } } @@ -104,7 +104,7 @@ public class JavaTestFinder implements TestFinder { for (PsiClass eachClass : cache.getClassesByName(eachName, scope)) { if (frameworks.isTestClass(eachClass) || frameworks.isPotentialTestClass(eachClass)) { classesWithProximities.add( - new Pair(eachClass, TestFinderHelper.calcTestNameProximity(klassName, eachName))); + Pair.create(eachClass, TestFinderHelper.calcTestNameProximity(klassName, eachName))); } } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java b/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java similarity index 89% rename from java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java rename to java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java index b41b36311a2a..d8c5d1c88b10 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java @@ -19,6 +19,7 @@ import com.intellij.ProjectTopics; import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; @@ -32,8 +33,6 @@ import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.Query; import com.intellij.util.containers.ConcurrentHashMap; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.messages.MessageBus; -import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; @@ -43,24 +42,18 @@ import java.util.*; /** * Author: dmitrylomov */ -public abstract class JavaFileManagerBase implements JavaFileManager, Disposable { +public class JavaFileManagerImpl implements JavaFileManager, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.file.impl.JavaFileManagerImpl"); private final ConcurrentHashMap myCachedObjectClassMap = new ConcurrentHashMap(); private final PsiManagerEx myManager; - private final ProjectRootManager myProjectRootManager; private volatile Set myNontrivialPackagePrefixes = null; private boolean myDisposed = false; private final PackageIndex myPackageIndex; - protected final MessageBusConnection myConnection; - public JavaFileManagerBase( - final PsiManagerEx manager, final ProjectRootManager projectRootManager, - final MessageBus bus) { - myManager = manager; - myProjectRootManager = projectRootManager; + public JavaFileManagerImpl(Project project) { + myManager = (PsiManagerEx)PsiManager.getInstance(project); myPackageIndex = PackageIndex.getInstance(myManager.getProject()); - myConnection = bus.connect(); - myConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() { + project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() { @Override public void rootsChanged(final ModuleRootEvent event) { myNontrivialPackagePrefixes = null; @@ -201,9 +194,10 @@ public abstract class JavaFileManagerBase implements JavaFileManager, Disposable @Override public Collection getNonTrivialPackagePrefixes() { - if (myNontrivialPackagePrefixes == null) { - Set names = new HashSet(); - final ProjectRootManager rootManager = myProjectRootManager; + Set names = myNontrivialPackagePrefixes; + if (names == null) { + names = new HashSet(); + final ProjectRootManager rootManager = ProjectRootManager.getInstance(myManager.getProject()); final List sourceRoots = rootManager.getModuleSourceRoots(JavaModuleSourceRootTypes.SOURCES); final ProjectFileIndex fileIndex = rootManager.getFileIndex(); for (final VirtualFile sourceRoot : sourceRoots) { @@ -214,7 +208,7 @@ public abstract class JavaFileManagerBase implements JavaFileManager, Disposable } myNontrivialPackagePrefixes = names; } - return myNontrivialPackagePrefixes; + return names; } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java index d855ab6f14db..35ec8b2800e7 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -66,13 +66,13 @@ public class JavaAllOverridingMethodsSearcher implements QueryExecutor(method, inInheritor))) return false; + if (!consumer.process(Pair.create(method, inInheritor))) return false; } } } continue; } - if (!consumer.process(new Pair(method, inInheritor))) return false; + if (!consumer.process(Pair.create(method, inInheritor))) return false; } return true; diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java index 577d38a30a15..351cb8f75c82 100644 --- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -154,7 +154,7 @@ public class GenericsUtil { PsiManager manager, PsiClass nestedLayer, PsiTypeParameter parameter) { - Pair types = new Pair(type1, type2); + Pair types = Pair.create(type1, type2); if (compared.contains(types)) { if (nestedLayer != null) { PsiSubstitutor subst = PsiSubstitutor.EMPTY; diff --git a/java/java-psi-api/src/com/intellij/psi/impl/source/resolve/DefaultParameterTypeInferencePolicy.java b/java/java-psi-api/src/com/intellij/psi/impl/source/resolve/DefaultParameterTypeInferencePolicy.java index aeb83e4f4cd4..e0920f62cd00 100644 --- a/java/java-psi-api/src/com/intellij/psi/impl/source/resolve/DefaultParameterTypeInferencePolicy.java +++ b/java/java-psi-api/src/com/intellij/psi/impl/source/resolve/DefaultParameterTypeInferencePolicy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -41,7 +41,7 @@ public class DefaultParameterTypeInferencePolicy extends ParameterTypeInferenceP @Override public Pair getInferredTypeWithNoConstraint(PsiManager manager, PsiType superType) { - return new Pair(superType, ConstraintType.SUBTYPE); + return Pair.create(superType, ConstraintType.SUBTYPE); } @Override diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index a2f1dc9c0daa..d2bd655bb23f 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -123,7 +123,7 @@ public class JavaDocInfoGenerator { elements = rawElements; } - return new Pair>(elements, mapProvider(pair.second, dropFirst)); + return Pair.create(elements, mapProvider(pair.second, dropFirst)); } @Override @@ -1481,7 +1481,7 @@ public class JavaDocInfoGenerator { String tagName = value.getText(); if (tagName != null && areWeakEqual(tagName, paramName)) { - parmTag = new Pair>(localTag, ourEmptyProvider); + parmTag = Pair.create(localTag, ourEmptyProvider); break; } } @@ -1498,7 +1498,7 @@ public class JavaDocInfoGenerator { try { final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); final PsiDocTag tag = elementFactory.createDocTagFromText("@exception " + paramName); - collectedTags.addLast(new Pair>(tag, ourEmptyProvider)); + collectedTags.addLast(Pair.create(tag, ourEmptyProvider)); } catch (IncorrectOperationException e) { LOG.error(e); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 3f4cea44d90a..748d907aec47 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -925,7 +925,7 @@ public class PsiClassImplUtil { final PsiMethod[] methodsByName = psiClass.findMethodsByName(name, false); final List> ret = new ArrayList>(methodsByName.length); for (final PsiMethod method : methodsByName) { - ret.add(new Pair(method, PsiSubstitutor.EMPTY)); + ret.add(Pair.create(method, PsiSubstitutor.EMPTY)); } return ret; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index f4f9e881d4ba..d70fa1f4be4b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -184,7 +184,7 @@ public class PsiSuperMethodImplUtil { // methods must be inherited from unrelated classes, so flatten hierarchy here // class C implements SAM1, SAM2 { void methodimpl() {} } //hms.getSuperSignatures().remove(aSuper); - flattened.add(new Pair(signature, aSuper)); + flattened.add(Pair.create(signature, aSuper)); } } putInMap(aClass, result, map, hms, signature); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiOldInferenceHelper.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiOldInferenceHelper.java index cc40582facb2..84e3b27dd60a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiOldInferenceHelper.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiOldInferenceHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -157,7 +157,7 @@ public class PsiOldInferenceHelper implements PsiInferenceHelper { } if (rawInference != null) return rawInference; - if (lowerBound != PsiType.NULL) return new Pair(lowerBound, ConstraintType.EQUALS); + if (lowerBound != PsiType.NULL) return Pair.create(lowerBound, ConstraintType.EQUALS); if (parent != null) { final Pair constraint = @@ -168,14 +168,14 @@ public class PsiOldInferenceHelper implements PsiInferenceHelper { } if (upperBound != PsiType.NULL) { - return new Pair(upperBound, ConstraintType.SUBTYPE); + return Pair.create(upperBound, ConstraintType.SUBTYPE); } return constraint; } } - if (upperBound != PsiType.NULL) return new Pair(upperBound, ConstraintType.SUBTYPE); + if (upperBound != PsiType.NULL) return Pair.create(upperBound, ConstraintType.SUBTYPE); return null; } @@ -403,7 +403,7 @@ public class PsiOldInferenceHelper implements PsiInferenceHelper { final boolean captureWildcard) { if (arg instanceof PsiWildcardType && !captureWildcard) return FAILED_INFERENCE; if (arg != PsiType.NULL) { - return new Pair(arg, constraintType); + return Pair.create(arg, constraintType); } return null; } @@ -460,7 +460,7 @@ public class PsiOldInferenceHelper implements PsiInferenceHelper { arg instanceof PsiIntersectionType || (psiClass != null && (isContraVariantPosition || !CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName()) || (arg instanceof PsiArrayType)))) { PsiType bound = intersectAllExtends(typeParam, arg); - return new Pair(bound, ConstraintType.SUPERTYPE); + return Pair.create(bound, ConstraintType.SUPERTYPE); } if (psiClass == null && arg instanceof PsiClassType) { return Pair.create(arg, ConstraintType.EQUALS); @@ -651,8 +651,8 @@ public class PsiOldInferenceHelper implements PsiInferenceHelper { } } - if (lowerBound != PsiType.NULL) return new Pair(lowerBound, ConstraintType.SUPERTYPE); - if (upperBound != PsiType.NULL) return new Pair(upperBound, ConstraintType.SUBTYPE); + if (lowerBound != PsiType.NULL) return Pair.create(lowerBound, ConstraintType.SUPERTYPE); + if (upperBound != PsiType.NULL) return Pair.create(upperBound, ConstraintType.SUBTYPE); return wildcardCaptured; } @@ -787,6 +787,6 @@ public class PsiOldInferenceHelper implements PsiInferenceHelper { } } - return new Pair(guess, constraint.getSecond()); + return Pair.create(guess, constraint.getSecond()); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticOverloading.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticOverloading.java new file mode 100644 index 000000000000..9d0f9dd30271 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticOverloading.java @@ -0,0 +1,8 @@ +interface StaticBase { + static void foo(T t) {} +} + +class Foo implements StaticBase { + static void foo(T t){} +} + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java index dfc6a7317641..95b3bfb7395d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java @@ -39,6 +39,7 @@ public class Interface8MethodsHighlightingTest extends LightCodeInsightFixtureTe public void testFinalStaticDefaultMethods() { doTest(false, false); } public void testIDEA122720() { doTest(false, false); } public void testIDEA123839() { doTest(false, false); } + public void testStaticOverloading() { doTest(false, false); } public void testDefaultSupersInStaticContext() { doTest(false, false); } diff --git a/java/java-tests/testSrc/com/intellij/psi/CodeFragmentsTest.java b/java/java-tests/testSrc/com/intellij/psi/CodeFragmentsTest.java index 6c68160bd5f8..8f6956808dea 100644 --- a/java/java-tests/testSrc/com/intellij/psi/CodeFragmentsTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/CodeFragmentsTest.java @@ -1,6 +1,8 @@ package com.intellij.psi; +import com.intellij.openapi.editor.Document; import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.PsiTestCase; import com.intellij.psi.search.GlobalSearchScope; @@ -13,4 +15,19 @@ public class CodeFragmentsTest extends PsiTestCase{ ref.bindToElement(arrayListClass); assertEquals("ArrayList.foo()", fragment.getText()); } + + public void testDontLoseDocument() { + PsiExpressionCodeFragment fragment = JavaCodeFragmentFactory.getInstance(myProject).createExpressionCodeFragment("a", null, null, true); + Document document = PsiDocumentManager.getInstance(myProject).getDocument(fragment); + document.insertString(1, "b"); + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + assertEquals("ab", fragment.getText()); + assertEquals("ab", fragment.getExpression().getText()); + + //noinspection UnusedAssignment + document = null; + + PlatformTestUtil.tryGcSoftlyReachableObjects(); + assertEquals("ab", PsiDocumentManager.getInstance(myProject).getDocument(fragment).getText()); + } } diff --git a/java/openapi/src/com/intellij/util/xml/converters/values/GenericDomValueConvertersRegistry.java b/java/openapi/src/com/intellij/util/xml/converters/values/GenericDomValueConvertersRegistry.java index 34fb74d5b951..064a306fe6ba 100644 --- a/java/openapi/src/com/intellij/util/xml/converters/values/GenericDomValueConvertersRegistry.java +++ b/java/openapi/src/com/intellij/util/xml/converters/values/GenericDomValueConvertersRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -113,7 +113,7 @@ public class GenericDomValueConvertersRegistry { @Nullable public Converter getConverter(@NotNull GenericDomValue domValue, @Nullable PsiType type) { - final Pair pair = new Pair(type, domValue); + final Pair pair = Pair.create(type, domValue); for (@NotNull Condition> condition : myConditionConverters.keySet()) { if (condition.value(pair)) { return myConditionConverters.get(condition); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java index 98dffabc70e6..03dddda7183f 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -24,7 +24,9 @@ import org.jetbrains.asm4.signature.SignatureReader; import org.jetbrains.asm4.signature.SignatureVisitor; import java.lang.annotation.RetentionPolicy; -import java.util.*; +import java.util.EnumSet; +import java.util.Map; +import java.util.Set; /** * @author: db @@ -334,7 +336,7 @@ class ClassfileAnalyzer { repr.updateClassUsages(myContext, myUsages); } - return new Pair>(repr, myUsages); + return Pair.create(repr, myUsages); } @Override diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java index e95258d74823..d96cf7c7b59e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -105,7 +105,7 @@ abstract class Difference { final Difference diff = py.difference(px); if (!diff.no()) { - changed.add(new Pair(x, diff)); + changed.add(Pair.create(x, diff)); } } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java index 20e3b76e4e16..2907b36db5e0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -360,7 +360,7 @@ public class Mappings { final Collection methods = r.findMethods(predicate); for (MethodRepr mm : methods) { if (isVisibleIn(fromClass, m, r)) { - container.add(new Pair(mm, r)); + container.add(Pair.create(mm, r)); cont = false; } } @@ -413,7 +413,7 @@ public class Mappings { final Collection methods = superClass.findMethods(predicate); for (MethodRepr mm : methods) { if (isVisibleIn(superClass, mm, fromClass)) { - container.add(new Pair(mm, superClass)); + container.add(Pair.create(mm, superClass)); cont = false; } } @@ -422,7 +422,7 @@ public class Mappings { } } else { - container.add(new Pair(MOCK_METHOD, MOCK_CLASS)); + container.add(Pair.create(MOCK_METHOD, MOCK_CLASS)); } } } @@ -433,7 +433,7 @@ public class Mappings { if (superClass != null) { final FieldRepr ff = superClass.findField(f.name); if (ff != null && isVisibleIn(superClass, ff, fromClass)) { - container.add(new Pair(ff, superClass)); + container.add(Pair.create(ff, superClass)); } else{ addOverriddenFields(f, superClass, container); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectMultiMaplet.java index 35edf8421a93..4f24b5cffdd7 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectMultiMaplet.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectMultiMaplet.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -65,7 +65,7 @@ abstract class ObjectObjectMultiMaplet implements Strea final String keyStr = a instanceof File && !SystemInfo.isFileSystemCaseSensitive? ((File)a).getPath().toLowerCase(Locale.US) : a.toString(); - keys.add(new Pair(a, keyStr)); + keys.add(Pair.create(a, keyStr)); return true; } }); diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java index 821a2ffea980..0d5f03fcde86 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java +++ b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java @@ -47,7 +47,7 @@ final class ProtobufClientMessageHandler exte } @Override - public final void messageReceived(ChannelHandlerContext context, MessageLite message) throws Exception { + public final void channelRead0(ChannelHandlerContext context, MessageLite message) throws Exception { final UUID messageUUID = myUuidGetter.getSessionUUID((JavacRemoteProto.Message)message); final RequestFuture future = myHandlers.get(messageUUID); final T handler = future != null ? future.getMessageHandler() : null; diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java index 8dc21b1b574f..c6b34ab97bed 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java @@ -112,7 +112,7 @@ public class BuildMain { } @Override - public void messageReceived(final ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception { + public void channelRead0(final ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception { final CmdlineRemoteProto.Message.Type type = message.getType(); final Channel channel = context.channel(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index f6d27c8f4253..a22c5f25b8d4 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -605,7 +605,7 @@ final class BuildSession implements Runnable, CanceledStatus { task.setIsAccessChanged(accessChanged); task.setIsFieldRemoved(fieldRemoved); final ConstantSearchFuture future = new ConstantSearchFuture(BuildSession.this); - final ConstantSearchFuture prev = mySearchTasks.put(new Pair(ownerClassName, fieldName), future); + final ConstantSearchFuture prev = mySearchTasks.put(Pair.create(ownerClassName, fieldName), future); if (prev != null) { prev.setDone(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/Utils.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/Utils.java index 27c333a5c156..f99ced20ef71 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/Utils.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/Utils.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.PathUtilRt; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.model.module.JpsModule; @@ -86,7 +87,7 @@ public class Utils { if (directoryBased == null) { return null; } - name = JpsProjectLoader.getDirectoryBaseProjectName(directoryBased); + name = PathUtilRt.suggestFileName(JpsProjectLoader.getDirectoryBaseProjectName(directoryBased)); locationHash = directoryBased.getPath().hashCode(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileGeneratedEvent.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileGeneratedEvent.java index 99084dfb9011..51821d8b8102 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileGeneratedEvent.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/FileGeneratedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -37,7 +37,7 @@ public class FileGeneratedEvent extends BuildMessage { public void add(String root, String relativePath) { if (root != null && relativePath != null) { - myPaths.add(new Pair(FileUtil.toSystemIndependentName(root), FileUtil.toSystemIndependentName(relativePath))); + myPaths.add(Pair.create(FileUtil.toSystemIndependentName(root), FileUtil.toSystemIndependentName(relativePath))); } else { LOG.info("Invalid file generation event: root=" + root + "; relativePath=" + relativePath); diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java index 65c92e2ae76f..0ecfe7617160 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java @@ -199,7 +199,7 @@ public class JavacServer { @ChannelHandler.Sharable private class CompilationRequestsHandler extends SimpleChannelInboundHandler { @Override - public void messageReceived(final ChannelHandlerContext context, JavacRemoteProto.Message message) throws Exception { + public void channelRead0(final ChannelHandlerContext context, JavacRemoteProto.Message message) throws Exception { final UUID sessionId = JavacProtoUtil.fromProtoUUID(message.getSessionId()); final JavacRemoteProto.Message.Type messageType = message.getMessageType(); @@ -276,7 +276,7 @@ public class JavacServer { } @ChannelHandler.Sharable - private static final class ChannelRegistrar extends ChannelHandlerAdapter { + private static final class ChannelRegistrar extends ChannelInboundHandlerAdapter { private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); public boolean isEmpty() { diff --git a/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java b/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java index 4bbbe937d2c2..1fa208092696 100644 --- a/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java +++ b/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java @@ -21,7 +21,10 @@ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.StringTokenizer; /** * @author Eugene Zhuravlev @@ -45,8 +48,7 @@ public class Launcher { // IDEA-120811; speeding up DefaultChannelIDd calculation for netty //if (Boolean.parseBoolean(System.getProperty("io.netty.random.id"))) { - final String id = UUID.randomUUID().toString(); - System.setProperty("io.netty.machineId", id.substring(id.length() - 8)); + System.setProperty("io.netty.machineId", "9e43d860"); System.setProperty("io.netty.processId", Integer.toString(new Random().nextInt(65535))); //} diff --git a/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java index 23db146a61fe..8646ba0c72aa 100644 --- a/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java +++ b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -93,7 +93,7 @@ public class FileTypeAssocTable { myExactFileNameMappings.put(exactFileNameMatcher.getFileName(), type); } } else { - myMatchingMappings.add(new Pair(matcher, type)); + myMatchingMappings.add(Pair.create(matcher, type)); } } diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java index d36e603bdad2..3b5a5e4a707e 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java @@ -20,7 +20,6 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.concurrency.BoundedTaskExecutor; import org.jdom.Element; @@ -109,7 +108,7 @@ public class JpsProjectLoader extends JpsLoaderBase { catch (IOException ignored) { } } - return StringUtil.replace(dir.getParentFile().getName(), ":", ""); + return dir.getParentFile().getName(); } private void loadFromDirectory(File dir) { diff --git a/lib/netty-all-5.0.0.Alpha2.jar b/lib/netty-all-4.1.0.Alpha1.jar similarity index 56% rename from lib/netty-all-5.0.0.Alpha2.jar rename to lib/netty-all-4.1.0.Alpha1.jar index 6ce077fd8069..ef99234e5fc2 100644 Binary files a/lib/netty-all-5.0.0.Alpha2.jar and b/lib/netty-all-4.1.0.Alpha1.jar differ diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt index 9e49edc3d29a..92b9434f6f34 100644 --- a/lib/required_for_dist.txt +++ b/lib/required_for_dist.txt @@ -47,7 +47,7 @@ microba.jar miglayout-swing.jar nanoxml-2.2.3.jar nekohtml-1.9.14.jar -netty-all-5.0.0.Alpha2.jar +netty-all-4.1.0.Alpha1.jar oromatcher.jar picocontainer.jar protobuf-2.5.0.jar diff --git a/lib/src/netty-all-5.0.0.Alpha2-sources.jar b/lib/src/netty-all-4.1.0.Alpha1-sources.jar similarity index 61% rename from lib/src/netty-all-5.0.0.Alpha2-sources.jar rename to lib/src/netty-all-4.1.0.Alpha1-sources.jar index 499abce4cdd6..a3fff4f2fe59 100644 Binary files a/lib/src/netty-all-5.0.0.Alpha2-sources.jar and b/lib/src/netty-all-4.1.0.Alpha1-sources.jar differ diff --git a/platform/analysis-api/src/com/intellij/codeInspection/CleanupLocalInspectionTool.java b/platform/analysis-api/src/com/intellij/codeInspection/CleanupLocalInspectionTool.java new file mode 100644 index 000000000000..930ae2d76dfb --- /dev/null +++ b/platform/analysis-api/src/com/intellij/codeInspection/CleanupLocalInspectionTool.java @@ -0,0 +1,19 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection; + +public interface CleanupLocalInspectionTool { +} diff --git a/platform/analysis-api/src/com/intellij/codeInspection/InspectionEP.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionEP.java index 9b794fe44f79..66d8b7d41ba3 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/InspectionEP.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionEP.java @@ -109,6 +109,9 @@ public class InspectionEP extends LanguageExtensionPoint implements InspectionPr @Attribute("applyToDialects") public boolean applyToDialects = true; + @Attribute("cleanupTool") + public boolean cleanupTool = false; + /** * Highlighting level for this inspection tool that is used in default settings. */ diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java index 54ec3939ef54..dada113cc006 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java @@ -16,6 +16,7 @@ package com.intellij.codeInspection.ex; import com.intellij.codeHighlighting.HighlightDisplayLevel; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.GlobalInspectionContext; import com.intellij.codeInspection.InspectionEP; import com.intellij.codeInspection.InspectionProfileEntry; @@ -104,6 +105,10 @@ public abstract class InspectionToolWrapper(profile, name)); + result.add(Pair.create(profile, name)); } } } - if (!e.getContent().isEmpty()) result.add(new Pair(e, generator.generateUniqueName("profiles_settings") + ".xml")); + if (!e.getContent().isEmpty()) result.add(Pair.create(e, generator.generateUniqueName("profiles_settings") + ".xml")); return result; } diff --git a/platform/analysis-impl/src/com/intellij/packageDependencies/DependencyValidationManagerImpl.java b/platform/analysis-impl/src/com/intellij/packageDependencies/DependencyValidationManagerImpl.java index 0cb4eb11da5e..48b9036dcd54 100644 --- a/platform/analysis-impl/src/com/intellij/packageDependencies/DependencyValidationManagerImpl.java +++ b/platform/analysis-impl/src/com/intellij/packageDependencies/DependencyValidationManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -321,11 +321,11 @@ public class DependencyValidationManagerImpl extends DependencyValidationManager String scopeName = element.getAttributeValue("name"); assert scopeName != null; final String name = generator.generateUniqueName(FileUtil.sanitizeFileName(scopeName)) + ".xml"; - result.add(new Pair(element, name)); + result.add(Pair.create(element, name)); } } if (!e.getChildren().isEmpty()) { - result.add(new Pair(e, generator.generateUniqueName("scope_settings") + ".xml")); + result.add(Pair.create(e, generator.generateUniqueName("scope_settings") + ".xml")); } return result; } diff --git a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java index 2c539bfd9575..569e208e8b9f 100644 --- a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java +++ b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java @@ -28,7 +28,6 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.lang.UrlClassLoader; import com.intellij.util.text.StringTokenizer; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -44,7 +43,9 @@ import java.util.regex.Pattern; @SuppressWarnings({"HardCodedStringLiteral"}) public class BootstrapClassLoaderUtil extends ClassUtilCore { - @NonNls public static final String PROPERTY_IGNORE_CLASSPATH = "ignore.classpath"; + private static final String PROPERTY_IGNORE_CLASSPATH = "ignore.classpath"; + private static final String PROPERTY_ALLOW_BOOTSTRAP_RESOURCES = "idea.allow.bootstrap.resources"; + private static final String PROPERTY_ADDITIONAL_CLASSPATH = "idea.additional.classpath"; private BootstrapClassLoaderUtil() { } @@ -60,10 +61,13 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { addParentClasspath(classpath); addIDEALibraries(classpath); addAdditionalClassPath(classpath); - UrlClassLoader newClassLoader = UrlClassLoader.build() + UrlClassLoader.Builder builder = UrlClassLoader.build() .urls(filterClassPath(classpath)) - .allowBootstrapResources() - .allowLock().useCache().get(); + .allowLock().useCache(); + if (Boolean.valueOf(System.getProperty(PROPERTY_ALLOW_BOOTSTRAP_RESOURCES, "true"))) { + builder.allowBootstrapResources(); + } + UrlClassLoader newClassLoader = builder.get(); // prepare plugins if (updatePlugins && !isLoadingOfExternalPluginsDisabled()) { @@ -183,7 +187,7 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { private static void addAdditionalClassPath(List classPath) { try { - StringTokenizer tokenizer = new StringTokenizer(System.getProperty("idea.additional.classpath", ""), File.pathSeparator, false); + StringTokenizer tokenizer = new StringTokenizer(System.getProperty(PROPERTY_ADDITIONAL_CLASSPATH, ""), File.pathSeparator, false); while (tokenizer.hasMoreTokens()) { String pathItem = tokenizer.nextToken(); classPath.add(new File(pathItem).toURI().toURL()); diff --git a/platform/core-api/src/com/intellij/codeInsight/PsiEquivalenceUtil.java b/platform/core-api/src/com/intellij/codeInsight/PsiEquivalenceUtil.java index 4b8e0e8a5c75..87703b89bf32 100644 --- a/platform/core-api/src/com/intellij/codeInsight/PsiEquivalenceUtil.java +++ b/platform/core-api/src/com/intellij/codeInsight/PsiEquivalenceUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -118,7 +118,7 @@ public class PsiEquivalenceUtil { findChildRangeDuplicates(first, last, scope, new PairConsumer() { @Override public void consume(final PsiElement start, final PsiElement end) { - result.add(new Pair(start, end)); + result.add(Pair.create(start, end)); } }); } diff --git a/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java b/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java index c57c07890dea..9fe19cd9f8bc 100644 --- a/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java +++ b/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java @@ -19,6 +19,8 @@ package com.intellij.psi; import com.intellij.lang.ASTNode; import com.intellij.lang.FileASTNode; import com.intellij.lang.Language; +import com.intellij.openapi.diagnostic.Attachment; +import com.intellij.openapi.diagnostic.ExceptionWithAttachments; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.util.registry.Registry; @@ -34,32 +36,58 @@ import java.lang.ref.SoftReference; /** * @author mike */ -public class PsiInvalidElementAccessException extends RuntimeException { +public class PsiInvalidElementAccessException extends RuntimeException implements ExceptionWithAttachments { private static final Key INVALIDATION_TRACE = Key.create("TRACK_INVALIDATION_KEY"); private final SoftReference myElementReference; // to prevent leaks, since exceptions are stored in IdeaLogger + private final Attachment[] myDiagnostic; + private final String myMessage; public PsiInvalidElementAccessException(PsiElement element) { - this(element, (String)null); + this(element, null, null); } public PsiInvalidElementAccessException(PsiElement element, @Nullable String message) { - this(element, getMessageWithReason(element, message), null); + this(element, message, null); } public PsiInvalidElementAccessException(PsiElement element, @Nullable Throwable cause) { - this(element, getMessageWithReason(element, null), cause); + this(element, null, cause); } - public PsiInvalidElementAccessException(PsiElement element, @Nullable String message, @Nullable Throwable cause) { - super(message, cause); + public PsiInvalidElementAccessException(@Nullable PsiElement element, @Nullable String message, @Nullable Throwable cause) { + super(null, cause); myElementReference = new SoftReference(element); + + if (element == null) { + myMessage = message; + myDiagnostic = Attachment.EMPTY_ARRAY; + } else { + Object trace = findInvalidationTrace(element.getNode()); + String reason = "Element: " + element.getClass() + + " because: " + reason(element) + + "\ninvalidated at: " + + (!isTrackingInvalidation() ? "disabled" : + trace != null ? "see attachment" : + "no info"); + myMessage = reason + (message == null ? "" : "; " + message); + if (trace == null) { + myDiagnostic = Attachment.EMPTY_ARRAY; + } else { + String diagnostic = trace instanceof Throwable ? ExceptionUtil.getThrowableText((Throwable)trace) : trace.toString(); + myDiagnostic = new Attachment[]{new Attachment("diagnostic.txt", diagnostic)}; + } + } } - private static String getMessageWithReason(@Nullable PsiElement element, @Nullable String message) { - return (element == null - ? "Unknown psi element" - : "Element: " + element.getClass() + " because: " + reason(element) + invalidationTraceText(element)) + - (message == null ? "" : "; " + message); + @Override + public String getMessage() { + return myMessage; + } + + @NotNull + @Override + public Attachment[] getAttachments() { + return myDiagnostic; } public static Object findInvalidationTrace(@Nullable ASTNode element) { @@ -81,16 +109,6 @@ public class PsiInvalidElementAccessException extends RuntimeException { return null; } - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - private static String invalidationTraceText(PsiElement element) { - Object trace = findInvalidationTrace(element.getNode()); - return "\ninvalidated at: " + - (!isTrackingInvalidation() ? "disabled" : - trace instanceof Throwable ? ExceptionUtil.getThrowableText((Throwable)trace) : - trace != null ? trace : - "no info"); - } - @NonNls @NotNull private static String reason(@NotNull PsiElement root){ diff --git a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java index 024062de3aeb..863672c69179 100644 --- a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java +++ b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -28,7 +28,6 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.PomModel; import com.intellij.pom.PomModelAspect; import com.intellij.pom.PomTransaction; @@ -144,7 +143,7 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel { startTransaction(transaction); try{ DebugUtil.startPsiModification(null); - myBlockedAspects.push(new Pair(aspect, transaction)); + myBlockedAspects.push(Pair.create(aspect, transaction)); final PomModelEvent event; try{ @@ -255,25 +254,23 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel { return; } - String newText = changedFile.getNode().getText(); + CharSequence newText = changedFile.getNode().getChars(); for (final PsiFile file : allFiles) { if (file != changedFile) { FileElement fileElement = ((PsiFileImpl)file).getTreeElement(); if (fileElement != null) { - String oldText = fileElement.getText(); + CharSequence oldText = fileElement.getChars(); reparseFile(file, newText, oldText); } } } } - private void reparseFile(final PsiFile file, String newText, String oldText) { + private void reparseFile(final PsiFile file, CharSequence newText, CharSequence oldText) { if (oldText.equals(newText)) return; PsiToDocumentSynchronizer synchronizer =((PsiDocumentManagerBase)PsiDocumentManager.getInstance(myProject)).getSynchronizer(); - int changeStart = StringUtil.commonPrefixLength(oldText, newText); - int changeEnd = oldText.length() - StringUtil.commonSuffixLength(oldText, newText); - TextRange changedPsiRange = DocumentCommitProcessor.getChangedPsiRange(file, changeStart, changeEnd, newText.length()); + TextRange changedPsiRange = DocumentCommitProcessor.getChangedPsiRange(file, oldText, newText); final DiffLog log = BlockSupport.getInstance(myProject).reparseRange(file, changedPsiRange, newText, new EmptyProgressIndicator()); synchronizer.setIgnorePsiEvents(true); try { diff --git a/platform/core-impl/src/com/intellij/pom/tree/events/impl/TreeChangeImpl.java b/platform/core-impl/src/com/intellij/pom/tree/events/impl/TreeChangeImpl.java index cd3997dd25ef..dd5ad7414835 100644 --- a/platform/core-impl/src/com/intellij/pom/tree/events/impl/TreeChangeImpl.java +++ b/platform/core-impl/src/com/intellij/pom/tree/events/impl/TreeChangeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -130,7 +130,7 @@ public class TreeChangeImpl implements TreeChange { private void addChangeAtOffset(final ASTNode child, final int nodeOffset) { int optimizedIndex = haveNotCalculated; - Pair element = new Pair(child, Integer.valueOf(nodeOffset)); + Pair element = Pair.create(child, Integer.valueOf(nodeOffset)); if (mySortedChanges.size() > 0) { // check adding at end Pair pair = mySortedChanges.get(mySortedChanges.size() - 1); diff --git a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java index 8e54370a8195..89b04e065df7 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java +++ b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java @@ -24,7 +24,6 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.UnfairTextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.PomManager; import com.intellij.pom.PomModel; @@ -112,15 +111,8 @@ public abstract class DocumentCommitProcessor { document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null); file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, data); } - final String oldPsiText = myTreeElementBeingReparsedSoItWontBeCollected.getText(); - int commonPrefixLength = StringUtil.commonPrefixLength(oldPsiText, chars); - final TextRange changedPsiRange; - if (commonPrefixLength == chars.length() && chars.length() == oldPsiText.length()) { - changedPsiRange = getChangedPsiRange(file, 0, 0, chars.length()); - } else { - int commonSuffixLength = StringUtil.commonSuffixLength(oldPsiText, chars); - changedPsiRange = getChangedPsiRange(file, commonPrefixLength, oldPsiText.length() - commonSuffixLength, chars.length()); - } + final CharSequence oldPsiText = myTreeElementBeingReparsedSoItWontBeCollected.getChars(); + final TextRange changedPsiRange = getChangedPsiRange(file, oldPsiText, chars); BlockSupport blockSupport = BlockSupport.getInstance(file.getProject()); final DiffLog diffLog = blockSupport.reparseRange(file, changedPsiRange, chars, task.indicator); @@ -151,11 +143,18 @@ public abstract class DocumentCommitProcessor { }; } - public static TextRange getChangedPsiRange(PsiFile file, int changeStart, int changeEnd, int newTextLength) { - if (file.getViewProvider().supportsIncrementalReparse(file.getLanguage())) { - return new UnfairTextRange(changeStart, changeEnd); + public static TextRange getChangedPsiRange(@NotNull PsiFile file, @NotNull CharSequence oldPsiText, @NotNull CharSequence newDocumentText) { + if (!file.getViewProvider().supportsIncrementalReparse(file.getLanguage())) { + return new TextRange(0, newDocumentText.length()); } - return new TextRange(0, newTextLength); + + int commonPrefixLength = StringUtil.commonPrefixLength(oldPsiText, newDocumentText); + if (commonPrefixLength == newDocumentText.length() && newDocumentText.length() == oldPsiText.length()) { + return new TextRange(0, newDocumentText.length()); + } + + int commonSuffixLength = StringUtil.commonSuffixLength(oldPsiText, newDocumentText); + return new TextRange(commonPrefixLength, Math.max(commonPrefixLength, oldPsiText.length() - commonSuffixLength)); } public static void doActualPsiChange(@NotNull final PsiFile file, @NotNull final DiffLog diffLog) { @@ -189,7 +188,7 @@ public abstract class DocumentCommitProcessor { private void assertAfterCommit(Document document, final PsiFile file, - String oldPsiText, + CharSequence oldPsiText, FileElement myTreeElementBeingReparsedSoItWontBeCollected) { if (myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() != document.getTextLength()) { final String documentText = document.getText(); @@ -200,7 +199,7 @@ public abstract class DocumentCommitProcessor { "; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText), new Attachment("file psi text", fileText), new Attachment("old text", documentText), - new Attachment("old psi file text", oldPsiText)); + new Attachment("old psi file text", oldPsiText.toString())); file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE); try { diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java index c580f65ebfc2..fc50aa297fd0 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java @@ -57,7 +57,8 @@ import java.util.*; public abstract class PsiDocumentManagerBase extends PsiDocumentManager implements DocumentListener { protected static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiDocumentManagerImpl"); - private static final Key HARD_REF_TO_PSI = new Key("HARD_REFERENCE_TO_PSI"); + private static final Key HARD_REF_TO_DOCUMENT = Key.create("HARD_REFERENCE_TO_DOCUMENT"); + private static final Key HARD_REF_TO_PSI = Key.create("HARD_REFERENCE_TO_PSI"); private static final Key> ACTION_AFTER_COMMIT = Key.create("ACTION_AFTER_COMMIT"); protected final Project myProject; @@ -164,6 +165,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen if (!viewProvider.isPhysical()) { cachePsi(document, file); + file.putUserData(HARD_REF_TO_DOCUMENT, document); } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java index c6c1d9724e7d..3669e037bf7b 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -509,7 +509,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { } MutableTextRange newRange = new MutableTextRange(start, end); - final Pair pair = new Pair(newRange, fragmentBuffer); + final Pair pair = Pair.create(newRange, fragmentBuffer); for (Pair affectedFragment : myAffectedFragments) { MutableTextRange range = affectedFragment.getFirst(); assert end <= range.getStartOffset() || range.getEndOffset() <= start : "Range :"+range+"; Added: "+newRange; diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java index 13a85846a045..48b26c4d57d4 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java @@ -104,10 +104,10 @@ public class BlockSupportImpl extends BlockSupport { final TextRange textRange = node.getTextRange(); final IReparseableElementType reparseable = (IReparseableElementType)elementType; - if (baseLanguage.isKindOf(reparseable.getLanguage())) { + if (baseLanguage.isKindOf(reparseable.getLanguage()) && textRange.getLength() + lengthShift > 0) { final int start = textRange.getStartOffset(); final int end = start + textRange.getLength() + lengthShift; - if (!assertFileLength(file, newFileText, node, elementType, start, end)) { + if (!assertFileLength2(file, newFileText, node, start, end)) { break; } @@ -137,9 +137,9 @@ public class BlockSupportImpl extends BlockSupport { return makeFullParse(node, newFileText, textLength, fileImpl, indicator); } - private static boolean assertFileLength(PsiFile file, CharSequence newFileText, ASTNode node, IElementType elementType, int start, int end) { + private static boolean assertFileLength2(PsiFile file, CharSequence newFileText, ASTNode node, int start, int end) { if (end > newFileText.length() || start > end) { - String message = "IOOBE: type=" + elementType + + String message = "Index out of bounds: type=" + node.getElementType() + "; file=" + file + "; file.class=" + file.getClass() + "; start=" + start + @@ -151,10 +151,9 @@ public class BlockSupportImpl extends BlockSupport { message += "; oldTextBefore==newTextBefore"; } LOG.error(message, - new Attachment(file.getName() + "_oldText.txt", node.getText()), - new Attachment(file.getName() + "_newText.txt", node.getText()), - new Attachment(file.getName() + "_oldTextBefore.txt", oldTextBefore), - new Attachment(file.getName() + "_newTextBefore.txt", newTextBefore) + new Attachment(file.getName() + "_oldNodeText.txt", node.getText()), + new Attachment(file.getName() + "_oldFileText.txt", file.getText()), + new Attachment(file.getName() + "_newFileText.txt", newFileText.toString()) ); return false; } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java index 7e1159929e3f..b91668439948 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -249,7 +249,7 @@ public class TreeUtil { } while (one == two && one != null); - return new Pair(one, two); + return Pair.create(one, two); } public static void clearCaches(@NotNull final TreeElement tree) { diff --git a/platform/indexing-api/src/com/intellij/psi/search/searches/DefinitionsScopedSearch.java b/platform/indexing-api/src/com/intellij/psi/search/searches/DefinitionsScopedSearch.java index 75d09a3b0e3f..5b3765930b41 100644 --- a/platform/indexing-api/src/com/intellij/psi/search/searches/DefinitionsScopedSearch.java +++ b/platform/indexing-api/src/com/intellij/psi/search/searches/DefinitionsScopedSearch.java @@ -82,13 +82,12 @@ public class DefinitionsScopedSearch extends ExtensibleQueryFactory() { + return ApplicationManager.getApplication().runReadAction(new Computable() { @Override public SearchScope compute() { - return PsiSearchHelper.SERVICE.getInstance(myElement.getProject()).getUseScope(myElement); + return myScope.intersectWith(PsiSearchHelper.SERVICE.getInstance(myElement.getProject()).getUseScope(myElement)); } }); - return myScope.intersectWith(accessScope); } } diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndex.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndex.java index ad76a809da90..9929c1c586d2 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndex.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndex.java @@ -91,7 +91,7 @@ public class IdIndex extends FileBasedIndexExtension { @Override public int getVersion() { - return 11 + (ourSnapshotMappingsEnabled ? 0xFF:0); // TODO: version should enumerate all word scanner versions and build version upon that set + return 12 + (ourSnapshotMappingsEnabled ? 0xFF:0); // TODO: version should enumerate all word scanner versions and build version upon that set } @Override diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java index b85fcd8796fa..df0e0b959a23 100644 --- a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java +++ b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java @@ -118,6 +118,8 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil { final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); if (file == null) return null; + PsiUtilCore.ensureValid(file); + final Language language = getLanguageInEditor(editor, project); if (language == null) return file; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 64f3c6396ba6..8b2acda41c48 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -635,8 +635,13 @@ public class CodeCompletionHandlerBase { }); context = contexts.get(contexts.size() - 1); if (context.shouldAddCompletionChar() && context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) { - DataContext dataContext = DataManager.getInstance().getDataContext(editor.getContentComponent()); - EditorActionManager.getInstance().getTypedAction().getHandler().execute(editor, completionChar, dataContext); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + DataContext dataContext = DataManager.getInstance().getDataContext(editor.getContentComponent()); + EditorActionManager.getInstance().getTypedAction().getHandler().execute(editor, completionChar, dataContext); + } + }); } for (CompletionAssertions.WatchingInsertionContext insertionContext : contexts) { insertionContext.stopWatching(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java index 6b467792c54f..d2b74e4bd293 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java @@ -30,6 +30,8 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.ex.RangeMarkerEx; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -54,6 +56,8 @@ class CompletionAssertions { return; } + FileViewProvider viewProvider = psiFile.getViewProvider(); + String message = "unsuccessful commit:"; message += "\nmatching=" + (psiFile == manager.getPsiFile(document)); message += "\ninjectedEditor=" + (editor instanceof EditorWindow); @@ -62,6 +66,8 @@ class CompletionAssertions { message += "\nfile=" + psiFile.getName(); message += "\nfile class=" + psiFile.getClass(); message += "\nfile.valid=" + psiFile.isValid(); + message += "\nfile.physical=" + psiFile.isPhysical(); + message += "\nfile.eventSystemEnabled=" + viewProvider.isEventSystemEnabled(); message += "\nlanguage=" + psiFile.getLanguage(); message += "\ndoc.length=" + docLength; message += "\npsiFile.length=" + psiLength; @@ -77,10 +83,13 @@ class CompletionAssertions { message += "\nnode.text.length=" + nodeText.length(); } } + VirtualFile virtualFile = viewProvider.getVirtualFile(); + message += "\nvirtualFile=" + virtualFile; + message += "\nvirtualFile.class=" + virtualFile.getClass(); message += "\n" + DebugUtil.currentStackTrace(); throw new LogEventException("Commit unsuccessful", message, - new Attachment(psiFile.getViewProvider().getVirtualFile().getPath() + "_file.txt", fileText), + new Attachment(virtualFile.getPath() + "_file.txt", fileText), createAstAttachment(psiFile, psiFile), new Attachment("docText.txt", document.getText())); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowParameterInfoContext.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowParameterInfoContext.java index 14e7487cc216..010cd3150b5e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowParameterInfoContext.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowParameterInfoContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -243,7 +243,7 @@ public class ShowParameterInfoContext implements CreateParameterInfoContext { short preferredPosition) { final TextRange textRange = list.getTextRange(); offset = textRange.contains(offset) ? offset:textRange.getStartOffset() + 1; - if (previousOffset == offset) return new Pair(previousBestPoint, previousBestPosition); + if (previousOffset == offset) return Pair.create(previousBestPoint, previousBestPosition); String listText = list.getText(); final boolean isMultiline = listText.indexOf('\n') >= 0 || listText.indexOf('\r') >= 0; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 548264e4676b..d0c98be6c976 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -474,13 +474,9 @@ public class TemplateState implements Disposable { return "no template"; } - String message = template.getKey(); - if (message == null || message.isEmpty()) { - message = template.getString(); - if (message == null) { - message = template.getTemplateText(); - } - } + String message = StringUtil.notNullize(template.getKey()); + message += "\n\nTemplate#string: " + StringUtil.notNullize(template.getString()); + message += "\n\nTemplate#text: " + StringUtil.notNullize(template.getTemplateText()); return message; } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseExpressionPostfixTemplateBase.java similarity index 55% rename from java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java rename to platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseExpressionPostfixTemplateBase.java index 6fcd986588df..5df46cbda734 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseExpressionPostfixTemplateBase.java @@ -15,20 +15,19 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; -import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; import org.jetbrains.annotations.NotNull; -abstract public class NonVoidPostfixTemplate extends PostfixTemplate { - protected NonVoidPostfixTemplate(@NotNull String name, @NotNull String example) { - super(name, example); +public abstract class ElseExpressionPostfixTemplateBase extends SurroundPostfixTemplateBase +{ + protected ElseExpressionPostfixTemplateBase(@NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull Condition typeChecker) { + super("else", "if (!exp)", psiInfo, typeChecker); } @Override - public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); - return expr != null && PostfixTemplatesUtils.isNonVoid(expr.getType()); + protected PsiElement getWrappedExpression(PsiElement expression) { + return myPsiInfo.getNegatedExpression(expression); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/IfPostfixTemplateBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/IfPostfixTemplateBase.java new file mode 100644 index 000000000000..1b7a2ddd7ad4 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/IfPostfixTemplateBase.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + + +import com.intellij.openapi.util.Condition; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +public abstract class IfPostfixTemplateBase extends SurroundPostfixTemplateBase { + + protected IfPostfixTemplateBase(@NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull Condition typeChecker) { + super("if", "if (expr)", psiInfo, typeChecker); + } + +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java new file mode 100644 index 000000000000..8f4716787453 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface PostfixTemplatePsiInfo { + + @NotNull + PsiElement createStatement(@NotNull PsiElement context, + @NotNull String prefix, + @NotNull String suffix); + + @NotNull + PsiElement createExpression(@NotNull PsiElement context, + @NotNull String prefix, + @NotNull String suffix); + + @Nullable + PsiElement getTopmostExpression(@NotNull PsiElement element); + + @NotNull + PsiElement getNegatedExpression(@NotNull PsiElement element); +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java new file mode 100644 index 000000000000..e286c2158d90 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + +import com.intellij.lang.surroundWith.Surrounder; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.refactoring.util.CommonRefactoringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class PostfixTemplatesUtils { + private PostfixTemplatesUtils() { + } + + @Nullable + public static TextRange surround(@NotNull Surrounder surrounder, + @NotNull Editor editor, + @NotNull PsiElement expr) { + Project project = expr.getProject(); + PsiElement[] elements = {expr}; + if (surrounder.isApplicable(elements)) { + return surrounder.surroundElements(project, editor, elements); + } + else { + showErrorHint(project, editor); + } + return null; + } + + public static void showErrorHint(@NotNull Project project, @NotNull Editor editor) { + CommonRefactoringUtil.showErrorHint(project, editor, "Can't expand postfix template", "Can't expand postfix template", ""); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java new file mode 100644 index 000000000000..7cdf70bf3cc9 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + + +public abstract class StatementWrapPostfixTemplate extends TypedPostfixTemplate { + + protected StatementWrapPostfixTemplate(@NotNull String name, + @NotNull String descr, + @NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull Condition typeChecker) { + super(name, descr, psiInfo, typeChecker); + } + + @Override + public void expand(@NotNull PsiElement context, @NotNull Editor editor) { + PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context); + assert topmostExpression != null; + PsiElement parent = topmostExpression.getParent(); + PsiElement expression = getWrappedExpression(topmostExpression); + PsiElement replace = parent.replace(expression); + afterExpand(replace, editor); + } + + protected PsiElement getWrappedExpression(PsiElement expression) { + if (StringUtil.isEmpty(getHead()) && StringUtil.isEmpty(getTail())) { + return expression; + } + return createNew(expression); + } + + protected PsiElement createNew(PsiElement expression) { + if (isStatement()) { + return myPsiInfo.createStatement(expression, getHead(), getTail()); + } + return myPsiInfo.createExpression(expression, getHead(), getTail()); + } + + protected void afterExpand(@NotNull PsiElement newElement, @NotNull Editor editor) { + editor.getCaretModel().moveToOffset(newElement.getTextRange().getEndOffset()); + } + + @NotNull + protected String getHead() { + return ""; + } + + @NotNull + protected String getTail() { + return ""; + } + + public boolean isStatement() { + return true; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java new file mode 100644 index 000000000000..378b81a6d7ef --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + +import com.intellij.lang.surroundWith.Surrounder; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +public abstract class SurroundPostfixTemplateBase extends StatementWrapPostfixTemplate { + + protected SurroundPostfixTemplateBase(@NotNull String name, + @NotNull String descr, + @NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull Condition typeChecker) { + super(name, descr, psiInfo, typeChecker); + } + + + @Override + public void expand(@NotNull PsiElement context, @NotNull final Editor editor) { + PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context); + PsiElement expression = getWrappedExpression(topmostExpression); + assert topmostExpression != null; + PsiElement replace = topmostExpression.replace(expression); + TextRange range = PostfixTemplatesUtils.surround(getSurrounder(), editor, replace); + + if (range != null) { + editor.getCaretModel().moveToOffset(range.getStartOffset()); + } + } + + public boolean isStatement() { + return false; + } + + @NotNull + protected abstract Surrounder getSurrounder(); +} + diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java similarity index 57% rename from java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java rename to platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java index 1f4ad8eb695b..0d7d424d99a8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java @@ -15,20 +15,28 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; import org.jetbrains.annotations.NotNull; -abstract public class BooleanPostfixTemplate extends PostfixTemplate { - protected BooleanPostfixTemplate(@NotNull String name, @NotNull String example) { +public abstract class TypedPostfixTemplate extends PostfixTemplate { + + protected final PostfixTemplatePsiInfo myPsiInfo; + protected final Condition myTypeChecker; + + protected TypedPostfixTemplate(@NotNull String name, + @NotNull String example, + @NotNull PostfixTemplatePsiInfo psiInfo, + @NotNull Condition typeChecker) { super(name, example); + this.myPsiInfo = psiInfo; + this.myTypeChecker = typeChecker; } @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression topmostExpression = PostfixTemplatesUtils.getTopmostExpression(context); - return topmostExpression != null && PostfixTemplatesUtils.isBoolean(topmostExpression.getType()); + PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context); + return topmostExpression != null && myTypeChecker.value(topmostExpression); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/unwrap/ScopeHighlighter.java b/platform/lang-impl/src/com/intellij/codeInsight/unwrap/ScopeHighlighter.java index 9a7f0506b7ad..39f70d4f22ea 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/unwrap/ScopeHighlighter.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/unwrap/ScopeHighlighter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -82,7 +82,7 @@ public class ScopeHighlighter { rangesToExtract.add(getRange(e)); } - return new Pair>(affectedRange, rangesToExtract); + return Pair.create(affectedRange, rangesToExtract); } private TextRange getRange(PsiElement e) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/unwrap/UnwrapDescriptorBase.java b/platform/lang-impl/src/com/intellij/codeInsight/unwrap/UnwrapDescriptorBase.java index 67fb29d58b6d..626ef32af8a2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/unwrap/UnwrapDescriptorBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/unwrap/UnwrapDescriptorBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,7 +51,7 @@ public abstract class UnwrapDescriptorBase implements UnwrapDescriptor { while (e != null) { for (Unwrapper u : getUnwrappers()) { if (u.isApplicableTo(e) && !ignored.contains(e)) { - result.add(new Pair(e, u)); + result.add(Pair.create(e, u)); u.collectElementsToIgnore(e, ignored); } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeCleanupAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeCleanupAction.java new file mode 100644 index 000000000000..225034882c9d --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeCleanupAction.java @@ -0,0 +1,173 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.intellij.codeInspection.actions; + +import com.intellij.analysis.AnalysisScope; +import com.intellij.codeInsight.FileModificationService; +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.daemon.impl.HighlightInfoProcessor; +import com.intellij.codeInsight.daemon.impl.LocalInspectionsPass; +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ex.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.profile.codeInspection.InspectionProfileManager; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.intellij.profile.codeInspection.ui.IDEInspectionToolsConfigurable; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiFile; +import com.intellij.util.SequentialModalProgressTask; +import com.intellij.util.SequentialTask; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +public class CodeCleanupAction extends CodeInspectionAction { + public CodeCleanupAction() { + super("Code Cleanup", "Code Cleanup"); + } + + @Override + protected void analyze(@NotNull final Project project, @NotNull final AnalysisScope scope) { + final InspectionProfile profile = myExternalProfile != null ? myExternalProfile : InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); + final List lTools = new ArrayList(); + final InspectionManagerEx managerEx = (InspectionManagerEx)InspectionManager.getInstance(project); + final GlobalInspectionContextImpl context = managerEx.createNewGlobalContext(false); + + final LinkedHashMap> results = new LinkedHashMap>(); + ProgressManager.getInstance().run(new Task.Backgroundable(project, "Inspect code...", true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + scope.accept(new PsiElementVisitor() { + @Override + public void visitFile(PsiFile file) { + final VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile == null) return; + for (final Tools tools : profile.getAllEnabledInspectionTools(project)) { + if (tools.getTool().getTool() instanceof CleanupLocalInspectionTool) { + final InspectionToolWrapper tool = tools.getEnabledTool(file); + if (tool instanceof LocalInspectionToolWrapper) { + lTools.add((LocalInspectionToolWrapper)tool); + tool.initialize(context); + } + } + } + + if (!lTools.isEmpty()) { + final LocalInspectionsPass pass = new LocalInspectionsPass(file, PsiDocumentManager.getInstance(project).getDocument(file), 0, + file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true, + HighlightInfoProcessor.getEmpty()); + Runnable runnable = new Runnable() { + public void run() { + pass.doInspectInBatch(context, managerEx, lTools); + } + }; + ApplicationManager.getApplication().runReadAction(runnable); + results.put(file, pass.getInfos()); + } + } + }); + } + + @Override + public void onSuccess() { + if (!FileModificationService.getInstance().preparePsiElementsForWrite(results.keySet())) return; + + final SequentialModalProgressTask progressTask = new SequentialModalProgressTask(project, "Code Cleanup", true); + progressTask.setMinIterationTime(200); + progressTask.setTask(new SequentialCleanupTask(project, results, progressTask)); + CommandProcessor.getInstance().executeCommand(project, new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().markCurrentCommandAsGlobal(project); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + ProgressManager.getInstance().run(progressTask); + } + }); + } + }, getTemplatePresentation().getText(), null); + } + }); + } + + @Override + protected IDEInspectionToolsConfigurable createConfigurable(InspectionProjectProfileManager projectProfileManager, + InspectionProfileManager profileManager) { + return new IDEInspectionToolsConfigurable(projectProfileManager, profileManager) { + @Override + protected boolean acceptTool(InspectionToolWrapper entry) { + return super.acceptTool(entry) && entry.isCleanupTool(); + } + }; + } +} + +class SequentialCleanupTask implements SequentialTask { + + private final Project myProject; + private final LinkedHashMap> myResults; + private Iterator myFileIterator; + private final SequentialModalProgressTask myProgressTask; + private int myCount = 0; + + public SequentialCleanupTask(Project project, LinkedHashMap> results, SequentialModalProgressTask task) { + myProject = project; + myResults = results; + myProgressTask = task; + myFileIterator = myResults.keySet().iterator(); + } + + @Override + public void prepare() {} + + @Override + public boolean isDone() { + return myFileIterator == null || !myFileIterator.hasNext(); + } + + @Override + public boolean iteration() { + final ProgressIndicator indicator = myProgressTask.getIndicator(); + if (indicator != null) { + indicator.setFraction((double) myCount++/myResults.size()); + } + final PsiFile file = myFileIterator.next(); + final List infos = myResults.get(file); + Collections.reverse(infos); //sort bottom - top + for (HighlightInfo info : infos) { + for (final Pair actionRange : info.quickFixActionRanges) { + actionRange.getFirst().getAction().invoke(myProject, null, file); + } + } + return true; + } + + @Override + public void stop() { + myFileIterator = null; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java index 839d12f213c5..b49edd1a7c26 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java @@ -47,12 +47,16 @@ import java.util.TreeSet; public class CodeInspectionAction extends BaseAnalysisAction { private GlobalInspectionContextImpl myGlobalInspectionContext = null; - private InspectionProfile myExternalProfile = null; + protected InspectionProfile myExternalProfile = null; public CodeInspectionAction() { super(InspectionsBundle.message("inspection.action.title"), InspectionsBundle.message("inspection.action.noun")); } + public CodeInspectionAction(String title, String analysisNoon) { + super(title, analysisNoon); + } + @Override protected void analyze(@NotNull Project project, @NotNull AnalysisScope scope) { try { @@ -110,7 +114,7 @@ public class CodeInspectionAction extends BaseAnalysisAction { panel.myBrowseProfilesCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - final IDEInspectionToolsConfigurable errorConfigurable = new IDEInspectionToolsConfigurable(projectProfileManager, profileManager); + final IDEInspectionToolsConfigurable errorConfigurable = createConfigurable(projectProfileManager, profileManager); final MySingleConfigurableEditor editor = new MySingleConfigurableEditor(project, errorConfigurable, manager); errorConfigurable.selectProfile(((Profile)profiles.getSelectedItem()).getName()); editor.show(); @@ -141,6 +145,11 @@ public class CodeInspectionAction extends BaseAnalysisAction { return panel.myAdditionalPanel; } + protected IDEInspectionToolsConfigurable createConfigurable(InspectionProjectProfileManager projectProfileManager, + InspectionProfileManager profileManager) { + return new IDEInspectionToolsConfigurable(projectProfileManager, profileManager); + } + private void reloadProfiles(JComboBox profiles, InspectionProfileManager inspectionProfileManager, InspectionProjectProfileManager inspectionProjectProfileManager, diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index 22e3767150a7..bae4d3297d34 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -62,6 +62,7 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.search.GlobalSearchScope; @@ -134,7 +135,8 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo // Should be accessed in EDT only. @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") private boolean myDocumentClearing; - protected int myLastAddedTextLength; + private int myLastAddedTextLength; + private int consoleTooMuchTextBufferRatio; public Editor getEditor() { return myEditor; @@ -339,6 +341,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo myJLayeredPane.finishUpdating(); } }; + consoleTooMuchTextBufferRatio = Registry.intValue("console.too.much.text.buffer.ratio"); } @Override @@ -751,7 +754,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo } private boolean isTheAmountOfTextTooBig(final int textLength) { - return textLength > myBuffer.getCyclicBufferSize() / 10; //magic number, it has no deep meaning + return textLength > myBuffer.getCyclicBufferSize() / consoleTooMuchTextBufferRatio; } private void clearHyperlinkAndFoldings() { diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java b/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java index afc5cd8eda39..deadaad0a0d1 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -166,7 +166,7 @@ public class ProjectRunConfigurationManager implements ProjectComponent, Persist for (final Object o : list) { Element library = (Element)o; final String name = generator.generateUniqueName(FileUtil.sanitizeFileName(library.getAttributeValue(RunManagerImpl.NAME_ATTR))) + ".xml"; - result.add(new Pair(library, name)); + result.add(Pair.create(library, name)); } return result; diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index 7edb9a9e9292..1b8f6ecb3907 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -409,8 +409,14 @@ class FindInProjectTask { }); if (!keys.isEmpty()) { - List hits = new ArrayList(); - FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor(hits), scope); + final List hits = new ArrayList(); + final GlobalSearchScope finalScope = scope; + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor(hits), + finalScope); + } + }); for (VirtualFile hit : hits) { if (myFileMask.value(hit)) { diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java index 123b3ee2c824..801209900ed5 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java @@ -188,7 +188,12 @@ public class FindInProjectUtil { final VirtualFile virtualFile = psiFile.getVirtualFile(); if (virtualFile == null) return 0; if (virtualFile.getFileType().isBinary()) return 0; // do not decompile .class files - final Document document = FileDocumentManager.getInstance().getDocument(virtualFile); + final Document document = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Document compute() { + return virtualFile.isValid() ? FileDocumentManager.getInstance().getDocument(virtualFile) : null; + } + }); if (document == null) return 0; final int[] offset = {0}; int count = 0; diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java index 384c92ee0427..dff4989bb2f6 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -584,7 +584,7 @@ public class SearchResults implements DocumentListener { } private void push() { - myCursorPositions.push(new Pair(myFindModel, myCursor)); + myCursorPositions.push(Pair.create(myFindModel, myCursor)); } public void nextOccurrence() { diff --git a/platform/lang-impl/src/com/intellij/find/ngrams/TrigramIndex.java b/platform/lang-impl/src/com/intellij/find/ngrams/TrigramIndex.java index 72f5f947d0e7..9025357b4908 100644 --- a/platform/lang-impl/src/com/intellij/find/ngrams/TrigramIndex.java +++ b/platform/lang-impl/src/com/intellij/find/ngrams/TrigramIndex.java @@ -103,7 +103,7 @@ public class TrigramIndex extends ScalarIndexExtension implements Custo @Override public int getVersion() { - return ENABLED ? 2 + (IdIndex.ourSnapshotMappingsEnabled ? 0xFF:0) : 1; + return ENABLED ? 3 + (IdIndex.ourSnapshotMappingsEnabled ? 0xFF:0) : 1; } @Override diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockUtil.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockUtil.java index d6079a7dfb8b..96cead0659b1 100644 --- a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockUtil.java +++ b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/BlockUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -57,7 +57,8 @@ class BlockUtil { public static Pair, List> splitBlocksByRightBound(@NotNull Block parent, @NotNull TextRange bounds) { final List subBlocks = parent.getSubBlocks(); - if (subBlocks.size() == 0) return new Pair, List>(Collections.emptyList(), Collections.emptyList()); + if (subBlocks.size() == 0) return Pair + .create(Collections.emptyList(), Collections.emptyList()); final ArrayList before = new ArrayList(subBlocks.size() / 2); final ArrayList after = new ArrayList(subBlocks.size() / 2); splitByRightBoundAndCollectBlocks(subBlocks, before, after, bounds); diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java index 1d38710f4c60..91f5d2af767b 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java @@ -40,14 +40,17 @@ import java.awt.*; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Map; public class GotoActionAction extends GotoActionBase implements DumbAware { public static final Comparator ELEMENTS_COMPARATOR = new Comparator() { @Override public int compare(MatchResult o1, MatchResult o2) { + if (o1.elementName.equals(GotoActionModel.INTENTIONS_KEY)) return -1; + if (o2.elementName.equals(GotoActionModel.INTENTIONS_KEY)) return 1; + if (o1.elementName.equals(GotoActionModel.SETTINGS_KEY)) return 1; if (o2.elementName.equals(GotoActionModel.SETTINGS_KEY)) return -1; + return o1.elementName.compareToIgnoreCase(o2.elementName); } }; @@ -103,7 +106,7 @@ public class GotoActionAction extends GotoActionBase implements DumbAware { } else { //element could be AnAction (SearchEverywhere) - final AnAction action = element instanceof AnAction ? ((AnAction)element) : (AnAction)((Map.Entry)element).getKey(); + final AnAction action = element instanceof AnAction ? ((AnAction)element) : ((GotoActionModel.ActionWrapper)element).getAction(); if (action != null) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 30e1bac9316d..ecff44f54a18 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -1718,9 +1718,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA private GotoActionModel createActionModel() { return new GotoActionModel(project, myFocusComponent, myEditor, myFile) { @Override - protected boolean actionMatches(String pattern, @NotNull AnAction anAction) { + protected MatchMode actionMatches(String pattern, @NotNull AnAction anAction) { return NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE) - .matches(anAction.getTemplatePresentation().getText()); + .matches(anAction.getTemplatePresentation().getText()) ? MatchMode.NAME : MatchMode.NONE; } }; } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java b/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java index 3d878249b59c..d79d52b6a0cb 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java @@ -19,11 +19,11 @@ import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CustomShortcutSet; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Trinity; import com.intellij.ui.ComboboxSpeedSearch; import com.intellij.ui.ComboboxWithBrowseButton; import com.intellij.ui.ListCellRendererWrapper; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -31,9 +31,9 @@ import java.awt.event.ActionListener; import java.awt.event.KeyEvent; public class TemplateKindCombo extends ComboboxWithBrowseButton { - private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.TemplateKindCombo"); public TemplateKindCombo() { + //noinspection unchecked getComboBox().setRenderer(new ListCellRendererWrapper() { @Override public void customize(final JList list, final Object value, final int index, final boolean selected, final boolean cellHasFocus) { @@ -56,16 +56,18 @@ public class TemplateKindCombo extends ComboboxWithBrowseButton { setButtonListener(null); } - public void addItem(String presentableName, Icon icon, String templateName) { + public void addItem(@NotNull String presentableName, @Nullable Icon icon, @NotNull String templateName) { + //noinspection unchecked getComboBox().addItem(new Trinity(presentableName, icon, templateName)); } + @NotNull public String getSelectedName() { //noinspection unchecked final Trinity trinity = (Trinity)getComboBox().getSelectedItem(); if (trinity == null) { // design time - return null; + return "yet_unknown"; } return trinity.third; } @@ -74,6 +76,7 @@ public class TemplateKindCombo extends ComboboxWithBrowseButton { if (name == null) return; ComboBoxModel model = getComboBox().getModel(); for (int i = 0, n = model.getSize(); i < n; i++) { + //noinspection unchecked Trinity trinity = (Trinity)model.getElementAt(i); if (name.equals(trinity.third)) { getComboBox().setSelectedItem(trinity); diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/AttributesDefaults.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/AttributesDefaults.java index 1e9686e67572..2bca472d56b2 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/AttributesDefaults.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/AttributesDefaults.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -62,7 +62,7 @@ public class AttributesDefaults { public void add(@NonNls @NotNull final String attributeKey, @NonNls @NotNull final String value, @Nullable final TextRange selectionRange) { - myNamesToValueAndRangeMap.put(attributeKey, new Pair(value, selectionRange)); + myNamesToValueAndRangeMap.put(attributeKey, Pair.create(value, selectionRange)); } public void add(@NonNls @NotNull final String attributeKey, diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java index 3c0d4a4e1f8d..910dddce6391 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java @@ -329,7 +329,7 @@ class FTManager { name = fileName.substring(0, extIndex); ext = fileName.substring(extIndex + nameExtDelimiter.length()); } - return new Pair(name, ext); + return Pair.create(name, ext); } } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/ui/CreateFromTemplatePanel.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/ui/CreateFromTemplatePanel.java index 5accabe91782..84bba59cefdd 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/ui/CreateFromTemplatePanel.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/ui/CreateFromTemplatePanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -170,7 +170,7 @@ public class CreateFromTemplatePanel{ } } } - myAttributes.add(new Pair(attribute, field)); + myAttributes.add(Pair.create(attribute, field)); myAttrPanel.add(label, new GridBagConstraints(0, myLastRow, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, insets, 0, 0)); myAttrPanel.add(field, new GridBagConstraints(1, myLastRow, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 20ebe82d1123..051368b8f1ae 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -48,6 +48,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.util.*; +import java.util.List; public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, Comparator { @NonNls public static final String SETTINGS_KEY = "$$$SETTINGS$$$"; @@ -154,11 +155,11 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C panel.setBackground(bg); - if (value instanceof Map.Entry) { + if (value instanceof ActionWrapper) { - final Map.Entry actionWithParentGroup = (Map.Entry)value; + final ActionWrapper actionWithParentGroup = (ActionWrapper)value; - final AnAction anAction = (AnAction)actionWithParentGroup.getKey(); + final AnAction anAction = actionWithParentGroup.getAction(); final Presentation templatePresentation = anAction.getTemplatePresentation(); final Icon icon = templatePresentation.getIcon(); @@ -169,10 +170,10 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C final Color fg = defaultActionForeground(isSelected, presentation); - final JLabel actionLabel = createActionLabel(anAction, templatePresentation.getText(), fg, bg, icon); + final JLabel actionLabel = createActionLabel(anAction, templatePresentation.getText() + "::" + actionWithParentGroup.getMode(), fg, bg, icon); panel.add(actionLabel, BorderLayout.WEST); - final String groupName = (String)actionWithParentGroup.getValue(); + final String groupName = actionWithParentGroup.getGroupName(); if (groupName != null) { final JLabel groupLabel = new JLabel(groupName); groupLabel.setBackground(bg); @@ -249,12 +250,20 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @Override public int compare(Object o1, Object o2) { - if (o1 instanceof Map.Entry && !(o2 instanceof Map.Entry)) { - return -1; - } - if (o2 instanceof Map.Entry && !(o1 instanceof Map.Entry)) { + if (o1 instanceof OptionDescription && !(o2 instanceof OptionDescription)) { return 1; } + if (o2 instanceof OptionDescription && !(o1 instanceof OptionDescription)) { + return 1; + } + + if (o1 instanceof OptionDescription) { + return ((OptionDescription)o1).compareTo(o2); + } + + if (o1 instanceof ActionWrapper && o2 instanceof ActionWrapper) { + return ((ActionWrapper)o1).compareTo((ActionWrapper)o2); + } return StringUtil.compare(getFullName(o1), getFullName(o2), true); } @@ -301,10 +310,15 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @Override @NotNull public Object[] getElementsByName(final String id, final boolean checkBoxState, final String pattern) { - final HashMap map = new HashMap(); + List objects = new ArrayList(); final AnAction act = myActionManager.getAction(id); if (act != null) { - map.put(act, myActionsMap.get(act)); + final HashMap map = new HashMap(); + final MatchMode matchMode = actionMatches(pattern, act); + final String groupName = myActionsMap.get(act); + if (map.put(act, groupName) == null) { + objects.add(new ActionWrapper(act, groupName, matchMode)); + } if (checkBoxState) { final Set ids = ((ActionManagerImpl)myActionManager).getActionIds(); for (AnAction action : map.keySet()) { //do not add already included actions @@ -313,17 +327,19 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C if (ids.contains(id)) { final AnAction anAction = myActionManager.getAction(id); map.put(anAction, null); + if (anAction != null) { + objects.add(new ActionWrapper(anAction, null, MatchMode.NON_MENU)); + } } } } else if (Comparing.strEqual(id, INTENTIONS_KEY)) { for (String intentionText : myIntentions.keySet()) { final ApplyIntentionAction intentionAction = myIntentions.get(intentionText); - if (actionMatches(pattern, intentionAction)) { - map.put(intentionAction, intentionText); + if (actionMatches(pattern, intentionAction) != MatchMode.NONE) { + objects.add(new ActionWrapper(intentionAction, intentionText, MatchMode.INTENTION)); } } } - Object[] objects = map.entrySet().toArray(new Map.Entry[map.size()]); if (Comparing.strEqual(id, SETTINGS_KEY)) { final Set words = myIndex.getProcessedWords(pattern); Set optionDescriptions = null; @@ -359,12 +375,10 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C iterator.remove(); } } - final Object[] descriptions = optionDescriptions.toArray(); - Arrays.sort(descriptions); - objects = ArrayUtil.mergeArrays(objects, descriptions); + objects.addAll(optionDescriptions); } } - return objects; + return objects.toArray(new Object[objects.size()]); } private void collectActions(Map result, ActionGroup group, final String containingGroupName) { @@ -427,29 +441,31 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @Override public String getElementName(final Object element) { if (element instanceof OptionDescription) return ((OptionDescription)element).getHit(); - if (!(element instanceof Map.Entry)) return null; - return ((AnAction)((Map.Entry)element).getKey()).getTemplatePresentation().getText(); + if (!(element instanceof ActionWrapper)) return null; + return ((ActionWrapper)element).getAction().getTemplatePresentation().getText(); } @Override public boolean matches(@NotNull final String name, @NotNull final String pattern) { final AnAction anAction = myActionManager.getAction(name); if (anAction == null) return true; - return actionMatches(pattern, anAction); + return actionMatches(pattern, anAction) != MatchMode.NONE; } - protected boolean actionMatches(String pattern, @NotNull AnAction anAction) { + protected MatchMode actionMatches(String pattern, @NotNull AnAction anAction) { final Pattern compiledPattern = getPattern(pattern); final Presentation presentation = anAction.getTemplatePresentation(); final String text = presentation.getText(); final String description = presentation.getDescription(); PatternMatcher matcher = getMatcher(); - if (text != null && matcher.matches(text, compiledPattern) || - description != null && !description.equals(text) && matcher.matches(description, compiledPattern)) { - return true; + if (text != null && matcher.matches(text, compiledPattern)) { + return MatchMode.NAME; + } + else if (description != null && !description.equals(text) && matcher.matches(description, compiledPattern)) { + return MatchMode.DESCRIPTION; } final String groupName = myActionsMap.get(anAction); - return groupName != null && text != null && matcher.matches(groupName + " " + text, compiledPattern); + return groupName != null && text != null && matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE; } @Nullable @@ -480,6 +496,10 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return compiledPattern; } + protected enum MatchMode { + NONE, INTENTION, NAME, DESCRIPTION, GROUP, NON_MENU + } + private String convertPattern(String pattern) { final int eol = pattern.indexOf('\n'); if (eol != -1) { @@ -587,4 +607,40 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C private PatternMatcher getMatcher() { return myMatcher.get(); } + + public static class ActionWrapper implements Comparable{ + private AnAction myAction; + private MatchMode myMode; + private String myGroupName; + + public ActionWrapper(AnAction action, String groupName, MatchMode mode) { + myAction = action; + myMode = mode; + myGroupName = groupName; + } + + public AnAction getAction() { + return myAction; + } + + public MatchMode getMode() { + return myMode; + } + + @Override + public int compareTo(ActionWrapper o) { + final int compared = myMode.compareTo(o.getMode()); + return compared != 0 + ? compared + : StringUtil.compare(myAction.getTemplatePresentation().getText(), o.getAction().getTemplatePresentation().getText(), true); + } + + public String getGroupName() { + return myGroupName; + } + + public void setGroupName(String groupName) { + myGroupName = groupName; + } + } } diff --git a/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/ColorSettingsPagesImpl.java b/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/ColorSettingsPagesImpl.java index 1b4e5322380c..dccf451c34f8 100644 --- a/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/ColorSettingsPagesImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/ColorSettingsPagesImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -55,7 +55,7 @@ public class ColorSettingsPagesImpl extends ColorSettingsPages { for (ColorSettingsPage page : getRegisteredPages()) { for (AttributesDescriptor descriptor : page.getAttributeDescriptors()) { if (descriptor.getKey() == key) { - Pair result = new Pair(page, descriptor); + Pair result = Pair.create(page, descriptor); myKeyToDescriptorMap.put(key, result); return result; } diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java index 40e1e793a23f..8482127982a4 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java +++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package com.intellij.openapi.vcs.checkin; import com.intellij.ide.todo.TodoFilter; import com.intellij.ide.todo.TodoIndexPatternProvider; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.diff.impl.string.DiffString; import com.intellij.openapi.diff.ex.DiffFragment; import com.intellij.openapi.diff.impl.ComparisonPolicy; import com.intellij.openapi.diff.impl.fragments.LineFragment; @@ -26,6 +25,7 @@ import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.diff.impl.processing.DiffCorrection; import com.intellij.openapi.diff.impl.processing.DiffFragmentsProcessor; import com.intellij.openapi.diff.impl.processing.DiffPolicy; +import com.intellij.openapi.diff.impl.string.DiffString; import com.intellij.openapi.diff.impl.util.TextDiffTypeEnum; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; @@ -119,7 +119,7 @@ public class TodoCheckinHandlerWorker { myPsiFile = myPsiManager.findFile(afterFile); } if (myPsiFile == null) { - mySkipped.add(new Pair(change.getAfterRevision().getFile(), ourInvalidFile)); + mySkipped.add(Pair.create(change.getAfterRevision().getFile(), ourInvalidFile)); continue; } @@ -182,11 +182,11 @@ public class TodoCheckinHandlerWorker { myBeforeContent = change.getBeforeRevision().getContent(); myAfterContent = change.getAfterRevision().getContent(); if (myAfterContent == null) { - myAcceptor.skipped(new Pair(myAfterFile, ourCannotLoadCurrentRevision)); + myAcceptor.skipped(Pair.create(myAfterFile, ourCannotLoadCurrentRevision)); return; } if (myBeforeContent == null) { - myAcceptor.skipped(new Pair(myAfterFile, ourCannotLoadPreviousRevision)); + myAcceptor.skipped(Pair.create(myAfterFile, ourCannotLoadPreviousRevision)); return; } ArrayList lineFragments = getLineFragments(myAfterFile.getPath(), myBeforeContent, myAfterContent); @@ -229,7 +229,7 @@ public class TodoCheckinHandlerWorker { }); } catch (VcsException e) { LOG.info(e); - myAcceptor.skipped(new Pair(myAfterFile, ourCannotLoadPreviousRevision)); + myAcceptor.skipped(Pair.create(myAfterFile, ourCannotLoadPreviousRevision)); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.java b/platform/lang-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.java index 407945ef7b33..5e797c532c84 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.java +++ b/platform/lang-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -210,7 +210,7 @@ public class ModuleVcsDetector implements ProjectComponent { for(final VirtualFile file: files) { for(final VcsDirectoryMapping mapping: myVcsManager.getDirectoryMappings()) { if (FileUtil.toSystemIndependentName(mapping.getDirectory()).equals(file.getPath())) { - result.add(new Pair(moduleName, mapping)); + result.add(Pair.create(moduleName, mapping)); break; } } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java index b6b66e96d5ab..ad2b44494044 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java @@ -22,13 +22,13 @@ */ package com.intellij.profile.codeInspection.ui; +import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.SeverityRegistrar; import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.codeInspection.ModifiableModel; -import com.intellij.codeInspection.ex.InspectionManagerEx; -import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.codeInspection.ex.InspectionToolRegistrar; +import com.intellij.codeInspection.ex.*; import com.intellij.icons.AllIcons; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.diagnostic.Logger; @@ -266,7 +266,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple private void addProfile(InspectionProfileImpl model) { final String modelName = model.getName(); - final SingleInspectionProfilePanel panel = new SingleInspectionProfilePanel(myProjectProfileManager, modelName, model); + final SingleInspectionProfilePanel panel = createPanel(model, modelName, true); myPanel.add(modelName, panel); if (!myPanels.containsKey(getProfilePrefix(model) + modelName)) { //noinspection unchecked @@ -399,6 +399,10 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple } } + protected boolean acceptTool(InspectionToolWrapper entry) { + return true; + } + @Override public void reset() { myDeletedProfiles.clear(); @@ -408,7 +412,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple for (Profile profile : getProfiles()) { model.addElement(profile); final String profileName = profile.getName(); - final SingleInspectionProfilePanel panel = new SingleInspectionProfilePanel(myProjectProfileManager, profileName, ((InspectionProfileImpl)profile).getModifiableModel()); + final SingleInspectionProfilePanel panel = createPanel((InspectionProfileImpl)profile, profileName, false); putProfile(profile, panel); myPanel.add(profileName, panel); } @@ -438,6 +442,15 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple } } + private SingleInspectionProfilePanel createPanel(InspectionProfileImpl profile, String profileName, boolean model) { + return new SingleInspectionProfilePanel(myProjectProfileManager, profileName, model ? profile : profile.getModifiableModel()) { + @Override + protected boolean accept(InspectionToolWrapper entry) { + return super.accept(entry) && InspectionToolsConfigurable.this.acceptTool(entry); + } + }; + } + private boolean isDeleteEnabled(@NotNull InspectionProfileImpl inspectionProfile) { final ProfileManager profileManager = inspectionProfile.getProfileManager(); diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index 8b980cfd4976..4f4a6f021e91 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -24,6 +24,7 @@ import com.intellij.codeInsight.daemon.impl.SeverityRegistrar; import com.intellij.codeInsight.daemon.impl.SeverityUtil; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.ModifiableModel; import com.intellij.codeInspection.ex.*; @@ -246,9 +247,7 @@ public class SingleInspectionProfilePanel extends JPanel { List tools = profile.getDefaultStates(myProjectProfileManager.getProject()); for (ScopeToolState state : tools) { final ArrayList descriptors = new ArrayList(); - if (state.getLevel() == HighlightDisplayLevel.NON_SWITCHABLE_ERROR) { - continue; - } + if (!accept(state.getTool())) continue; Project project = myProjectProfileManager.getProject(); myDescriptors.put(new Descriptor(state, profile, project), descriptors); InspectionToolWrapper toolWrapper = state.getTool(); @@ -259,6 +258,10 @@ public class SingleInspectionProfilePanel extends JPanel { } } + protected boolean accept(InspectionToolWrapper entry) { + return entry.getDefaultLevel() != HighlightDisplayLevel.NON_SWITCHABLE_ERROR; + } + private void postProcessModification() { wereToolSettingsModified(); //resetup configs diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java index 31502dbd66c5..043ac483d2ed 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -563,7 +563,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager { if (node == null || node.getElementType() != TokenType.WHITE_SPACE) { return new Pair(null, charTable); } - return new Pair(elementAt, charTable); + return Pair.create(elementAt, charTable); } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index 6cb43283952f..fc17bf25a33f 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -135,7 +135,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe LOG.info("Version has changed for stub index " + extension.getKey() + ". The index will be rebuilt."); } FileUtil.delete(indexRootDir); - IndexingStamp.rewriteVersion(versionFile, version); + IndexingStamp.rewriteVersion(versionFile, version); // todo snapshots indices } for (int attempt = 0; attempt < 2; attempt++) { @@ -157,7 +157,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe LOG.info(e); needRebuild = true; FileUtil.delete(indexRootDir); - IndexingStamp.rewriteVersion(versionFile, version); + IndexingStamp.rewriteVersion(versionFile, version); // todo snapshots indices } } return needRebuild; @@ -445,7 +445,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe } private static class MyIndex extends MapReduceIndex { - public MyIndex(final IndexStorage storage) { + public MyIndex(final IndexStorage storage) throws IOException { super(null, null, storage); } diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index 0b565e657cd7..58d562543b1c 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -227,7 +227,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi @NotNull @Override public UpdatableIndex createIndexImplementation(@NotNull final ID indexId, @NotNull final FileBasedIndex owner, @NotNull IndexStorage storage) - throws StorageException { + throws StorageException, IOException { if (storage instanceof MemoryIndexStorage) { final MemoryIndexStorage memStorage = (MemoryIndexStorage)storage; memStorage.addBufferingStateListener(new MemoryIndexStorage.BufferingStateListener() { @@ -273,7 +273,8 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi private class MyIndex extends MapReduceIndex { private StubIndexImpl myStubIndex; - public MyIndex(final ID indexId, final IndexStorage storage, final DataIndexer indexer) throws StorageException { + public MyIndex(final ID indexId, final IndexStorage storage, final DataIndexer indexer) + throws StorageException, IOException { super(indexId, indexer, storage); checkNameStorage(); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ByteSequenceDataExternalizer.java b/platform/lang-impl/src/com/intellij/util/indexing/ByteSequenceDataExternalizer.java new file mode 100644 index 000000000000..216ad325bee3 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/indexing/ByteSequenceDataExternalizer.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2014 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.util.indexing; + +import com.intellij.openapi.util.io.ByteSequence; +import com.intellij.util.io.DataExternalizer; +import org.jetbrains.annotations.NotNull; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.io.InputStream; + +/** +* Created by Maxim.Mossienko on 5/7/2014. +*/ +class ByteSequenceDataExternalizer implements DataExternalizer { + static final ByteSequenceDataExternalizer INSTANCE = new ByteSequenceDataExternalizer(); + @Override + public void save(@NotNull DataOutput out, ByteSequence value) throws IOException { + out.write(value.getBytes(), value.getOffset(), value.getLength()); // todo fix double copying + } + + @Override + public ByteSequence read(@NotNull DataInput in) throws IOException { + byte[] buf = new byte[((InputStream)in).available()]; // todo fix double copying + in.readFully(buf); + return new ByteSequence(buf); + } +} diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java index f888981f21d4..913f57ee14d3 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java @@ -17,11 +17,14 @@ package com.intellij.util.indexing; import com.intellij.openapi.util.Computable; +import com.intellij.util.io.DataExternalizer; import gnu.trove.TIntHashSet; import gnu.trove.TIntProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.DataOutput; +import java.io.IOException; import java.util.Iterator; import java.util.List; @@ -168,4 +171,24 @@ class ChangeTrackingValueContainer extends UpdatableValueContainer public @Nullable TIntHashSet getInvalidated() { return myInvalidated; } + + @Override + public void saveTo(DataOutput out, DataExternalizer externalizer) throws IOException { + if (needsCompacting()) { + getMergedData().saveTo(out, externalizer); + } else { + final TIntHashSet set = myInvalidated; + if (set != null && set.size() > 0) { + for (int inputId : set.toArray()) { + ValueContainerImpl.saveInvalidateCommand(out, inputId); + } + } + + final ValueContainer toAppend = getAddedDelta(); + if (toAppend != null && toAppend.size() > 0) { + toAppend.saveTo(out, externalizer); + } + } + } + } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java b/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java index 6607745d5b44..40e5d26e702e 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java @@ -15,9 +15,7 @@ */ package com.intellij.util.indexing; -import com.intellij.openapi.application.PathManager; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vfs.newvfs.persistent.ContentHashesUtil; import com.intellij.openapi.vfs.newvfs.persistent.FlushingDaemon; import com.intellij.util.io.IOUtil; @@ -33,28 +31,27 @@ import java.security.MessageDigest; * @since 4/10/2014. */ class ContentHashesSupport { - private static final ContentHashesUtil.HashEnumerator ourHashesWithFileType; + private static volatile ContentHashesUtil.HashEnumerator ourHashesWithFileType; - static { - ContentHashesUtil.HashEnumerator hashEnumerator = null; - try { - final File hashEnumeratorFile = new File(PathManager.getIndexRoot(), "hashesWithFileType"); - hashEnumerator = IOUtil.openCleanOrResetBroken(new ThrowableComputable() { - @Override - public ContentHashesUtil.HashEnumerator compute() throws IOException { - return new ContentHashesUtil.HashEnumerator(hashEnumeratorFile, null); - } - }, hashEnumeratorFile); - FlushingDaemon.everyFiveSeconds(new Runnable() { - @Override - public void run() { - if (ourHashesWithFileType.isDirty()) ourHashesWithFileType.force(); - } - }); - } catch (IOException ex) { - throw new RuntimeException(ex); - } finally { - ourHashesWithFileType = hashEnumerator; + static void initContentHashesEnumerator() throws IOException { + if (ourHashesWithFileType != null) return; + synchronized (ContentHashesSupport.class) { + if (ourHashesWithFileType != null) return; + ContentHashesUtil.HashEnumerator hashEnumerator = null; + final File hashEnumeratorFile = new File(IndexInfrastructure.getPersistentIndexRoot(), "hashesWithFileType"); + try { + hashEnumerator = new ContentHashesUtil.HashEnumerator(hashEnumeratorFile, null); + FlushingDaemon.everyFiveSeconds(new Runnable() { + @Override + public void run() { + if (ourHashesWithFileType.isDirty()) ourHashesWithFileType.force(); + } + }); + ourHashesWithFileType = hashEnumerator; + } catch (IOException ex) { + IOUtil.deleteAllFilesStartingWith(hashEnumeratorFile); + throw ex; + } } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/CustomImplementationFileBasedIndexExtension.java b/platform/lang-impl/src/com/intellij/util/indexing/CustomImplementationFileBasedIndexExtension.java index d504daf8e808..e0e5d8e79db8 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/CustomImplementationFileBasedIndexExtension.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/CustomImplementationFileBasedIndexExtension.java @@ -21,8 +21,10 @@ package com.intellij.util.indexing; import org.jetbrains.annotations.NotNull; +import java.io.IOException; + public abstract class CustomImplementationFileBasedIndexExtension extends FileBasedIndexExtension { @NotNull public abstract UpdatableIndex createIndexImplementation(@NotNull ID indexId, @NotNull FileBasedIndex owner, @NotNull IndexStorage storage) - throws StorageException; + throws StorageException, IOException; } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index f9593ebcf58a..fa4935428203 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -381,7 +381,10 @@ public class FileBasedIndexImpl extends FileBasedIndex { versionChanged = true; LOG.info("Version has changed for index " + name + ". The index will be rebuilt."); } - FileUtil.delete(IndexInfrastructure.getIndexRootDir(name)); + if (extension.hasSnapshotMapping() && (isCurrentVersionCorrupted || versionChanged)) { + safeDelete(IndexInfrastructure.getPersistentIndexRootDir(name)); + } + safeDelete(IndexInfrastructure.getIndexRootDir(name)); IndexingStamp.rewriteVersion(versionFile, version); } @@ -394,8 +397,14 @@ public class FileBasedIndexImpl extends FileBasedIndex { throws IOException { MapIndexStorage storage = null; final ID name = extension.getName(); + boolean contentHashesEnumeratorOk = false; + for (int attempt = 0; attempt < 2; attempt++) { try { + if (extension.hasSnapshotMapping()) { + ContentHashesSupport.initContentHashesEnumerator(); + contentHashesEnumeratorOk = true; + } storage = new MapIndexStorage( IndexInfrastructure.getStorageFile(name), extension.getKeyDescriptor(), @@ -443,6 +452,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { } catch (Exception e) { LOG.info(e); + boolean instantiatedStorage = storage != null; try { if (storage != null) storage.close(); storage = null; @@ -450,12 +460,22 @@ public class FileBasedIndexImpl extends FileBasedIndex { catch (Exception ignored) { } - FileUtil.delete(IndexInfrastructure.getIndexRootDir(name)); + safeDelete(IndexInfrastructure.getIndexRootDir(name)); + + if (extension.hasSnapshotMapping() && (!contentHashesEnumeratorOk || instantiatedStorage)) { + safeDelete(IndexInfrastructure.getPersistentIndexRootDir(name)); // todo there is possibility of corruption of storage and content hashes + } IndexingStamp.rewriteVersion(versionFile, version); } } } + private static boolean safeDelete(File dir) { + File directory = FileUtil.findSequentNonexistentFile(dir.getParentFile(), dir.getName(), ""); + boolean success = dir.renameTo(directory); + return FileUtil.delete(success ? directory:dir); + } + private static void saveRegisteredIndices(@NotNull Collection> ids) { final File file = getRegisteredIndicesFile(); try { @@ -519,7 +539,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { extension.hasSnapshotMapping() && IdIndex.ourSnapshotMappingsEnabled ? createInputsIndexExternalizer(extension, indexId, extension.getKeyDescriptor()) : null; - index = new MapReduceIndex(indexId, extension.getIndexer(), storage, externalizer); + index = new MapReduceIndex(indexId, extension.getIndexer(), storage, externalizer, extension.getValueExternalizer()); } index.setInputIdToDataKeysIndex(new Factory>>() { @Override @@ -1591,8 +1611,11 @@ public class FileBasedIndexImpl extends FileBasedIndex { for (ID indexId : myIndices.keySet()) { final MapReduceIndex index = (MapReduceIndex)getIndex(indexId); assert index != null; - final IndexStorage indexStorage = index.getStorage(); - ((MemoryIndexStorage)indexStorage).setBufferingEnabled(enabled); + MemoryIndexStorage storage = (MemoryIndexStorage)index.getStorage(); + if (storage.isBufferingEnabled() == enabled) { + break; // already set it + } + storage.setBufferingEnabled(enabled); } return holder; } @@ -1620,7 +1643,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { indicesToDrop.remove(key.toString()); } for (String s : indicesToDrop) { - FileUtil.delete(IndexInfrastructure.getIndexRootDir(ID.create(s))); + safeDelete(IndexInfrastructure.getIndexRootDir(ID.create(s))); } } @@ -1715,7 +1738,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { byte[] hash; try { currentBytes = content.getBytes(); - hash = fileType.isBinary() ? null:ContentHashesSupport.calcContentHashWithFileType(currentBytes, fileType); + hash = fileType.isBinary() || !IdIndex.ourSnapshotMappingsEnabled ? null:ContentHashesSupport.calcContentHashWithFileType(currentBytes, fileType); } catch (IOException e) { currentBytes = ArrayUtil.EMPTY_BYTE_ARRAY; @@ -2641,6 +2664,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { @SuppressWarnings({"WhileLoopSpinsOnField", "SynchronizeOnThis"}) private static class StorageGuard { private int myHolds = 0; + private int myWaiters = 0; public interface Holder { void leave(); @@ -2663,31 +2687,34 @@ public class FileBasedIndexImpl extends FileBasedIndex { public synchronized Holder enter(boolean mode) { if (mode) { while (myHolds < 0) { - try { - wait(); - } - catch (InterruptedException ignored) { - } + doWait(); } myHolds++; return myTrueHolder; } else { while (myHolds > 0) { - try { - wait(); - } - catch (InterruptedException ignored) { - } + doWait(); } myHolds--; return myFalseHolder; } } + private void doWait() { + try { + ++myWaiters; + wait(); + } + catch (InterruptedException ignored) { + } finally { + --myWaiters; + } + } + private synchronized void leave(boolean mode) { myHolds += mode ? -1 : 1; - if (myHolds == 0) { + if (myHolds == 0 && myWaiters > 0) { notifyAll(); } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java index f795c3594dba..7a70278e3c33 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java @@ -36,6 +36,7 @@ import java.util.Locale; public class IndexInfrastructure { private static final boolean ourUnitTestMode = ApplicationManager.getApplication().isUnitTestMode(); private static final String STUB_VERSIONS = ".versions"; + private static final String PERSISTENT_INDEX_DIRECTORY_NAME = ".persistent"; private IndexInfrastructure() { } @@ -60,14 +61,35 @@ public class IndexInfrastructure { return getIndexDirectory(indexName, false); } + public static File getPersistentIndexRoot() { + File indexDir = new File(PathManager.getIndexRoot() + File.separator + PERSISTENT_INDEX_DIRECTORY_NAME); + indexDir.mkdirs(); + return indexDir; + } + + @NotNull + public static File getPersistentIndexRootDir(@NotNull ID indexName) { + return getIndexDirectory(indexName, false, PERSISTENT_INDEX_DIRECTORY_NAME); + } + @NotNull private static File getIndexDirectory(@NotNull ID indexName, boolean forVersion) { + return getIndexDirectory(indexName, forVersion, ""); + } + + @NotNull + private static File getIndexDirectory(@NotNull ID indexName, boolean forVersion, String relativePath) { final String dirName = indexName.toString().toLowerCase(Locale.US); - // store StubIndices under StubUpdating index' root to ensure they are deleted - // when StubUpdatingIndex version is changed - final File indexDir = indexName instanceof StubIndexKey - ? new File(getIndexRootDir(StubUpdatingIndex.INDEX_ID), forVersion ? STUB_VERSIONS : dirName) - : new File(PathManager.getIndexRoot(), dirName); + File indexDir; + + if (indexName instanceof StubIndexKey) { + // store StubIndices under StubUpdating index' root to ensure they are deleted + // when StubUpdatingIndex version is changed + indexDir = new File(getIndexDirectory(StubUpdatingIndex.INDEX_ID, false, relativePath), forVersion ? STUB_VERSIONS : dirName); + } else { + if (relativePath.length() > 0) relativePath = File.separator + relativePath; + indexDir = new File(PathManager.getIndexRoot() + relativePath, dirName); + } indexDir.mkdirs(); return indexDir; } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java index 3c186c925448..7395a93f8343 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java @@ -19,21 +19,22 @@ package com.intellij.util.indexing; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.*; +import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; +import com.intellij.openapi.util.io.ByteSequence; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.Processor; +import com.intellij.util.SmartList; +import com.intellij.util.SystemProperties; import com.intellij.util.io.*; +import com.intellij.util.io.DataOutputStream; import gnu.trove.THashMap; import gnu.trove.TObjectObjectProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Set; +import java.io.*; +import java.util.*; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -48,10 +49,12 @@ public class MapReduceIndex implements UpdatableIndex myIndexer; @NotNull protected final IndexStorage myStorage; private final boolean myHasSnapshotMapping; + + private final DataExternalizer myValueExternalizer; private final DataExternalizer> mySnapshotIndexExternalizer; private PersistentHashMap> myInputsIndex; - private PersistentHashMap> mySnapshotMapping; + private final PersistentHashMap myContents; private PersistentHashMap myInputsSnapshotMapping; private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock(); @@ -60,19 +63,34 @@ public class MapReduceIndex implements UpdatableIndex indexId, DataIndexer indexer, - @NotNull IndexStorage storage) { - this(indexId, indexer, storage, null); + @NotNull IndexStorage storage) throws IOException { + this(indexId, indexer, storage, null, null); } public MapReduceIndex(@Nullable final ID indexId, DataIndexer indexer, @NotNull IndexStorage storage, - DataExternalizer> snapshotIndexExternalizer) { + DataExternalizer> snapshotIndexExternalizer, + DataExternalizer valueDataExternalizer) throws IOException { myIndexId = indexId; myIndexer = indexer; myStorage = storage; myHasSnapshotMapping = snapshotIndexExternalizer != null; + mySnapshotIndexExternalizer = snapshotIndexExternalizer; + myValueExternalizer = valueDataExternalizer; + final File saved = myHasSnapshotMapping && myIndexId != null ? new File(IndexInfrastructure.getPersistentIndexRootDir(myIndexId), "values") : null; + + if (saved != null) { + try { + myContents = new PersistentHashMap(saved, EnumeratorIntegerDescriptor.INSTANCE, ByteSequenceDataExternalizer.INSTANCE); + } catch (IOException ex) { + IOUtil.deleteAllFilesStartingWith(saved); + throw ex; + } + } else { + myContents = null; + } } @NotNull @@ -93,10 +111,6 @@ public class MapReduceIndex implements UpdatableIndex implements UpdatableIndex createInputSnapshotMapping() throws IOException { assert myIndexId != null; final File fileIdToHashIdFile = new File(IndexInfrastructure.getIndexRootDir(myIndexId), "fileIdToHashId"); - return IOUtil.openCleanOrResetBroken(new ThrowableComputable, IOException>() { - @Override - public PersistentHashMap compute() throws IOException { - return new PersistentHashMap(fileIdToHashIdFile, EnumeratorIntegerDescriptor.INSTANCE, EnumeratorIntegerDescriptor.INSTANCE, 4096) { - @Override - protected boolean wantCompactIntegralValues() { - return true; - } - }; - } - }, fileIdToHashIdFile); + try { + return new PersistentHashMap(fileIdToHashIdFile, EnumeratorIntegerDescriptor.INSTANCE, + EnumeratorIntegerDescriptor.INSTANCE, 4096) { + @Override + protected boolean wantNonnegativeIntegralValues() { + return true; + } + }; + } + catch (IOException ex) { + IOUtil.deleteAllFilesStartingWith(fileIdToHashIdFile); + throw ex; + } } private static void cleanMapping(@NotNull PersistentHashMap index) { @@ -142,7 +158,7 @@ public class MapReduceIndex implements UpdatableIndex implements UpdatableIndex implements UpdatableIndex> createSnapshotMappingIndex() throws IOException { - assert myIndexId != null; - final File hashIdToKeysFile = new File(IndexInfrastructure.getIndexRootDir(myIndexId), "hashIdToKeys"); - return IOUtil.openCleanOrResetBroken(new ThrowableComputable>, IOException>() { - @Override - public PersistentHashMap> compute() throws IOException { - return new PersistentHashMap>(hashIdToKeysFile, EnumeratorIntegerDescriptor.INSTANCE, mySnapshotIndexExternalizer); - } - }, hashIdToKeysFile); - } - @Nullable private PersistentHashMap> createInputsIndex() throws IOException { Factory>> factory = myInputsIndexFactory; @@ -275,40 +279,64 @@ public class MapReduceIndex implements UpdatableIndex update(final int inputId, @Nullable Input content) { + final boolean weProcessPhysicalContent = content == null || + (content instanceof FileContent && + ((FileContent)content).getUserData(FileBasedIndexImpl.ourPhysicalContentKey) != null); - final Map data = content != null ? myIndexer.map(content) : Collections.emptyMap(); + Map data = null; + boolean havePersistentData = false; + Integer hashId = null; + if (myContents != null && weProcessPhysicalContent && content != null) { + try { + hashId = getHashOfContent((FileContent)content); + if (doReadSavedPersistentData) { + ByteSequence bytes = myContents.get(hashId); + if (bytes != null) { + data = deserializeSavedPersistentData(bytes); + havePersistentData = true; + } + } else { + havePersistentData = myContents.containsMapping(hashId); + } + } catch (IOException ex) { + // todo: + throw new RuntimeException(ex); + } + } + + if (data == null) data = content != null ? myIndexer.map(content) : Collections.emptyMap(); + + if (hashId != null && !havePersistentData && data.size() > 0) { + savePersistentData(data, hashId); + } ProgressManager.checkCanceled(); final NotNullComputable> oldKeysGetter; final int savedInputId; - - boolean weProcessPhysicalContent = content == null || - (content instanceof FileContent && - ((FileContent)content).getUserData(FileBasedIndexImpl.ourPhysicalContentKey) != null); - if (myHasSnapshotMapping && weProcessPhysicalContent) { - try { // optimistically (out of index update write section) read current snapshot keys for file - final Integer hashId = myInputsSnapshotMapping.get(inputId); - final Collection keys = hashId != null ? mySnapshotMapping.get(hashId): null; + try { oldKeysGetter = new NotNullComputable>() { - @NotNull - @Override - public Collection compute() { + @NotNull + @Override + public Collection compute() { try { Integer currentHashId = myInputsSnapshotMapping.get(inputId); Collection currentKeys; - if ((currentHashId == null && hashId == null) || (currentHashId != null && currentHashId.equals(hashId))) { - currentKeys = keys; - } else { // optimistic reading file's current keys failed - currentKeys = currentHashId != null ? mySnapshotMapping.get(currentHashId): null; + if (currentHashId != null) { + ByteSequence byteSequence = myContents.get(currentHashId); + currentKeys = byteSequence != null ? deserializeSavedPersistentData(byteSequence).keySet() : Collections.emptyList(); + } + else { + currentKeys = Collections.emptyList(); } - return currentKeys == null ? Collections.emptyList() : currentKeys; + return currentKeys; } catch (IOException e) { throw new RuntimeException(e); } @@ -316,22 +344,7 @@ public class MapReduceIndex implements UpdatableIndex implements UpdatableIndex finalData = data; return new Computable() { @Override public Boolean compute() { @@ -364,7 +378,7 @@ public class MapReduceIndex implements UpdatableIndex implements UpdatableIndex deserializeSavedPersistentData(ByteSequence bytes) throws IOException { + DataInputStream stream = new DataInputStream(new UnsyncByteArrayInputStream(bytes.getBytes(), bytes.getOffset(), bytes.getLength())); + int pairs = DataInputOutputUtil.readINT(stream); + if (pairs == 0) return Collections.emptyMap(); + Map result = new THashMap(pairs); + while (stream.available() > 0) { + Value value = myValueExternalizer.read(stream); + Collection keys = mySnapshotIndexExternalizer.read(stream); + for(Key k:keys) result.put(k, value); + } + return result; + } + + private static Integer getHashOfContent(FileContent content) throws IOException { + Integer previouslyCalculatedContentHashId = content.getUserData(ourSavedContentHashIdKey); + if (previouslyCalculatedContentHashId == null) { + byte[] hash = content instanceof FileContentImpl ? ((FileContentImpl)content).getHash():null; + if (hash == null) { + previouslyCalculatedContentHashId = ContentHashesSupport + .calcContentHashIdWithFileType(content.getContent(), content.getFileType()); + } else { + previouslyCalculatedContentHashId = ContentHashesSupport.enumerateHash(hash); + } + content.putUserData(ourSavedContentHashIdKey, previouslyCalculatedContentHashId); + } + return previouslyCalculatedContentHashId; + } + + private static final ThreadLocalCachedByteArray ourSpareByteArray = new ThreadLocalCachedByteArray(); + + private void savePersistentData(Map data, int id) { + try { + BufferExposingByteArrayOutputStream out = new BufferExposingByteArrayOutputStream(ourSpareByteArray.getBuffer(4 * data.size())); + DataOutputStream stream = new DataOutputStream(out); + int size = data.size(); + DataInputOutputUtil.writeINT(stream, size); + + if (size > 0) { + THashMap> values = new THashMap>(); + List keysForNullValue = null; + for (Map.Entry e : data.entrySet()) { + Value value = e.getValue(); + + List keys = value != null ? values.get(value):keysForNullValue; + if (keys == null) { + if (value != null) values.put(value, keys = new SmartList()); + else keys = keysForNullValue = new SmartList(); + } + keys.add(e.getKey()); + } + + if (keysForNullValue != null) { + myValueExternalizer.save(stream, null); + mySnapshotIndexExternalizer.save(stream, keysForNullValue); + } + + for(Value value:values.keySet()) { + myValueExternalizer.save(stream, value); + mySnapshotIndexExternalizer.save(stream, values.get(value)); + } + } + + myContents.put(id, new ByteSequence(out.getInternalBuffer(), 0, out.size())); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + private static final com.intellij.openapi.util.Key ourSavedContentHashIdKey = com.intellij.openapi.util.Key.create("saved.content.hash.id"); protected void updateWithMap(final int inputId, diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java index 47efe30fbf84..3a5864d1c908 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java @@ -16,8 +16,11 @@ package com.intellij.util.indexing; +import com.intellij.util.io.DataExternalizer; import org.jetbrains.annotations.NotNull; +import java.io.DataOutput; +import java.io.IOException; import java.util.Iterator; import java.util.List; @@ -78,4 +81,6 @@ public abstract class ValueContainer { void setNeedsCompacting(boolean value) { myNeedsCompacting = value; } + + public abstract void saveTo(DataOutput out, DataExternalizer externalizer) throws IOException; } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java index ddc538154177..8fb895ba7e00 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java @@ -18,11 +18,18 @@ package com.intellij.util.indexing; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.ThreadLocalCachedIntArray; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.SmartList; import com.intellij.util.containers.EmptyIterator; +import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.DataInputOutputUtil; import gnu.trove.*; import org.jetbrains.annotations.NotNull; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.IOException; import java.util.*; /** @@ -413,6 +420,133 @@ class ValueContainerImpl extends UpdatableValueContainer implement } } + private static final ThreadLocalCachedIntArray ourSpareBuffer = new ThreadLocalCachedIntArray(); + + private static final int INT_BITS_SHIFT = 5; + private static int nextSetBit(int bitIndex, int[] bits, int bitsLength) { + int wordIndex = bitIndex >> INT_BITS_SHIFT; + if (wordIndex >= bitsLength) { + return -1; + } + + int word = bits[wordIndex] & (-1 << bitIndex); + + while (true) { + if (word != 0) { + return (wordIndex << INT_BITS_SHIFT) + Long.numberOfTrailingZeros(word); + } + if (++wordIndex == bitsLength) { + return -1; + } + word = bits[wordIndex]; + } + } + + @Override + public void saveTo(DataOutput out, DataExternalizer externalizer) throws IOException { + DataInputOutputUtil.writeINT(out, size()); + + for (final Iterator valueIterator = getValueIterator(); valueIterator.hasNext();) { + final Value value = valueIterator.next(); + externalizer.save(out, value); + Object input = getInput(value); + + if (input instanceof Integer) { + DataInputOutputUtil.writeINT(out, (Integer)input); // most common 90% case during index building + } else { + // serialize positive file ids with delta encoding after sorting numbers via bitset + + if (input instanceof TIntHashSet) { + TIntHashSet set = (TIntHashSet)input; + DataInputOutputUtil.writeINT(out, -set.size()); + // todo it would be nice to have compressed random access serializable bitset or at least file ids sorted + final int[] max = {0}, min = {Integer.MAX_VALUE}; + + set.forEach(new TIntProcedure() { + @Override + public boolean execute(int value) { + max[0] = Math.max(max[0], value); + min[0] = Math.min(min[0], value); + return true; + } + }); + + assert min[0] > 0; + + final int offset = (min[0] >> INT_BITS_SHIFT) << INT_BITS_SHIFT; + final int bitsLength = ((max[0] - offset) >> INT_BITS_SHIFT) + 1; + final int[] bits = ourSpareBuffer.getBuffer(bitsLength); + for(int i = 0; i < bitsLength; ++i) bits[i] = 0; + + set.forEach(new TIntProcedure() { + @Override + public boolean execute(int value) { + final int id = value - offset; + bits[id >> INT_BITS_SHIFT] |= (1 << (id)); + return true; + } + }); + + int pos = nextSetBit(0, bits, bitsLength); + int prev = 0; + + while (pos != -1) { + DataInputOutputUtil.writeINT(out, pos + offset - prev); + prev = pos + offset; + pos = nextSetBit(pos + 1, bits, bitsLength); + } + } else if (input instanceof IdBitSet) { + IdBitSet idBitSet = (IdBitSet)input; + + DataInputOutputUtil.writeINT(out, -idBitSet.numberOfBitsSet()); + + int pos = idBitSet.nextSetBit(0); + int prev = 0; + + while (pos != -1) { + DataInputOutputUtil.writeINT(out, pos - prev); + prev = pos; + pos = idBitSet.nextSetBit(pos + 1); + } + } else { + throw new IncorrectOperationException("Unexpected else"); + } + } + } + } + + static void saveInvalidateCommand(DataOutput out, int inputId) throws IOException { + DataInputOutputUtil.writeINT(out, -inputId); + } + + public void readFrom(DataInputStream stream, DataExternalizer externalizer) throws IOException { + while (stream.available() > 0) { + final int valueCount = DataInputOutputUtil.readINT(stream); + if (valueCount < 0) { + removeAssociatedValue(-valueCount); + setNeedsCompacting(true); + } + else { + for (int valueIdx = 0; valueIdx < valueCount; valueIdx++) { + final Value value = externalizer.read(stream); + int idCountOrSingleValue = DataInputOutputUtil.readINT(stream); + if (idCountOrSingleValue > 0) { + addValue(idCountOrSingleValue, value); + } else { + idCountOrSingleValue = -idCountOrSingleValue; + ensureFileSetCapacityForValue(value, idCountOrSingleValue); + int prev = 0; + for (int i = 0; i < idCountOrSingleValue; i++) { + final int id = DataInputOutputUtil.readINT(stream); + addValue(prev + id, value); + prev += id; + } + } + } + } + } + } + private static class SingleValueIterator implements IntIterator { private final int myValue; private boolean myValueRead = false; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java index c4f12ec2095e..0eb1a5410083 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java @@ -15,29 +15,28 @@ */ package com.intellij.util.indexing; -import com.intellij.openapi.util.ThreadLocalCachedIntArray; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; -import com.intellij.util.io.*; +import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.DataOutputStream; -import gnu.trove.TIntHashSet; +import com.intellij.util.io.KeyDescriptor; +import com.intellij.util.io.PersistentHashMap; import org.jetbrains.annotations.NotNull; import java.io.*; -import java.util.Iterator; /** * @author Dmitry Avdeev * Date: 8/10/11 */ class ValueContainerMap extends PersistentHashMap> { - @NotNull private final ValueContainerExternalizer myValueContainerExternalizer; + @NotNull private final DataExternalizer myValueExternalizer; ValueContainerMap(@NotNull final File file, @NotNull KeyDescriptor keyKeyDescriptor, @NotNull DataExternalizer valueExternalizer) throws IOException { super(file, keyKeyDescriptor, new ValueContainerExternalizer(valueExternalizer)); - myValueContainerExternalizer = (ValueContainerExternalizer)myValueExternalizer; + myValueExternalizer = valueExternalizer; } @NotNull @@ -53,17 +52,7 @@ class ValueContainerMap extends PersistentHashMap 0) { - for (int inputId : set.toArray()) { - ValueContainerExternalizer.saveInvalidateCommand(_out, inputId); - } - } - - final ValueContainer toAppend = valueContainer.getAddedDelta(); - if (toAppend != null && toAppend.size() > 0) { - myValueContainerExternalizer.save(_out, toAppend); - } + valueContainer.saveTo(_out, myValueExternalizer); appendData(key, new PersistentHashMap.ValueDataAppender() { @Override @@ -80,122 +69,24 @@ class ValueContainerMap extends PersistentHashMap implements DataExternalizer> { - @NotNull private final DataExternalizer myExternalizer; + @NotNull private final DataExternalizer myValueExternalizer; - private ValueContainerExternalizer(@NotNull DataExternalizer externalizer) { - myExternalizer = externalizer; + private ValueContainerExternalizer(@NotNull DataExternalizer valueExternalizer) { + myValueExternalizer = valueExternalizer; } @Override public void save(@NotNull final DataOutput out, @NotNull final ValueContainer container) throws IOException { - saveImpl(out, container); - } - - public static void saveInvalidateCommand(final DataOutput out, int inputId) throws IOException { - DataInputOutputUtil.writeINT(out, -inputId); - } - private static final ThreadLocalCachedIntArray ourSpareBuffer = new ThreadLocalCachedIntArray(); - - private void saveImpl(@NotNull DataOutput out, @NotNull final ValueContainer container) throws IOException { - DataInputOutputUtil.writeINT(out, container.size()); - - for (final Iterator valueIterator = container.getValueIterator(); valueIterator.hasNext();) { - final T value = valueIterator.next(); - myExternalizer.save(out, value); - ValueContainer.IntIterator ids = container.getInputIdsIterator(value); - - if (ids.size() == 1) { - DataInputOutputUtil.writeINT(out, ids.next()); // most common 90% case during index building - } else { - DataInputOutputUtil.writeINT(out, -ids.size()); - // serialize positive file ids with delta encoding after sorting numbers via bitset - // todo it would be nice to have compressed random access serializable bitset or at least file ids sorted - int max = 0, min = Integer.MAX_VALUE; - - while (ids.hasNext()) { - final int id = ids.next(); - max = Math.max(id, max); - min = Math.min(id, min); - } - - assert min > 0; - - final int offset = (min >> INT_BITS_SHIFT) << INT_BITS_SHIFT; - final int bitsLength = ((max - offset) >> INT_BITS_SHIFT) + 1; - final int[] bits = ourSpareBuffer.getBuffer(bitsLength); - for(int i = 0; i < bitsLength; ++i) bits[i] = 0; - - ids = container.getInputIdsIterator(value); - while (ids.hasNext()) { - final int id = ids.next() - offset; - bits[id >> INT_BITS_SHIFT] |= (1 << (id)); - } - - int pos = nextSetBit(0, bits, bitsLength); - int prev = 0; - - while (pos != -1) { - DataInputOutputUtil.writeINT(out, pos + offset - prev); - prev = pos + offset; - pos = nextSetBit(pos + 1, bits, bitsLength); - } - } - } + container.saveTo(out, myValueExternalizer); } @NotNull @Override public ValueContainerImpl read(@NotNull final DataInput in) throws IOException { - DataInputStream stream = (DataInputStream)in; final ValueContainerImpl valueContainer = new ValueContainerImpl(); - while (stream.available() > 0) { - final int valueCount = DataInputOutputUtil.readINT(in); - if (valueCount < 0) { - valueContainer.removeAssociatedValue(-valueCount); - valueContainer.setNeedsCompacting(true); - } - else { - for (int valueIdx = 0; valueIdx < valueCount; valueIdx++) { - final T value = myExternalizer.read(in); - int idCountOrSingleValue = DataInputOutputUtil.readINT(in); - if (idCountOrSingleValue > 0) { - valueContainer.addValue(idCountOrSingleValue, value); - } else { - idCountOrSingleValue = -idCountOrSingleValue; - valueContainer.ensureFileSetCapacityForValue(value, idCountOrSingleValue); - int prev = 0; - for (int i = 0; i < idCountOrSingleValue; i++) { - final int id = DataInputOutputUtil.readINT(in); - valueContainer.addValue(prev + id, value); - prev += id; - } - } - } - } - } + valueContainer.readFrom((DataInputStream)in, myValueExternalizer); return valueContainer; } - - private static final int INT_BITS_SHIFT = 5; - private static int nextSetBit(int bitIndex, int[] bits, int bitsLength) { - int wordIndex = bitIndex >> INT_BITS_SHIFT; - if (wordIndex >= bitsLength) { - return -1; - } - - int word = bits[wordIndex] & (-1 << bitIndex); - - while (true) { - if (word != 0) { - return (wordIndex << INT_BITS_SHIFT) + Long.numberOfTrailingZeros(word); - } - if (++wordIndex == bitsLength) { - return -1; - } - word = bits[wordIndex]; - } - } } - } diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index a37059f98cfa..90308f5dbfda 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -91,7 +91,8 @@ public class BrowserUtil { } private static BrowserLauncher getBrowserLauncher() { - return ApplicationManager.getApplication() == null ? new BrowserLauncherAppless() : BrowserLauncher.getInstance(); + BrowserLauncher launcher = ApplicationManager.getApplication() == null ? null : BrowserLauncher.getInstance(); + return launcher == null ? new BrowserLauncherAppless() : launcher; } public static void open(@NotNull @NonNls String url) { diff --git a/platform/platform-api/src/com/intellij/ide/dnd/DnDSupport.java b/platform/platform-api/src/com/intellij/ide/dnd/DnDSupport.java index cb4302a2e3ae..2a70e0f4e3a9 100644 --- a/platform/platform-api/src/com/intellij/ide/dnd/DnDSupport.java +++ b/platform/platform-api/src/com/intellij/ide/dnd/DnDSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -93,7 +93,7 @@ public class DnDSupport implements DnDTarget, DnDSource, Disposable { final DnDImage image = myImageProvider.fun(new DnDActionInfo(action, dragOrigin)); if (image != null) { final Point point = image.getPoint(); - return new Pair(image.getImage(), point == null ? dragOrigin : point); + return Pair.create(image.getImage(), point == null ? dragOrigin : point); } } return null; diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java index 0e21560c7e08..30c1aa2b7859 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -161,7 +161,7 @@ public class DefaultActionGroup extends ActionGroup { actionAdded(action, actionManager); } else { - myPairs.add(new Pair(action, constraint)); + myPairs.add(Pair.create(action, constraint)); } } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequest.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequest.java index 9dd01a443427..2262948ae269 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequest.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -91,7 +91,7 @@ public abstract class DiffRequest { } public void addOtherLayer(final String name, DiffRequest request) { - myAdditional.add(new Pair(name, request)); + myAdditional.add(Pair.create(name, request)); } public List> getOtherLayers() { diff --git a/platform/platform-api/src/com/intellij/openapi/options/SettingsEditorGroup.java b/platform/platform-api/src/com/intellij/openapi/options/SettingsEditorGroup.java index 60abc11eecf1..6ed22110f03a 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/SettingsEditorGroup.java +++ b/platform/platform-api/src/com/intellij/openapi/options/SettingsEditorGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -28,7 +28,7 @@ public class SettingsEditorGroup extends SettingsEditor { public void addEditor(String name, SettingsEditor editor) { Disposer.register(this, editor); - myEditors.add(new Pair>(name, editor)); + myEditors.add(Pair.create(name, editor)); } public void addGroup(SettingsEditorGroup group) { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index 5f79c6a5dd40..72ac12abc065 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -1027,7 +1027,7 @@ public class Messages { else { InputDialogWithCheckbox dialog = new InputDialogWithCheckbox(message, title, checkboxText, checked, checkboxEnabled, icon, initialValue, validator); dialog.show(); - return new Pair(dialog.getInputString(), dialog.isChecked()); + return Pair.create(dialog.getInputString(), dialog.isChecked()); } } diff --git a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java index 4dfec8669bf9..94eaa4db1ccb 100644 --- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java +++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java @@ -62,7 +62,7 @@ import java.util.*; }, storageChooser = HttpConfigurable.StorageChooser.class ) -public class HttpConfigurable implements PersistentStateComponent, ApplicationComponent, JDOMExternalizable, +public class HttpConfigurable implements PersistentStateComponent, ApplicationComponent, ExportableApplicationComponent { private static final Logger LOG = Logger.getInstance("#com.intellij.util.net.HttpConfigurable"); public boolean PROXY_TYPE_IS_SOCKS = false; @@ -98,6 +98,7 @@ public class HttpConfigurable implements PersistentStateComponent EP_NAME = ExtensionPointName.create("com.intellij.httpRequestHandler"); - public boolean isSupported(FullHttpRequest request) { + public boolean isSupported(@NotNull FullHttpRequest request) { return request.getMethod() == HttpMethod.GET || request.getMethod() == HttpMethod.HEAD; } - public abstract boolean process(QueryStringDecoder urlDecoder, FullHttpRequest request, ChannelHandlerContext context) + public abstract boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException; protected static boolean checkPrefix(@NotNull String uri, @NotNull String prefix) { diff --git a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroTable.java b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroTable.java index a6ee5c3cf292..f574d5211b0b 100644 --- a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroTable.java +++ b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroTable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -90,7 +90,7 @@ public class PathMacroTable extends Table { macroEditor.show(); if (macroEditor.isOK()) { final String name = macroEditor.getName(); - myMacros.add(new Pair(name, macroEditor.getValue())); + myMacros.add(Pair.create(name, macroEditor.getValue())); Collections.sort(myMacros, MACRO_COMPARATOR); final int index = indexOfMacroWithName(name); LOG.assertTrue(index >= 0); @@ -176,7 +176,7 @@ public class PathMacroTable extends Table { if (myUndefinedMacroNames != null) { for (String undefinedMacroName : myUndefinedMacroNames) { - macros.add(new Pair(undefinedMacroName, "")); + macros.add(Pair.create(undefinedMacroName, "")); } } Collections.sort(macros, MACRO_COMPARATOR); diff --git a/platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java b/platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java index 2fbb2d17a41c..1e9f2a1fbc50 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java @@ -20,6 +20,7 @@ import com.intellij.idea.Main; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.ErrorLogger; +import com.intellij.openapi.diagnostic.ExceptionWithAttachments; import com.intellij.openapi.diagnostic.IdeaLoggingEvent; import com.intellij.util.ExceptionUtil; import com.intellij.util.containers.ContainerUtil; @@ -100,11 +101,7 @@ public class DialogAppender extends AppenderSkeleton { if (info == null) { return; } - Throwable throwable = info.getThrowable(); - //noinspection ThrowableResultOfMethodCallIgnored - Throwable rootCause = ExceptionUtil.getRootCause(throwable); - ideaEvent = rootCause instanceof LogEventException ? ((LogEventException)rootCause).getLogMessage() : - new IdeaLoggingEvent(message == null ? " " : message.toString(), throwable); + ideaEvent = extractLoggingEvent(message, info.getThrowable()); } for (int i = errorLoggers.length - 1; i >= 0; i--) { final ErrorLogger logger = errorLoggers[i]; @@ -134,6 +131,22 @@ public class DialogAppender extends AppenderSkeleton { } } + private static IdeaLoggingEvent extractLoggingEvent(Object message, Throwable throwable) { + //noinspection ThrowableResultOfMethodCallIgnored + Throwable rootCause = ExceptionUtil.getRootCause(throwable); + if (rootCause instanceof LogEventException) { + return ((LogEventException)rootCause).getLogMessage(); + } + + String strMessage = message == null ? " " : message.toString(); + ExceptionWithAttachments withAttachments = ExceptionUtil.findCause(throwable, ExceptionWithAttachments.class); + if (withAttachments != null) { + return LogMessageEx.createEvent(strMessage, ExceptionUtil.getThrowableText(throwable), withAttachments.getAttachments()); + } + + return new IdeaLoggingEvent(strMessage, throwable); + } + @TestOnly Runnable getDialogRunnable() { return myDialogRunnable; diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java index 14a3180d9b4e..98e803981fe0 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java @@ -138,13 +138,11 @@ public class EditorHyperlinkSupport { @Nullable private RangeHighlighter findLinkRangeAt(final int offset) { + //noinspection LoopStatementThatDoesntLoop for (final RangeHighlighter highlighter : getHyperlinks(offset, offset, myEditor)) { - if (highlighter.isValid()) { return highlighter; - } } return null; - } @Nullable @@ -160,7 +158,6 @@ public class EditorHyperlinkSupport { } public static List getHyperlinks(int startOffset, int endOffset, final Editor editor) { - List list = new ArrayList(); final MarkupModelEx markupModel = (MarkupModelEx)editor.getMarkupModel(); final CommonProcessors.CollectProcessor processor = new CommonProcessors.CollectProcessor(); markupModel.processRangeHighlightersOverlappingWith(startOffset, endOffset, @@ -168,11 +165,12 @@ public class EditorHyperlinkSupport { @Override public boolean value(RangeHighlighterEx rangeHighlighterEx) { return HYPERLINK_LAYER == rangeHighlighterEx.getLayer() && + rangeHighlighterEx.isValid() && getHyperlinkInfo(rangeHighlighterEx) != null; } - }, processor)); - list.addAll(processor.getResults()); - return list; + }, processor) + ); + return new ArrayList(processor.getResults()); } public void removeHyperlink(@NotNull RangeHighlighter hyperlink) { diff --git a/platform/platform-impl/src/com/intellij/featureStatistics/ProductivityFeaturesRegistryImpl.java b/platform/platform-impl/src/com/intellij/featureStatistics/ProductivityFeaturesRegistryImpl.java index 870a163003ca..edae16b0a004 100644 --- a/platform/platform-impl/src/com/intellij/featureStatistics/ProductivityFeaturesRegistryImpl.java +++ b/platform/platform-impl/src/com/intellij/featureStatistics/ProductivityFeaturesRegistryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -104,7 +104,7 @@ public class ProductivityFeaturesRegistryImpl extends ProductivityFeaturesRegist final ApplicabilityFilter[] applicabilityFilters = provider.getApplicabilityFilters(); if (applicabilityFilters != null) { for (ApplicabilityFilter applicabilityFilter : applicabilityFilters) { - myApplicabilityFilters.add(new Pair(applicabilityFilter.getPrefix(), applicabilityFilter)); + myApplicabilityFilters.add(Pair.create(applicabilityFilter.getPrefix(), applicabilityFilter)); } } } @@ -123,7 +123,7 @@ public class ProductivityFeaturesRegistryImpl extends ProductivityFeaturesRegist } ApplicabilityFilter filter = (ApplicabilityFilter)klass.newInstance(); - myApplicabilityFilters.add(new Pair(filterElement.getAttributeValue(PREFIX_ATTR), filter)); + myApplicabilityFilters.add(Pair.create(filterElement.getAttributeValue(PREFIX_ATTR), filter)); } catch (Exception e) { LOG.error("Cannot instantiate filter " + className, e); diff --git a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java index b5a5b40b3848..e3e1945d14f1 100644 --- a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java @@ -58,12 +58,12 @@ public class XmlRpcServerImpl implements XmlRpcServer { static final class XmlRpcRequestHandler extends HttpRequestHandler { @Override - public boolean isSupported(FullHttpRequest request) { + public boolean isSupported(@NotNull FullHttpRequest request) { return request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS; } @Override - public boolean process(QueryStringDecoder urlDecoder, FullHttpRequest request, ChannelHandlerContext context) throws IOException { + public boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException { return SERVICE.getInstance().process(urlDecoder.path(), request, context, null); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacro.java b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacro.java index 09d88584d5cc..be8f2d66dda4 100644 --- a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacro.java +++ b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacro.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -125,7 +125,7 @@ public class ActionMacro implements JDOMExternalizable { TypedDescriptor typedDescriptor = (TypedDescriptor)action; actionNode.setText(typedDescriptor.getText().replaceAll(" ", " ")); actionNode.setAttribute(ATTRIBUTE_KEY_CODES, unparseKeyCodes( - new Pair, List>(typedDescriptor.getKeyCodes(), typedDescriptor.getKeyModifiers()))); + Pair.create(typedDescriptor.getKeyCodes(), typedDescriptor.getKeyModifiers()))); } else if (action instanceof IdActionDescriptor) { actionNode = new Element(ELEMENT_ACTION); diff --git a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java index 4d2529ed2375..ecaf9da52151 100644 --- a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -165,7 +165,7 @@ public class ActionMacroConfigurationPanel implements Disposable { while (!canRenameMacro(newName)); if (myRenamingList == null) myRenamingList = new ArrayList>(); - myRenamingList.add(new Pair(macro.getName(), newName)); + myRenamingList.add(Pair.create(macro.getName(), newName)); macro.setName(newName); myMacrosList.repaint(); } diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java index 91e2625c3a6b..ea0ff866b030 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java @@ -89,16 +89,10 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep { } }); panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - panel.add(radioButton, BorderLayout.NORTH); - final JLabel label = new JLabel(myColumnMode ? IconUtil.scale(icon, .2) : icon) { - @Override - public Dimension getPreferredSize() { - Dimension size = super.getPreferredSize(); - if (myColumnMode) size.width *=2; - return size; - } - }; + panel.add(radioButton, myColumnMode ? BorderLayout.WEST : BorderLayout.NORTH); + final JLabel label = new JLabel(myColumnMode ? IconUtil.scale(icon, .33) : icon); label.setVerticalAlignment(SwingConstants.TOP); + label.setHorizontalAlignment(SwingConstants.RIGHT); panel.add(label, BorderLayout.CENTER); group.add(radioButton); @@ -106,11 +100,13 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep { } add(buttonsPanel, BorderLayout.CENTER); myPreviewLabel = new JLabel(); - myPreviewLabel.setHorizontalAlignment(SwingConstants.CENTER); + myPreviewLabel.setHorizontalAlignment(myColumnMode ? SwingConstants.LEFT : SwingConstants.CENTER); myPreviewLabel.setVerticalAlignment(SwingConstants.CENTER); if (myColumnMode) { add(buttonsPanel, BorderLayout.WEST); - add(myPreviewLabel, BorderLayout.CENTER); + JPanel wrapperPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + wrapperPanel.add(myPreviewLabel); + add(wrapperPanel, BorderLayout.CENTER); } applyLaf(myDefaultLafName, this); myInitial = false; @@ -161,7 +157,7 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep { } if (myColumnMode) { myPreviewLabel.setIcon(myLafNames.get(lafName)); - myPreviewLabel.setBorder(BorderFactory.createLineBorder(UIManager.getColor("Label.foreground"))); + myPreviewLabel.setBorder(BorderFactory.createLineBorder(UIManager.getColor("Label.disabledForeground"))); } } catch (ClassNotFoundException e) { diff --git a/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java index 02e4d54f1135..60e21c1c4417 100644 --- a/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -559,7 +559,7 @@ public class DnDManagerImpl extends DnDManager implements Disposable { Pair pair = dnDDragStartBean.isEmpty() ? null : source.createDraggedImage(action, dge.getDragOrigin()); if (pair == null) { - pair = new Pair(EMPTY_IMAGE, new Point(0, 0)); + pair = Pair.create(EMPTY_IMAGE, new Point(0, 0)); } if (!DragSource.isDragImageSupported()) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/NumberedFragmentHighlighter.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/NumberedFragmentHighlighter.java index ec67e791cb57..bc8b9638e725 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/NumberedFragmentHighlighter.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/NumberedFragmentHighlighter.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 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.highlighting; import com.intellij.codeInsight.daemon.GutterMark; @@ -9,7 +24,10 @@ import com.intellij.openapi.diff.impl.fragments.LineFragment; import com.intellij.openapi.diff.impl.util.TextDiffTypeEnum; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.markup.*; +import com.intellij.openapi.editor.markup.HighlighterLayer; +import com.intellij.openapi.editor.markup.HighlighterTargetArea; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.util.containers.MultiMap; @@ -169,11 +187,11 @@ public class NumberedFragmentHighlighter extends FragmentHighlighterImpl { Pair pair1 = value.iterator().next(); Pair pair2 = value.get(value.size() - 1); TextDiffTypeEnum type = mergeDiffType(value); - whereTo.put(entry.getKey(), new Pair(String.valueOf(pair1.getFirst()) + "-" + - String.valueOf(pair2.getFirst()), type)); + whereTo.put(entry.getKey(), Pair.create(String.valueOf(pair1.getFirst()) + "-" + + String.valueOf(pair2.getFirst()), type)); } else { Pair pair = value.iterator().next(); - whereTo.put(entry.getKey(), new Pair(String.valueOf(pair.getFirst()), pair.getSecond())); + whereTo.put(entry.getKey(), Pair.create(String.valueOf(pair.getFirst()), pair.getSecond())); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index 37ab37828658..59d56ce5a751 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -761,7 +761,7 @@ public final class EditorUtil { if (second.line >= document.getLineCount()) { second = editor.offsetToLogicalPosition(document.getTextLength()); } - return new Pair(first, second); + return Pair.create(first, second); } public static void scrollToTheEnd(@NotNull Editor editor) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractDataProvider.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractDataProvider.java index 03f7b0d90aea..7d4740e74301 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractDataProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.intellij.openapi.editor.impl.softwrap.mapping; -import com.intellij.openapi.editor.impl.softwrap.mapping.DataProvider; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.Nullable; @@ -37,7 +36,7 @@ public abstract class AbstractDataProvider, V> i @Override public Pair getData() { V data = doGetData(); - return data == null ? null : new Pair(myKey, data); + return data == null ? null : Pair.create(myKey, data); } /** diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/AbstractFileType.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/AbstractFileType.java index f3ba81716bb7..7b43dfdff4f3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/AbstractFileType.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/AbstractFileType.java @@ -22,9 +22,9 @@ import com.intellij.lang.Commenter; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.*; import com.intellij.openapi.fileTypes.ex.ExternalizableFileType; +import com.intellij.openapi.options.ExternalInfo; import com.intellij.openapi.options.ExternalizableScheme; import com.intellij.openapi.options.SettingsEditor; -import com.intellij.openapi.options.ExternalInfo; import com.intellij.openapi.util.*; import com.intellij.util.text.StringTokenizer; import org.jdom.Element; @@ -328,7 +328,7 @@ public class AbstractFileType extends UserFileType implements String pattern = mapping.getAttributeValue(ATTRIBUTE_PATTERN); FileNameMatcher matcher = ext != null ? new ExtensionFileNameMatcher(ext) : FileTypeManager.parseFromString(pattern); - result.add(new Pair(matcher, mapping.getAttributeValue(ATTRIBUTE_TYPE))); + result.add(Pair.create(matcher, mapping.getAttributeValue(ATTRIBUTE_TYPE))); } return result; diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java index 817cdaa5e458..2d3083fec099 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -472,7 +472,7 @@ public final class IdeKeyEventDispatcher implements Disposable { if (shortcut instanceof KeyboardShortcut) { KeyboardShortcut keyShortcut = (KeyboardShortcut)shortcut; if (keyShortcut.getFirstKeyStroke().equals(myFirstKeyStroke)) { - secondKeyStrokes.add(new Pair(action, keyShortcut.getSecondKeyStroke())); + secondKeyStrokes.add(Pair.create(action, keyShortcut.getSecondKeyStroke())); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapImpl.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapImpl.java index 912005072b72..2cb015fcb850 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapImpl.java @@ -528,10 +528,6 @@ public class KeymapImpl implements Keymap, ExternalizableScheme { public Shortcut[] getShortcuts(String actionId) { LinkedHashSet shortcuts = myActionId2ListOfShortcuts.get(actionId); - // Shortcuts of bounded action has more priority than keystrokes of given action, - // and likely this behaviour can't be changed completely because of IDEA-58896. - // But. If shortcuts for actionId has been explicitly defined in current keymap - // then shortcuts of bounded action won't be used. if (shortcuts == null) { Shortcut[] boundShortcuts = getBoundShortcuts(actionId); if (boundShortcuts!= null) return boundShortcuts; @@ -548,12 +544,19 @@ public class KeymapImpl implements Keymap, ExternalizableScheme { return shortcuts.isEmpty() ? ourEmptyShortcutsArray : shortcuts.toArray(new Shortcut[shortcuts.size()]); } + @Nullable + private Shortcut[] getOwnShortcuts(String actionId) { + LinkedHashSet own = myActionId2ListOfShortcuts.get(actionId); + if (own == null) return null; + return own.isEmpty() ? ourEmptyShortcutsArray : own.toArray(new Shortcut[own.size()]); + } + @Nullable private Shortcut[] getBoundShortcuts(String actionId) { KeymapManagerEx keymapManager = getKeymapManager(); boolean hasBoundedAction = keymapManager.getBoundActions().contains(actionId); if (hasBoundedAction) { - return getShortcuts(keymapManager.getActionBinding(actionId)); + return getOwnShortcuts(keymapManager.getActionBinding(actionId)); } return null; } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java index c330b9b6e73e..17a208f08eb6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java @@ -147,7 +147,9 @@ public class ActionsTreeUtil { final String id = action instanceof ActionStub ? ((ActionStub)action).getId() : actionManager.getId(action); if (id != null) { String binding = getActionBinding(keymap, id); - boolean bound = binding != null && actionManager.getAction(binding) != null; + boolean bound = binding != null + && actionManager.getAction(binding) != null // do not hide bound action, that miss the 'bound-with' + && !hasAssociatedShortcutsInHierarchy(id, keymap); // do not hide bound actions when they are redefined return filter == null ? !bound : !bound && filter.value(action); } @@ -156,6 +158,14 @@ public class ActionsTreeUtil { }; } + private static boolean hasAssociatedShortcutsInHierarchy(String id, Keymap keymap) { + while (keymap != null) { + if (((KeymapImpl)keymap).hasOwnActionId(id)) return true; + keymap = keymap.getParent(); + } + return false; + } + private static void fillGroupIgnorePopupFlag(ActionGroup actionGroup, Group group, Condition filtered) { AnAction[] mainMenuTopGroups = actionGroup instanceof DefaultActionGroup ? ((DefaultActionGroup)actionGroup).getChildActionsOrStubs() @@ -292,10 +302,6 @@ public class ActionsTreeUtil { else { String actionId = editorAction instanceof ActionStub ? ((ActionStub)editorAction).getId() : actionManager.getId(editorAction); if (actionId == null) continue; - if (actionId.startsWith(EDITOR_PREFIX)) { - AnAction action = actionManager.getActionOrStub('$' + actionId.substring(6)); - if (action != null) continue; - } if (filtered == null || filtered.value(editorAction)) { ids.add(actionId); } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java index 2c6bfe1f8fc6..4e5a6cca747b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -98,7 +98,7 @@ public class BackgroundTaskQueue { if (isTestMode()) { // test tasks are executed in this thread without the progress manager RunBackgroundable.runIfBackgroundThread(task, new EmptyProgressIndicator(), null); } else { - myProcessor.add(new Pair>(task, pi), state); + myProcessor.add(Pair.create(task, pi), state); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/StatusBarProgress.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/StatusBarProgress.java index 37cfe2f768b1..385db8ea8144 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/StatusBarProgress.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/StatusBarProgress.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -55,7 +55,7 @@ public class StatusBarProgress extends ProgressIndicatorBase { String info = statusBar.getInfo(); if (info == null) info = ""; - myStatusBar2SavedText.put(statusBar, new Pair(info, info)); // initial value + myStatusBar2SavedText.put(statusBar, Pair.create(info, info)); // initial value } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 8fd90f6b8215..c79e4118f36c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -840,11 +840,11 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt myChangedProjectFiles.put(project, changedProjectFiles); } - changedProjectFiles.add(new Pair(cause, storage)); + changedProjectFiles.add(Pair.create(cause, storage)); } } else { - myChangedApplicationFiles.add(new Pair(cause, storage)); + myChangedApplicationFiles.add(Pair.create(cause, storage)); } myChangedFilesAlarm.cancelAllRequests(); diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/CallCommand.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/CallCommand.java index d6552b46d7e6..eeb1dd8a62bd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/CallCommand.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/CallCommand.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -123,7 +123,7 @@ public class CallCommand extends AbstractCommand { for (Class eachClass : classes) { try { Method method = eachClass.getMethod(methodName, types); - return new Pair(method, eachClass); + return Pair.create(method, eachClass); } catch (NoSuchMethodException ignored) { continue; diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/TodoForRanges.java b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/TodoForRanges.java index a0b00be30119..724e33c3290f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/TodoForRanges.java +++ b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/TodoForRanges.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -91,7 +91,7 @@ public abstract class TodoForRanges { if (range.contains(item.getTextRange())) { TextRange todoRange = new TextRange(offset - range.getStartOffset() + item.getTextRange().getStartOffset(), offset - range.getStartOffset() + item.getTextRange().getEndOffset()); - result.add(new Pair(todoRange, item.getPattern().getAttributes().getTextAttributes())); + result.add(Pair.create(todoRange, item.getPattern().getAttributes().getTextAttributes())); iterator.remove(); } else { break; diff --git a/platform/platform-impl/src/io/netty/bootstrap/BootstrapUtil.java b/platform/platform-impl/src/io/netty/bootstrap/BootstrapUtil.java index 90029325db35..928729775e3d 100644 --- a/platform/platform-impl/src/io/netty/bootstrap/BootstrapUtil.java +++ b/platform/platform-impl/src/io/netty/bootstrap/BootstrapUtil.java @@ -2,7 +2,6 @@ package io.netty.bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelPromise; public final class BootstrapUtil { public static ChannelFuture initAndRegister(Channel channel, Bootstrap bootstrap) throws Throwable { @@ -14,10 +13,9 @@ public final class BootstrapUtil { throw e; } - ChannelPromise regPromise = channel.newPromise(); - channel.unsafe().register(regPromise); + ChannelFuture regFuture = bootstrap.group().register(channel); //noinspection ThrowableResultOfMethodCallIgnored - if (regPromise.cause() != null) { + if (regFuture.cause() != null) { if (channel.isRegistered()) { channel.close(); } @@ -25,6 +23,6 @@ public final class BootstrapUtil { channel.unsafe().closeForcibly(); } } - return regPromise; + return regFuture; } } diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java index 537ef9018dce..5565e77a8cfb 100644 --- a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java +++ b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; @ChannelHandler.Sharable -public final class ChannelRegistrar extends ChannelHandlerAdapter { +public final class ChannelRegistrar extends ChannelInboundHandlerAdapter { private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); public boolean isEmpty() { diff --git a/platform/platform-impl/src/org/jetbrains/io/Decoder.java b/platform/platform-impl/src/org/jetbrains/io/Decoder.java index c4ad24677309..24b25d8cdfb9 100644 --- a/platform/platform-impl/src/org/jetbrains/io/Decoder.java +++ b/platform/platform-impl/src/org/jetbrains/io/Decoder.java @@ -18,10 +18,9 @@ package org.jetbrains.io; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; import org.jetbrains.annotations.Nullable; -public abstract class Decoder extends SimpleChannelInboundHandler { +public abstract class Decoder extends SimpleChannelInboundHandlerAdapter { protected ByteBuf cumulation; protected Decoder() { diff --git a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java index 37587622a9f6..ed279b4bbd37 100644 --- a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java +++ b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java @@ -16,12 +16,11 @@ package org.jetbrains.io; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.QueryStringDecoder; -abstract class DelegatingHttpRequestHandlerBase extends SimpleChannelInboundHandler { +abstract class DelegatingHttpRequestHandlerBase extends SimpleChannelInboundHandlerAdapter { @Override protected void messageReceived(ChannelHandlerContext context, FullHttpRequest message) throws Exception { if (BuiltInServer.LOG.isDebugEnabled()) { diff --git a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java index bae08aca51dd..e9d1cdf0c67b 100644 --- a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java +++ b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java @@ -37,7 +37,6 @@ import java.net.BindException; import java.net.InetSocketAddress; import java.net.Socket; import java.util.Random; -import java.util.UUID; public final class NettyUtil { public static final int DEFAULT_CONNECT_ATTEMPT_COUNT = 20; @@ -46,8 +45,7 @@ public final class NettyUtil { static { // IDEA-120811 if (SystemProperties.getBooleanProperty("io.netty.random.id", true)) { - String id = UUID.randomUUID().toString(); - System.setProperty("io.netty.machineId", id.substring(id.length() - 8)); + System.setProperty("io.netty.machineId", "9e43d860"); System.setProperty("io.netty.processId", Integer.toString(new Random().nextInt(65535))); } } @@ -88,7 +86,7 @@ public final class NettyUtil { } } - OioSocketChannel channel = new OioSocketChannel(bootstrap.group().next(), socket); + OioSocketChannel channel = new OioSocketChannel(socket); BootstrapUtil.initAndRegister(channel, bootstrap).awaitUninterruptibly(); return channel; } diff --git a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java index bddce72242e6..466c996b4c19 100644 --- a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java +++ b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java @@ -107,7 +107,7 @@ class PortUnificationServerHandler extends Decoder { NettyUtil.addHttpServerCodec(pipeline); pipeline.addLast(delegatingHttpRequestHandler); if (BuiltInServer.LOG.isDebugEnabled()) { - pipeline.addLast(new ChannelHandlerAdapter() { + pipeline.addLast(new ChannelOutboundHandlerAdapter() { @Override public void write(ChannelHandlerContext context, Object message, ChannelPromise promise) throws Exception { if (message instanceof HttpResponse) { diff --git a/platform/platform-impl/src/org/jetbrains/io/SimpleChannelInboundHandlerAdapter.java b/platform/platform-impl/src/org/jetbrains/io/SimpleChannelInboundHandlerAdapter.java new file mode 100644 index 000000000000..06085e572dfa --- /dev/null +++ b/platform/platform-impl/src/org/jetbrains/io/SimpleChannelInboundHandlerAdapter.java @@ -0,0 +1,24 @@ +package org.jetbrains.io; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +/** + * You should use this class instead of {@link SimpleChannelInboundHandler} to simplify migration to netty 5 in the future. + */ +public abstract class SimpleChannelInboundHandlerAdapter extends SimpleChannelInboundHandler { + protected SimpleChannelInboundHandlerAdapter() { + super(true); + } + + protected SimpleChannelInboundHandlerAdapter(boolean autoRelease) { + super(autoRelease); + } + + @Override + protected final void channelRead0(ChannelHandlerContext ctx, I message) throws Exception { + messageReceived(ctx, message); + } + + protected abstract void messageReceived(ChannelHandlerContext context, I message) throws Exception; +} \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index efce9bf6dcbc..911cc1fa4cb5 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -520,6 +520,8 @@ action.MoveLineDown.description=Move selected lines one line down action.MoveLineUp.text=Move Line _Up action.MoveLineUp.description=Move selected lines one line up group.AnalyzeMenu.text=Analy_ze +action.CodeCleanup.text=_Code Cleanup... +action.CodeCleanup.description=Run cleanup inspections and apply quick fixes action.InspectCode.text=_Inspect Code... action.InspectCode.description=Inspect code action.InferNullity.text=Infer _Nullity... diff --git a/platform/platform-resources-en/src/messages/VcsBundle.properties b/platform/platform-resources-en/src/messages/VcsBundle.properties index ce2f577926ca..594db771aa60 100644 --- a/platform/platform-resources-en/src/messages/VcsBundle.properties +++ b/platform/platform-resources-en/src/messages/VcsBundle.properties @@ -396,7 +396,7 @@ multiple.file.merge.title=Files Merged with Conflicts multiple.file.merge.properties.title=Files Merged with Property Conflicts multiple.file.merge.accept.yours=Accept &Yours multiple.file.merge.accept.theirs=Accept &Theirs -multiple.file.merge.merge=&Merge +multiple.file.merge.merge=&Merge... multiple.file.merge.column.name=Name multiple.file.merge.request.title=Merge Revisions for {0} multiple.file.merge.column.type=Type diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 1a518eed66ce..d1924f1b96a4 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -399,3 +399,9 @@ ide.inertial.mouse.fix=false ide.inertial.mouse.fix.description=See IDEA-71508 emmet.segments.limit=50 +command.line.execution.timeout=30 + +console.too.much.text.buffer.ratio=10 +console.too.much.text.buffer.ratio.description=Used for disabling of console processing(console filters for highlights, foldings...),\n\ + when there is too much of text to process.\n\ + The ratio is used against the console cycle buffer size (idea.cycle.buffer.size/theRatio=maxTextLength). diff --git a/platform/platform-resources/src/idea/PlatformLangActionManager.xml b/platform/platform-resources/src/idea/PlatformLangActionManager.xml index a8374eb3b1e6..c5d83d776ce4 100644 --- a/platform/platform-resources/src/idea/PlatformLangActionManager.xml +++ b/platform/platform-resources/src/idea/PlatformLangActionManager.xml @@ -42,6 +42,7 @@ + diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/KeymapTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/KeymapTest.java index 8474e0749e1c..1fa32cd7981a 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/KeymapTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/KeymapTest.java @@ -396,6 +396,7 @@ public class KeymapTest extends PlatformTestCase { KeymapManagerEx.getInstanceEx().unbindShortcuts(DEPENDENT); } } + public void testRemovingChildMappingIsTheSameAsResetting() throws Exception { myParent.clearOwnActionsIds(); myChild.clearOwnActionsIds(); @@ -474,4 +475,187 @@ public class KeymapTest extends PlatformTestCase { KeymapManagerEx.getInstanceEx().unbindShortcuts(DEPENDENT); } } + + public void testLookingForShortcutsInParentFirstAndOnlyThenConsiderBoundActions() throws Exception { + myParent.clearOwnActionsIds(); + myChild.clearOwnActionsIds(); + KeymapImpl myGrandChild = myChild.deriveKeymap(); + myChild.setName("GrandChild"); + assertSame(myChild, myGrandChild.getParent()); + + String BASE = "BASE_ACTION"; + String DEPENDENT = "DEPENDENT_ACTION"; + + KeymapManagerEx.getInstanceEx().bindShortcuts(BASE, DEPENDENT); + try { + // parent: + // BASE -> shortcut1 <-- change is here + // DEPENDENT -> BASE + // child: + // - + // grand-child: + // - + myParent.addShortcut(BASE, shortcut1); + + assertSameElements(myParent.getShortcuts(BASE), shortcut1); + assertSameElements(myChild.getShortcuts(BASE), shortcut1); + assertSameElements(myGrandChild.getShortcuts(BASE), shortcut1); + + assertSameElements(myParent.getShortcuts(DEPENDENT), shortcut1); + assertSameElements(myChild.getShortcuts(DEPENDENT), shortcut1); + assertSameElements(myGrandChild.getShortcuts(DEPENDENT), shortcut1); + + assertTrue(myParent.hasOwnActionId(BASE)); + assertFalse(myParent.hasOwnActionId(DEPENDENT)); + assertFalse(myChild.hasOwnActionId(BASE)); + assertFalse(myChild.hasOwnActionId(DEPENDENT)); + assertFalse(myGrandChild.hasOwnActionId(BASE)); + assertFalse(myGrandChild.hasOwnActionId(DEPENDENT)); + + // parent: + // BASE -> shortcut1 + // DEPENDENT -> BASE + // child: + // BASE -> parent:BASE + // DEPENDENT -> shortcut1, +shortcut2 <-- change is here + // grand-child: + // BASE -> parent:BASE + // DEPENDENT -> child:DEPENDENT + myChild.addShortcut(DEPENDENT, shortcut2); + + assertSameElements(myParent.getShortcuts(BASE), shortcut1); + assertSameElements(myChild.getShortcuts(BASE), shortcut1); + assertSameElements(myGrandChild.getShortcuts(BASE), shortcut1); + + assertSameElements(myParent.getShortcuts(DEPENDENT), shortcut1); + assertSameElements(myChild.getShortcuts(DEPENDENT), shortcut1, shortcut2); + assertSameElements(myGrandChild.getShortcuts(DEPENDENT), shortcut1, shortcut2); + + assertSameElements(myParent.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myChild.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myGrandChild.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myParent.getActionIds(shortcut2)); + assertSameElements(myChild.getActionIds(shortcut2), DEPENDENT); + assertSameElements(myGrandChild.getActionIds(shortcut2), DEPENDENT); + + assertTrue(myParent.hasOwnActionId(BASE)); + assertFalse(myParent.hasOwnActionId(DEPENDENT)); + assertFalse(myChild.hasOwnActionId(BASE)); + assertTrue(myChild.hasOwnActionId(DEPENDENT)); + assertFalse(myGrandChild.hasOwnActionId(BASE)); + assertFalse(myGrandChild.hasOwnActionId(DEPENDENT)); + + // parent: + // BASE -> shortcut1 + // DEPENDENT -> BASE + // child: + // BASE -> parent:BASE + // DEPENDENT -> shortcut1, +shortcut2 + // grand-child: + // BASE -> parent:BASE + // DEPENDENT -> shortcut1, shortcut2, + shortcutA <-- change is here + myGrandChild.addShortcut(DEPENDENT, shortcutA); + + assertSameElements(myParent.getShortcuts(BASE), shortcut1); + assertSameElements(myChild.getShortcuts(BASE), shortcut1); + assertSameElements(myGrandChild.getShortcuts(BASE), shortcut1); + + assertSameElements(myParent.getShortcuts(DEPENDENT), shortcut1); + assertSameElements(myChild.getShortcuts(DEPENDENT), shortcut1, shortcut2); + assertSameElements(myGrandChild.getShortcuts(DEPENDENT), shortcut1, shortcut2, shortcutA); + + assertSameElements(myParent.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myChild.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myGrandChild.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myParent.getActionIds(shortcut2)); + assertSameElements(myChild.getActionIds(shortcut2), DEPENDENT); + assertSameElements(myGrandChild.getActionIds(shortcut2), DEPENDENT); + assertSameElements(myParent.getActionIds(shortcutA)); + assertSameElements(myChild.getActionIds(shortcutA)); + assertSameElements(myGrandChild.getActionIds(shortcutA), DEPENDENT); + + assertTrue(myParent.hasOwnActionId(BASE)); + assertFalse(myParent.hasOwnActionId(DEPENDENT)); + assertFalse(myChild.hasOwnActionId(BASE)); + assertTrue(myChild.hasOwnActionId(DEPENDENT)); + assertFalse(myGrandChild.hasOwnActionId(BASE)); + assertTrue(myGrandChild.hasOwnActionId(DEPENDENT)); + + // Now let's try the other way round - redefine base shortcut in children and check that DEPENDENT action uses the cottect one + myChild.clearOwnActionsIds(); + myGrandChild.clearOwnActionsIds(); + + // parent: + // BASE -> shortcut1 + // DEPENDENT -> BASE + // child: + // BASE -> shortcut1, +shortcut2 <-- change is here + // DEPENDENT -> child:BASE + // grand-child: + // BASE -> child:BASE + // DEPENDENT -> child:BASE + myChild.addShortcut(BASE, shortcut2); + + assertSameElements(myParent.getShortcuts(BASE), shortcut1); + assertSameElements(myChild.getShortcuts(BASE), shortcut1, shortcut2); + assertSameElements(myGrandChild.getShortcuts(BASE), shortcut1, shortcut2); + + assertSameElements(myParent.getShortcuts(DEPENDENT), shortcut1); + assertSameElements(myChild.getShortcuts(DEPENDENT), shortcut1, shortcut2); + assertSameElements(myGrandChild.getShortcuts(DEPENDENT), shortcut1, shortcut2); + + assertSameElements(myParent.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myChild.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myGrandChild.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myParent.getActionIds(shortcut2)); + assertSameElements(myChild.getActionIds(shortcut2), BASE, DEPENDENT); + assertSameElements(myGrandChild.getActionIds(shortcut2), BASE, DEPENDENT); + + assertTrue(myParent.hasOwnActionId(BASE)); + assertFalse(myParent.hasOwnActionId(DEPENDENT)); + assertTrue(myChild.hasOwnActionId(BASE)); + assertFalse(myChild.hasOwnActionId(DEPENDENT)); + assertFalse(myGrandChild.hasOwnActionId(BASE)); + assertFalse(myGrandChild.hasOwnActionId(DEPENDENT)); + + // parent: + // BASE -> shortcut1 + // DEPENDENT -> BASE + // child: + // BASE -> shortcut1, shortcut2 + // DEPENDENT -> child:BASE + // grand-child: + // BASE -> shortcut1, shortcut2, +shortcutA <-- change is here + // DEPENDENT -> grand-child:BASE + myGrandChild.addShortcut(BASE, shortcutA); + + assertSameElements(myParent.getShortcuts(BASE), shortcut1); + assertSameElements(myChild.getShortcuts(BASE), shortcut1, shortcut2); + assertSameElements(myGrandChild.getShortcuts(BASE), shortcut1, shortcut2, shortcutA); + + assertSameElements(myParent.getShortcuts(DEPENDENT), shortcut1); + assertSameElements(myChild.getShortcuts(DEPENDENT), shortcut1, shortcut2); + assertSameElements(myGrandChild.getShortcuts(DEPENDENT), shortcut1, shortcut2, shortcutA); + + assertSameElements(myParent.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myChild.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myGrandChild.getActionIds(shortcut1), BASE, DEPENDENT); + assertSameElements(myParent.getActionIds(shortcut2)); + assertSameElements(myChild.getActionIds(shortcut2), BASE, DEPENDENT); + assertSameElements(myGrandChild.getActionIds(shortcut2), BASE, DEPENDENT); + assertSameElements(myParent.getActionIds(shortcutA)); + assertSameElements(myChild.getActionIds(shortcutA)); + assertSameElements(myGrandChild.getActionIds(shortcutA), BASE, DEPENDENT); + + assertTrue(myParent.hasOwnActionId(BASE)); + assertFalse(myParent.hasOwnActionId(DEPENDENT)); + assertTrue(myChild.hasOwnActionId(BASE)); + assertFalse(myChild.hasOwnActionId(DEPENDENT)); + assertTrue(myGrandChild.hasOwnActionId(BASE)); + assertFalse(myGrandChild.hasOwnActionId(DEPENDENT)); + } + finally { + KeymapManagerEx.getInstanceEx().unbindShortcuts(DEPENDENT); + } + } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ui/ActionsTreeTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ui/ActionsTreeTest.java index 35fe8a58def8..18384192dc11 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ui/ActionsTreeTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ui/ActionsTreeTest.java @@ -19,10 +19,13 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.QuickList; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.ex.KeymapManagerEx; +import com.intellij.openapi.keymap.impl.KeymapImpl; import com.intellij.openapi.keymap.impl.KeymapManagerImpl; import com.intellij.testFramework.LightPlatformCodeInsightTestCase; +import com.intellij.testFramework.PlatformTestCase; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -34,15 +37,26 @@ public class ActionsTreeTest extends LightPlatformCodeInsightTestCase { private static final String EXISTENT_ACTION = "DummyExistent"; private static final String NON_EXISTENT_ACTION = "DummyNonExistent"; private static final String ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION = "DummyWithUseShortcutOfExistentAction"; + private static final String ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED = "DummyWithUseShortcutOfExistentActionRedefined"; + private static final String ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED_IN_PARENT = "DummyWithUseShortcutOfExistentActionRedefinedInParent"; private static final String ACTION_WITH_USE_SHORTCUT_OF_NON_EXISTENT_ACTION = "DummyWithUseShortcutOfNonExistentAction"; + + private static final String ACTION_EDITOR_DELETE_WITH_SHORTCUT = "EditorDelete"; + private static final String ACTION_EDITOR_CUT_WITHOUT_SHORTCUT = "EditorCut"; private AnAction myActionWithoutTextAndDescription; private AnAction myActionWithTextOnly; private AnAction myActionWithTextAndDescription; private AnAction myActionExistent; private AnAction myActionWithUseShortcutOfExistent; + private AnAction myActionWithUseShortcutOfExistentRedefined; + private AnAction myActionWithUseShortcutOfExistentRedefinedInParent; private AnAction myActionWithUseShortcutOfNonExistent; + private ActionsTree myActionsTree; + static { + PlatformTestCase.initPlatformLangPrefix(); + } public void setUp() throws Exception { super.setUp(); @@ -52,24 +66,54 @@ public class ActionsTreeTest extends LightPlatformCodeInsightTestCase { myActionWithTextAndDescription = new MyAction("text", "description"); myActionExistent = new MyAction("text", "description"); myActionWithUseShortcutOfExistent = new MyAction("text", "description"); + myActionWithUseShortcutOfExistentRedefined = new MyAction("text", "description"); + myActionWithUseShortcutOfExistentRedefinedInParent = new MyAction("text", "description"); myActionWithUseShortcutOfNonExistent = new MyAction("text", "description"); + myActionWithUseShortcutOfNonExistent = new MyAction("text", "description"); + ActionManager actionManager = ActionManager.getInstance(); actionManager.registerAction(ACTION_WITHOUT_TEXT_AND_DESCRIPTION, myActionWithoutTextAndDescription); actionManager.registerAction(ACTION_WITH_TEXT_ONLY, myActionWithTextOnly); actionManager.registerAction(ACTION_WITH_TEXT_AND_DESCRIPTION, myActionWithTextAndDescription); actionManager.registerAction(EXISTENT_ACTION, myActionExistent); actionManager.registerAction(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION, myActionWithUseShortcutOfExistent); + actionManager.registerAction(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED, myActionWithUseShortcutOfExistentRedefined); + actionManager.registerAction(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED_IN_PARENT, myActionWithUseShortcutOfExistentRedefinedInParent); actionManager.registerAction(ACTION_WITH_USE_SHORTCUT_OF_NON_EXISTENT_ACTION, myActionWithUseShortcutOfNonExistent); KeymapManagerEx.getInstanceEx().bindShortcuts(EXISTENT_ACTION, ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION); + KeymapManagerEx.getInstanceEx().bindShortcuts(EXISTENT_ACTION, ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED); + KeymapManagerEx.getInstanceEx().bindShortcuts(EXISTENT_ACTION, ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED_IN_PARENT); KeymapManagerEx.getInstanceEx().bindShortcuts(NON_EXISTENT_ACTION, ACTION_WITH_USE_SHORTCUT_OF_NON_EXISTENT_ACTION); + assertEquals(KeymapManagerEx.getInstanceEx().getActionBinding(ACTION_EDITOR_DELETE_WITH_SHORTCUT), "$Delete"); + assertEquals(KeymapManagerEx.getInstanceEx().getActionBinding(ACTION_EDITOR_CUT_WITHOUT_SHORTCUT), "$Cut"); + assertNotNull(actionManager.getAction(ACTION_EDITOR_DELETE_WITH_SHORTCUT)); + assertNotNull(actionManager.getAction(ACTION_EDITOR_CUT_WITHOUT_SHORTCUT)); + DefaultActionGroup group = (DefaultActionGroup)actionManager.getAction(IdeActions.GROUP_EDITOR); - group.addAll(myActionWithoutTextAndDescription, myActionWithTextOnly, myActionWithTextAndDescription, - myActionExistent, myActionWithUseShortcutOfExistent, myActionWithUseShortcutOfNonExistent); + group.addAll(myActionWithoutTextAndDescription, + myActionWithTextOnly, + myActionWithTextAndDescription, + myActionExistent, + myActionWithUseShortcutOfExistent, + myActionWithUseShortcutOfExistentRedefined, + myActionWithUseShortcutOfExistentRedefinedInParent, + myActionWithUseShortcutOfNonExistent); // populate action tree myActionsTree = new ActionsTree(); - myActionsTree.reset(KeymapManager.getInstance().getActiveKeymap(), new QuickList[0]); + + KeyboardShortcut shortcut1 = new KeyboardShortcut(KeyStroke.getKeyStroke('1'), null); + KeyboardShortcut shortcut2 = new KeyboardShortcut(KeyStroke.getKeyStroke('2'), null); + KeymapImpl parent = new KeymapImpl(); + parent.addShortcut(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED_IN_PARENT, shortcut1); + parent.setName("parent"); + parent.setCanModify(false); + KeymapImpl child = parent.deriveKeymap(); + child.setName("child"); + child.addShortcut(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED, shortcut2); + child.addShortcut(ACTION_EDITOR_DELETE_WITH_SHORTCUT, shortcut2); + myActionsTree.reset(child, new QuickList[0]); } @Override @@ -82,15 +126,21 @@ public class ActionsTreeTest extends LightPlatformCodeInsightTestCase { group.remove(myActionWithTextAndDescription); group.remove(myActionExistent); group.remove(myActionWithUseShortcutOfExistent); + group.remove(myActionWithUseShortcutOfExistentRedefined); + group.remove(myActionWithUseShortcutOfExistentRedefinedInParent); group.remove(myActionWithUseShortcutOfNonExistent); actionManager.unregisterAction(ACTION_WITHOUT_TEXT_AND_DESCRIPTION); actionManager.unregisterAction(ACTION_WITH_TEXT_ONLY); actionManager.unregisterAction(ACTION_WITH_TEXT_AND_DESCRIPTION); actionManager.unregisterAction(EXISTENT_ACTION); actionManager.unregisterAction(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION); + actionManager.unregisterAction(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED); + actionManager.unregisterAction(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED_IN_PARENT); actionManager.unregisterAction(ACTION_WITH_USE_SHORTCUT_OF_NON_EXISTENT_ACTION); ((KeymapManagerImpl)KeymapManager.getInstance()).unbindShortcuts(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION); + ((KeymapManagerImpl)KeymapManager.getInstance()).unbindShortcuts(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED); + ((KeymapManagerImpl)KeymapManager.getInstance()).unbindShortcuts(ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED_IN_PARENT); ((KeymapManagerImpl)KeymapManager.getInstance()).unbindShortcuts(ACTION_WITH_USE_SHORTCUT_OF_NON_EXISTENT_ACTION); } finally { @@ -105,10 +155,14 @@ public class ActionsTreeTest extends LightPlatformCodeInsightTestCase { ACTION_WITH_TEXT_ONLY, ACTION_WITH_TEXT_AND_DESCRIPTION, EXISTENT_ACTION, - ACTION_WITH_USE_SHORTCUT_OF_NON_EXISTENT_ACTION), + ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED, + ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED_IN_PARENT, + ACTION_WITH_USE_SHORTCUT_OF_NON_EXISTENT_ACTION, + ACTION_EDITOR_DELETE_WITH_SHORTCUT), // this action is shown, since the keymap redefines the shortcut of $Delete Arrays.asList( NON_EXISTENT_ACTION, - ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION + ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION, + ACTION_EDITOR_CUT_WITHOUT_SHORTCUT // this one is not shown since bound to $cut ) ); } @@ -121,10 +175,14 @@ public class ActionsTreeTest extends LightPlatformCodeInsightTestCase { ACTION_WITH_TEXT_ONLY, ACTION_WITH_TEXT_AND_DESCRIPTION, EXISTENT_ACTION, + ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED, + ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION_REDEFINED_IN_PARENT, ACTION_WITH_USE_SHORTCUT_OF_NON_EXISTENT_ACTION), Arrays.asList( NON_EXISTENT_ACTION, - ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION + ACTION_WITH_USE_SHORTCUT_OF_EXISTENT_ACTION, + ACTION_EDITOR_DELETE_WITH_SHORTCUT, + ACTION_EDITOR_CUT_WITHOUT_SHORTCUT ) ); } diff --git a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java b/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java index 4dcd4da5aa87..d8c973a13af5 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java @@ -443,9 +443,9 @@ public class PersistentMapTest extends TestCase { if (checkMap.size() == 0) { checkMap.put(r.nextInt(), 0); checkMap.put(r.nextInt(), 0); - checkMap.put(0, r.nextInt()); + checkMap.put(0, Math.abs(r.nextInt())); } else { - checkMap.put(r.nextInt(), r.nextInt()); + checkMap.put(r.nextInt(), Math.abs(r.nextInt())); } } @@ -455,7 +455,7 @@ public class PersistentMapTest extends TestCase { try { map = new PersistentHashMap(file, EnumeratorIntegerDescriptor.INSTANCE, EnumeratorIntegerDescriptor.INSTANCE) { @Override - protected boolean wantCompactIntegralValues() { + protected boolean wantNonnegativeIntegralValues() { return true; } }; @@ -480,7 +480,7 @@ public class PersistentMapTest extends TestCase { started = System.currentTimeMillis(); map = new PersistentHashMap(file, EnumeratorIntegerDescriptor.INSTANCE, EnumeratorIntegerDescriptor.INSTANCE) { @Override - protected boolean wantCompactIntegralValues() { + protected boolean wantNonnegativeIntegralValues() { return true; } }; diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java index d6cc3b2cc4e7..890d77578a81 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 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. @@ -21,6 +21,7 @@ import com.intellij.openapi.components.StorageId; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.xmlb.Accessor; import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; @@ -92,7 +93,11 @@ class DefaultStateSerializer { //assert mergeInto == null; return (T)stateElement; } - else if (JDOMExternalizable.class.isAssignableFrom(stateClass) && mergeInto == null) { + else if (JDOMExternalizable.class.isAssignableFrom(stateClass)) { + if (mergeInto != null) { + String elementText = JDOMUtil.writeElement(stateElement, "\n"); + LOG.error("State is " + stateClass.getName() + ", merge into is " + mergeInto.toString() + ", state element text is " + elementText); + } try { final T t = stateClass.newInstance(); try { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/ProjectLibraryTable.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/ProjectLibraryTable.java index 9510390bdca7..f84441d462a4 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/ProjectLibraryTable.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/ProjectLibraryTable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -91,7 +91,7 @@ public class ProjectLibraryTable extends LibraryTableBase { for (final Object o : list) { Element library = (Element)o; @NonNls final String name = generator.generateUniqueName(FileUtil.sanitizeFileName(library.getAttributeValue(LibraryImpl.LIBRARY_NAME_ATTR))) + ".xml"; - result.add(new Pair(library, name)); + result.add(Pair.create(library, name)); } return result; diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java index 462c59d6434d..715f98393317 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java @@ -1,5 +1,6 @@ package com.intellij.remoteServer.impl.configuration; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.UnnamedConfigurable; @@ -66,7 +67,7 @@ public class RemoteServerConfigurable extends NamedConfigurable> myConfigurable = server.getType().createConfigurable(innerConfiguration); - myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD); + myAlarm = new Alarm().setActivationComponent(myMainPanel); queueChangesCheck(); } @@ -78,16 +79,10 @@ public class RemoteServerConfigurable extends NamedConfigurable> @Override public void run() { - UIUtil.invokeLaterIfNeeded(new Runnable() { - - @Override - public void run() { - checkChanges(); - queueChangesCheck(); - } - }); + checkChanges(); + queueChangesCheck(); } - }, CHANGES_CHECK_TIME); + }, CHANGES_CHECK_TIME, ModalityState.any()); } private void checkChanges() { diff --git a/platform/util-rt/src/com/intellij/openapi/util/Pair.java b/platform/util-rt/src/com/intellij/openapi/util/Pair.java index 9c85fa536554..ffa8e7cd1398 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/Pair.java +++ b/platform/util-rt/src/com/intellij/openapi/util/Pair.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -24,6 +24,7 @@ public class Pair { @NotNull public static Pair create(A first, B second) { + //noinspection DontUsePairConstructor return new Pair(first, second); } diff --git a/platform/util/src/com/intellij/openapi/diagnostic/Attachment.java b/platform/util/src/com/intellij/openapi/diagnostic/Attachment.java index 36c3cb7ee63d..aada37a4f4f1 100644 --- a/platform/util/src/com/intellij/openapi/diagnostic/Attachment.java +++ b/platform/util/src/com/intellij/openapi/diagnostic/Attachment.java @@ -7,6 +7,7 @@ import com.intellij.util.PathUtilRt; import java.io.UnsupportedEncodingException; public class Attachment { + public static final Attachment[] EMPTY_ARRAY = new Attachment[0]; private final String myPath; private final byte[] myBytes; private boolean myIncluded = true; diff --git a/platform/util/src/com/intellij/openapi/diagnostic/ExceptionWithAttachments.java b/platform/util/src/com/intellij/openapi/diagnostic/ExceptionWithAttachments.java new file mode 100644 index 000000000000..d7968a5825d2 --- /dev/null +++ b/platform/util/src/com/intellij/openapi/diagnostic/ExceptionWithAttachments.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2014 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.diagnostic; + +import org.jetbrains.annotations.NotNull; + +/** + * @author peter + */ +public interface ExceptionWithAttachments { + @NotNull + Attachment[] getAttachments(); +} diff --git a/platform/util/src/com/intellij/openapi/util/TraceableDisposable.java b/platform/util/src/com/intellij/openapi/util/TraceableDisposable.java index c1c70463ca9b..038f2eec78c9 100644 --- a/platform/util/src/com/intellij/openapi/util/TraceableDisposable.java +++ b/platform/util/src/com/intellij/openapi/util/TraceableDisposable.java @@ -60,7 +60,6 @@ public class TraceableDisposable { @SuppressWarnings("HardCodedStringLiteral") @Override public void printStackTrace(PrintWriter s) { - super.printStackTrace(s); if (CREATE_TRACE != null) { s.println("--------------Creation trace: "); CREATE_TRACE.printStackTrace(s); @@ -69,6 +68,8 @@ public class TraceableDisposable { s.println("--------------Kill trace: "); KILL_TRACE.printStackTrace(s); } + s.println("-------------Own trace:"); + super.printStackTrace(s); } } } diff --git a/platform/util/src/com/intellij/util/ExceptionUtil.java b/platform/util/src/com/intellij/util/ExceptionUtil.java index a43638f5839e..d22d122ad2b2 100644 --- a/platform/util/src/com/intellij/util/ExceptionUtil.java +++ b/platform/util/src/com/intellij/util/ExceptionUtil.java @@ -35,7 +35,7 @@ public class ExceptionUtil { } } - public static T findCause(Throwable e, Class klass) { + public static T findCause(Throwable e, Class klass) { while (e != null && !klass.isInstance(e)) { e = e.getCause(); } diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 78ed0fe7f44a..3f222addf7ac 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -32,7 +32,7 @@ import java.util.Arrays; */ class IntToIntBtree { public static int version() { - return 3 + (IOUtil.ourByteBuffersUseNativeByteOrder ? 0xFF : 0); + return 4 + (IOUtil.ourByteBuffersUseNativeByteOrder ? 0xFF : 0); } private static final int HAS_ZERO_KEY_MASK = 0xFF000000; diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java index a202cd825e74..3375e952e434 100644 --- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java @@ -22,6 +22,12 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; +// Assigns / store unique integral id for Data instances. +// Btree stores mapping between integer hash code into integer that interpreted in following way: +// Positive value is address in myFile with unique key record. +// When there is hash value collisions the value is negative and it is -address of collision list (keyAddress, nextCollisionAddress)+ +// It is possible to directly associate nonnegative int or long with Data instances when Data is integral value and represent it's own hash code +// e.g. Data are integers and hash code for them are values themselves public class PersistentBTreeEnumerator extends PersistentEnumeratorBase { private static final int PAGE_SIZE; private static final int DEFAULT_PAGE_SIZE = 32768; @@ -279,6 +285,67 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase)myDataDescriptor).toInt(key), myResultBuf); + if (!hasMapping) { + return NULL_ID; + } + + return keyIdToNonnegattiveOffset(myResultBuf[0]); + } + catch (IllegalStateException e) { + CorruptedException exception = new CorruptedException(myFile); + exception.initCause(e); + throw exception; + } finally { + unlockStorage(); + } + } + + public long keyIdToNonnegattiveOffset(int value) { + if (value >= 0) return value; + return myStorage.getLong(-value); + } + + public void putNonnegativeValue(Data key, long value) throws IOException { + assert value >= 0; + assert myInlineKeysNoMapping; + try { + lockStorage(); + markDirty(true); + int intKey = ((InlineKeyDescriptor)myDataDescriptor).toInt(key); + if (value < Integer.MAX_VALUE) { + btree.put(intKey, (int) value); + } else { + int pos = nextLongValueRecord(); + myStorage.putLong(pos, value); + btree.put(intKey, -pos); + } + } catch (IllegalStateException e) { + CorruptedException exception = new CorruptedException(myFile); + exception.initCause(e); + throw exception; + } finally { + unlockStorage(); + } + + } + + private int nextLongValueRecord() { + assert myInlineKeysNoMapping; + if (myDuplicatedValuesPageStart == -1 || myDuplicatedValuesPageOffset == btree.pageSize) { + myDuplicatedValuesPageStart = allocPage(); + myDuplicatedValuesPageOffset = 0; + } + + int duplicatedValueOff = myDuplicatedValuesPageOffset; + myDuplicatedValuesPageOffset += 8; // size of long + return myDuplicatedValuesPageStart + duplicatedValueOff; + } + @Override protected int enumerateImpl(final Data value, final boolean onlyCheckForExisting, boolean saveNewValue) throws IOException { try { @@ -407,6 +474,7 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorDelegate implements PersistentMap { + // PersistentHashMap (PHM) works in following (generic) way: + // particular key is translated via myEnumerator into int, as part of enumeration process for new key additional space is reserved in + // myEnumerator.myStorage for offset in .values file (myValueStorage) where (serialized) value is stored. Once new value is written + // the offset storage is updated. When the key is removed from PHM, offset storage is set to zero. It is important to note that offset + // is nonnegative and can be 4 or 8 bytes, depending on size of .values file. + // PHM can work in appendable mode: for particular key additional calculated chunk of value can be appended to .values file with offset + // of previously calculated chunk. + // For performance reasons we try hard to minimize storage occupied by keys / offsets to .values file: this storage is allocated as (limited) + // direct bytebuffers so 4 bytes offset is used until it is possible. Generic record produced by enumerator used with PHM as part of new + // key enumeration is ? [.values file offset 4 or 8 bytes], however for unique integral keys enumerate_id isn't produced. + // Also for certain Value types it is possible to avoid random reads at all: e.g. in case Value is nonnegative integer the value can be stored + // directly in storage used for offset and in case of btreeenumerator directly in btree leaf. private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.PersistentHashMap"); private static final int DEAD_KEY_NUMBER_MASK = 0xFFFFFFFF; + private final File myStorageFile; + private final KeyDescriptor myKeyDescriptor; private PersistentHashMapValueStorage myValueStorage; protected final DataExternalizer myValueExternalizer; private static final long NULL_ADDR = 0; @@ -63,6 +76,7 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< @NotNull private final byte[] myRecordBuffer; @NotNull private final byte[] mySmallRecordBuffer; private final boolean myIntMapping; + private final boolean myDirectlyStoreLongFileOffsetMode; private final boolean myCanReEnumerate; private int myLargeIndexWatermarkId; // starting with this id we store offset in adjacent file in long format private boolean myIntAddressForNewRecord; @@ -110,13 +124,18 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< public PersistentHashMap(@NotNull final File file, @NotNull KeyDescriptor keyDescriptor, @NotNull DataExternalizer valueExternalizer, final int initialSize) throws IOException { super(checkDataFiles(file), keyDescriptor, initialSize); + + myStorageFile = file; + myKeyDescriptor = keyDescriptor; + myAppendCache = createAppendCache(keyDescriptor); final PersistentEnumeratorBase.RecordBufferHandler recordHandler = myEnumerator.getRecordHandler(); myParentValueRefOffset = recordHandler.getRecordBuffer(myEnumerator).length; - myIntMapping = valueExternalizer instanceof IntInlineKeyDescriptor && wantCompactIntegralValues(); + myIntMapping = valueExternalizer instanceof IntInlineKeyDescriptor && wantNonnegativeIntegralValues(); + myDirectlyStoreLongFileOffsetMode = keyDescriptor instanceof InlineKeyDescriptor && myEnumerator instanceof PersistentBTreeEnumerator; - myRecordBuffer = new byte[myParentValueRefOffset + 8]; - mySmallRecordBuffer = new byte[myParentValueRefOffset + 4]; + myRecordBuffer = myDirectlyStoreLongFileOffsetMode ? new byte[0]:new byte[myParentValueRefOffset + 8]; + mySmallRecordBuffer = myDirectlyStoreLongFileOffsetMode ? new byte[0]:new byte[myParentValueRefOffset + 4]; myEnumerator.setRecordHandler(new PersistentEnumeratorBase.RecordBufferHandler() { @Override @@ -183,7 +202,7 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } } - protected boolean wantCompactIntegralValues() { + protected boolean wantNonnegativeIntegralValues() { return false; } @@ -199,13 +218,25 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< protected void onDropFromCache(final Key key, @NotNull final BufferExposingByteArrayOutputStream bytes) { myEnumerator.lockStorage(); try { - final int id = enumerate(key); - long oldHeaderRecord = readValueId(id); + long previousRecord; + final int id; + if (myDirectlyStoreLongFileOffsetMode) { + previousRecord = ((PersistentBTreeEnumerator)myEnumerator).getNonnegativeValue(key); + id = -1; + } else { + id = enumerate(key); + previousRecord = readValueId(id); + } - long headerRecord = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), oldHeaderRecord); + long headerRecord = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), previousRecord); - updateValueId(id, headerRecord, oldHeaderRecord, key, 0); - if (oldHeaderRecord == NULL_ADDR) { + if (myDirectlyStoreLongFileOffsetMode) { + ((PersistentBTreeEnumerator)myEnumerator).putNonnegativeValue(key, headerRecord); + } else { + updateValueId(id, headerRecord, previousRecord, key, 0); + } + + if (previousRecord == NULL_ADDR) { myLiveAndGarbageKeysCounter += LIVE_KEY_MASK; } @@ -297,34 +328,47 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } protected void doPut(Key key, Value value) throws IOException { - myEnumerator.lockStorage(); - try { - myEnumerator.markDirty(true); - myAppendCache.remove(key); - - final int id = enumerate(key); - if (myIntMapping) { - myEnumerator.myStorage.putInt(id + myParentValueRefOffset, (Integer)value); - return; - } + long newValueOffset = -1; + if (!myIntMapping) { final BufferExposingByteArrayOutputStream bytes = new BufferExposingByteArrayOutputStream(); AppendStream appenderStream = ourFlyweightAppenderStream.getValue(); appenderStream.setOut(bytes); myValueExternalizer.save(appenderStream, value); appenderStream.setOut(null); + newValueOffset = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), 0); + } - long oldheader = readValueId(id); - if (oldheader != NULL_ADDR) { + myEnumerator.lockStorage(); + try { + myEnumerator.markDirty(true); + myAppendCache.remove(key); + + long oldValueOffset; + if (myDirectlyStoreLongFileOffsetMode) { + if (myIntMapping) { + ((PersistentBTreeEnumerator)myEnumerator).putNonnegativeValue(key, (Integer)value); + return; + } + oldValueOffset = ((PersistentBTreeEnumerator)myEnumerator).getNonnegativeValue(key); + ((PersistentBTreeEnumerator)myEnumerator).putNonnegativeValue(key, newValueOffset); + } else { + final int id = enumerate(key); + if (myIntMapping) { + myEnumerator.myStorage.putInt(id + myParentValueRefOffset, (Integer)value); + return; + } + + oldValueOffset = readValueId(id); + updateValueId(id, newValueOffset, oldValueOffset, key, 0); + } + + if (oldValueOffset != NULL_ADDR) { myLiveAndGarbageKeysCounter++; } else { myLiveAndGarbageKeysCounter += LIVE_KEY_MASK; } - - long header = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), 0); - - updateValueId(id, header, oldheader, key, 0); } finally { myEnumerator.unlockStorage(); @@ -407,41 +451,64 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< @Nullable protected Value doGet(Key key) throws IOException { + final long valueOffset; + final int id; + myEnumerator.lockStorage(); try { myAppendCache.remove(key); - final int id = tryEnumerate(key); - if (id == PersistentEnumerator.NULL_ID) { - return null; + + if (myDirectlyStoreLongFileOffsetMode) { + valueOffset = ((PersistentBTreeEnumerator)myEnumerator).getNonnegativeValue(key); + if (myIntMapping) { + return (Value)(Integer)(int)valueOffset; + } + id = -1; + } else { + id = tryEnumerate(key); + if (id == PersistentEnumerator.NULL_ID) { + return null; + } + + if (myIntMapping) { + return (Value)(Integer)myEnumerator.myStorage.getInt(id + myParentValueRefOffset); + } + + valueOffset = readValueId(id); } - if (myIntMapping) { - return (Value)(Integer)myEnumerator.myStorage.getInt(id + myParentValueRefOffset); - } - - final long oldHeader = readValueId(id); - if (oldHeader == PersistentEnumerator.NULL_ID) { + if (valueOffset == NULL_ADDR) { return null; } - PersistentHashMapValueStorage.ReadResult readResult = myValueStorage.readBytes(oldHeader); - if (readResult.offset != oldHeader) { + } finally { + myEnumerator.unlockStorage(); + } + + PersistentHashMapValueStorage.ReadResult readResult = myValueStorage.readBytes(valueOffset); + + if (readResult.offset != valueOffset) { // compacted several chunks produced during append + myEnumerator.lockStorage(); + try { myEnumerator.markDirty(true); - updateValueId(id, readResult.offset, oldHeader, key, 0); + if (myDirectlyStoreLongFileOffsetMode) { + ((PersistentBTreeEnumerator)myEnumerator).putNonnegativeValue(key, readResult.offset); + } else { + updateValueId(id, readResult.offset, valueOffset, key, 0); + } myLiveAndGarbageKeysCounter++; myReadCompactionGarbageSize += readResult.buffer.length; - } - - final DataInputStream input = new DataInputStream(new UnsyncByteArrayInputStream(readResult.buffer)); - try { - return myValueExternalizer.read(input); - } - finally { - input.close(); + } finally { + myEnumerator.unlockStorage(); } } + + final DataInputStream input = new DataInputStream(new UnsyncByteArrayInputStream(readResult.buffer)); + try { + return myValueExternalizer.read(input); + } finally { - myEnumerator.unlockStorage(); + input.close(); } } @@ -455,12 +522,17 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< myEnumerator.lockStorage(); try { myAppendCache.remove(key); - final int id = tryEnumerate(key); - if (id == PersistentEnumerator.NULL_ID) { - return false; + if (myDirectlyStoreLongFileOffsetMode) { + if (myIntMapping) return true; + return ((PersistentBTreeEnumerator)myEnumerator).getNonnegativeValue(key) != NULL_ADDR; + } else { + final int id = tryEnumerate(key); + if (id == PersistentEnumerator.NULL_ID) { + return false; + } + if (myIntMapping) return true; + return readValueId(id) != NULL_ADDR; } - if(myIntMapping) return true; - return readValueId(id) != NULL_ADDR; } finally { myEnumerator.unlockStorage(); @@ -476,21 +548,28 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< protected void doRemove(Key key) throws IOException { myEnumerator.lockStorage(); try { - myAppendCache.remove(key); - final int id = tryEnumerate(key); - if (id == PersistentEnumerator.NULL_ID) { - return; - } - assert !myIntMapping; // removal isn't supported - myEnumerator.markDirty(true); + final long record; - final long record = readValueId(id); + myAppendCache.remove(key); + if (myDirectlyStoreLongFileOffsetMode) { + assert !myIntMapping; // removal isn't supported + record = ((PersistentBTreeEnumerator)myEnumerator).getNonnegativeValue(key); + ((PersistentBTreeEnumerator)myEnumerator).putNonnegativeValue(key, NULL_ADDR); + } else { + final int id = tryEnumerate(key); + if (id == PersistentEnumerator.NULL_ID) { + return; + } + assert !myIntMapping; // removal isn't supported + myEnumerator.markDirty(true); + + record = readValueId(id); + updateValueId(id, NULL_ADDR, record, key, 0); + } if (record != NULL_ADDR) { myLiveAndGarbageKeysCounter++; myLiveAndGarbageKeysCounter -= LIVE_KEY_MASK; } - - updateValueId(id, NULL_ADDR, record, key, 0); } finally { myEnumerator.unlockStorage(); @@ -669,6 +748,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } private long readValueId(final int keyId) { + if (myDirectlyStoreLongFileOffsetMode) { + return ((PersistentBTreeEnumerator)myEnumerator).keyIdToNonnegattiveOffset(keyId); + } long address = myEnumerator.myStorage.getInt(keyId + myParentValueRefOffset); if (address == 0 || address == -POSITIVE_VALUE_SHIFT) { return NULL_ADDR; @@ -690,6 +772,11 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< private int requests; private int updateValueId(int keyId, long value, long oldValue, @Nullable Key key, int processingKey) throws IOException { + if (myDirectlyStoreLongFileOffsetMode) { + ((PersistentBTreeEnumerator)myEnumerator).putNonnegativeValue(((InlineKeyDescriptor)myKeyDescriptor).fromInt(processingKey), + value); + return keyId; + } final boolean newKey = oldValue == NULL_ADDR; if (newKey) ++requests; boolean defaultSizeInfo = true; @@ -733,4 +820,8 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } return keyId; } + + public String toString() { + return super.toString() + ":"+myStorageFile; + } } diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java index 132067d6dbc7..c25ea4eda084 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -74,7 +74,7 @@ class XmlSerializerImpl { } private static synchronized Binding _getClassBinding(Class aClass, Type originalType, @Nullable Accessor accessor) { - final Pair p = new Pair(originalType, accessor); + final Pair p = Pair.create(originalType, accessor); Map, Binding> map = getBindingCacheMap(); diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/MembershipMap.java b/platform/vcs-api/src/com/intellij/openapi/vcs/MembershipMap.java index bedfd95930a7..161bcc39f377 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/MembershipMap.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/MembershipMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -19,7 +19,9 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.util.PairProcessor; -import java.util.*; +import java.util.Comparator; +import java.util.Iterator; +import java.util.ListIterator; /** * @author irengrig @@ -82,7 +84,7 @@ public class MembershipMap extends AreaMap { getSimiliar(key, new PairProcessor() { @Override public boolean process(final Key key, final Val val) { - result.set(new Pair(key, val)); + result.set(Pair.create(key, val)); return true; } }); diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ReadonlyListsMerger.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ReadonlyListsMerger.java index 330d21c8d73b..6aa25599f641 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/ReadonlyListsMerger.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ReadonlyListsMerger.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -59,8 +59,8 @@ public class ReadonlyListsMerger { for (int i = 0; i < idxs.length; i++) { if (idxs[i] == -1) continue; // at end final ReadonlyList list = myLists.get(i); - if ((minIdxs == null) || (myComparator.compare(new Pair(new CompoundNumber(i, idxs[i]), list.get(idxs[i])), - new Pair(minIdxs, myLists.get(minIdxs.getMemberNumber()).get(minIdxs.getIdx()))) <= 0)) { + if ((minIdxs == null) || (myComparator.compare(Pair.create(new CompoundNumber(i, idxs[i]), list.get(idxs[i])), + Pair.create(minIdxs, myLists.get(minIdxs.getMemberNumber()).get(minIdxs.getIdx()))) <= 0)) { minIdxs = new CompoundNumber(i, idxs[i]); } } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/RequestsMerger.java b/platform/vcs-api/src/com/intellij/openapi/vcs/RequestsMerger.java index 6f27bf76c693..6939d4389635 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/RequestsMerger.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/RequestsMerger.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -226,12 +226,12 @@ public class RequestsMerger { } private static void add(final MyState from, final MyState to, final MyExitAction... action) { - myMap.put(new Pair(from, to), action); + myMap.put(Pair.create(from, to), action); } @Nullable public static MyExitAction[] getExit(final MyState from, final MyState to) { - return myMap.get(new Pair(from, to)); + return myMap.get(Pair.create(from, to)); } } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/committed/VcsCommittedListsZipperAdapter.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/committed/VcsCommittedListsZipperAdapter.java index a668c24d9ebe..fcd2c4c9ca84 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/committed/VcsCommittedListsZipperAdapter.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/committed/VcsCommittedListsZipperAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -60,7 +60,7 @@ public abstract class VcsCommittedListsZipperAdapter implements VcsCommittedList } } - return new Pair, List>(groups, singles); + return Pair.create(groups, singles); } public CommittedChangeList zip(final RepositoryLocationGroup group, final List lists) { diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/impl/ContentRevisionCache.java b/platform/vcs-api/src/com/intellij/openapi/vcs/impl/ContentRevisionCache.java index 3dd5cdfeacf3..fdbb526119e2 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/impl/ContentRevisionCache.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/impl/ContentRevisionCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -82,14 +82,14 @@ public class ContentRevisionCache { public void putCustom(FilePath path, VcsRevisionNumber number, final Object o) { synchronized (myLock) { - myCustom.put(new Pair(path, number), o); + myCustom.put(Pair.create(path, number), o); } } @Nullable public Object getCustom(FilePath path, VcsRevisionNumber number) { synchronized (myLock) { - return myCustom.get(new Pair(path, number)); + return myCustom.get(Pair.create(path, number)); } } @@ -261,7 +261,7 @@ public class ContentRevisionCache { currentRevision = putIntoCurrentCache(cache, path, vcsKey, loader); final byte[] cachedCurrent = cache.getBytes(path, currentRevision, vcsKey, UniqueType.REPOSITORY_CONTENT); if (cachedCurrent != null) { - return new Pair(currentRevision, cachedCurrent); + return Pair.create(currentRevision, cachedCurrent); } checkLocalFileSize(path); loaded = loader.get(); @@ -275,7 +275,7 @@ public class ContentRevisionCache { public static Pair getOrLoadCurrentAsString(final Project project, FilePath path, @NotNull VcsKey vcsKey, final CurrentRevisionProvider loader) throws VcsException, IOException { Pair pair = getOrLoadCurrentAsBytes(project, path, vcsKey, loader); - return new Pair(pair.getFirst(), bytesToString(path, pair.getSecond())); + return Pair.create(pair.getFirst(), bytesToString(path, pair.getSecond())); } private static class CurrentKey { diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java b/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java index cd649d36e86e..a5fa2c121ed2 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -134,7 +134,7 @@ public class FileGroup implements JDOMExternalizable { ArrayList> files = new ArrayList>(); for (UpdatedFile file : myFiles) { VcsRevisionNumber number = getRevision(vcsManager, file); - files.add(new Pair(file.getPath(), number)); + files.add(Pair.create(file.getPath(), number)); } return files; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java index 618264ca07d9..8181678c1c5b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java @@ -331,14 +331,14 @@ public class PathsVerifier { } private void addPatch(final FilePatch patch, final VirtualFile file) { - final Pair patchPair = new Pair(file, ApplyFilePatchFactory.createGeneral(patch)); + final Pair patchPair = Pair.create(file, ApplyFilePatchFactory.createGeneral(patch)); if (patch instanceof TextFilePatch) { - myTextPatches.add(new Pair(file, ApplyFilePatchFactory.create((TextFilePatch) patch))); + myTextPatches.add(Pair.create(file, ApplyFilePatchFactory.create((TextFilePatch)patch))); } else { final ApplyFilePatchBase applyBinaryPatch = (ApplyFilePatchBase) ((patch instanceof BinaryFilePatch) ? ApplyFilePatchFactory .create((BinaryFilePatch) patch) : ApplyFilePatchFactory.create((ShelveChangesManager.ShelvedBinaryFilePatch) patch)); - myBinaryPatches.add(new Pair>(file, applyBinaryPatch)); + myBinaryPatches.add(Pair.create(file, applyBinaryPatch)); } myWritableFiles.add(file); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/VcsQuickListPopupAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/VcsQuickListPopupAction.java index 85433543d9d4..39f4af453b98 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/VcsQuickListPopupAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/VcsQuickListPopupAction.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 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.vcs.actions; import com.intellij.ide.actions.QuickSwitchSchemeAction; @@ -158,7 +173,7 @@ public class VcsQuickListPopupAction extends QuickSwitchSchemeAction implements return new Pair(SupportedVCS.NOT_IN_VCS, null); } else if (activeVcss.length == 1) { // get by name - return new Pair(SupportedVCS.VCS, activeVcss[0]); + return Pair.create(SupportedVCS.VCS, activeVcss[0]); } // by current file @@ -166,7 +181,7 @@ public class VcsQuickListPopupAction extends QuickSwitchSchemeAction implements if (file != null) { final AbstractVcs vscForFile = ProjectLevelVcsManager.getInstance(project).getVcsFor(file); if (vscForFile != null) { - return new Pair(SupportedVCS.VCS, vscForFile); + return Pair.create(SupportedVCS.VCS, vscForFile); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java index e5762dd28643..433723377188 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -115,7 +115,7 @@ public class ChangeListWorker implements ChangeListsWriteOperations { final Collection changes = changeList.getChanges(); for (Change change : changes) { if (change.isMoved() || change.isRenamed()) { - moves.putValue(change.getBeforeRevision().getFile(), new Pair(change, changeList.getName())); + moves.putValue(change.getBeforeRevision().getFile(), Pair.create(change, changeList.getName())); } } } @@ -564,7 +564,7 @@ public class ChangeListWorker implements ChangeListsWriteOperations { final String beforeKey = beforePath == null ? null : beforePath.getIOFile().getAbsolutePath(); final FilePath afterPath = ChangesUtil.getAfterPath(change); final String afterKey = afterPath == null ? null : afterPath.getIOFile().getAbsolutePath(); - return new Pair(beforeKey, afterKey); + return Pair.create(beforeKey, afterKey); } private void preparation() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java index 03788f196192..969077f9bd28 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -263,7 +263,7 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { // update value in cache synchronized (myLock) { oldPair = myData.get(s); - myData.put(s, new Pair(myVcsRoot, newNumber)); + myData.put(s, Pair.create(myVcsRoot, newNumber)); } if (oldPair == null || oldPair.getSecond().compareTo(newNumber) != 0) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java index 8c820b7677ac..62edecf68862 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -94,7 +94,7 @@ public class VcsChangeDetailsManager { if (! convertor.canComment(change)) continue; RefreshablePanel panel = convertor.comment(change, parent, myQueue); if (panel != null) { - panels.add(new Pair("Diff", panel)); + panels.add(Pair.create("Diff", panel)); break; // only one of dedicated for now } } @@ -102,7 +102,7 @@ public class VcsChangeDetailsManager { if (provider.canComment(change)) { RefreshablePanel panel = provider.comment(change, parent, myQueue); if (panel != null) { - panels.add(new Pair(provider.getName(), panel)); + panels.add(Pair.create(provider.getName(), panel)); } } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsCurrentRevisionProxy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsCurrentRevisionProxy.java index cb34c2574a20..16ef7515a738 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsCurrentRevisionProxy.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsCurrentRevisionProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -135,6 +135,6 @@ public class VcsCurrentRevisionProxy implements ContentRevision { } Charset charset = myFile.getCharset(); charset = charset == null ? EncodingManager.getInstance().getDefaultCharset() : charset; - return new Pair(currentRevision, contentRevision.getContent().getBytes(charset)); + return Pair.create(currentRevision, contentRevision.getContent().getBytes(charset)); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/MultipleDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/MultipleDiffRequestPresentable.java index 5f06a4b03ada..9ef4d081ca95 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/MultipleDiffRequestPresentable.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/MultipleDiffRequestPresentable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,7 +51,7 @@ public class MultipleDiffRequestPresentable implements DiffRequestPresentable { final List> list = new ArrayList>(); final DiffRequestPresentable requestPresentable = convertor.convert(myChange, false); if (requestPresentable != null) { - list.add(new Pair("", requestPresentable)); + list.add(Pair.create("", requestPresentable)); } final Map layers = myChange.getOtherLayers(); for (Map.Entry entry : layers.entrySet()) { @@ -59,7 +59,7 @@ public class MultipleDiffRequestPresentable implements DiffRequestPresentable { final Change value = entry.getValue(); final DiffRequestPresentable additional = convertor.convert(value, true); if (additional != null) { - list.add(new Pair(key, additional)); + list.add(Pair.create(key, additional)); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java index 4c13ef015123..2da25f6e92c1 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -639,7 +639,7 @@ public class CommittedChangesCache implements PersistentStateComponent incomingChanges = cache.loadIncomingChanges(); - byVcs.putValue(cache.getVcs(), new Pair>(cache.getLocation(), incomingChanges)); + byVcs.putValue(cache.getVcs(), Pair.create(cache.getLocation(), incomingChanges)); } } catch (IOException e) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RepositoryLocationCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RepositoryLocationCache.java index afec2654a71b..e277f3095fc2 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RepositoryLocationCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RepositoryLocationCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -46,7 +46,7 @@ public class RepositoryLocationCache { } public RepositoryLocation getLocation(final AbstractVcs vcs, final FilePath filePath, final boolean silent) { - final Pair key = new Pair(vcs.getName(), filePath.getIOFile().getAbsolutePath()); + final Pair key = Pair.create(vcs.getName(), filePath.getIOFile().getAbsolutePath()); RepositoryLocation location = myMap.get(key); if (location != null) { return location; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/dbCommitted/KnownRepositoryLocations.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/dbCommitted/KnownRepositoryLocations.java index 09144347fb92..b71198f6940b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/dbCommitted/KnownRepositoryLocations.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/dbCommitted/KnownRepositoryLocations.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -106,7 +106,7 @@ public class KnownRepositoryLocations { public long getLocationId(final String key, final String path) { synchronized (myMap) { - final Long id = myLocations.get(new Pair(key, path)); + final Long id = myLocations.get(Pair.create(key, path)); assert id != null; return id; } @@ -115,7 +115,7 @@ public class KnownRepositoryLocations { public void add(final String key, final String path, final long id) { synchronized (myMap) { myMap.putValue(key, path); - myLocations.put(new Pair(key, path), id); + myLocations.put(Pair.create(key, path), id); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index e652c425ec64..e6a758e67671 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -135,7 +135,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { final Set> set = new HashSet>(); for (FilePatchInProgress.PatchChange change : includedChanges) { final TextFilePatch patch = change.getPatchInProgress().getPatch(); - final Pair pair = new Pair(patch.getBeforeName(), patch.getAfterName()); + final Pair pair = Pair.create(patch.getBeforeName(), patch.getAfterName()); if (set.contains(pair)) continue; set.add(pair); acceptChange(includedTrinity, change); @@ -811,8 +811,8 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { final String basePath = patchChange.getPatchInProgress().getBase().getPath(); final String basePathCorrected = basePath.trim().replace('/', File.separatorChar); if (parentPath.startsWith(basePathCorrected)) { - return Arrays.asList(new Pair(basePathCorrected, Stress.BOLD), - new Pair(StringUtil.tail(parentPath, basePathCorrected.length()), Stress.PLAIN)); + return Arrays.asList(Pair.create(basePathCorrected, Stress.BOLD), + Pair.create(StringUtil.tail(parentPath, basePathCorrected.length()), Stress.PLAIN)); } } return null; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/FilePatchInProgress.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/FilePatchInProgress.java index cacdf62dbba6..efe76a073e2f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/FilePatchInProgress.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/FilePatchInProgress.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -258,7 +258,7 @@ public class FilePatchInProgress implements Strippable { } public Pair getKey() { - return new Pair(myPatch.getBeforeName(), myPatch.getAfterName()); + return Pair.create(myPatch.getBeforeName(), myPatch.getAfterName()); } private void refresh() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/OneBaseStrategy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/OneBaseStrategy.java index 442b0dcc8f43..e485e023c827 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/OneBaseStrategy.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/OneBaseStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -19,7 +19,6 @@ import com.intellij.openapi.diff.impl.patch.TextFilePatch; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.MultiMap; -import org.jetbrains.annotations.Nullable; import java.util.*; @@ -108,13 +107,13 @@ class OneBaseStrategy extends AutoMatchStrategy { } } if (sameStrip) { - privilegedSurvivor = new Pair>(file, patches); + privilegedSurvivor = Pair.create(file, patches); break; } } if (privilegedSurvivor == null) { final VirtualFile first = myVariants.keySet().iterator().next(); - privilegedSurvivor = new Pair>(first, myVariants.get(first)); + privilegedSurvivor = Pair.create(first, myVariants.get(first)); } myVariants.clear(); myVariants.put(privilegedSurvivor.getFirst(), privilegedSurvivor.getSecond()); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java index 258fd99de560..2ec6b59af070 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -258,7 +258,7 @@ public class ShelvedChangesViewManager implements ProjectComponent { private void putMovedMessage(final String beforeName, final String afterName) { final String movedMessage = RelativePathCalculator.getMovedString(beforeName, afterName); if (movedMessage != null) { - myMoveRenameInfo.put(new Pair(beforeName, afterName), movedMessage); + myMoveRenameInfo.put(Pair.create(beforeName, afterName), movedMessage); } } @@ -450,7 +450,7 @@ public class ShelvedChangesViewManager implements ProjectComponent { } else if (nodeValue instanceof ShelvedChange) { ShelvedChange change = (ShelvedChange) nodeValue; - final String movedMessage = myMoveRenameInfo.get(new Pair(change.getBeforePath(), change.getAfterPath())); + final String movedMessage = myMoveRenameInfo.get(Pair.create(change.getBeforePath(), change.getAfterPath())); renderFileName(change.getBeforePath(), change.getFileStatus(), movedMessage); } else if (nodeValue instanceof ShelvedBinaryFile) { @@ -459,7 +459,7 @@ public class ShelvedChangesViewManager implements ProjectComponent { if (path == null) { path = binaryFile.AFTER_PATH; } - final String movedMessage = myMoveRenameInfo.get(new Pair(binaryFile.BEFORE_PATH, binaryFile.AFTER_PATH)); + final String movedMessage = myMoveRenameInfo.get(Pair.create(binaryFile.BEFORE_PATH, binaryFile.AFTER_PATH)); renderFileName(path, binaryFile.getFileStatus(), movedMessage); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesListView.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesListView.java index ea6b317b8f2b..e38afbb2e961 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesListView.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesListView.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -666,7 +666,7 @@ public class ChangesListView extends Tree implements TypeSafeDataProvider, Advan @Nullable public Pair createDraggedImage(DnDAction action, Point dragOrigin) { final Image image = DragImageFactory.createImage(this); - return new Pair(image, new Point(-image.getWidth(null), -image.getHeight(null))); + return Pair.create(image, new Point(-image.getWidth(null), -image.getHeight(null))); } @Override diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java index 904b070d2a57..cbf9d2b1889a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java @@ -410,7 +410,7 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme if (myProject.isDisposed() || myProject.isDefault()) return; final ContentManager contentManager = getContentManager(); if (contentManager == null) { - myPendingOutput.add(new Pair(message, attributes)); + myPendingOutput.add(Pair.create(message, attributes)); } else { getOrCreateConsoleContent(contentManager); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java index 498f3d1a5c28..fe064fd5d513 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java @@ -67,7 +67,7 @@ public class VcsInitialization { ApplicationManager.getApplication().invokeLater(runnable); return; } - myList.add(new Pair(vcsInitObject, runnable)); + myList.add(Pair.create(vcsInitObject, runnable)); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java index 1a4b39055e82..de1a40d80f36 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -385,7 +385,7 @@ public class NewMappings { if (vf == null) { vf = lfs.refreshAndFindFileByPath(dm.getDirectory()); } - return vf == null ? null : new Pair(vf, dm); + return vf == null ? null : Pair.create(vf, dm); } }, ObjectsConvertor.NOT_NULL); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateFilesHelper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateFilesHelper.java index 951a0a314541..80ce02b846c6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateFilesHelper.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateFilesHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -67,7 +67,7 @@ public class UpdateFilesHelper { private static void iterateGroup(final FileGroup group, final Consumer> callback) { for (FileGroup.UpdatedFile updatedFile : group.getUpdatedFiles()) { - callback.consume(new Pair(updatedFile.getPath(), updatedFile.getVcsName())); + callback.consume(Pair.create(updatedFile.getPath(), updatedFile.getVcsName())); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateInfoTree.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateInfoTree.java index 36c256212dc0..405eaee95060 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateInfoTree.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateInfoTree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -285,7 +285,7 @@ public class UpdateInfoTree extends PanelWithActionsAndCloseButton implements Di final VirtualFilePointer result = myNext; final FileStatus status = myStatus; step(); - return new Pair(result, status); + return Pair.create(result, status); } private void step() { @@ -457,7 +457,7 @@ public class UpdateInfoTree extends PanelWithActionsAndCloseButton implements Di if (scope != null) { PackageSet packageSet = scope.getValue(); if (packageSet instanceof PackageSetBase) { - return new Pair((PackageSetBase)packageSet, holder); + return Pair.create((PackageSetBase)packageSet, holder); } } } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/facade/graph/permanent/PermanentGraphBuilder.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/facade/graph/permanent/PermanentGraphBuilder.java index 2b65eac5fb19..e8f4be4546a2 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/facade/graph/permanent/PermanentGraphBuilder.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/facade/graph/permanent/PermanentGraphBuilder.java @@ -19,12 +19,15 @@ package com.intellij.vcs.log.facade.graph.permanent; import com.intellij.openapi.util.Pair; import com.intellij.util.SmartList; import com.intellij.vcs.log.GraphCommit; +import com.intellij.vcs.log.facade.utils.Flags; import com.intellij.vcs.log.facade.utils.impl.BitSetFlags; import com.intellij.vcs.log.newgraph.SomeGraph; -import com.intellij.vcs.log.facade.utils.Flags; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static com.intellij.vcs.log.facade.graph.permanent.DuplicateParentFixer.fixDuplicateParentCommits; @@ -54,7 +57,7 @@ public class PermanentGraphBuilder { PermanentGraphBuilder builder = new PermanentGraphBuilder(commits, simpleNodes, longEdgesCount, nodeToHashIndex); PermanentGraphImpl permanentGraph = builder.build(); - return new Pair>(permanentGraph, builder.commitsWithNotLoadParentMap); + return Pair.create(permanentGraph, builder.commitsWithNotLoadParentMap); } private static int nextCommitHashIndex(List commits, int nodeIndex) { diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/newgraph/facade/GraphActionDispatcher.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/newgraph/facade/GraphActionDispatcher.java index e31a435ae7cc..13a45c26573f 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/newgraph/facade/GraphActionDispatcher.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/newgraph/facade/GraphActionDispatcher.java @@ -19,9 +19,6 @@ package com.intellij.vcs.log.newgraph.facade; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Pair; import com.intellij.vcs.log.GraphCommit; -import com.intellij.vcs.log.graph.ChangeCursorActionRequest; -import com.intellij.vcs.log.graph.ClickGraphAction; -import com.intellij.vcs.log.graph.MouseOverAction; import com.intellij.vcs.log.graph.*; import com.intellij.vcs.log.newgraph.SomeGraph; import com.intellij.vcs.log.newgraph.gpaph.Edge; @@ -159,7 +156,7 @@ public class GraphActionDispatcher { SpecialRowElement overArrow = myGraphData.getGraphRender().getCellPainter().mouseOverArrow(graphCell, point.x, point.y); GraphElement overElement = myGraphData.getGraphRender().getCellPainter().mouseOver(graphCell, point.x, point.y); - return new Pair(overArrow, overElement); + return Pair.create(overArrow, overElement); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index f40af264f4f6..b3b1ef099301 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -315,6 +315,9 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C private void performAction(@NotNull MouseEvent e, @NotNull PairFunction actionConstructor) { int row = PositionUtil.getRowIndex(e.getPoint()); + if (row > getRowCount() - 1) { + return; + } Point point = calcPoint4Graph(e.getPoint()); GraphFacade graphFacade = myDataPack.getGraphFacade(); GraphAnswer answer = graphFacade.performAction(actionConstructor.fun(row, point)); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml index 2b47e3a3c33d..d160d0598b18 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml @@ -943,13 +943,13 @@ INTERFACE_REDUNDANT_MODIFIERS = new HashSet(Arrays.asList(PsiModifier.ABSTRACT, PsiModifier.STATIC)); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java index 16dcce5c564d..d9c69901e528 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.openapi.project.Project; @@ -28,7 +29,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; -public class UnnecessaryParenthesesInspection extends BaseInspection { +public class UnnecessaryParenthesesInspection extends BaseInspection implements CleanupLocalInspectionTool { @SuppressWarnings({"PublicField"}) public boolean ignoreClarifyingParentheses = false; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java index d120d66f1db1..7e97eb601b2e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.openapi.project.Project; @@ -28,8 +29,7 @@ import com.siyeh.ig.PsiReplacementUtil; import com.siyeh.ig.psiutils.ClassUtils; import org.jetbrains.annotations.NotNull; -public class UnnecessaryQualifierForThisInspection - extends BaseInspection { +public class UnnecessaryQualifierForThisInspection extends BaseInspection implements CleanupLocalInspectionTool { @Override @NotNull diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java index 5c014906557f..c1a75887c6aa 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; @@ -29,7 +30,7 @@ import com.siyeh.ig.InspectionGadgetsFix; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class UnnecessarySemicolonInspection extends BaseInspection { +public class UnnecessarySemicolonInspection extends BaseInspection implements CleanupLocalInspectionTool { @Override @NotNull diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperConstructorInspection.java index 83c70a19f11f..38d8bca7d3b1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperConstructorInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperConstructorInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.openapi.project.Project; @@ -26,8 +27,7 @@ import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import org.jetbrains.annotations.NotNull; -public class UnnecessarySuperConstructorInspection - extends BaseInspection { +public class UnnecessarySuperConstructorInspection extends BaseInspection implements CleanupLocalInspectionTool { @Override @NotNull diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperQualifierInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperQualifierInspection.java index fea9d878f9de..e311b54ccc81 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperQualifierInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperQualifierInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.openapi.project.Project; @@ -29,7 +30,7 @@ import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class UnnecessarySuperQualifierInspection extends BaseInspection { +public class UnnecessarySuperQualifierInspection extends BaseInspection implements CleanupLocalInspectionTool { @Override @Nls diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java index 72ad69a54dcd..aa2d3ea2fce1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; @@ -34,7 +35,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; -public class UnnecessaryThisInspection extends BaseInspection { +public class UnnecessaryThisInspection extends BaseInspection implements CleanupLocalInspectionTool { @SuppressWarnings("PublicField") public boolean ignoreAssignments = false; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java index 6e8280194ec8..82014a4dd617 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; @@ -30,7 +31,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class UnnecessaryToStringCallInspection extends BaseInspection { +public class UnnecessaryToStringCallInspection extends BaseInspection implements CleanupLocalInspectionTool { @Override @Nls diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java index 07cb79af2d9d..e79f9df5fa7d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -42,7 +43,7 @@ import java.util.List; /** * @see com.siyeh.ipp.fqnames.ReplaceFullyQualifiedNameWithImportIntention */ -public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection { +public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection implements CleanupLocalInspectionTool { @SuppressWarnings("PublicField") public boolean m_ignoreJavadoc = false; // left here to prevent changes to project files. diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java index ce84d8e173f9..c8d9fb80cf19 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java @@ -7,7 +7,7 @@ public class MismatchedStringBuilderQueryUpdate { b.append(""); System.out.println("" + b + ""); - final StringBuilder c = new StringBuilder(); + final StringBuilder c = new StringBuilder(); c.append(' '); } @@ -17,4 +17,17 @@ public class MismatchedStringBuilderQueryUpdate { sb.append("abc"); return sb.reverse(); } + + void indexedList(List list) { + StringBuilder stringBuilder = new StringBuilder(); // <--- false warning here + list.forEach(stringBuilder::append); + System.out.println(stringBuilder.toString()); + } +} +interface List { + default void forEach(Consumer action) { + } +} +interface Consumer { + void accept(T t); } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/expected.xml deleted file mode 100644 index 43998eaeb786..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/expected.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - MismatchedStringBuilderQueryUpdate.java - 10 - Mismatched query and update of StringBuilder - Contents of StringBuilder <code>c</code> are updated, but never queried #loc - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MismatchedStringBuilderQueryUpdateInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MismatchedStringBuilderQueryUpdateInspectionTest.java index 4a739a04234a..293d372d6ca6 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MismatchedStringBuilderQueryUpdateInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MismatchedStringBuilderQueryUpdateInspectionTest.java @@ -1,10 +1,16 @@ package com.siyeh.ig.bugs; -import com.siyeh.ig.IGInspectionTestCase; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; -public class MismatchedStringBuilderQueryUpdateInspectionTest extends IGInspectionTestCase { +public class MismatchedStringBuilderQueryUpdateInspectionTest extends LightInspectionTestCase { - public void test() throws Exception { - doTest("com/siyeh/igtest/bugs/mismatched_string_builder_query_update", new MismatchedStringBuilderQueryUpdateInspection()); + public void testMismatchedStringBuilderQueryUpdate() throws Exception { + doTest(); + } + + @Override + protected InspectionProfileEntry getInspection() { + return new MismatchedStringBuilderQueryUpdateInspection(); } } \ No newline at end of file diff --git a/plugins/ant/src/com/intellij/lang/ant/ReflectedProject.java b/plugins/ant/src/com/intellij/lang/ant/ReflectedProject.java index 3147067f3725..9fb88751d4fa 100644 --- a/plugins/ant/src/com/intellij/lang/ant/ReflectedProject.java +++ b/plugins/ant/src/com/intellij/lang/ant/ReflectedProject.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -77,7 +77,7 @@ public final class ReflectedProject { ourProjectsLock.lock(); try { ourProjects.add(new SoftReference>( - new Pair(reflectedProj, classLoader) + Pair.create(reflectedProj, classLoader) )); } finally { diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java index 3bdcbeb150eb..f758fe660202 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java @@ -349,7 +349,7 @@ public class AntConfigurationImpl extends AntConfigurationBase implements Persis public void setTargetForEvent(final AntBuildFile buildFile, final String targetName, final ExecutionEvent event) { synchronized (myEventToTargetMap) { - myEventToTargetMap.put(event, new Pair(buildFile, targetName)); + myEventToTargetMap.put(event, Pair.create(buildFile, targetName)); } } @@ -364,7 +364,7 @@ public class AntConfigurationImpl extends AntConfigurationBase implements Persis for (Map.Entry> entry : myEventToTargetMap.entrySet()) { final Pair pair = entry.getValue(); if (pair != null && Comparing.equal(pair.getSecond(), oldTargetName)) { - entry.setValue(new Pair(pair.getFirst(), newTargetName)); + entry.setValue(Pair.create(pair.getFirst(), newTargetName)); } } } @@ -691,7 +691,7 @@ public class AntConfigurationImpl extends AntConfigurationBase implements Persis final Element element = (Element)o; final String url = element.getAttributeValue(URL); if (url != null) { - files.add(new Pair(element, url)); + files.add(Pair.create(element, url)); } } @@ -738,7 +738,7 @@ public class AntConfigurationImpl extends AntConfigurationBase implements Persis try { final AntBuildFileBase buildFile = addBuildFileImpl(file); buildFile.readProperties(element); - buildFiles.add(new Pair(element, buildFile)); + buildFiles.add(Pair.create(element, buildFile)); } catch (AntNoFileException ignored) { } diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomExtender.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomExtender.java index 02ab264cc894..af3c9a84071f 100644 --- a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomExtender.java +++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomExtender.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -259,7 +259,7 @@ public class AntDomExtender extends DomExtender{ registerAttribute(registrar, attribName, type, converterClass); if (types == null) { // augment the map if this was a newly added attribute - registeredAttribs.put(_attribName, new Pair(type, converterClass)); + registeredAttribs.put(_attribName, Pair.create(type, converterClass)); } } } diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/PropertyProviderFinder.java b/plugins/ant/src/com/intellij/lang/ant/dom/PropertyProviderFinder.java index bacdda88f49f..7421e57d9fd5 100644 --- a/plugins/ant/src/com/intellij/lang/ant/dom/PropertyProviderFinder.java +++ b/plugins/ant/src/com/intellij/lang/ant/dom/PropertyProviderFinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -165,7 +165,7 @@ public abstract class PropertyProviderFinder extends AntDomRecursiveVisitor { final String dependentTargetEffectiveName = myNameContext.calcTargetReferenceText(token); final AntDomTarget dependent = getTargetByName(dependentTargetEffectiveName); if (dependent != null) { - depsMap.put(token, new Pair(dependent, dependentTargetEffectiveName)); + depsMap.put(token, Pair.create(dependent, dependentTargetEffectiveName)); } addDependency(effectiveTargetName, dependentTargetEffectiveName); } @@ -368,7 +368,7 @@ public abstract class PropertyProviderFinder extends AntDomRecursiveVisitor { public void pushPrefix(String prefix, InclusionKind kind) { myCurrentPrefix = null; - myPrefixes.addLast(new Pair(prefix, kind)); + myPrefixes.addLast(Pair.create(prefix, kind)); } public void popPrefix() { diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/TargetResolver.java b/plugins/ant/src/com/intellij/lang/ant/dom/TargetResolver.java index 6bb683adeaee..25041fd33f18 100644 --- a/plugins/ant/src/com/intellij/lang/ant/dom/TargetResolver.java +++ b/plugins/ant/src/com/intellij/lang/ant/dom/TargetResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -130,7 +130,7 @@ public class TargetResolver extends PropertyProviderFinder { final String declaredRef = it.next(); final AntDomTarget result = getTargetByName(declaredRef); if (result != null) { - myResult.add(declaredRef, new Pair(result, declaredRef)); // treat declared name as effective name + myResult.add(declaredRef, Pair.create(result, declaredRef)); // treat declared name as effective name it.remove(); } } diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java index 0b36db82a451..d4ab5560edf6 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -314,10 +314,10 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis assert profileName != null; final String name = generator.generateUniqueName(FileUtil.sanitizeFileName(profileName)) + ".xml"; - result.add(new Pair(element, name)); + result.add(Pair.create(element, name)); } } - result.add(new Pair(e, generator.generateUniqueName("profiles_settings") + ".xml")); + result.add(Pair.create(e, generator.generateUniqueName("profiles_settings") + ".xml")); return result; } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java index 0ad007a80863..02341fe2dafb 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -208,7 +208,7 @@ public class CvsCommittedChangesProvider implements CachingCommittedChangesProvi if (cvsResult.hasErrors()) { throw cvsResult.composeError(); } - return new Pair(result.get(), filePath); + return Pair.create(result.get(), filePath); } @Override diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml index 8328e61b01f9..3386049aff73 100644 --- a/plugins/devkit/resources/META-INF/plugin.xml +++ b/plugins/devkit/resources/META-INF/plugin.xml @@ -138,6 +138,11 @@ groupKey="inspections.group.name" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.idea.devkit.inspections.internal.UseCoupleInspection"/> + diff --git a/plugins/devkit/resources/inspectionDescriptions/DontUsePairConstructor.html b/plugins/devkit/resources/inspectionDescriptions/DontUsePairConstructor.html new file mode 100644 index 000000000000..d1cb8f0582a4 --- /dev/null +++ b/plugins/devkit/resources/inspectionDescriptions/DontUsePairConstructor.html @@ -0,0 +1,6 @@ + + +Using of Pair constructor produces unnecessary generic declarations. Use Pair.create(a, b) + + + \ No newline at end of file diff --git a/plugins/devkit/src/build/PluginBuildConfiguration.java b/plugins/devkit/src/build/PluginBuildConfiguration.java index 5b5dc7bf8394..3604b0f0d13a 100644 --- a/plugins/devkit/src/build/PluginBuildConfiguration.java +++ b/plugins/devkit/src/build/PluginBuildConfiguration.java @@ -39,6 +39,7 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import org.jetbrains.idea.devkit.DevKitBundle; import org.jetbrains.idea.devkit.module.PluginDescriptorConstants; @@ -110,6 +111,11 @@ public class PluginBuildConfiguration implements ModuleComponent, JDOMExternaliz return myPluginXmlContainer.getConfigFile(PluginDescriptorConstants.META_DATA); } + @TestOnly + public void setPluginXmlFromVirtualFile(VirtualFile virtualFile) { + myPluginXmlContainer.getConfiguration().replaceConfigFile(PluginDescriptorConstants.META_DATA, virtualFile.getUrl()); + } + private void createDescriptor(final String url) { final ConfigFileInfo descriptor = new ConfigFileInfo(PluginDescriptorConstants.META_DATA, url); myPluginXmlContainer.getConfiguration().addConfigFile(descriptor); diff --git a/plugins/devkit/src/dom/ExtensionPoint.java b/plugins/devkit/src/dom/ExtensionPoint.java index 6a5074f7ce02..ddd2573497a7 100644 --- a/plugins/devkit/src/dom/ExtensionPoint.java +++ b/plugins/devkit/src/dom/ExtensionPoint.java @@ -65,6 +65,20 @@ public interface ExtensionPoint extends DomElement { With addWith(); + /** + * Returns the fully qualified EP name + * + * @return {@code PluginID.name} or {@code qualifiedName}. + * @since 14 + */ + @NotNull + String getEffectiveQualifiedName(); + + /** + * Returns the actually defined name. + * + * @return {@link #getName()} if defined, {@link #getQualifiedName()} otherwise. + */ @NotNull String getEffectiveName(); diff --git a/plugins/devkit/src/dom/Extensions.java b/plugins/devkit/src/dom/Extensions.java index f07357e56fe4..738a3a792079 100644 --- a/plugins/devkit/src/dom/Extensions.java +++ b/plugins/devkit/src/dom/Extensions.java @@ -42,7 +42,7 @@ public interface Extensions extends DomElement { Extension addExtension(); - Extension addExtension(String name); + Extension addExtension(String qualifiedEPName); @NotNull String getEpPrefix(); diff --git a/plugins/devkit/src/dom/impl/ExtensionPointImpl.java b/plugins/devkit/src/dom/impl/ExtensionPointImpl.java index f4eb409e6164..1287948c2752 100644 --- a/plugins/devkit/src/dom/impl/ExtensionPointImpl.java +++ b/plugins/devkit/src/dom/impl/ExtensionPointImpl.java @@ -45,4 +45,14 @@ public abstract class ExtensionPointImpl implements ExtensionPoint { return StringUtil.notNullize(plugin.getPluginId(), "com.intellij"); } + + @NotNull + @Override + public String getEffectiveQualifiedName() { + if (DomUtil.hasXml(getQualifiedName())) { + return getQualifiedName().getRawText(); + } + + return getNamePrefix() + "." + getName().getRawText(); + } } diff --git a/plugins/devkit/src/dom/impl/ExtensionsImpl.java b/plugins/devkit/src/dom/impl/ExtensionsImpl.java index e52cdca34c2f..d820e08bd568 100644 --- a/plugins/devkit/src/dom/impl/ExtensionsImpl.java +++ b/plugins/devkit/src/dom/impl/ExtensionsImpl.java @@ -15,10 +15,12 @@ */ package org.jetbrains.idea.devkit.dom.impl; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.xml.XmlTag; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.devkit.dom.Extension; import org.jetbrains.idea.devkit.dom.Extensions; +import org.jetbrains.idea.devkit.dom.IdeaPlugin; /** * @author Dmitry Avdeev @@ -27,16 +29,20 @@ import org.jetbrains.idea.devkit.dom.Extensions; public abstract class ExtensionsImpl implements Extensions { @Override - public Extension addExtension(String name) { + public Extension addExtension(String qualifiedEPName) { Extension extension = addExtension(); XmlTag tag = extension.getXmlTag(); - tag.setName(name.substring(getDefaultExtensionNs().getStringValue().length() + 1)); + tag.setName(qualifiedEPName.substring(StringUtil.commonPrefixLength(qualifiedEPName, getEpPrefix()))); return extension; } @NotNull public String getEpPrefix() { String prefix = getDefaultExtensionNs().getStringValue(); + if (prefix == null) { + final IdeaPlugin ideaPlugin = getParentOfType(IdeaPlugin.class, true); + prefix = ideaPlugin == null ? null : StringUtil.notNullize(ideaPlugin.getPluginId(), "com.intellij"); + } if (prefix == null) prefix = getXmlns().getStringValue(); return prefix != null ? prefix + "." : ""; } diff --git a/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java b/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java index 15d0d0abb89c..80a3aabce8f3 100644 --- a/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java +++ b/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java @@ -49,6 +49,19 @@ public class PluginXmlDomFileDescription extends DomFileDescription else if (element instanceof IdeaVersion) { annotateIdeaVersion((IdeaVersion)element, holder); } + else if (element instanceof Extensions) { + annotateExtensions((Extensions)element, holder); + } + } + + private void annotateExtensions(Extensions extensions, DomElementAnnotationHolder holder) { + final GenericAttributeValue xmlnsAttribute = extensions.getXmlns(); + if (!DomUtil.hasXml(xmlnsAttribute)) return; + + final Annotation annotation = holder.createAnnotation(xmlnsAttribute, + HighlightSeverity.WARNING, + "Use defaultExtensionNs instead"); + annotation.setHighlightType(ProblemHighlightType.LIKE_DEPRECATED); } private void annotateIdeaVersion(IdeaVersion ideaVersion, DomElementAnnotationHolder holder) { diff --git a/plugins/devkit/src/inspections/DevKitInspectionBase.java b/plugins/devkit/src/inspections/DevKitInspectionBase.java index 9ded8e216fc0..5b58a7af8287 100644 --- a/plugins/devkit/src/inspections/DevKitInspectionBase.java +++ b/plugins/devkit/src/inspections/DevKitInspectionBase.java @@ -26,9 +26,12 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.xml.*; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.xml.DomFileElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.DevKitBundle; +import org.jetbrains.idea.devkit.dom.Dependency; +import org.jetbrains.idea.devkit.dom.IdeaPlugin; import org.jetbrains.idea.devkit.module.PluginModuleType; import org.jetbrains.idea.devkit.util.ActionType; import org.jetbrains.idea.devkit.util.ComponentType; @@ -62,7 +65,8 @@ public abstract class DevKitInspectionBase extends BaseJavaLocalInspectionTool { if (PluginModuleType.isOfType(module)) { return checkModule(module, psiClass, null, includeActions); - } else { + } + else { Set types = null; final List modules = PluginModuleType.getCandidateModules(module); for (Module m : modules) { @@ -78,20 +82,26 @@ public abstract class DevKitInspectionBase extends BaseJavaLocalInspectionTool { if (!DescriptorUtil.isPluginXml(pluginXml)) return types; assert pluginXml != null; - final XmlDocument document = pluginXml.getDocument(); - assert document != null; - - final XmlTag rootTag = document.getRootTag(); - assert rootTag != null; - final String qualifiedName = psiClass.getQualifiedName(); if (qualifiedName != null) { final RegistrationTypeFinder finder = new RegistrationTypeFinder(psiClass, types); - DescriptorUtil.processComponents(rootTag, finder); + // "main" plugin.xml + processPluginXml(pluginXml, finder, includeActions); - if (includeActions) { - DescriptorUtil.processActions(rootTag, finder); + // plugin.xml files + final VirtualFile pluginXmlDirectory = pluginXml.getVirtualFile().getParent(); + final DomFileElement fileElement = DescriptorUtil.getIdeaPlugin(pluginXml); + for (Dependency dependency : fileElement.getRootElement().getDependencies()) { + final String configFile = dependency.getConfigFile().getValue(); + if (configFile != null) { + final VirtualFile depVirtualFile = pluginXmlDirectory.findChild(configFile); + if (depVirtualFile == null) continue; + final PsiFile depPluginXml = PsiManager.getInstance(module.getProject()).findFile(depVirtualFile); + if (DescriptorUtil.isPluginXml(depPluginXml)) { + processPluginXml((XmlFile)depPluginXml, finder, includeActions); + } + } } types = finder.getTypes(); @@ -100,6 +110,18 @@ public abstract class DevKitInspectionBase extends BaseJavaLocalInspectionTool { return types; } + private static void processPluginXml(XmlFile xmlFile, RegistrationTypeFinder finder, boolean includeActions) { + final XmlDocument document = xmlFile.getDocument(); + if (document == null) return; + final XmlTag rootTag = document.getRootTag(); + if (rootTag == null) return; + + DescriptorUtil.processComponents(rootTag, finder); + if (includeActions) { + DescriptorUtil.processActions(rootTag, finder); + } + } + @Nullable protected static PsiElement getAttValueToken(@NotNull XmlAttribute attribute) { final XmlAttributeValue valueElement = attribute.getValueElement(); @@ -132,13 +154,14 @@ public abstract class DevKitInspectionBase extends BaseJavaLocalInspectionTool { return false; } - static class RegistrationTypeFinder implements ComponentType.Processor, ActionType.Processor { + + private static class RegistrationTypeFinder implements ComponentType.Processor, ActionType.Processor { private Set myTypes; private final String myQualifiedName; private final PsiManager myManager; private final GlobalSearchScope myScope; - public RegistrationTypeFinder(PsiClass psiClass, Set types) { + private RegistrationTypeFinder(PsiClass psiClass, Set types) { myTypes = types; myQualifiedName = psiClass.getQualifiedName(); myManager = psiClass.getManager(); diff --git a/plugins/devkit/src/inspections/internal/DontUseNewPairInspection.java b/plugins/devkit/src/inspections/internal/DontUseNewPairInspection.java new file mode 100644 index 000000000000..23405f180c5a --- /dev/null +++ b/plugins/devkit/src/inspections/internal/DontUseNewPairInspection.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2014 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.idea.devkit.inspections.internal; + +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.PsiClassReferenceType; +import com.intellij.psi.util.PsiUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.devkit.inspections.quickfix.ChangeToPairCreateQuickFix; + +import java.util.Arrays; + +/** + * @author Konstantin Bulenkov + */ +public class DontUseNewPairInspection extends InternalInspection { + private static final String PAIR_FQN = "com.intellij.openapi.util.Pair"; + + @Override + public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { + return new JavaElementVisitor() { + @Override + public void visitNewExpression(PsiNewExpression expression) { + final PsiType type = expression.getType(); + final PsiExpressionList params = expression.getArgumentList(); + if (type != null && type.getCanonicalText().startsWith(PAIR_FQN) && params != null + && !(type instanceof PsiArrayType) + && expression.getText().indexOf('(') > 0 + && type instanceof PsiClassReferenceType + && !PsiUtil.getLanguageLevel(expression).isAtLeast(LanguageLevel.JDK_1_7)) { //diamonds + final PsiType[] types = ((PsiClassReferenceType)type).getParameters(); + if (Arrays.equals(types, params.getExpressionTypes())) { + holder.registerProblem(expression, "Replace to Pair.create()", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + new ChangeToPairCreateQuickFix()); + } + } + super.visitNewExpression(expression); + } + }; + } + + @Nls + @NotNull + @Override + public String getDisplayName() { + return "Don't use Pair constructor"; + } + + @NotNull + @Override + public String getShortName() { + return "DontUsePairConstructor"; + } +} + diff --git a/plugins/devkit/src/inspections/quickfix/ChangeToPairCreateQuickFix.java b/plugins/devkit/src/inspections/quickfix/ChangeToPairCreateQuickFix.java new file mode 100644 index 000000000000..a8462a002486 --- /dev/null +++ b/plugins/devkit/src/inspections/quickfix/ChangeToPairCreateQuickFix.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2014 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.idea.devkit.inspections.quickfix; + +import com.intellij.codeInspection.LocalQuickFixBase; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementFactory; +import com.intellij.psi.PsiExpression; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import org.jetbrains.annotations.NotNull; + +/** + * @author Konstantin Bulenkov + */ +public class ChangeToPairCreateQuickFix extends LocalQuickFixBase { + public ChangeToPairCreateQuickFix() { + super("Change to Pair.create(..., ...)"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + PsiElement element = descriptor.getPsiElement(); + if (element == null) { + return; + } + String text = element.getText(); + String newText = "com.intellij.openapi.util.Pair.create(" + text.substring(text.indexOf('(') + 1); + PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + PsiExpression expression = factory.createExpressionFromText(newText, element.getContext()); + PsiElement newElement = element.replace(expression); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(newElement); + } +} diff --git a/plugins/devkit/src/inspections/quickfix/RegisterActionFix.java b/plugins/devkit/src/inspections/quickfix/RegisterActionFix.java index 061deef3d7b3..3eb7ef22ca46 100644 --- a/plugins/devkit/src/inspections/quickfix/RegisterActionFix.java +++ b/plugins/devkit/src/inspections/quickfix/RegisterActionFix.java @@ -16,14 +16,17 @@ package org.jetbrains.idea.devkit.inspections.quickfix; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; import com.intellij.psi.xml.XmlFile; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.TestOnly; import org.jetbrains.idea.devkit.DevKitBundle; import org.jetbrains.idea.devkit.actions.NewActionDialog; +import org.jetbrains.idea.devkit.util.ActionData; import org.jetbrains.idea.devkit.util.ActionType; -import org.jetbrains.annotations.NotNull; public class RegisterActionFix extends AbstractRegisterFix { private NewActionDialog myDialog; @@ -37,6 +40,11 @@ public class RegisterActionFix extends AbstractRegisterFix { } public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + super.applyFix(project, descriptor); + return; + } + try { myDialog = new NewActionDialog(myClass); myDialog.show(); @@ -52,9 +60,20 @@ public class RegisterActionFix extends AbstractRegisterFix { public void patchPluginXml(XmlFile pluginXml, PsiClass aClass) throws IncorrectOperationException { if (ActionType.GROUP.isOfType(aClass)) { - ActionType.GROUP.patchPluginXml(pluginXml, aClass, myDialog); - } else { - ActionType.ACTION.patchPluginXml(pluginXml, aClass, myDialog); + ActionType.GROUP.patchPluginXml(pluginXml, aClass, getActionData()); + } + else { + ActionType.ACTION.patchPluginXml(pluginXml, aClass, getActionData()); } } + + @TestOnly + public static ActionData ourTestActionData = null; + + private ActionData getActionData() { + if (ApplicationManager.getApplication().isUnitTestMode()) { + return ourTestActionData; + } + return myDialog; + } } diff --git a/plugins/devkit/src/inspections/quickfix/RegisterExtensionFixProvider.java b/plugins/devkit/src/inspections/quickfix/RegisterExtensionFixProvider.java index ba02d703c93c..488d1b12111e 100644 --- a/plugins/devkit/src/inspections/quickfix/RegisterExtensionFixProvider.java +++ b/plugins/devkit/src/inspections/quickfix/RegisterExtensionFixProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -30,7 +30,11 @@ import com.intellij.psi.search.PsiSearchHelper; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlTag; +import com.intellij.util.xml.DomElement; +import com.intellij.util.xml.DomUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.devkit.dom.ExtensionPoint; import java.util.ArrayList; import java.util.HashSet; @@ -102,6 +106,7 @@ public class RegisterExtensionFixProvider implements UnusedDeclarationFixProvide } else if ("with".equals(tag.getName())) { XmlTag extensionPointTag = tag.getParentTag(); + if (extensionPointTag == null) return; if (!"extensionPoint".equals(extensionPointTag.getName())) return; String attrName = tag.getAttributeValue("attribute"); String tagName = tag.getAttributeValue("tag"); @@ -112,15 +117,10 @@ public class RegisterExtensionFixProvider implements UnusedDeclarationFixProvide } } + @Nullable private static String getEPName(XmlTag tag) { - String qName = tag.getAttributeValue("qualifiedName"); - if (qName != null) { - return qName; - } - String name = tag.getAttributeValue("name"); - if (name != null) { - return "com.intellij." + name; - } - return null; + final DomElement domElement = DomUtil.getDomElement(tag); + if (!(domElement instanceof ExtensionPoint)) return null; + return ((ExtensionPoint)domElement).getEffectiveQualifiedName(); } } diff --git a/plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java b/plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java index 2c1aec6f72c7..eb5cb74c401c 100644 --- a/plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java +++ b/plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,13 +25,14 @@ import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; @@ -54,9 +55,8 @@ import java.util.Collections; import java.util.List; /** -* @author Dmitry Avdeev -* Date: 1/20/12 -*/ + * @author Dmitry Avdeev + */ class RegisterInspectionFix implements IntentionAction { private final PsiClass myPsiClass; @@ -96,7 +96,7 @@ class RegisterInspectionFix implements IntentionAction { public static void choosePluginDescriptor(final Project project, Editor editor, final PsiFile file, final Consumer> consumer) { - Module module = ModuleUtil.findModuleForPsiElement(file); + Module module = ModuleUtilCore.findModuleForPsiElement(file); assert module != null; List> elements = DomService.getInstance().getFileElements(IdeaPlugin.class, project, module.getModuleContentWithDependenciesScope()); @@ -163,8 +163,9 @@ class RegisterInspectionFix implements IntentionAction { .put("java-impl", "IdeaPlugin.xml") .build(); - private static List> findAppropriateIntelliJModule(String name, List> elements) { - String extensionsFile = INTELLIJ_MODULES.get(name); + private static List> findAppropriateIntelliJModule(String moduleName, + List> elements) { + String extensionsFile = INTELLIJ_MODULES.get(moduleName); if (extensionsFile != null) { for (DomFileElement element : elements) { if (element.getFile().getName().equals(extensionsFile)) { @@ -180,7 +181,7 @@ class RegisterInspectionFix implements IntentionAction { Extension extension = new WriteCommandAction(project, file) { @Override - protected void run(Result result) throws Throwable { + protected void run(@NotNull Result result) throws Throwable { final Extensions extensions = getExtension(plugin, myEp.getName()); Extension extension = extensions.addExtension(myEp.getName()); XmlTag tag = extension.getXmlTag(); @@ -193,21 +194,19 @@ class RegisterInspectionFix implements IntentionAction { public static Extensions getExtension(IdeaPlugin plugin, String epName) { final List extensionsList = plugin.getExtensions(); - Extensions extensions = null; - for (Extensions e : extensionsList) { - if (e.getXmlTag() instanceof IncludedXmlTag) { + for (Extensions extensions : extensionsList) { + if (extensions.getXmlTag() instanceof IncludedXmlTag) { continue; } - String s = e.getDefaultExtensionNs().getStringValue(); + String s = extensions.getDefaultExtensionNs().getStringValue(); if (s != null && epName.startsWith(s)) { - extensions = e; - break; + return extensions; } } - if (extensions == null) { - extensions = plugin.addExtensions(); - extensions.getDefaultExtensionNs().setStringValue("com.intellij"); - } + + Extensions extensions = plugin.addExtensions(); + final String epPrefix = StringUtil.getPackageName(epName); + extensions.getDefaultExtensionNs().setStringValue(epPrefix); return extensions; } diff --git a/plugins/devkit/src/util/DescriptorUtil.java b/plugins/devkit/src/util/DescriptorUtil.java index 3a773e9e5fa9..3cf574f9ca48 100644 --- a/plugins/devkit/src/util/DescriptorUtil.java +++ b/plugins/devkit/src/util/DescriptorUtil.java @@ -87,7 +87,7 @@ public class DescriptorUtil { return getIdeaPlugin((XmlFile)file) != null; } - private static DomFileElement getIdeaPlugin(XmlFile file) { + public static DomFileElement getIdeaPlugin(XmlFile file) { return DomManager.getDomManager(file.getProject()).getFileElement(file, IdeaPlugin.class); } } diff --git a/plugins/devkit/testData/codeInsight/deprecatedAttributes.xml b/plugins/devkit/testData/codeInsight/deprecatedAttributes.xml index 9b14b401cc68..d77d1c0732df 100644 --- a/plugins/devkit/testData/codeInsight/deprecatedAttributes.xml +++ b/plugins/devkit/testData/codeInsight/deprecatedAttributes.xml @@ -8,4 +8,6 @@ max="deprecated" /> + xmlns="com.intellij"/> + \ No newline at end of file diff --git a/plugins/devkit/testData/codeInsight/extensionPoints.xml b/plugins/devkit/testData/codeInsight/pluginWithXInclude-extensionPoints.xml similarity index 100% rename from plugins/devkit/testData/codeInsight/extensionPoints.xml rename to plugins/devkit/testData/codeInsight/pluginWithXInclude-extensionPoints.xml diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/RegisteredAction.java b/plugins/devkit/testData/inspections/componentNotRegistered/RegisteredAction.java new file mode 100644 index 000000000000..92231a2c0fe0 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/RegisteredAction.java @@ -0,0 +1,7 @@ +import com.intellij.openapi.actionSystem.AnAction; + +public class RegisteredAction extends AnAction { + + public static class InnerAction extends AnAction {} + +} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/RegisteredApplicationComponent.java b/plugins/devkit/testData/inspections/componentNotRegistered/RegisteredApplicationComponent.java new file mode 100644 index 000000000000..0d3a597bbd3c --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/RegisteredApplicationComponent.java @@ -0,0 +1,9 @@ +import com.intellij.openapi.components.ApplicationComponent; + +public class RegisteredApplicationComponent + implements ApplicationComponent { + + public static class InnerStaticClassApplicationContext + implements ApplicationComponent { + } +} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredAbstractApplicationComponent.java b/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredAbstractApplicationComponent.java new file mode 100644 index 000000000000..d4d9cf5c18e8 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredAbstractApplicationComponent.java @@ -0,0 +1,3 @@ +import com.intellij.openapi.components.ApplicationComponent; + +public abstract class UnregisteredAbstractApplicationComponent implements ApplicationComponent {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredAction.java b/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredAction.java new file mode 100644 index 000000000000..e19a0633cce9 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredAction.java @@ -0,0 +1,12 @@ +import com.intellij.openapi.actionSystem.AnAction; + +public class UnregisteredAction + extends AnAction { + + public static class InnerAction + extends AnAction {} + + + protected static class NonPublicIsIgnored extends AnAction {} + +} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredApplicationComponent.java b/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredApplicationComponent.java new file mode 100644 index 000000000000..ebc72cab3f7c --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredApplicationComponent.java @@ -0,0 +1,15 @@ +import com.intellij.openapi.components.ApplicationComponent; + +public class UnregisteredApplicationComponent + implements ApplicationComponent, UnregisteredApplicationComponentInterface { + + public static UnregisteredApplicationComponentInterface getInstance() { + return null; + } + + public static class InnerStaticClassApplicationContext + implements ApplicationComponent {} + + public class InnerClassApplicationContextIsNotChecked implements ApplicationComponent {} + +} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredApplicationComponentInterface.java b/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredApplicationComponentInterface.java new file mode 100644 index 000000000000..6f7c10402295 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/UnregisteredApplicationComponentInterface.java @@ -0,0 +1 @@ +public interface UnregisteredApplicationComponentInterface {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/registeredAction-plugin.xml b/plugins/devkit/testData/inspections/componentNotRegistered/registeredAction-plugin.xml new file mode 100644 index 000000000000..e2216421f271 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/registeredAction-plugin.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/registeredActionInOptionalPluginDescriptor-optional-plugin.xml b/plugins/devkit/testData/inspections/componentNotRegistered/registeredActionInOptionalPluginDescriptor-optional-plugin.xml new file mode 100644 index 000000000000..e2216421f271 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/registeredActionInOptionalPluginDescriptor-optional-plugin.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/registeredActionInOptionalPluginDescriptor-plugin.xml b/plugins/devkit/testData/inspections/componentNotRegistered/registeredActionInOptionalPluginDescriptor-plugin.xml new file mode 100644 index 000000000000..0ace22f7d835 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/registeredActionInOptionalPluginDescriptor-plugin.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/registeredApplicationComponent-plugin.xml b/plugins/devkit/testData/inspections/componentNotRegistered/registeredApplicationComponent-plugin.xml new file mode 100644 index 000000000000..04ecd12b1d64 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/registeredApplicationComponent-plugin.xml @@ -0,0 +1,11 @@ + + + + RegisteredApplicationComponent + + + RegisteredApplicationComponent.InnerStaticClassApplicationContext + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/extensions/plugin.xml b/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredAction-plugin.xml similarity index 100% rename from plugins/devkit/testData/extensions/plugin.xml rename to plugins/devkit/testData/inspections/componentNotRegistered/unregisteredAction-plugin.xml diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredAction-plugin_after.xml b/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredAction-plugin_after.xml new file mode 100644 index 000000000000..89977dbe52d4 --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredAction-plugin_after.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredApplicationComponent-plugin.xml b/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredApplicationComponent-plugin.xml new file mode 100644 index 000000000000..9d47e45ee4de --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredApplicationComponent-plugin.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredApplicationComponent-plugin_after.xml b/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredApplicationComponent-plugin_after.xml new file mode 100644 index 000000000000..abc6a373be6d --- /dev/null +++ b/plugins/devkit/testData/inspections/componentNotRegistered/unregisteredApplicationComponent-plugin_after.xml @@ -0,0 +1,9 @@ + + + + + UnregisteredApplicationComponent + UnregisteredApplicationComponentInterface + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/ExtensionPoint.java b/plugins/devkit/testData/inspections/registerExtensionFix/ExtensionPoint.java new file mode 100644 index 000000000000..482b20ae9896 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/ExtensionPoint.java @@ -0,0 +1 @@ +public interface ExtensionPoint {} \ No newline at end of file diff --git a/plugins/devkit/testData/extensions/GlobalInspection.java b/plugins/devkit/testData/inspections/registerExtensionFix/GlobalInspection.java similarity index 100% rename from plugins/devkit/testData/extensions/GlobalInspection.java rename to plugins/devkit/testData/inspections/registerExtensionFix/GlobalInspection.java diff --git a/plugins/devkit/testData/extensions/LocalInspection.java b/plugins/devkit/testData/inspections/registerExtensionFix/LocalInspection.java similarity index 100% rename from plugins/devkit/testData/extensions/LocalInspection.java rename to plugins/devkit/testData/inspections/registerExtensionFix/LocalInspection.java diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/MyExtensionPoint.java b/plugins/devkit/testData/inspections/registerExtensionFix/MyExtensionPoint.java new file mode 100644 index 000000000000..5e18b48af922 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/MyExtensionPoint.java @@ -0,0 +1 @@ +public class MyExtensionPoint implements ExtensionPoint {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/MyLanguageExtensionPoint.java b/plugins/devkit/testData/inspections/registerExtensionFix/MyLanguageExtensionPoint.java new file mode 100644 index 000000000000..e3341b9e8f90 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/MyLanguageExtensionPoint.java @@ -0,0 +1,2 @@ +public class MyLanguageExtensionPoint + implements MyLanguageExtensionPointInterface {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/MyLanguageExtensionPointInterface.java b/plugins/devkit/testData/inspections/registerExtensionFix/MyLanguageExtensionPointInterface.java new file mode 100644 index 000000000000..df681d3377f2 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/MyLanguageExtensionPointInterface.java @@ -0,0 +1 @@ +public interface MyLanguageExtensionPointInterface {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPoint.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPoint.xml new file mode 100644 index 000000000000..6515ebf709d9 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPoint.xml @@ -0,0 +1,9 @@ + + com.my.plugin + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoExtensionsTag.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoExtensionsTag.xml new file mode 100644 index 000000000000..7c36bd5f69f0 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoExtensionsTag.xml @@ -0,0 +1,6 @@ + + com.my.plugin + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoExtensionsTag_after.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoExtensionsTag_after.xml new file mode 100644 index 000000000000..95200ef62daa --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoExtensionsTag_after.xml @@ -0,0 +1,9 @@ + + com.my.plugin + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoPluginId.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoPluginId.xml new file mode 100644 index 000000000000..3d1b666277b4 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoPluginId.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoPluginId_after.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoPluginId_after.xml new file mode 100644 index 000000000000..64116e75289f --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointNoPluginId_after.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointQualifiedName.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointQualifiedName.xml new file mode 100644 index 000000000000..ffb0e4065baf --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointQualifiedName.xml @@ -0,0 +1,6 @@ + + com.my.plugin + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointQualifiedName_after.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointQualifiedName_after.xml new file mode 100644 index 000000000000..9fabec2e19df --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointQualifiedName_after.xml @@ -0,0 +1,9 @@ + + com.my.plugin + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttribute.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttribute.xml new file mode 100644 index 000000000000..cc95dc410e5f --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttribute.xml @@ -0,0 +1,11 @@ + + com.my.plugin + + + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttributeAndTag.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttributeAndTag.xml new file mode 100644 index 000000000000..d0c44f47bdb1 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttributeAndTag.xml @@ -0,0 +1,12 @@ + + com.my.plugin + + + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttributeAndTag_after.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttributeAndTag_after.xml new file mode 100644 index 000000000000..5c73c02a0ad1 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttributeAndTag_after.xml @@ -0,0 +1,15 @@ + + com.my.plugin + + + + + + + + + MyLanguageExtensionPoint + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttribute_after.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttribute_after.xml new file mode 100644 index 000000000000..9b4f4738b3f1 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPointWithKnownRequiredAttribute_after.xml @@ -0,0 +1,12 @@ + + com.my.plugin + + + + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/extensionPoint_after.xml b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPoint_after.xml new file mode 100644 index 000000000000..c32c9d5e6107 --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/extensionPoint_after.xml @@ -0,0 +1,10 @@ + + com.my.plugin + + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/extensions/globalInspection.xml b/plugins/devkit/testData/inspections/registerExtensionFix/globalInspection.xml similarity index 71% rename from plugins/devkit/testData/extensions/globalInspection.xml rename to plugins/devkit/testData/inspections/registerExtensionFix/globalInspection.xml index 9f649860b310..e050eda45f36 100644 --- a/plugins/devkit/testData/extensions/globalInspection.xml +++ b/plugins/devkit/testData/inspections/registerExtensionFix/globalInspection.xml @@ -1,6 +1,5 @@ - \ No newline at end of file diff --git a/plugins/devkit/testData/extensions/localInspection.xml b/plugins/devkit/testData/inspections/registerExtensionFix/localInspection.xml similarity index 100% rename from plugins/devkit/testData/extensions/localInspection.xml rename to plugins/devkit/testData/inspections/registerExtensionFix/localInspection.xml diff --git a/plugins/devkit/testData/inspections/registerExtensionFix/plugin.xml b/plugins/devkit/testData/inspections/registerExtensionFix/plugin.xml new file mode 100644 index 000000000000..6fb76a66265d --- /dev/null +++ b/plugins/devkit/testData/inspections/registerExtensionFix/plugin.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/AbstractApplicationComponent.java b/plugins/devkit/testData/inspections/registrationProblems/code/AbstractApplicationComponent.java new file mode 100644 index 000000000000..516b6825104d --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/AbstractApplicationComponent.java @@ -0,0 +1 @@ +public abstract class AbstractApplicationComponent implements com.intellij.openapi.components.ApplicationComponent {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/ActionAbstractClass.xml b/plugins/devkit/testData/inspections/registrationProblems/code/ActionAbstractClass.xml new file mode 100644 index 000000000000..855ef7053488 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/ActionAbstractClass.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/ActionWithoutDefaultCtor.xml b/plugins/devkit/testData/inspections/registrationProblems/code/ActionWithoutDefaultCtor.xml new file mode 100644 index 000000000000..1b69b08c3e48 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/ActionWithoutDefaultCtor.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/ActionWrongClass.xml b/plugins/devkit/testData/inspections/registrationProblems/code/ActionWrongClass.xml new file mode 100644 index 000000000000..7c0a4cd7dd75 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/ActionWrongClass.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/ApplicationComponentInterface.java b/plugins/devkit/testData/inspections/registrationProblems/code/ApplicationComponentInterface.java new file mode 100644 index 000000000000..57db893522d6 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/ApplicationComponentInterface.java @@ -0,0 +1 @@ +public interface ApplicationComponentInterface {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/ApplicationComponentWrongClass.xml b/plugins/devkit/testData/inspections/registrationProblems/code/ApplicationComponentWrongClass.xml new file mode 100644 index 000000000000..51eb3e148f58 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/ApplicationComponentWrongClass.xml @@ -0,0 +1,7 @@ + + + + MyApplicationComponentWrongClass + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/ComponentAbstractImplementation.xml b/plugins/devkit/testData/inspections/registrationProblems/code/ComponentAbstractImplementation.xml new file mode 100644 index 000000000000..afe6aef8ae90 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/ComponentAbstractImplementation.xml @@ -0,0 +1,7 @@ + + + + AbstractApplicationComponent + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/MyAbstractAction.java b/plugins/devkit/testData/inspections/registrationProblems/code/MyAbstractAction.java new file mode 100644 index 000000000000..70e8865acf9d --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/MyAbstractAction.java @@ -0,0 +1 @@ +public abstract class MyAbstractAction extends com.intellij.openapi.actionSystem.AnAction {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/MyActionWithoutDefaultCtor.java b/plugins/devkit/testData/inspections/registrationProblems/code/MyActionWithoutDefaultCtor.java new file mode 100644 index 000000000000..e16d7814372e --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/MyActionWithoutDefaultCtor.java @@ -0,0 +1,5 @@ +public class MyActionWithoutDefaultCtor extends com.intellij.openapi.actionSystem.AnAction { + + public MyActionWithoutDefaultCtor(String something) {} + +} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/MyActionWrongClass.java b/plugins/devkit/testData/inspections/registrationProblems/code/MyActionWrongClass.java new file mode 100644 index 000000000000..18c87be1aeaa --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/MyActionWrongClass.java @@ -0,0 +1 @@ +public class MyActionWrongClass extends java.lang.String {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/code/MyApplicationComponentWrongClass.java b/plugins/devkit/testData/inspections/registrationProblems/code/MyApplicationComponentWrongClass.java new file mode 100644 index 000000000000..21f7577a2c98 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/code/MyApplicationComponentWrongClass.java @@ -0,0 +1 @@ +public class MyApplicationComponentWrongClass {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/AbstractApplicationComponent.java b/plugins/devkit/testData/inspections/registrationProblems/xml/AbstractApplicationComponent.java new file mode 100644 index 000000000000..22ef502463e5 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/AbstractApplicationComponent.java @@ -0,0 +1 @@ +public abstract class AbstractApplicationComponent implements com.intellij.openapi.components.ApplicationComponent {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ActionAbstractClass.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ActionAbstractClass.xml new file mode 100644 index 000000000000..8c1c7646fbe4 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ActionAbstractClass.xml @@ -0,0 +1,6 @@ + + + MyAbstractAction"/> + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ActionUnresolvedClass.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ActionUnresolvedClass.xml new file mode 100644 index 000000000000..9eabf1d79bc7 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ActionUnresolvedClass.xml @@ -0,0 +1,6 @@ + + + INVALID_VALUE"/> + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ActionWithoutDefaultCtor.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ActionWithoutDefaultCtor.xml new file mode 100644 index 000000000000..aa0fca023817 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ActionWithoutDefaultCtor.xml @@ -0,0 +1,6 @@ + + + MyActionWithoutDefaultCtor"/> + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ActionWrongClass.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ActionWrongClass.xml new file mode 100644 index 000000000000..0ba10a7e7435 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ActionWrongClass.xml @@ -0,0 +1,6 @@ + + + java.lang.String"/> + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ApplicationComponent.java b/plugins/devkit/testData/inspections/registrationProblems/xml/ApplicationComponent.java new file mode 100644 index 000000000000..2aaeb3d23609 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ApplicationComponent.java @@ -0,0 +1,4 @@ +public class ApplicationComponent + implements com.intellij.openapi.components.ApplicationComponent, + ApplicationComponentInterface { +} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ApplicationComponentInterface.java b/plugins/devkit/testData/inspections/registrationProblems/xml/ApplicationComponentInterface.java new file mode 100644 index 000000000000..57db893522d6 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ApplicationComponentInterface.java @@ -0,0 +1 @@ +public interface ApplicationComponentInterface {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentAbstractImplementation.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentAbstractImplementation.xml new file mode 100644 index 000000000000..77fc2972341b --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentAbstractImplementation.xml @@ -0,0 +1,7 @@ + + + + AbstractApplicationComponent + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentClassNotAssignableToInterface.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentClassNotAssignableToInterface.xml new file mode 100644 index 000000000000..b1eef9f328e9 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentClassNotAssignableToInterface.xml @@ -0,0 +1,8 @@ + + + + java.lang.Runnable + ApplicationComponent + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentMissingImplementation.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentMissingImplementation.xml new file mode 100644 index 000000000000..194bca7f080e --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentMissingImplementation.xml @@ -0,0 +1,7 @@ + + + + java.lang.Runnable + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentMultipleWithSameInterface.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentMultipleWithSameInterface.xml new file mode 100644 index 000000000000..5b3c328cb58d --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentMultipleWithSameInterface.xml @@ -0,0 +1,33 @@ + + + + ApplicationComponentInterface + ApplicationComponent + + + ApplicationComponentInterface + ApplicationComponent + + + + + + + MyModuleComponentInterface + MyModuleComponent + + + MyModuleComponentInterface + MyModuleComponent + + + + + MyModuleComponentInterface + MyModuleComponent + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentUnresolvedClass.xml b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentUnresolvedClass.xml new file mode 100644 index 000000000000..9915e5521a40 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/ComponentUnresolvedClass.xml @@ -0,0 +1,9 @@ + + + + INVALID_VALUE + INVALID_VALUE + INVALID_VALUE + + + \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/MyAbstractAction.java b/plugins/devkit/testData/inspections/registrationProblems/xml/MyAbstractAction.java new file mode 100644 index 000000000000..095dedc8f122 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/MyAbstractAction.java @@ -0,0 +1 @@ +public abstract class MyAbstractAction extends com.intellij.openapi.actionSystem.AnAction {} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/MyActionWithoutDefaultCtor.java b/plugins/devkit/testData/inspections/registrationProblems/xml/MyActionWithoutDefaultCtor.java new file mode 100644 index 000000000000..50ea42d34031 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/MyActionWithoutDefaultCtor.java @@ -0,0 +1,5 @@ +public class MyActionWithoutDefaultCtor extends com.intellij.openapi.actionSystem.AnAction { + + public MyActionWithoutDefaultCtor(String something) {} + +} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/MyModuleComponent.java b/plugins/devkit/testData/inspections/registrationProblems/xml/MyModuleComponent.java new file mode 100644 index 000000000000..ba1dd41eddc7 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/MyModuleComponent.java @@ -0,0 +1,4 @@ +public class MyModuleComponent + implements com.intellij.openapi.module.ModuleComponent, + MyModuleComponentInterface { +} \ No newline at end of file diff --git a/plugins/devkit/testData/inspections/registrationProblems/xml/MyModuleComponentInterface.java b/plugins/devkit/testData/inspections/registrationProblems/xml/MyModuleComponentInterface.java new file mode 100644 index 000000000000..297d0c1f6582 --- /dev/null +++ b/plugins/devkit/testData/inspections/registrationProblems/xml/MyModuleComponentInterface.java @@ -0,0 +1 @@ +public interface MyModuleComponentInterface {} \ No newline at end of file diff --git a/plugins/devkit/testData/pluginXmlDomStubs/pluginXmlStubs.xml b/plugins/devkit/testData/pluginXmlDomStubs/pluginXmlStubs.xml index 300033972a3a..30e95aa28cd1 100644 --- a/plugins/devkit/testData/pluginXmlDomStubs/pluginXmlStubs.xml +++ b/plugins/devkit/testData/pluginXmlDomStubs/pluginXmlStubs.xml @@ -5,10 +5,6 @@ anotherPlugin - - - - diff --git a/plugins/devkit/testSources/codeInsight/CreateClassFixTest.java b/plugins/devkit/testSources/codeInsight/CreateClassFixTest.java index 573d52eac5b7..46b84e1e5112 100644 --- a/plugins/devkit/testSources/codeInsight/CreateClassFixTest.java +++ b/plugins/devkit/testSources/codeInsight/CreateClassFixTest.java @@ -25,59 +25,104 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.application.PluginPathManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Ref; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; -import com.intellij.testFramework.fixtures.*; -import com.intellij.util.ui.UIUtil; +import com.intellij.testFramework.fixtures.CodeInsightTestFixture; +import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; +import com.intellij.testFramework.fixtures.JavaTestFixtureFactory; +import com.intellij.testFramework.fixtures.TestFixtureBuilder; import org.jetbrains.idea.devkit.inspections.RegistrationProblemsInspection; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import org.testng.Assert; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import java.util.Arrays; import java.util.List; -public class CreateClassFixTest { +@RunWith(Parameterized.class) +public class CreateClassFixTest extends UsefulTestCase{ protected CodeInsightTestFixture myFixture; - @BeforeMethod - public void setUp() throws Exception { - final JavaTestFixtureFactory fixtureFactory = JavaTestFixtureFactory.getFixtureFactory(); - final TestFixtureBuilder testFixtureBuilder = fixtureFactory.createFixtureBuilder(); - myFixture = fixtureFactory.createCodeInsightFixture(testFixtureBuilder.getFixture()); - myFixture.setTestDataPath(PluginPathManager.getPluginHomePath("DevKit") + "/testData"); + @org.junit.runners.Parameterized.Parameter(0) public String myTestName; + @org.junit.runners.Parameterized.Parameter(1) public boolean myCreateClass; - testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class) - .addContentRoot(myFixture.getTempDirPath()).addSourceRoot(getSourceRoot()); - myFixture.enableInspections(new RegistrationProblemsInspection()); - myFixture.setUp(); + @Before + public void setUp() throws Exception { + final Ref ex = new Ref(); + Runnable runnable = new Runnable() { + public void run() { + try { + CreateClassFixTest.super.setUp(); + final JavaTestFixtureFactory fixtureFactory = JavaTestFixtureFactory.getFixtureFactory(); + final TestFixtureBuilder testFixtureBuilder = fixtureFactory.createFixtureBuilder(); + myFixture = fixtureFactory.createCodeInsightFixture(testFixtureBuilder.getFixture()); + myFixture.setTestDataPath(PluginPathManager.getPluginHomePath("devkit") + "/testData"); + + testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class) + .addContentRoot(myFixture.getTempDirPath()).addSourceRoot(getSourceRoot()); + myFixture.enableInspections(new RegistrationProblemsInspection()); + myFixture.setUp(); + } + catch (Exception e) { + ex.set(e); + } + } + }; + invokeTestRunnable(runnable); + final Exception exception = ex.get(); + if (exception != null) { + throw exception; + } } - @AfterMethod + @After public void tearDown() throws Exception { - myFixture.tearDown(); - myFixture = null; + final Ref ex = new Ref(); + Runnable runnable = new Runnable() { + public void run() { + try { + myFixture.tearDown(); + myFixture = null; + CreateClassFixTest.super.tearDown(); + } + catch (Exception e) { + ex.set(e); + } + } + }; + invokeTestRunnable(runnable); + final Exception exception = ex.get(); + if (exception != null) { + throw exception; + } } private static String getSourceRoot() { return "codeInsight"; } - @DataProvider - public Object[][] data() { - return new Object[][]{{"Action", true}, {"Impl", true}, {"Intf", true}, {"Intf", false}}; + @Parameterized.Parameters(name = "{0} : {1}") + public static List data() { + return Arrays.asList(new Object[]{"Action", true}, + new Object[]{"Impl", true}, + new Object[]{"Intf", true}, + new Object[]{"Intf", false}); } - @Test(dataProvider = "data", enabled = true) - public void test(final String testName, final boolean createClass) throws Throwable { + @Test + public void runSingle() throws Throwable { Runnable runnable = new Runnable() { public void run() { IntentionAction resultAction = null; - final String createAction = QuickFixBundle.message(createClass ? "create.class.text" : "create.interface.text", testName); - final List actions = myFixture.getAvailableIntentions(getSourceRoot() + "/plugin" + testName + ".xml"); + final String createAction = QuickFixBundle.message(myCreateClass ? "create.class.text" : "create.interface.text", myTestName); + final List actions = myFixture.getAvailableIntentions(getSourceRoot() + "/plugin" + myTestName + ".xml"); for (IntentionAction action : actions) { if (Comparing.strEqual(action.getText(), createAction)) { resultAction = action; @@ -87,9 +132,9 @@ public class CreateClassFixTest { Assert.assertNotNull(resultAction); myFixture.launchAction(resultAction); final Project project = myFixture.getProject(); - Assert.assertNotNull(JavaPsiFacade.getInstance(project).findClass(testName, GlobalSearchScope.allScope(project))); + Assert.assertNotNull(JavaPsiFacade.getInstance(project).findClass(myTestName, GlobalSearchScope.allScope(project))); } }; - UIUtil.invokeAndWaitIfNeeded(runnable); + invokeTestRunnable(runnable); } } diff --git a/plugins/devkit/testSources/codeInsight/CreateExtensionTest.java b/plugins/devkit/testSources/codeInsight/CreateExtensionTest.java deleted file mode 100644 index a11ea559ce68..000000000000 --- a/plugins/devkit/testSources/codeInsight/CreateExtensionTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.idea.devkit.codeInsight; - -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; -import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; -import com.intellij.openapi.application.PluginPathManager; -import com.intellij.testFramework.TestDataPath; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; - -/** - * @author Dmitry Avdeev - * Date: 1/20/12 - */ -@TestDataPath("$CONTENT_ROOT/testData/extensions") -public class CreateExtensionTest extends LightCodeInsightFixtureTestCase { - - @Override - public void setUp() throws Exception { - super.setUp(); - myFixture.addClass("package com.intellij.codeInspection; public class LocalInspectionTool {} "); - myFixture.addClass("package com.intellij.codeInspection; public class GlobalInspectionTool {} "); - myFixture.enableInspections(new UnusedDeclarationInspection(), new UnusedSymbolLocalInspection()); - } - - public void testCreateLocalInspectionMapping() throws Exception { - myFixture.testHighlighting("LocalInspection.java", "plugin.xml"); - IntentionAction intention = myFixture.findSingleIntention("Register inspection"); - myFixture.launchAction(intention); - myFixture.checkResultByFile("plugin.xml", "localInspection.xml", true); - } - - public void testCreateGlobalInspectionMapping() throws Exception { - myFixture.testHighlighting("GlobalInspection.java", "localInspection.xml"); - IntentionAction intention = myFixture.findSingleIntention("Register inspection"); - myFixture.launchAction(intention); - myFixture.checkResultByFile("localInspection.xml", "globalInspection.xml", true); - } - - @Override - protected String getBasePath() { - return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/extensions"; - } - -} diff --git a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy index 32952830d17e..3e61a93bd4db 100644 --- a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy +++ b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy @@ -224,7 +224,7 @@ public class PluginXmlFunctionalTest extends JavaCodeInsightFixtureTestCase { } public void testPluginWithXInclude() throws Throwable { - myFixture.testHighlighting("pluginWithXInclude.xml", "extensionPoints.xml"); + myFixture.testHighlighting("pluginWithXInclude.xml", "pluginWithXInclude-extensionPoints.xml"); } public void testExtensionPointPresentation() { diff --git a/plugins/devkit/testSources/inspections/ComponentNotRegisteredInspectionTest.java b/plugins/devkit/testSources/inspections/ComponentNotRegisteredInspectionTest.java new file mode 100644 index 000000000000..a939738cfdf5 --- /dev/null +++ b/plugins/devkit/testSources/inspections/ComponentNotRegisteredInspectionTest.java @@ -0,0 +1,149 @@ +/* + * Copyright 2000-2014 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.idea.devkit.inspections; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.devkit.dom.Anchor; +import org.jetbrains.idea.devkit.inspections.quickfix.RegisterActionFix; +import org.jetbrains.idea.devkit.util.ActionData; + +@TestDataPath("$CONTENT_ROOT/testData/inspections/componentNotRegistered") +public class ComponentNotRegisteredInspectionTest extends PluginModuleTestCase { + + @Override + protected String getBasePath() { + return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/inspections/componentNotRegistered"; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + myFixture.addClass("package com.intellij.openapi.actionSystem; public class AnAction {}"); + myFixture.addClass("package com.intellij.openapi.components; public interface ApplicationComponent {}"); + + myFixture.enableInspections(new ComponentNotRegisteredInspection()); + } + + public void testRegisteredAction() { + setPluginXml("registeredAction-plugin.xml"); + myFixture.testHighlighting("RegisteredAction.java"); + } + + public void testRegisteredActionInOptionalPluginDescriptor() { + setPluginXml("registeredActionInOptionalPluginDescriptor-plugin.xml"); + myFixture.copyFileToProject("registeredActionInOptionalPluginDescriptor-optional-plugin.xml", + "META-INF/optional-plugin.xml"); + + myFixture.testHighlighting("RegisteredAction.java"); + } + + public void testUnregisteredAction() { + setPluginXml("unregisteredAction-plugin.xml"); + myFixture.testHighlighting("UnregisteredAction.java"); + + RegisterActionFix.ourTestActionData = new MyActionData("UnregisteredAction"); + final IntentionAction registerAction = myFixture.findSingleIntention("Register Action"); + myFixture.launchAction(registerAction); + + myFixture.checkResultByFile("META-INF/plugin.xml", "unregisteredAction-plugin_after.xml", true); + } + + public void testRegisteredApplicationComponent() { + setPluginXml("registeredApplicationComponent-plugin.xml"); + myFixture.testHighlighting("RegisteredApplicationComponent.java"); + } + + public void testUnregisteredAbstractApplicationComponent() { + myFixture.testHighlighting("UnregisteredAbstractApplicationComponent.java"); + } + + public void testUnregisteredApplicationComponentWithoutPluginXml() { + myFixture.testHighlighting("UnregisteredApplicationComponent.java", + "UnregisteredApplicationComponentInterface.java"); + } + + public void testUnregisteredApplicationComponentWithRegisterFix() { + setPluginXml("unregisteredApplicationComponent-plugin.xml"); + + myFixture.testHighlighting("UnregisteredApplicationComponent.java", + "UnregisteredApplicationComponentInterface.java"); + final IntentionAction registerAction = myFixture.findSingleIntention("Register Application Component"); + myFixture.launchAction(registerAction); + + myFixture.checkResultByFile("META-INF/plugin.xml", "unregisteredApplicationComponent-plugin_after.xml", true); + } + + + private static class MyActionData implements ActionData { + private final String myActionClassFqn; + + public MyActionData(String actionClassFqn) { + myActionClassFqn = actionClassFqn; + } + + @NotNull + @Override + public String getActionId() { + return StringUtil.getShortName(myActionClassFqn); + } + + @NotNull + @Override + public String getActionText() { + return "Action Text " + myActionClassFqn; + } + + @Override + public String getActionDescription() { + return "Description " + myActionClassFqn; + } + + @Nullable + @Override + public String getSelectedGroupId() { + return getActionId() + "Group"; + } + + @Nullable + @Override + public String getSelectedActionId() { + return getActionId() + "SelectedAction"; + } + + @Override + public String getSelectedAnchor() { + return Anchor.before.name(); + } + + @Nullable + @Override + public String getFirstKeyStroke() { + return "1st Key " + getActionId(); + } + + @Nullable + @Override + public String getSecondKeyStroke() { + return "2nd Key " + getActionId(); + } + } +} diff --git a/plugins/devkit/testSources/inspections/PluginModuleTestCase.java b/plugins/devkit/testSources/inspections/PluginModuleTestCase.java new file mode 100644 index 000000000000..c8dd51c356e6 --- /dev/null +++ b/plugins/devkit/testSources/inspections/PluginModuleTestCase.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2014 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.idea.devkit.inspections; + +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.TestDataFile; +import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.devkit.build.PluginBuildConfiguration; +import org.jetbrains.idea.devkit.module.PluginModuleType; + +public abstract class PluginModuleTestCase extends LightCodeInsightFixtureTestCase { + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return new DefaultLightProjectDescriptor() { + @Override + public ModuleType getModuleType() { + return PluginModuleType.getInstance(); + } + }; + } + + protected void setPluginXml(@TestDataFile String pluginXml) { + final VirtualFile file = myFixture.copyFileToProject(pluginXml, "META-INF/plugin.xml"); + final PluginBuildConfiguration pluginBuildConfiguration = PluginBuildConfiguration.getInstance(myModule); + assertNotNull(pluginBuildConfiguration); + pluginBuildConfiguration.setPluginXmlFromVirtualFile(file); + } +} diff --git a/plugins/devkit/testSources/inspections/RegistrationProblemsInspectionCodeTest.java b/plugins/devkit/testSources/inspections/RegistrationProblemsInspectionCodeTest.java new file mode 100644 index 000000000000..7e08e6fbf04e --- /dev/null +++ b/plugins/devkit/testSources/inspections/RegistrationProblemsInspectionCodeTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2014 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.idea.devkit.inspections; + +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.TestDataPath; + +@TestDataPath("$CONTENT_ROOT/testData/inspections/registrationProblems/code") +public class RegistrationProblemsInspectionCodeTest extends PluginModuleTestCase { + + @Override + protected String getBasePath() { + return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/inspections/registrationProblems/code"; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + myFixture.addClass("package com.intellij.openapi.actionSystem; public class AnAction {}"); + + myFixture.addClass("package com.intellij.openapi.components; public interface ApplicationComponent {}"); + myFixture.addClass("package com.intellij.openapi.module; public interface ModuleComponent {}"); + + myFixture.enableInspections(new RegistrationProblemsInspection()); + } + + public void testComponentAbstractImplementation() { + setPluginXml("ComponentAbstractImplementation.xml"); + myFixture.testHighlighting("AbstractApplicationComponent.java"); + } + + public void testComponentWrongClass() { + setPluginXml("ApplicationComponentWrongClass.xml"); + myFixture.testHighlighting("MyApplicationComponentWrongClass.java"); + } + + public void testActionAbstractClass() { + setPluginXml("ActionAbstractClass.xml"); + myFixture.testHighlighting("MyAbstractAction.java"); + } + + public void testActionWithoutDefaultCtor() { + setPluginXml("ActionWithoutDefaultCtor.xml"); + myFixture.testHighlighting("MyActionWithoutDefaultCtor.java"); + } + + public void testActionWrongClass() { + setPluginXml("ActionWrongClass.xml"); + myFixture.testHighlighting("MyActionWrongClass.java"); + } +} diff --git a/plugins/devkit/testSources/inspections/RegistrationProblemsInspectionXmlTest.java b/plugins/devkit/testSources/inspections/RegistrationProblemsInspectionXmlTest.java new file mode 100644 index 000000000000..5bee865dbf59 --- /dev/null +++ b/plugins/devkit/testSources/inspections/RegistrationProblemsInspectionXmlTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2014 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.idea.devkit.inspections; + +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.TestDataPath; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; + +@TestDataPath("$CONTENT_ROOT/testData/inspections/registrationProblems/xml") +public class RegistrationProblemsInspectionXmlTest extends LightCodeInsightFixtureTestCase { + + @Override + protected String getBasePath() { + return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/inspections/registrationProblems/xml"; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + myFixture.addClass("package com.intellij.openapi.actionSystem; public class AnAction {}"); + + myFixture.addClass("package com.intellij.openapi.components; public interface ApplicationComponent {}"); + myFixture.addClass("package com.intellij.openapi.module; public interface ModuleComponent {}"); + + myFixture.enableInspections(new RegistrationProblemsInspection()); + } + + public void testComponentAbstractImplementation() { + myFixture.testHighlighting("ComponentAbstractImplementation.xml", + "AbstractApplicationComponent.java"); + } + + public void testComponentClassNotAssignableToInterface() { + myFixture.testHighlighting("ComponentClassNotAssignableToInterface.xml", + "ApplicationComponent.java"); + } + + public void testComponentMissingImplementation() { + myFixture.testHighlighting("ComponentMissingImplementation.xml"); + } + + public void testComponentMultipleWithSameInterface() { + myFixture.testHighlighting("ComponentMultipleWithSameInterface.xml", + "ApplicationComponent.java", "ApplicationComponentInterface.java", + "MyModuleComponent.java", "MyModuleComponentInterface.java"); + } + + public void testComponentUnresolvedClass() { + myFixture.testHighlighting("ComponentUnresolvedClass.xml"); + } + + public void testActionAbstractClass() { + myFixture.testHighlighting("ActionAbstractClass.xml", + "MyAbstractAction.java"); + } + + public void testActionUnresolvedClass() { + myFixture.testHighlighting("ActionUnresolvedClass.xml"); + } + + public void testActionWithoutDefaultCtor() { + myFixture.testHighlighting("ActionWithoutDefaultCtor.xml", + "MyActionWithoutDefaultCtor.java"); + } + + public void testActionWrongClass() { + myFixture.testHighlighting("ActionWrongClass.xml"); + } +} diff --git a/plugins/devkit/testSources/inspections/quickfix/RegisterExtensionFixProviderTest.java b/plugins/devkit/testSources/inspections/quickfix/RegisterExtensionFixProviderTest.java new file mode 100644 index 000000000000..77b7f47594bf --- /dev/null +++ b/plugins/devkit/testSources/inspections/quickfix/RegisterExtensionFixProviderTest.java @@ -0,0 +1,120 @@ +/* + * Copyright 2000-2014 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.idea.devkit.inspections.quickfix; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; +import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.TestDataPath; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; + +/** + * @author Dmitry Avdeev + * Date: 1/20/12 + */ +@TestDataPath("$CONTENT_ROOT/testData/inspections/registerExtensionFix") +public class RegisterExtensionFixProviderTest extends LightCodeInsightFixtureTestCase { + + @Override + public void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(new UnusedDeclarationInspection(), new UnusedSymbolLocalInspection()); + } + + public void testCreateLocalInspectionMapping() { + myFixture.addClass("package com.intellij.codeInspection; public class LocalInspectionTool {} "); + + myFixture.testHighlighting("LocalInspection.java", "plugin.xml"); + IntentionAction intention = myFixture.findSingleIntention("Register inspection"); + myFixture.launchAction(intention); + myFixture.checkResultByFile("plugin.xml", "localInspection.xml", true); + } + + public void testCreateGlobalInspectionMapping() { + myFixture.addClass("package com.intellij.codeInspection; public class GlobalInspectionTool {} "); + + myFixture.testHighlighting("GlobalInspection.java", "plugin.xml"); + IntentionAction intention = myFixture.findSingleIntention("Register inspection"); + myFixture.launchAction(intention); + myFixture.checkResultByFile("plugin.xml", "globalInspection.xml", true); + } + + public void testCreateExtensionPointMapping() { + myFixture.testHighlighting("MyExtensionPoint.java", + "extensionPoint.xml", + "ExtensionPoint.java"); + IntentionAction intention = myFixture.findSingleIntention("Register extension"); + myFixture.launchAction(intention); + myFixture.checkResultByFile("extensionPoint.xml", "extensionPoint_after.xml", true); + } + + public void testCreateExtensionPointMappingWithKnownRequiredAttribute() { + myFixture.addClass("package com.intellij.lang; public class LanguageExtensionPoint {}"); + + myFixture.testHighlighting("MyLanguageExtensionPoint.java", + "MyLanguageExtensionPointInterface.java", + "extensionPointWithKnownRequiredAttribute.xml"); + IntentionAction intention = myFixture.findSingleIntention("Register extension"); + myFixture.launchAction(intention); + myFixture.checkResultByFile("extensionPointWithKnownRequiredAttribute.xml", + "extensionPointWithKnownRequiredAttribute_after.xml", true); + } + + public void testCreateExtensionPointMappingWithKnownRequiredAttributeAndTag() { + myFixture.addClass("package com.intellij.lang; public class LanguageExtensionPoint {}"); + + myFixture.testHighlighting("MyLanguageExtensionPoint.java", + "MyLanguageExtensionPointInterface.java", + "extensionPointWithKnownRequiredAttributeAndTag.xml"); + IntentionAction intention = myFixture.findSingleIntention("Register extension"); + myFixture.launchAction(intention); + myFixture.checkResultByFile("extensionPointWithKnownRequiredAttributeAndTag.xml", + "extensionPointWithKnownRequiredAttributeAndTag_after.xml", true); + } + + public void testCreateExtensionPointMappingNoExtensionsTag() { + myFixture.testHighlighting("MyExtensionPoint.java", + "extensionPointNoExtensionsTag.xml", + "ExtensionPoint.java"); + IntentionAction intention = myFixture.findSingleIntention("Register extension"); + myFixture.launchAction(intention); + myFixture.checkResultByFile("extensionPointNoExtensionsTag.xml", "extensionPointNoExtensionsTag_after.xml", true); + } + + public void testCreateExtensionPointMappingNoPluginId() { + myFixture.testHighlighting("MyExtensionPoint.java", + "extensionPointNoPluginId.xml", + "ExtensionPoint.java"); + IntentionAction intention = myFixture.findSingleIntention("Register extension"); + myFixture.launchAction(intention); + myFixture.checkResultByFile("extensionPointNoPluginId.xml", "extensionPointNoPluginId_after.xml", true); + } + + public void testCreateExtensionPointQualifiedNameMapping() { + myFixture.testHighlighting("MyExtensionPoint.java", + "extensionPointQualifiedName.xml", + "ExtensionPoint.java"); + IntentionAction intention = myFixture.findSingleIntention("Register extension"); + myFixture.launchAction(intention); + myFixture.checkResultByFile("extensionPointQualifiedName.xml", "extensionPointQualifiedName_after.xml", true); + } + + @Override + protected String getBasePath() { + return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/inspections/registerExtensionFix"; + } +} diff --git a/plugins/devkit/testSources/testAssistant/TestDataPathCompletionTest.java b/plugins/devkit/testSources/testAssistant/TestDataPathCompletionTest.java index 299e8c1ac89f..1cabc84383ba 100644 --- a/plugins/devkit/testSources/testAssistant/TestDataPathCompletionTest.java +++ b/plugins/devkit/testSources/testAssistant/TestDataPathCompletionTest.java @@ -48,6 +48,6 @@ public class TestDataPathCompletionTest extends TestDataPathTestCase { @Override protected String getBasePath() { - return PluginPathManager.getPluginHomePathRelative("DevKit") + "/testData/completeTestDataPath"; + return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/completeTestDataPath"; } } diff --git a/plugins/devkit/testSources/testAssistant/TestDataPathResolvingTest.java b/plugins/devkit/testSources/testAssistant/TestDataPathResolvingTest.java index 890b0586aa3f..9709b641e087 100644 --- a/plugins/devkit/testSources/testAssistant/TestDataPathResolvingTest.java +++ b/plugins/devkit/testSources/testAssistant/TestDataPathResolvingTest.java @@ -53,6 +53,6 @@ public class TestDataPathResolvingTest extends TestDataPathTestCase { @Override protected String getBasePath() { - return PluginPathManager.getPluginHomePathRelative("DevKit") + "/testData/resolveTestDataPath"; + return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/resolveTestDataPath"; } } diff --git a/plugins/devkit/testSources/testAssistant/TestDataReferenceCollectorTest.java b/plugins/devkit/testSources/testAssistant/TestDataReferenceCollectorTest.java index 42ef122d7d62..2142a2b335aa 100644 --- a/plugins/devkit/testSources/testAssistant/TestDataReferenceCollectorTest.java +++ b/plugins/devkit/testSources/testAssistant/TestDataReferenceCollectorTest.java @@ -74,6 +74,6 @@ public class TestDataReferenceCollectorTest extends LightCodeInsightFixtureTestC @Override protected String getBasePath() { - return PluginPathManager.getPluginHomePathRelative("DevKit") + "/testData/"; + return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/"; } } diff --git a/plugins/devkit/testSources/testng.xml b/plugins/devkit/testSources/testng.xml deleted file mode 100644 index fd97179ebe16..000000000000 --- a/plugins/devkit/testSources/testng.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java index 337877020df0..baf835820ddb 100644 --- a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java +++ b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -197,7 +197,7 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider< final Collection changes = commit.getChanges(); if (changes.size() == 1) { - return new Pair(commit, changes.iterator().next().getAfterRevision().getFile()); + return Pair.create(commit, changes.iterator().next().getAfterRevision().getFile()); } for (Change change : changes) { if (change.getAfterRevision() != null && FileUtil.filesEqual(filePath.getIOFile(), change.getAfterRevision().getFile().getIOFile())) { @@ -209,7 +209,7 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider< if (history.isEmpty()) { return new Pair(commit, filePath); } - return new Pair(commit, ((GitFileRevision) history.get(history.size() - 1)).getPath()); + return Pair.create(commit, ((GitFileRevision)history.get(history.size() - 1)).getPath()); } @Override diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinHandlerFactory.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinHandlerFactory.java index b11098edf492..935689545899 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCheckinHandlerFactory.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinHandlerFactory.java @@ -295,7 +295,7 @@ public class GitCheckinHandlerFactory extends VcsCheckinHandlerFactory { message = messageCommonStart + " is in the detached HEAD state.
" + "You can look around, make experimental changes and commit them, but be sure to checkout a branch not to lose your work.
" + "Otherwise you risk losing your changes.
" + - readMore("http://sitaramc.github.com/concepts/detached-head.html", "Read more about detached HEAD"); + readMore("http://gitolite.com/detached-head.html", "Read more about detached HEAD"); } final int choice = Messages.showOkCancelDialog(myPanel.getComponent(), XmlStringUtil.wrapInHtml(message), title, diff --git a/plugins/git4idea/src/git4idea/config/GitConfigUtil.java b/plugins/git4idea/src/git4idea/config/GitConfigUtil.java index 4212fe4a2247..f3dae2551630 100644 --- a/plugins/git4idea/src/git4idea/config/GitConfigUtil.java +++ b/plugins/git4idea/src/git4idea/config/GitConfigUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -96,7 +96,7 @@ public class GitConfigUtil { while ((pos = output.indexOf('\u0000', start)) != -1) { String value = output.substring(start, pos); start = pos + 1; - result.add(new Pair(key, value)); + result.add(Pair.create(key, value)); } return result; } diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 3641c51f1627..66e6836535cd 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -730,7 +730,7 @@ public class GitHistoryUtils { final List> rc = new ArrayList>(); for (GitLogRecord record : parser.parse(output)) { record.setUsedHandler(h); - rc.add(new Pair(new SHAHash(record.getHash()), record.getDate())); + rc.add(Pair.create(new SHAHash(record.getHash()), record.getDate())); } return rc; } @@ -1026,7 +1026,7 @@ public class GitHistoryUtils { indexCommit = parentsShortHashes[0]; } } - return new Pair(AbstractHash.create(gitLogRecord.getHash()), indexCommit == null ? null : AbstractHash.create(indexCommit)); + return Pair.create(AbstractHash.create(gitLogRecord.getHash()), indexCommit == null ? null : AbstractHash.create(indexCommit)); } return null; } @@ -1050,7 +1050,7 @@ public class GitHistoryUtils { for (GitLogRecord gitLogRecord : gitLogRecords) { ProgressManager.checkCanceled(); final GitHeavyCommit gitCommit = createCommit(project, refs, root, gitLogRecord); - result.add(new Pair(gitLogRecord.getShortenedRefLog(), gitCommit)); + result.add(Pair.create(gitLogRecord.getShortenedRefLog(), gitCommit)); } return result; } diff --git a/plugins/git4idea/src/git4idea/history/browser/FictiveTableCellRenderer.java b/plugins/git4idea/src/git4idea/history/browser/FictiveTableCellRenderer.java index 80206b12b84f..ae9aba9c59ee 100644 --- a/plugins/git4idea/src/git4idea/history/browser/FictiveTableCellRenderer.java +++ b/plugins/git4idea/src/git4idea/history/browser/FictiveTableCellRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -84,7 +84,7 @@ public abstract class FictiveTableCellRenderer extends ColoredListCellRenderer { append(pair.getFirst(), pair.getSecond()); final String adj = description.getMaxString(i); if (adj != null) { - final int adjWidth = helper.getWidth(new Pair(adj, pair.getSecond())); + final int adjWidth = helper.getWidth(Pair.create(adj, pair.getSecond())); appendFixedTextFragmentWidth(adjWidth); fixedWidth += adjWidth; } else { @@ -104,12 +104,12 @@ public abstract class FictiveTableCellRenderer extends ColoredListCellRenderer { if (fixedWidth < parentWidth) { // todo this should be rewised final Trinity tag = getMoreTag(); - final int more = helper.getWidth(new Pair(tag.getFirst(), tag.getSecond())); + final int more = helper.getWidth(Pair.create(tag.getFirst(), tag.getSecond())); if (more < difference) { final String truncated = CommittedChangeListRenderer .truncateDescription(changeable.getFirst(), helper.getFontMetrics(changeable.getSecond()), difference - more); - final int truncatedWidth = helper.getWidth(new Pair(truncated, changeable.getSecond())); + final int truncatedWidth = helper.getWidth(Pair.create(truncated, changeable.getSecond())); append(truncated, changeable.getSecond()); append(tag.getFirst(), tag.getSecond(), tag.getThird()); if (truncatedWidth > 0) { diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/DetailsCache.java b/plugins/git4idea/src/git4idea/history/wholeTree/DetailsCache.java index 6eed431ec02a..1063014d3021 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/DetailsCache.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/DetailsCache.java @@ -1,9 +1,12 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -68,7 +71,7 @@ public class DetailsCache { public GitHeavyCommit convert(final VirtualFile root, final AbstractHash hash) { synchronized (myLock) { - return myCache.get(new Pair(root, hash)); + return myCache.get(Pair.create(root, hash)); } } @@ -80,7 +83,7 @@ public class DetailsCache { public void acceptAnswer(final Collection commits, final VirtualFile root) { synchronized (myLock) { for (GitHeavyCommit commit : commits) { - myCache.put(new Pair(root, commit.getShortHash()), commit); + myCache.put(Pair.create(root, commit.getShortHash()), commit); } } SwingUtilities.invokeLater(new Runnable() { @@ -97,14 +100,14 @@ public class DetailsCache { public void putBranches(final VirtualFile root, final AbstractHash hash, final List s) { synchronized (myLock) { - myBranches.put(new Pair(root, hash), s); + myBranches.put(Pair.create(root, hash), s); } } @Nullable public List getBranches(final VirtualFile root, final AbstractHash hash) { synchronized (myLock) { - return myBranches.get(new Pair(root, hash)); + return myBranches.get(Pair.create(root, hash)); } } @@ -120,7 +123,7 @@ public class DetailsCache { final GitHeavyCommit value = entry.getValue(); if (! value.getLocalBranches().isEmpty() || ! value.getRemoteBranches().isEmpty() || ! value.getTags().isEmpty()) { - forDeletion.add(new Pair(entry.getKey().getFirst(), entry.getKey().getSecond())); + forDeletion.add(Pair.create(entry.getKey().getFirst(), entry.getKey().getSecond())); } } for (Pair pair : forDeletion) { @@ -200,7 +203,7 @@ public class DetailsCache { if (! root.equals(entry.getKey().getFirst())) continue; AbstractHash hash = value.getShortHash(); if (hash.equals(headHash) || hashes.contains(value.getHash().getValue())) { - forDeletion.add(new Pair(entry.getKey().getFirst(), entry.getKey().getSecond())); + forDeletion.add(Pair.create(entry.getKey().getFirst(), entry.getKey().getSecond())); } } for (Pair pair : forDeletion) { diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java index 209d2ad3f410..95e072d33600 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -390,7 +390,7 @@ public class GitLogUI implements Disposable { for (int row : mySelectedRows) { final CommitI commitI = myModel.getCommitAt(row); if (commitI != null) { - myData.add(new Pair(commitI.selectRepository(SelectorList.getInstance()), commitI.getHash())); + myData.add(Pair.create(commitI.selectRepository(SelectorList.getInstance()), commitI.getHash())); } } } @@ -402,7 +402,7 @@ public class GitLogUI implements Disposable { final CommitI commitI = myModel.getCommitAt(row); if (commitI != null) { final Pair pair = - new Pair(commitI.selectRepository(SelectorList.getInstance()), commitI.getHash()); + Pair.create(commitI.selectRepository(SelectorList.getInstance()), commitI.getHash()); if (myData.remove(pair)) { selectionModel.addSelectionInterval(row, row); if (myData.isEmpty()) return; @@ -414,7 +414,7 @@ public class GitLogUI implements Disposable { final CommitI commitI = myModel.getCommitAt(i); if (commitI == null) continue; final Pair pair = - new Pair(commitI.selectRepository(SelectorList.getInstance()), commitI.getHash()); + Pair.create(commitI.selectRepository(SelectorList.getInstance()), commitI.getHash()); if (myData.remove(pair)) { selectionModel.addSelectionInterval(i, i); if (myData.isEmpty()) break; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java index ffc0b74b49a8..2a04482d32a6 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java @@ -244,7 +244,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver moduleDataNode = projectDataNode.createChild(ProjectKeys.MODULE, moduleData); - moduleMap.put(moduleName, new Pair, IdeaModule>(moduleDataNode, gradleModule)); + moduleMap.put(moduleName, Pair.create(moduleDataNode, gradleModule)); } // populate modules nodes diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java index 556d3b34efe6..c6c36d8cce19 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -50,30 +50,30 @@ import static org.jetbrains.plugins.gradle.service.resolve.GradleResolverUtil.ca */ public class GradleImplicitContributor implements GradleMethodContextContributor { private final static Map BUILT_IN_TASKS = newHashMap( - new Pair("assemble", GRADLE_API_DEFAULT_TASK), - new Pair("build", GRADLE_API_DEFAULT_TASK), - new Pair("buildDependents", GRADLE_API_DEFAULT_TASK), - new Pair("buildNeeded", GRADLE_API_DEFAULT_TASK), - new Pair("clean", GRADLE_API_TASKS_DELETE), - new Pair("jar", GRADLE_API_TASKS_BUNDLING_JAR), - new Pair("war", GRADLE_API_TASKS_BUNDLING_WAR), - new Pair("classes", GRADLE_API_DEFAULT_TASK), - new Pair("compileJava", GRADLE_API_TASKS_COMPILE_JAVA_COMPILE), - new Pair("compileTestJava", GRADLE_API_DEFAULT_TASK), - new Pair("processTestResources", GRADLE_API_DEFAULT_TASK), - new Pair("testClasses", GRADLE_API_DEFAULT_TASK), - new Pair("processResources", GRADLE_LANGUAGE_JVM_TASKS_PROCESS_RESOURCES), - new Pair("setupBuild", GRADLE_BUILDSETUP_TASKS_SETUP_BUILD), - new Pair("wrapper", GRADLE_API_TASKS_WRAPPER_WRAPPER), - new Pair("javadoc", GRADLE_API_TASKS_JAVADOC_JAVADOC), - new Pair("dependencies", GRADLE_API_TASKS_DIAGNOSTICS_DEPENDENCY_REPORT_TASK), - new Pair("dependencyInsight", GRADLE_API_TASKS_DIAGNOSTICS_DEPENDENCY_INSIGHT_REPORT_TASK), - new Pair("projects", GRADLE_API_TASKS_DIAGNOSTICS_PROJECT_REPORT_TASK), - new Pair("properties", GRADLE_API_TASKS_DIAGNOSTICS_PROPERTY_REPORT_TASK), - new Pair("tasks", GRADLE_API_TASKS_DIAGNOSTICS_TASK_REPORT_TASK), - new Pair("check", GRADLE_API_DEFAULT_TASK), - new Pair("test", GRADLE_API_TASKS_TESTING_TEST), - new Pair("uploadArchives", GRADLE_API_TASKS_UPLOAD) + Pair.create("assemble", GRADLE_API_DEFAULT_TASK), + Pair.create("build", GRADLE_API_DEFAULT_TASK), + Pair.create("buildDependents", GRADLE_API_DEFAULT_TASK), + Pair.create("buildNeeded", GRADLE_API_DEFAULT_TASK), + Pair.create("clean", GRADLE_API_TASKS_DELETE), + Pair.create("jar", GRADLE_API_TASKS_BUNDLING_JAR), + Pair.create("war", GRADLE_API_TASKS_BUNDLING_WAR), + Pair.create("classes", GRADLE_API_DEFAULT_TASK), + Pair.create("compileJava", GRADLE_API_TASKS_COMPILE_JAVA_COMPILE), + Pair.create("compileTestJava", GRADLE_API_DEFAULT_TASK), + Pair.create("processTestResources", GRADLE_API_DEFAULT_TASK), + Pair.create("testClasses", GRADLE_API_DEFAULT_TASK), + Pair.create("processResources", GRADLE_LANGUAGE_JVM_TASKS_PROCESS_RESOURCES), + Pair.create("setupBuild", GRADLE_BUILDSETUP_TASKS_SETUP_BUILD), + Pair.create("wrapper", GRADLE_API_TASKS_WRAPPER_WRAPPER), + Pair.create("javadoc", GRADLE_API_TASKS_JAVADOC_JAVADOC), + Pair.create("dependencies", GRADLE_API_TASKS_DIAGNOSTICS_DEPENDENCY_REPORT_TASK), + Pair.create("dependencyInsight", GRADLE_API_TASKS_DIAGNOSTICS_DEPENDENCY_INSIGHT_REPORT_TASK), + Pair.create("projects", GRADLE_API_TASKS_DIAGNOSTICS_PROJECT_REPORT_TASK), + Pair.create("properties", GRADLE_API_TASKS_DIAGNOSTICS_PROPERTY_REPORT_TASK), + Pair.create("tasks", GRADLE_API_TASKS_DIAGNOSTICS_TASK_REPORT_TASK), + Pair.create("check", GRADLE_API_DEFAULT_TASK), + Pair.create("test", GRADLE_API_TASKS_TESTING_TEST), + Pair.create("uploadArchives", GRADLE_API_TASKS_UPLOAD) ); @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingGettersInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingGettersInspection.java index c66b9673dde8..7a0225c3be0b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingGettersInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingGettersInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -102,10 +102,10 @@ public class ClashingGettersInspection extends BaseInspection { final String info = PsiFormatUtil .formatMethod(getter, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_NAME); - return new Pair(((GrMethod)getter).getNameIdentifierGroovy(), "method " + info); + return Pair.create(((GrMethod)getter).getNameIdentifierGroovy(), "method " + info); } else if (getter instanceof GrMethod) { - return new Pair(((GrMethod)getter).getNameIdentifierGroovy(), "getter '" + name + "'"); + return Pair.create(((GrMethod)getter).getNameIdentifierGroovy(), "getter '" + name + "'"); } else { final String info = PsiFormatUtil diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyEditorTextProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyEditorTextProvider.java index 6e72bc9533d0..65c7bbce2dbc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyEditorTextProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyEditorTextProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -83,6 +83,6 @@ public class GroovyEditorTextProvider implements EditorTextProvider { public Pair findExpression(PsiElement element, boolean allowMethodCalls) { PsiElement expression = findExpressionInner(element, allowMethodCalls); if (expression == null) return null; - return new Pair(expression, expression.getTextRange()); + return Pair.create(expression, expression.getTextRange()); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dgm/GroovyExtensionProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dgm/GroovyExtensionProvider.java index 007883a65d76..906f1efc8070 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dgm/GroovyExtensionProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dgm/GroovyExtensionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,7 +51,7 @@ public class GroovyExtensionProvider { public Pair, List> collectExtensions(GlobalSearchScope resolveScope) { PsiPackage aPackage = JavaPsiFacade.getInstance(myProject).findPackage("META-INF.services"); if (aPackage == null) { - return new Pair, List>(Collections.emptyList(), Collections.emptyList()); + return Pair.create(Collections.emptyList(), Collections.emptyList()); } @@ -68,7 +68,7 @@ public class GroovyExtensionProvider { } } - return new Pair, List>(instanceClasses, staticClasses); + return Pair.create(instanceClasses, staticClasses); } private static void collectClasses(IProperty pr, List classes) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/InstanceOfInstruction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/InstanceOfInstruction.java index a766d27726fb..3a7429978047 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/InstanceOfInstruction.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/InstanceOfInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -50,7 +50,7 @@ public class InstanceOfInstruction extends InstructionImpl implements MixinTypeI GrExpression operand = ((GrInstanceOfExpression)element).getOperand(); final GrTypeElement typeElement = ((GrInstanceOfExpression)element).getTypeElement(); if (operand instanceof GrReferenceExpression && ((GrReferenceExpression)operand).getQualifier() == null && typeElement != null) { - return new Pair(((GrInstanceOfExpression)element).getOperand(), typeElement.getType()); + return Pair.create(((GrInstanceOfExpression)element).getOperand(), typeElement.getType()); } } else if (element instanceof GrBinaryExpression && ControlFlowBuilderUtil.isInstanceOfBinary((GrBinaryExpression)element)) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index 73c9735ca2f4..beef8eeee926 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -828,7 +828,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { if (!PsiTreeUtil.isAncestor(currScope, scopeWhenAdded, true)) break; } } - myPending.add(i, new Pair(instruction, scopeWhenAdded)); + myPending.add(i, Pair.create(instruction, scopeWhenAdded)); } public void visitWhileStatement(GrWhileStatement whileStatement) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java index 0c8abfbdf3a3..52abb733ae51 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java @@ -581,7 +581,7 @@ public class GrClassImplUtil { if (!checkBases) { final PsiMethod[] methods = grType.findMethodsByName( name, false); for (PsiMethod method : methods) { - result.add(new Pair(method, PsiSubstitutor.EMPTY)); + result.add(Pair.create(method, PsiSubstitutor.EMPTY)); } } else { @@ -590,7 +590,7 @@ public class GrClassImplUtil { if (candidateInfos != null) { for (CandidateInfo info : candidateInfos) { final PsiElement element = info.getElement(); - result.add(new Pair((PsiMethod)element, info.getSubstitutor())); + result.add(Pair.create((PsiMethod)element, info.getSubstitutor())); } } } @@ -604,7 +604,7 @@ public class GrClassImplUtil { List> result = new ArrayList>(); for (List infos : allMethodsMap.values()) { for (CandidateInfo info : infos) { - result.add(new Pair((PsiMethod)info.getElement(), info.getSubstitutor())); + result.add(Pair.create((PsiMethod)info.getElement(), info.getSubstitutor())); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java index 03c7d4dc22d5..40e3f5ff4f7a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java @@ -452,7 +452,7 @@ public class ResolveUtil { while (sibling != null) { final GrLabeledStatement labelStatement = findLabelStatementIn(sibling, last, labelName); if (labelStatement != null) { - return new Pair(statement, labelStatement); + return Pair.create(statement, labelStatement); } sibling = sibling.getPrevSibling(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcActionBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcActionBase.java index b952f25d5107..a975d4df25b3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcActionBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcActionBase.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 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.mvc; import com.intellij.openapi.actionSystem.ActionPlaces; @@ -43,7 +58,7 @@ public abstract class MvcActionBase extends DumbAwareAction { for (Module mod : ModuleManager.getInstance(module.getProject()).getModules()) { if (commonPluginModuleFramework.getCommonPluginsModuleName(mod).equals(module.getName())) { if (commonPluginModuleFramework.hasSupport(mod)) { - return new Pair(commonPluginModuleFramework, mod); + return Pair.create(commonPluginModuleFramework, mod); } return null; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java index 901a6d3f1635..9af339c55aaa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java @@ -248,7 +248,7 @@ public class MvcModuleStructureSynchronizer extends AbstractProjectComponent { boolean shouldSchedule; synchronized (myOrders) { shouldSchedule = myOrders.isEmpty(); - myOrders.add(new Pair(on, action)); + myOrders.add(Pair.create(on, action)); } if (shouldSchedule) { StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java index 4776713cb6ea..fa17c11e2f30 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java @@ -480,18 +480,18 @@ public class GenerationUtil { private static final Map> binOpTypes = new HashMap>(); static { - binOpTypes.put(mPLUS_ASSIGN, new Pair("+", mPLUS)); - binOpTypes.put(mMINUS_ASSIGN, new Pair("-", mMINUS)); - binOpTypes.put(mSTAR_ASSIGN, new Pair("*", mSTAR)); - binOpTypes.put(mDIV_ASSIGN, new Pair("/", mDIV)); - binOpTypes.put(mMOD_ASSIGN, new Pair("%", mMOD)); + binOpTypes.put(mPLUS_ASSIGN, Pair.create("+", mPLUS)); + binOpTypes.put(mMINUS_ASSIGN, Pair.create("-", mMINUS)); + binOpTypes.put(mSTAR_ASSIGN, Pair.create("*", mSTAR)); + binOpTypes.put(mDIV_ASSIGN, Pair.create("/", mDIV)); + binOpTypes.put(mMOD_ASSIGN, Pair.create("%", mMOD)); binOpTypes.put(mSL_ASSIGN, new Pair("<<", COMPOSITE_LSHIFT_SIGN)); binOpTypes.put(mSR_ASSIGN, new Pair(">>", COMPOSITE_RSHIFT_SIGN)); binOpTypes.put(mBSR_ASSIGN, new Pair(">>>", COMPOSITE_TRIPLE_SHIFT_SIGN)); - binOpTypes.put(mBAND_ASSIGN, new Pair("&", mBAND)); - binOpTypes.put(mBOR_ASSIGN, new Pair("|", mBOR)); - binOpTypes.put(mBXOR_ASSIGN, new Pair("^", mBXOR)); - binOpTypes.put(mSTAR_STAR_ASSIGN, new Pair("**", mSTAR_STAR)); + binOpTypes.put(mBAND_ASSIGN, Pair.create("&", mBAND)); + binOpTypes.put(mBOR_ASSIGN, Pair.create("|", mBOR)); + binOpTypes.put(mBXOR_ASSIGN, Pair.create("^", mBXOR)); + binOpTypes.put(mSTAR_STAR_ASSIGN, Pair.create("**", mSTAR_STAR)); } public static Pair getBinaryOperatorType(IElementType op_assign) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java index a8972f86939a..c79ae1ca0b7c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java @@ -18,6 +18,7 @@ package org.zmlx.hg4idea.action; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; @@ -70,6 +71,7 @@ public class HgCommonBranchActions extends ActionGroup { @Override public void actionPerformed(AnActionEvent e) { + FileDocumentManager.getInstance().saveAllDocuments(); final UpdatedFiles updatedFiles = UpdatedFiles.create(); final HgMergeCommand hgMergeCommand = new HgMergeCommand(myProject, mySelectedRepository.getRoot()); hgMergeCommand.setRevision(myBranchName);//there is no difference between branch or revision or bookmark as parameter to merge, @@ -111,6 +113,7 @@ public class HgCommonBranchActions extends ActionGroup { @Override public void actionPerformed(AnActionEvent e) { final VirtualFile repository = mySelectedRepository.getRoot(); + FileDocumentManager.getInstance().saveAllDocuments(); final HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(myProject, repository); hgUpdateCommand.setBranch(myBranchName); new Task.Backgroundable(myProject, HgVcsMessages.message("action.hg4idea.updateTo.description", myBranchName)) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgUpdateCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgUpdateCommand.java index 660ff40baebe..863eba5f8271 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgUpdateCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgUpdateCommand.java @@ -13,9 +13,11 @@ package org.zmlx.hg4idea.command; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.HgVcs; @@ -25,6 +27,9 @@ import org.zmlx.hg4idea.execution.HgDeleteModifyPromptHandler; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class HgUpdateCommand { @@ -69,11 +74,36 @@ public class HgUpdateCommand { final HgCommandExecutor executor = new HgCommandExecutor(project); executor.setShowOutput(true); - final HgCommandResult result = + HgCommandResult result = executor.executeInCurrentThread(repo, "update", arguments, new HgDeleteModifyPromptHandler()); + if (detectLocalChangeConflict(result)) { + final AtomicInteger exitCode = new AtomicInteger(); + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + exitCode.set(Messages.showOkCancelDialog(project, + "Your uncommitted changes couldn't be merged into the requested changeset.\n" + + "Would you like to perform Force Update and discard them?", + "Update Conflict", "&Force Update", "&Cancel", + Messages.getWarningIcon())); + } + }); + if (exitCode.get() == Messages.YES) { + arguments.add("-C"); + result = + executor.executeInCurrentThread(repo, "update", arguments, new HgDeleteModifyPromptHandler()); + } + } + project.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(project, null); VfsUtil.markDirtyAndRefresh(true, true, false, repo); return result; } + private static boolean detectLocalChangeConflict(HgCommandResult result) { + // error messages from mercurial after update command: "abort: outstanding uncommitted merges", "abort: uncommitted changes" + final Pattern UNCOMMITTED_PATTERN = Pattern.compile(".*abort.*uncommitted\\s*(changes|merges).*", Pattern.DOTALL); + Matcher matcher = UNCOMMITTED_PATTERN.matcher(result.getRawError()); + return matcher.matches(); + } } diff --git a/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxAntGenerator.java b/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxAntGenerator.java index 7ebe6296c042..d0e65967f7e6 100644 --- a/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxAntGenerator.java +++ b/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxAntGenerator.java @@ -46,41 +46,41 @@ public class JavaFxAntGenerator { if (!StringUtil.isEmptyOrSpaces(preloaderJar) && !StringUtil.isEmptyOrSpaces(preloaderClass)) { preloaderFiles = artifactFileNameWithoutExtension + "_preloader_files"; topLevelTagsCollector.add(new SimpleTag("fx:fileset", - new Pair("id", preloaderFiles), - new Pair("requiredFor", "preloader"), - new Pair("dir", tempDirPath), - new Pair("includes", preloaderJar))); + Pair.create("id", preloaderFiles), + Pair.create("requiredFor", "preloader"), + Pair.create("dir", tempDirPath), + Pair.create("includes", preloaderJar))); allButPreloader = "all_but_preloader_" + artifactFileNameWithoutExtension; - topLevelTagsCollector.add(new SimpleTag("fx:fileset", new Pair("id", allButPreloader), - new Pair("dir", tempDirPath), - new Pair("excludes", preloaderJar), - new Pair("includes", "**/*.jar"))); + topLevelTagsCollector.add(new SimpleTag("fx:fileset", Pair.create("id", allButPreloader), + Pair.create("dir", tempDirPath), + Pair.create("excludes", preloaderJar), + Pair.create("includes", "**/*.jar"))); } final String allButSelf = "all_but_" + artifactFileNameWithoutExtension; - final SimpleTag allButSelfAndPreloader = new SimpleTag("fx:fileset", new Pair("id", allButSelf), - new Pair("dir", tempDirPath), - new Pair("includes", "**/*.jar")); - allButSelfAndPreloader.add(new SimpleTag("exclude", new Pair("name", artifactFileName))); + final SimpleTag allButSelfAndPreloader = new SimpleTag("fx:fileset", Pair.create("id", allButSelf), + Pair.create("dir", tempDirPath), + Pair.create("includes", "**/*.jar")); + allButSelfAndPreloader.add(new SimpleTag("exclude", Pair.create("name", artifactFileName))); if (preloaderJar != null) { - allButSelfAndPreloader.add(new SimpleTag("exclude", new Pair("name", preloaderJar))); + allButSelfAndPreloader.add(new SimpleTag("exclude", Pair.create("name", preloaderJar))); } topLevelTagsCollector.add(allButSelfAndPreloader); final String all = "all_" + artifactFileNameWithoutExtension; - final SimpleTag allIncluded = new SimpleTag("fx:fileset", new Pair("id", all), - new Pair("dir", tempDirPath), - new Pair("includes", "**/*.jar")); + final SimpleTag allIncluded = new SimpleTag("fx:fileset", Pair.create("id", all), + Pair.create("dir", tempDirPath), + Pair.create("includes", "**/*.jar")); topLevelTagsCollector.add(allIncluded); //register application final String appId = artifactFileNameWithoutExtension + "_id"; - final SimpleTag applicationTag = new SimpleTag("fx:application", new Pair("id", appId), - new Pair("name", artifactName), - new Pair("mainClass", packager.getAppClass())); + final SimpleTag applicationTag = new SimpleTag("fx:application", Pair.create("id", appId), + Pair.create("name", artifactName), + Pair.create("mainClass", packager.getAppClass())); if (preloaderFiles != null) { - applicationTag.addAttribute(new Pair("preloaderClass", preloaderClass)); + applicationTag.addAttribute(Pair.create("preloaderClass", preloaderClass)); } appendValuesFromPropertiesFile(applicationTag, packager.getHtmlParamFile(), "fx:htmlParam", false); @@ -90,19 +90,19 @@ public class JavaFxAntGenerator { topLevelTagsCollector.add(applicationTag); if (packager.convertCss2Bin()) { - final SimpleTag css2binTag = new SimpleTag("fx:csstobin", new Pair("outdir", tempDirPath)); - css2binTag.add(new SimpleTag("fileset", new Pair("dir", tempDirPath), new Pair("includes", "**/*.css"))); + final SimpleTag css2binTag = new SimpleTag("fx:csstobin", Pair.create("outdir", tempDirPath)); + css2binTag.add(new SimpleTag("fileset", Pair.create("dir", tempDirPath), Pair.create("includes", "**/*.css"))); topLevelTagsCollector.add(css2binTag); } //create jar task final SimpleTag createJarTag = new SimpleTag("fx:jar", - new Pair("destfile", tempDirPath + File.separator + artifactFileName)); - createJarTag.add(new SimpleTag("fx:application", new Pair("refid", appId))); + Pair.create("destfile", tempDirPath + File.separator + artifactFileName)); + createJarTag.add(new SimpleTag("fx:application", Pair.create("refid", appId))); final List fileset2Jar = new ArrayList(); - fileset2Jar.add(new Pair("dir", tempDirPath)); - fileset2Jar.add(new Pair("excludes", "**/*.jar")); + fileset2Jar.add(Pair.create("dir", tempDirPath)); + fileset2Jar.add(Pair.create("excludes", "**/*.jar")); createJarTag.add(new SimpleTag("fileset", fileset2Jar.toArray(new Pair[fileset2Jar.size()]))); createJarTag.add(createResourcesTag(preloaderFiles, false, allButPreloader, allButSelf, all)); @@ -111,9 +111,9 @@ public class JavaFxAntGenerator { if (manifestAttributes != null) { final SimpleTag manifestTag = new SimpleTag("manifest"); for (JavaFxManifestAttribute pair : manifestAttributes) { - manifestTag.add(new SimpleTag("attribute", - new Pair("name", pair.getName()), - new Pair("value", pair.getValue()))); + manifestTag.add(new SimpleTag("attribute", + Pair.create("name", pair.getName()), + Pair.create("value", pair.getValue()))); } createJarTag.add(manifestTag); } @@ -122,21 +122,21 @@ public class JavaFxAntGenerator { //deploy task final SimpleTag deployTag = new SimpleTag("fx:deploy", - new Pair("width", packager.getWidth()), - new Pair("height", packager.getHeight()), - new Pair("updatemode", packager.getUpdateMode()), - new Pair("outdir", tempDirPath + File.separator + "deploy"), - new Pair("outfile", artifactFileNameWithoutExtension)); + Pair.create("width", packager.getWidth()), + Pair.create("height", packager.getHeight()), + Pair.create("updatemode", packager.getUpdateMode()), + Pair.create("outdir", tempDirPath + File.separator + "deploy"), + Pair.create("outfile", artifactFileNameWithoutExtension)); final JavaFxPackagerConstants.NativeBundles bundle = packager.getNativeBundle(); if (bundle != JavaFxPackagerConstants.NativeBundles.none) { - deployTag.addAttribute(new Pair("nativeBundles", bundle.name())); + deployTag.addAttribute(Pair.create("nativeBundles", bundle.name())); } if (packager.isEnabledSigning()) { - deployTag.add(new SimpleTag("fx:permissions", new Pair("elevated", "true"))); + deployTag.add(new SimpleTag("fx:permissions", Pair.create("elevated", "true"))); } - deployTag.add(new SimpleTag("fx:application", new Pair("refid", appId))); + deployTag.add(new SimpleTag("fx:application", Pair.create("refid", appId))); final List infoPairs = new ArrayList(); appendIfNotEmpty(infoPairs, "title", packager.getTitle()); @@ -157,10 +157,10 @@ public class JavaFxAntGenerator { String all) { final SimpleTag resourcesTag = new SimpleTag("fx:resources"); if (preloaderFiles != null) { - resourcesTag.add(new SimpleTag("fx:fileset", new Pair("refid", preloaderFiles))); - resourcesTag.add(new SimpleTag("fx:fileset", new Pair("refid", includeSelf ? allButPreloader : allButSelf))); + resourcesTag.add(new SimpleTag("fx:fileset", Pair.create("refid", preloaderFiles))); + resourcesTag.add(new SimpleTag("fx:fileset", Pair.create("refid", includeSelf ? allButPreloader : allButSelf))); } else { - resourcesTag.add(new SimpleTag("fx:fileset", new Pair("refid", includeSelf ? all : allButSelf))); + resourcesTag.add(new SimpleTag("fx:fileset", Pair.create("refid", includeSelf ? all : allButSelf))); } return resourcesTag; } @@ -186,7 +186,7 @@ public class JavaFxAntGenerator { final String propValue = properties.getProperty(propName); if (!StringUtil.isEmptyOrSpaces(propValue)) { applicationTag - .add(new SimpleTag(paramTagName, new Pair("name", propName), new Pair("value", propValue))); + .add(new SimpleTag(paramTagName, Pair.create("name", propName), Pair.create("value", propValue))); } else if (allowNoNamed) { applicationTag.add(new SimpleTag("fx:argument", propName) { diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/ant/JavaFxChunkBuildExtension.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/ant/JavaFxChunkBuildExtension.java index 5dd7136dcc6f..884c6be31bd1 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/ant/JavaFxChunkBuildExtension.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/ant/JavaFxChunkBuildExtension.java @@ -33,7 +33,10 @@ import com.intellij.util.Base64Converter; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.javaFX.packaging.*; +import org.jetbrains.plugins.javaFX.packaging.JavaFxAntGenerator; +import org.jetbrains.plugins.javaFX.packaging.JavaFxApplicationArtifactType; +import org.jetbrains.plugins.javaFX.packaging.JavaFxArtifactProperties; +import org.jetbrains.plugins.javaFX.packaging.JavaFxArtifactPropertiesProvider; import java.io.File; import java.io.IOException; @@ -78,12 +81,12 @@ public class JavaFxChunkBuildExtension extends ChunkBuildExtension { } if (javaSdk != null) { final Tag taskdef = new Tag("taskdef", - new Pair("resource", "com/sun/javafx/tools/ant/antlib.xml"), - new Pair("uri", "javafx:com.sun.javafx.tools.ant"), - new Pair("classpath", - BuildProperties - .propertyRef(BuildProperties.getJdkHomeProperty(javaSdk.getName())) + - "/lib/ant-javafx.jar")); + Pair.create("resource", "com/sun/javafx/tools/ant/antlib.xml"), + Pair.create("uri", "javafx:com.sun.javafx.tools.ant"), + Pair.create("classpath", + BuildProperties + .propertyRef(BuildProperties.getJdkHomeProperty(javaSdk.getName())) + + "/lib/ant-javafx.jar")); generator.add(taskdef); } } @@ -171,21 +174,22 @@ public class JavaFxChunkBuildExtension extends ChunkBuildExtension { final Pair[] keysDescriptions = createKeysDescriptions(artifactName); if (selfSigning) { generator.add(new Tag("genkey", - ArrayUtil.prepend(new Pair("dname", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_VENDOR_SIGN_PROPERTY, artifactName))), + ArrayUtil.prepend(Pair.create("dname", BuildProperties + .propertyRef(artifactBasedProperty(ARTIFACT_VENDOR_SIGN_PROPERTY, artifactName))), keysDescriptions))); } final Tag signjar = new Tag("signjar", keysDescriptions); - final Tag fileset = new Tag("fileset", new Pair("dir", tempDirPath + "/deploy")); - fileset.add(new Tag("include", new Pair("name", "*.jar"))); + final Tag fileset = new Tag("fileset", Pair.create("dir", tempDirPath + "/deploy")); + fileset.add(new Tag("include", Pair.create("name", "*.jar"))); signjar.add(fileset); generator.add(signjar); } final DirectoryAntCopyInstructionCreator creator = new DirectoryAntCopyInstructionCreator(BuildProperties.propertyRef(context.getConfiguredArtifactOutputProperty(artifact))); generator.add(creator.createDirectoryContentCopyInstruction(tempDirPath + "/deploy")); - final Tag deleteTag = new Tag("delete", new Pair("includeemptydirs", "true")); - deleteTag.add(new Tag("fileset", new Pair("dir", tempDirPath))); + final Tag deleteTag = new Tag("delete", Pair.create("includeemptydirs", "true")); + deleteTag.add(new Tag("fileset", Pair.create("dir", tempDirPath))); generator.add(deleteTag); } @@ -214,10 +218,10 @@ public class JavaFxChunkBuildExtension extends ChunkBuildExtension { private static Pair[] createKeysDescriptions(String artifactName) { return new Pair[]{ - new Pair("alias", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_ALIAS_SIGN_PROPERTY, artifactName))), - new Pair("keystore", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_KEYSTORE_SIGN_PROPERTY, artifactName))), - new Pair("storepass", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_STOREPASS_SIGN_PROPERTY, artifactName))), - new Pair("keypass", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACTKEYPASS_SIGN_PROPERTY, artifactName)))}; + Pair.create("alias", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_ALIAS_SIGN_PROPERTY, artifactName))), + Pair.create("keystore", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_KEYSTORE_SIGN_PROPERTY, artifactName))), + Pair.create("storepass", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_STOREPASS_SIGN_PROPERTY, artifactName))), + Pair.create("keypass", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACTKEYPASS_SIGN_PROPERTY, artifactName)))}; } @Nullable diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/EditMavenPropertyDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/EditMavenPropertyDialog.java index e8009a009ba0..b9890601f770 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/EditMavenPropertyDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/EditMavenPropertyDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -96,6 +96,6 @@ public class EditMavenPropertyDialog extends DialogWrapper { } public Pair getValue() { - return new Pair((String)myNameBox.getEditor().getItem(), myValueField.getText()); + return Pair.create((String)myNameBox.getEditor().getItem(), myValueField.getText()); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenPropertiesPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenPropertiesPanel.java index 375d2ccc52c0..826963a14d80 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenPropertiesPanel.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenPropertiesPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -21,8 +21,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; /** * @author Sergey Evdokimov @@ -67,7 +69,7 @@ public class MavenPropertiesPanel extends AddEditRemovePanel map) { List> result = new ArrayList>(); for (Map.Entry e : map.entrySet()) { - result.add(new Pair(e.getKey(), e.getValue())); + result.add(Pair.create(e.getKey(), e.getValue())); } setData(result); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginDescriptor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginDescriptor.java index 49b8b995dd9f..78d318d0e9bf 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginDescriptor.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -128,7 +128,7 @@ public class MavenPluginDescriptor extends AbstractExtensionPointBean { throw new RuntimeException("Failed to parse mavenId: " + mavenId + " (mavenId should has format 'groupId:artifactId')"); } - return new Pair(mavenId.substring(0, idx), mavenId.substring(idx + 1)); + return Pair.create(mavenId.substring(0, idx), mavenId.substring(idx + 1)); } public static Map>>> getDescriptorsMap() { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java index 0b3a8b5c60e9..bb465f5e5fc1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -100,8 +100,8 @@ public class MavenProjectReader { repairModelBody(model); - return new Pair>(new RawModelReadResult(model, problems, alwaysOnProfiles), - applied.getActivatedProfiles()); + return Pair.create(new RawModelReadResult(model, problems, alwaysOnProfiles), + applied.getActivatedProfiles()); } private RawModelReadResult doReadProjectModel(VirtualFile file, boolean headerOnly) { diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java index cb198d649ca9..6b92d396c34e 100644 --- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -96,6 +96,7 @@ public class PropertiesHighlighter extends SyntaxHighlighterBase { DISPLAY_NAMES.put(PROPERTY_KEY_VALUE_SEPARATOR, new Pair(PropertiesBundle.message("options.properties.attribute.descriptor.key.value.separator"), null)); DISPLAY_NAMES.put(PROPERTY_COMMENT, new Pair(PropertiesBundle.message("options.properties.attribute.descriptor.comment"), null)); DISPLAY_NAMES.put(PROPERTIES_VALID_STRING_ESCAPE, new Pair(PropertiesBundle.message("options.properties.attribute.descriptor.valid.string.escape"), null)); - DISPLAY_NAMES.put(PROPERTIES_INVALID_STRING_ESCAPE, new Pair(PropertiesBundle.message("options.properties.attribute.descriptor.invalid.string.escape"), HighlightSeverity.WARNING)); + DISPLAY_NAMES.put(PROPERTIES_INVALID_STRING_ESCAPE, Pair + .create(PropertiesBundle.message("options.properties.attribute.descriptor.invalid.string.escape"), HighlightSeverity.WARNING)); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java index 6a25f57cf906..f13ed5a97a03 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -222,7 +222,7 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent>(stored, InfoReliability.setByUser)); } else { - whatToInit.add(new Pair(root, newConfig)); + whatToInit.add(Pair.create(root, newConfig)); newConfig.addBranches(branchUrl, new InfoStorage>(new ArrayList(), InfoReliability.empty)); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java index cff64beea8b2..6e9693bdd6eb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -89,7 +89,7 @@ public class SvnContentRevision implements ContentRevision, MarkerVcsContentRevi @Override public Pair get() throws VcsException, IOException { - return new Pair(getRevisionNumber(), getUpToDateBinaryContent()); + return Pair.create(getRevisionNumber(), getUpToDateBinaryContent()); } }).getSecond(); } else { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java index 2e2145b8853a..f9d9e2a996f6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -47,7 +47,10 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNMoveClient; +import org.tmatesoft.svn.core.wc.SVNStatus; +import org.tmatesoft.svn.core.wc.SVNStatusType; import java.io.File; import java.io.IOException; @@ -579,7 +582,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp } } final File tmpFile = FileUtil.findSequentNonexistentFile(myStorageForUndo, "tmp", ""); - myUndoStorageContents.add(0, new Pair(new File(file.getPath()), tmpFile)); + myUndoStorageContents.add(0, Pair.create(new File(file.getPath()), tmpFile)); new File(file.getPath()).renameTo(tmpFile); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java index 6bf4014d442d..8f23eeb8d0a8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -144,7 +144,7 @@ public class SvnFileSystemListenerWrapper { final Project project = getProject(args); if (project != null) { myMarker.start(project); - myStarted.put(project, new Pair(method.getName(), newArr)); + myStarted.put(project, Pair.create(method.getName(), newArr)); Disposer.register(project, new Disposable() { public void dispose() { myStarted.remove(project); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index b8a5c14b5d97..992d02c25169 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -361,7 +361,7 @@ public class SvnUtil { if (path == null) { result.putValue(new Pair(null, null), committable); } else { - result.putValue(new Pair(path.getRepositoryUrlUrl(), path.getFormat()), committable); + result.putValue(Pair.create(path.getRepositoryUrlUrl(), path.getFormat()), committable); } } return result; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 54616f46c1a6..953182348cb3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -879,7 +879,7 @@ public class SvnVcs extends AbstractVcs { myPropertyCache.put(keyForVf(file), cachedMap); } - cachedMap.put(propName, new Pair>(propValue, tsTrinity)); + cachedMap.put(propName, Pair.create(propValue, tsTrinity)); return propValue; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CleanupWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CleanupWorker.java index 8ef4d71e66e1..7623f083eb86 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CleanupWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CleanupWorker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -83,7 +83,7 @@ public class CleanupWorker { vcs.getFactory(path).createCleanupClient().cleanup(path, handler); } catch (VcsException ex) { - exceptions.add(new Pair(ex, currentRoot)); + exceptions.add(Pair.create(ex, currentRoot)); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java index 880f6935d157..5748aa59280e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -101,7 +101,7 @@ public class LoadRecentBranchRevisions extends TaskDescriptor { new PairConsumer>() { public void consume(SvnChangeList svnList, TreeStructureNode tree) { indicator.setText2(SvnBundle.message("progress.text2.processing.revision", svnList.getNumber())); - list.add(new Pair>(svnList, tree)); + list.add(Pair.create(svnList, tree)); } }); } catch (VcsException e) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browserCache/RepositoryLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browserCache/RepositoryLoader.java index d2f8b633773b..e824b06358b0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browserCache/RepositoryLoader.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browserCache/RepositoryLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,8 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.dialogs.RepositoryTreeNode; import org.jetbrains.idea.svn.auth.SvnAuthenticationProvider; +import org.jetbrains.idea.svn.dialogs.RepositoryTreeNode; import org.tmatesoft.svn.core.ISVNDirEntryHandler; import org.tmatesoft.svn.core.SVNDirEntry; import org.tmatesoft.svn.core.SVNErrorMessage; @@ -48,7 +48,7 @@ class RepositoryLoader extends Loader { public void load(final RepositoryTreeNode node, final Expander afterRefreshExpander) { ApplicationManager.getApplication().assertIsDispatchThread(); - final Pair data = new Pair(node, afterRefreshExpander); + final Pair data = Pair.create(node, afterRefreshExpander); if (! myQueueProcessorActive) { startLoadTask(data); myQueueProcessorActive = true; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java index 320c24248516..0045d0c26b27 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -148,14 +148,14 @@ public class RootsAndBranches implements CommittedChangeListDecorator { for (Map.Entry entry : myMergePanels.entrySet()) { final String localPath = entry.getKey(); final WCInfoWithBranches wcInfo = entry.getValue().getWcInfo(); - states.put(new Pair(localPath, wcInfo.getUrl().toString()), entry.getValue().getInfo()); + states.put(Pair.create(localPath, wcInfo.getUrl().toString()), entry.getValue().getInfo()); } createPanels(myLocation, new Runnable() { public void run() { for (Map.Entry entry : myMergePanels.entrySet()) { final String localPath = entry.getKey(); final WCInfoWithBranches wcInfo = entry.getValue().getWcInfo(); - final Pair key = new Pair(localPath, wcInfo.getUrl().toString()); + final Pair key = Pair.create(localPath, wcInfo.getUrl().toString()); final SvnMergeInfoRootPanelManual.InfoHolder infoHolder = states.get(key); if (infoHolder != null) { entry.getValue().initSelection(infoHolder); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedListsZipper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedListsZipper.java index 13359c4d5f23..9f846ca7a57f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedListsZipper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedListsZipper.java @@ -75,7 +75,7 @@ public class SvnCommittedListsZipper implements VcsCommittedListsZipper { groups.add(group); } } - return new Pair, List>(groups, singles); + return Pair.create(groups, singles); } public CommittedChangeList zip(final RepositoryLocationGroup group, final List lists) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java index 19e663183643..3029f156a69c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -290,7 +290,7 @@ public class IntegratedSelectedOptionsDialog extends DialogWrapper { SvnBundle.message("action.Subversion.integrate.changes.messages.title")); return null; } - return new Pair(info, targetUrl); + return Pair.create(info, targetUrl); } } return null; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java index 9c880b6d3dda..782bd789e00e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java @@ -131,8 +131,8 @@ public class MergeCalculatorTask extends BaseMergeTask implements indicator.checkCanceled(); if (sourceLatest >= svnList.getNumber()) return; list.add( - new Pair>(svnList, - tree) + Pair.create(svnList, + tree) ); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java index fb0f52362cdf..8a0519b5f2ad 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -86,7 +86,7 @@ public class MergeInfoHolder { } private static Pair createKey(final WCPaths root, final WCInfoWithBranches.Branch branch) { - return new Pair(root.getPath(), branch.getUrl()); + return Pair.create(root.getPath(), branch.getUrl()); } public void refresh(final boolean ignoreEnabled) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java index 38f15dd271f8..1ef6d5565263 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -355,7 +355,7 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment { } private void markRename(@NotNull final File beforeFile, @NotNull final File afterFile) { - myToBeDeleted.add(new Pair(beforeFile, afterFile)); + myToBeDeleted.add(Pair.create(beforeFile, afterFile)); } public ThroughRenameInfo findToFile(@NotNull final FilePath file, @Nullable final File firstTo) { diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/BranchInfo.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/BranchInfo.java index 9778bf5adee2..4626ab11f9d1 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/BranchInfo.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/BranchInfo.java @@ -53,4 +53,26 @@ public class BranchInfo { } return list; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + BranchInfo info = (BranchInfo)o; + + if (original != info.original) return false; + if (name != null ? !name.equals(info.name) : info.name != null) return false; + if (repository != null ? !repository.equals(info.repository) : info.repository != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (repository != null ? repository.hashCode() : 0); + result = 31 * result + (original ? 1 : 0); + return result; + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index 2f065a9b89cf..3b8ba30d2288 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -377,13 +377,52 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe } List branches = task.getBranches(false); - VcsTaskHandler.TaskInfo info = fromBranches(branches); + // we should have exactly one branch per repo + MultiMap multiMap = new MultiMap(); + for (BranchInfo branch : branches) { + multiMap.putValue(branch.repository, branch); + } + for (String repo: multiMap.keySet()) { + Collection infos = multiMap.get(repo); + if (infos.size() > 1) { + // cleanup needed + List existing = getAllBranches(repo); + for (Iterator iterator = infos.iterator(); iterator.hasNext(); ) { + BranchInfo info = iterator.next(); + if (!existing.contains(info)) { + iterator.remove(); + if (infos.size() == 1) { + break; + } + } + } + } + } + + VcsTaskHandler.TaskInfo info = fromBranches(new ArrayList(multiMap.values())); switchBranch(info); return task; } - public void switchBranch(VcsTaskHandler.TaskInfo info) { + private List getAllBranches(final String repo) { + ArrayList infos = new ArrayList(); + VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject); + for (VcsTaskHandler handler : handlers) { + VcsTaskHandler.TaskInfo[] tasks = handler.getCurrentTasks(); + for (VcsTaskHandler.TaskInfo info : tasks) { + infos.addAll(ContainerUtil.filter(BranchInfo.fromTaskInfo(info, false), new Condition() { + @Override + public boolean value(BranchInfo info) { + return Comparing.equal(info.repository, repo); + } + })); + } + } + return infos; + } + + private void switchBranch(VcsTaskHandler.TaskInfo info) { VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject); for (VcsTaskHandler handler : handlers) { handler.switchToTask(info, null); @@ -402,7 +441,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject); for (VcsTaskHandler handler : handlers) { VcsTaskHandler.TaskInfo info = handler.getActiveTask(); - if (previousActive != null) { + if (previousActive != null && previousActive.getBranches(false).isEmpty()) { addBranches(previousActive, info, false); } addBranches(task, info, true); diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java index 1e8909b666c4..54c00c38b83e 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java @@ -155,6 +155,48 @@ public class TaskBranchesTest extends PlatformTestCase { assertEquals("foo", branches.get(0).name); } + public void testBranchBloating() throws Exception { + initRepository("foo"); + LocalTask defaultTask = myTaskManager.getActiveTask(); + assertNotNull(defaultTask); + assertEquals(0, defaultTask.getBranches().size()); + LocalTaskImpl foo = myTaskManager.createLocalTask("foo"); + LocalTask localTask = myTaskManager.activateTask(foo, false); + myTaskManager.createBranch(localTask, defaultTask, myTaskManager.suggestBranchName(localTask)); + assertEquals(2, localTask.getBranches().size()); + assertEquals(1, defaultTask.getBranches().size()); + + myTaskManager.activateTask(localTask, false); + LocalTaskImpl bar = myTaskManager.createLocalTask("bar"); + LocalTask barTask = myTaskManager.activateTask(bar, false); + myTaskManager.createBranch(localTask, defaultTask, myTaskManager.suggestBranchName(barTask)); + assertEquals(1, defaultTask.getBranches().size()); + } + + public void testCleanupRemovedBranch() { + GitRepository repository = initRepository("foo"); + LocalTask defaultTask = myTaskManager.getActiveTask(); + assertNotNull(defaultTask); + assertEquals(0, defaultTask.getBranches().size()); + LocalTaskImpl foo = myTaskManager.createLocalTask("foo"); + LocalTask localTask = myTaskManager.activateTask(foo, false); + myTaskManager.createBranch(localTask, defaultTask, myTaskManager.suggestBranchName(localTask)); + assertEquals(2, localTask.getBranches().size()); + assertEquals(1, defaultTask.getBranches().size()); + + // let's add non-existing branch + BranchInfo info = new BranchInfo(); + info.name = "non-existing"; + info.repository = defaultTask.getBranches().get(0).repository; + defaultTask.addBranch(info); + + assertEquals("foo", repository.getCurrentBranch().getName()); + myTaskManager.activateTask(defaultTask, false); + assertEquals("master", repository.getCurrentBranch().getName()); + // do not re-create "non-existing" + assertEquals(2, repository.getBranches().getLocalBranches().size()); + } + private List initRepositories(String... names) { return ContainerUtil.map(names, new Function() { @Override diff --git a/plugins/testng/testSources/com/theoryinpractice/testng/referenceContributor/TestNGDataProviderTest.java b/plugins/testng/testSources/com/theoryinpractice/testng/referenceContributor/TestNGDataProviderTest.java index 536fda278456..6aba9d549b07 100644 --- a/plugins/testng/testSources/com/theoryinpractice/testng/referenceContributor/TestNGDataProviderTest.java +++ b/plugins/testng/testSources/com/theoryinpractice/testng/referenceContributor/TestNGDataProviderTest.java @@ -62,10 +62,10 @@ public class TestNGDataProviderTest extends LightCodeInsightFixtureTestCase { @DataProvider public Object[][] data() { return new Object[][]{ - new Object[]{"private", ArrayUtil.EMPTY_STRING_ARRAY}, - new Object[]{"privateinsuper", ArrayUtil.EMPTY_STRING_ARRAY}, - new Object[]{"protectedinsuper", new String[]{"data"}}, - new Object[]{"privateindataproviderclass", ArrayUtil.EMPTY_STRING_ARRAY}, + new Object[]{"private", new String[]{"data"}}, + new Object[]{"privateinsuper", ArrayUtil.EMPTY_STRING_ARRAY}, + new Object[]{"protectedinsuper", new String[]{"data"}}, + new Object[]{"privateindataproviderclass", new String[]{"data"}}, }; } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/GridBuildUtil.java b/plugins/ui-designer/src/com/intellij/uiDesigner/GridBuildUtil.java index 2d710bf3296a..3b082802ec4b 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/GridBuildUtil.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/GridBuildUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -320,7 +320,7 @@ public class GridBuildUtil { } - return new Pair( + return Pair.create( new Integer(Util.eliminate(y, rowSpans, null)), new Integer(Util.eliminate(x, colSpans, null)) ); diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/StringDescriptorManager.java b/plugins/ui-designer/src/com/intellij/uiDesigner/StringDescriptorManager.java index 389d0a617172..0956d73cac29 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/StringDescriptorManager.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/StringDescriptorManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -90,7 +90,7 @@ public class StringDescriptorManager { public IProperty resolveToProperty(@NotNull StringDescriptor descriptor, @Nullable Locale locale) { String propFileName = descriptor.getDottedBundleName(); - Pair cacheKey = new Pair(locale, propFileName); + Pair cacheKey = Pair.create(locale, propFileName); PropertiesFile propertiesFile; synchronized (myPropertiesFileCache) { propertiesFile = myPropertiesFileCache.get(cacheKey); diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/KeyChooserDialog.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/KeyChooserDialog.java index 5e2abf8519e3..414f62c9b58a 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/KeyChooserDialog.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/KeyChooserDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -19,7 +19,6 @@ import com.intellij.ide.DataManager; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -157,7 +156,7 @@ public final class KeyChooserDialog extends DialogWrapper{ final String key = property.getUnescapedKey(); final String value = property.getValue(); if (key != null) { - myPairs.add(new Pair(key, value != null? value : NULL)); + myPairs.add(Pair.create(key, value != null ? value : NULL)); } } Collections.sort(myPairs, new MyPairComparator()); diff --git a/python/helpers/pydev/_completer.py b/python/helpers/pydev/_pydev_completer.py similarity index 71% rename from python/helpers/pydev/_completer.py rename to python/helpers/pydev/_pydev_completer.py index 4d34fec2d1ae..93e0bfa3969f 100644 --- a/python/helpers/pydev/_completer.py +++ b/python/helpers/pydev/_pydev_completer.py @@ -1,3 +1,4 @@ +import pydevconsole try: import __builtin__ @@ -13,13 +14,14 @@ except NameError: # version < 2.3 -- didn't have the True/False builtins try: import java.lang #@UnusedImport - import jyimportsTipper #as importsTipper #changed to be backward compatible with 1.5 - importsTipper = jyimportsTipper + import _pydev_jy_imports_tipper #as _pydev_imports_tipper #changed to be backward compatible with 1.5 + _pydev_imports_tipper = _pydev_jy_imports_tipper except ImportError: IS_JYTHON = False - import importsTipper + import _pydev_imports_tipper -dir2 = importsTipper.GenerateImportsTipForModule +import pydevd_vars +dir2 = _pydev_imports_tipper.GenerateImportsTipForModule #======================================================================================================================= @@ -153,3 +155,43 @@ class Completer: return words +#======================================================================================================================= +# GenerateCompletionsAsXML +#======================================================================================================================= +def GenerateCompletionsAsXML(frame, act_tok): + if frame is None: + return '' + + #Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329 + #(Names not resolved in generator expression in method) + #See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html + updated_globals = {} + updated_globals.update(frame.f_globals) + updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals + + if pydevconsole.IPYTHON: + completions = pydevconsole.get_completions(act_tok, act_tok, updated_globals, frame.f_locals) + else: + completer = Completer(updated_globals, None) + #list(tuple(name, descr, parameters, type)) + completions = completer.complete(act_tok) + + valid_xml = pydevd_vars.makeValidXmlValue + quote = pydevd_vars.quote + + msg = [""] + + for comp in completions: + msg.append('') + msg.append("") + + return ''.join(msg) + diff --git a/python/helpers/pydev/_pydev_execfile.py b/python/helpers/pydev/_pydev_execfile.py index 1d8e141371de..d60d7ed94bb0 100644 --- a/python/helpers/pydev/_pydev_execfile.py +++ b/python/helpers/pydev/_pydev_execfile.py @@ -1,7 +1,8 @@ #We must redefine it in Py3k if it's not already there def execfile(file, glob=None, loc=None): if glob is None: - glob = globals() + import sys + glob = sys._getframe().f_back.f_globals if loc is None: loc = glob stream = open(file, 'rb') diff --git a/python/helpers/pydev/_pydev_filesystem_encoding.py b/python/helpers/pydev/_pydev_filesystem_encoding.py new file mode 100644 index 000000000000..670625fe0c0f --- /dev/null +++ b/python/helpers/pydev/_pydev_filesystem_encoding.py @@ -0,0 +1,39 @@ +def __getfilesystemencoding(): + ''' + Note: there's a copy of this method in interpreterInfo.py + ''' + import sys + try: + ret = sys.getfilesystemencoding() + if not ret: + raise RuntimeError('Unable to get encoding.') + return ret + except: + try: + #Handle Jython + from java.lang import System + env = System.getProperty("os.name").lower() + if env.find('win') != -1: + return 'ISO-8859-1' #mbcs does not work on Jython, so, use a (hopefully) suitable replacement + return 'utf-8' + except: + pass + + #Only available from 2.3 onwards. + if sys.platform == 'win32': + return 'mbcs' + return 'utf-8' + +def getfilesystemencoding(): + try: + ret = __getfilesystemencoding() + + #Check if the encoding is actually there to be used! + if hasattr('', 'encode'): + ''.encode(ret) + if hasattr('', 'decode'): + ''.decode(ret) + + return ret + except: + return 'utf-8' diff --git a/python/helpers/pydev/importsTipper.py b/python/helpers/pydev/_pydev_imports_tipper.py similarity index 99% rename from python/helpers/pydev/importsTipper.py rename to python/helpers/pydev/_pydev_imports_tipper.py index 97fc76a91b3e..e4b3b863f210 100644 --- a/python/helpers/pydev/importsTipper.py +++ b/python/helpers/pydev/_pydev_imports_tipper.py @@ -2,7 +2,7 @@ import os.path import inspect import sys -from _tipper_common import DoFind +from _pydev_tipper_common import DoFind #completion types. @@ -151,7 +151,9 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr, dirComps = dir(obj_to_complete) if hasattr(obj_to_complete, '__dict__'): dirComps.append('__dict__') - + if hasattr(obj_to_complete, '__class__'): + dirComps.append('__class__') + getCompleteInfo = True if len(dirComps) > 1000: diff --git a/python/helpers/pydev/jyimportsTipper.py b/python/helpers/pydev/_pydev_jy_imports_tipper.py similarity index 99% rename from python/helpers/pydev/jyimportsTipper.py rename to python/helpers/pydev/_pydev_jy_imports_tipper.py index cd8da2614357..43e4d0b67140 100644 --- a/python/helpers/pydev/jyimportsTipper.py +++ b/python/helpers/pydev/_pydev_jy_imports_tipper.py @@ -4,7 +4,7 @@ from java.lang import StringBuffer #@UnresolvedImport from java.lang import String #@UnresolvedImport import java.lang #@UnresolvedImport import sys -from _tipper_common import DoFind +from _pydev_tipper_common import DoFind try: diff --git a/python/helpers/pydev/_tipper_common.py b/python/helpers/pydev/_pydev_tipper_common.py similarity index 100% rename from python/helpers/pydev/_tipper_common.py rename to python/helpers/pydev/_pydev_tipper_common.py diff --git a/python/helpers/pydev/_pydev_xmlrpc_hook.py b/python/helpers/pydev/_pydev_xmlrpc_hook.py new file mode 100644 index 000000000000..22d445a0c867 --- /dev/null +++ b/python/helpers/pydev/_pydev_xmlrpc_hook.py @@ -0,0 +1,74 @@ +from pydev_imports import SimpleXMLRPCServer +from pydev_ipython.inputhook import get_inputhook, set_return_control_callback +import select +import sys + +select_fn = select.select +if sys.platform.startswith('java'): + select_fn = select.cpython_compatible_select + +class InputHookedXMLRPCServer(SimpleXMLRPCServer): + ''' An XML-RPC Server that can run hooks while polling for new requests. + + This code was designed to work with IPython's inputhook methods and + to allow Debug framework to have a place to run commands during idle + too. + ''' + def __init__(self, *args, **kwargs): + SimpleXMLRPCServer.__init__(self, *args, **kwargs) + # Tell the inputhook mechanisms when control should be returned + set_return_control_callback(self.return_control) + self.debug_hook = None + self.return_control_osc = False + + def return_control(self): + ''' A function that the inputhooks can call (via inputhook.stdin_ready()) to find + out if they should cede control and return ''' + if self.debug_hook: + # Some of the input hooks check return control without doing + # a single operation, so we don't return True on every + # call when the debug hook is in place to allow the GUI to run + # XXX: Eventually the inputhook code will have diverged enough + # from the IPython source that it will be worthwhile rewriting + # it rather than pretending to maintain the old API + self.return_control_osc = not self.return_control_osc + if self.return_control_osc: + return True + r, unused_w, unused_e = select_fn([self], [], [], 0) + return bool(r) + + def setDebugHook(self, debug_hook): + self.debug_hook = debug_hook + + def serve_forever(self): + ''' Serve forever, running defined hooks regularly and when idle. + Does not support shutdown ''' + inputhook = get_inputhook() + while True: + # Block for default 1/2 second when no GUI is in progress + timeout = 0.5 + if self.debug_hook: + self.debug_hook() + timeout = 0.1 + if inputhook: + try: + inputhook() + # The GUI has given us an opportunity to try receiving, normally + # this happens because the input hook has already polled the + # server has knows something is waiting + timeout = 0.020 + except: + inputhook = None + r, unused_w, unused_e = select_fn([self], [], [], timeout) + if self in r: + try: + self._handle_request_noblock() + except AttributeError: + # Older libraries do not support _handle_request_noblock, so fall + # back to the handle_request version + self.handle_request() + # Running the request may have changed the inputhook in use + inputhook = get_inputhook() + + def shutdown(self): + raise NotImplementedError('InputHookedXMLRPCServer does not support shutdown') diff --git a/python/helpers/pydev/interpreterInfo.py b/python/helpers/pydev/interpreterInfo.py index f6056d0de60e..103253e62600 100644 --- a/python/helpers/pydev/interpreterInfo.py +++ b/python/helpers/pydev/interpreterInfo.py @@ -6,138 +6,247 @@ what is what: sys.builtin_module_names: contains the builtin modules embeeded in python (rigth now, we specify all manually). sys.prefix: A string giving the site-specific directory prefix where the platform independent Python files are installed -format is something as +format is something as EXECUTABLE:python.exe|libs@compiled_dlls$builtin_mods all internal are separated by | ''' import sys -import os - try: - #Just check if False and True are defined (depends on version, not whether it's jython/python) + import os.path + def fullyNormalizePath(path): + '''fixes the path so that the format of the path really reflects the directories in the system + ''' + return os.path.normpath(path) + join = os.path.join +except: # ImportError or AttributeError. + # See: http://stackoverflow.com/questions/10254353/error-while-installing-jython-for-pydev + def fullyNormalizePath(path): + '''fixes the path so that the format of the path really reflects the directories in the system + ''' + return path + + def join(a, b): + if a.endswith('/') or a.endswith('\\'): + return a + b + return a + '/' + b + + +IS_PYTHON_3K = 0 + +try: + if sys.version_info[0] == 3: + IS_PYTHON_3K = 1 +except: + # That's OK, not all versions of python have sys.version_info + pass + +try: + # Just check if False and True are defined (depends on version, not whether it's jython/python) False True except: - exec ('True, False = 1,0') #An exec is used so that python 3k does not give a syntax error - -import pydevd_constants - -if pydevd_constants.USE_LIB_COPY: - import _pydev_time as time -else: - import time + exec ('True, False = 1,0') # An exec is used so that python 3k does not give a syntax error if sys.platform == "cygwin": - + try: - import ctypes #use from the system if available + import ctypes # use from the system if available except ImportError: - sys.path.append(os.path.join(sys.path[0], 'ThirdParty/wrapped_for_pydev')) + sys.path.append(join(sys.path[0], 'third_party/wrapped_for_pydev')) import ctypes - + def nativePath(path): MAX_PATH = 512 # On cygwin NT, its 260 lately, but just need BIG ENOUGH buffer '''Get the native form of the path, like c:\\Foo for /cygdrive/c/Foo''' retval = ctypes.create_string_buffer(MAX_PATH) path = fullyNormalizePath(path) - ctypes.cdll.cygwin1.cygwin_conv_to_win32_path(path, retval) #@UndefinedVariable - return retval.value + CCP_POSIX_TO_WIN_A = 0 + ctypes.cdll.cygwin1.cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, retval, MAX_PATH) + return retval.value + else: def nativePath(path): return fullyNormalizePath(path) - -def fullyNormalizePath(path): - '''fixes the path so that the format of the path really reflects the directories in the system + + + +def __getfilesystemencoding(): ''' - return os.path.normpath(path) + Note: there's a copy of this method in _pydev_filesystem_encoding.py + ''' + try: + ret = sys.getfilesystemencoding() + if not ret: + raise RuntimeError('Unable to get encoding.') + return ret + except: + try: + # Handle Jython + from java.lang import System + env = System.getProperty("os.name").lower() + if env.find('win') != -1: + return 'ISO-8859-1' # mbcs does not work on Jython, so, use a (hopefully) suitable replacement + return 'utf-8' + except: + pass + + # Only available from 2.3 onwards. + if sys.platform == 'win32': + return 'mbcs' + return 'utf-8' + +def getfilesystemencoding(): + try: + ret = __getfilesystemencoding() + + #Check if the encoding is actually there to be used! + if hasattr('', 'encode'): + ''.encode(ret) + if hasattr('', 'decode'): + ''.decode(ret) + + return ret + except: + return 'utf-8' + +file_system_encoding = getfilesystemencoding() + +def tounicode(s): + if hasattr(s, 'decode'): + # Depending on the platform variant we may have decode on string or not. + return s.decode(file_system_encoding) + return s + +def toutf8(s): + if hasattr(s, 'encode'): + return s.encode('utf-8') + return s + +def toasciimxl(s): + # output for xml without a declared encoding + + # As the output is xml, we have to encode chars (< and > are ok as they're not accepted in the filesystem name -- + # if it was allowed, we'd have to do things more selectively so that < and > don't get wrongly replaced). + s = s.replace("&", "&") + + try: + ret = s.encode('ascii', 'xmlcharrefreplace') + except: + # use workaround + ret = '' + for c in s: + try: + ret += c.encode('ascii') + except: + try: + # Python 2: unicode is a valid identifier + ret += unicode("&#%d;") % ord(c) + except: + # Python 3: a string is already unicode, so, just doing it directly should work. + ret += "&#%d;" % ord(c) + return ret if __name__ == '__main__': try: - #just give some time to get the reading threads attached (just in case) + # just give some time to get the reading threads attached (just in case) + import time time.sleep(0.1) except: pass - + try: executable = nativePath(sys.executable) except: executable = sys.executable - + if sys.platform == "cygwin" and not executable.endswith('.exe'): executable += '.exe' - + try: - s = 'Version%s.%s' % (sys.version_info[0], sys.version_info[1]) + major = str(sys.version_info[0]) + minor = str(sys.version_info[1]) except AttributeError: - #older versions of python don't have version_info + # older versions of python don't have version_info import string s = string.split(sys.version, ' ')[0] s = string.split(s, '.') major = s[0] minor = s[1] - s = 'Version%s.%s' % (major, minor) - - sys.stdout.write('%s\n' % (s,)) - - sys.stdout.write('EXECUTABLE:%s|\n' % executable) - - #this is the new implementation to get the system folders - #(still need to check if it works in linux) - #(previously, we were getting the executable dir, but that is not always correct...) - prefix = nativePath(sys.prefix) - #print_ 'prefix is', prefix - + + s = tounicode('%s.%s') % (tounicode(major), tounicode(minor)) + + contents = [tounicode('')] + contents.append(tounicode('%s') % (tounicode(s),)) + + contents.append(tounicode('%s') % tounicode(executable)) + + # this is the new implementation to get the system folders + # (still need to check if it works in linux) + # (previously, we were getting the executable dir, but that is not always correct...) + prefix = tounicode(nativePath(sys.prefix)) + # print_ 'prefix is', prefix + result = [] - + path_used = sys.path try: - path_used = path_used[:] #Use a copy. + path_used = path_used[1:] # Use a copy (and don't include the directory of this script as a path.) except: - pass #just ignore it... - + pass # just ignore it... + for p in path_used: - p = nativePath(p) - + p = tounicode(nativePath(p)) + try: - import string #to be compatible with older versions - if string.find(p, prefix) == 0: #was startswith + import string # to be compatible with older versions + if string.find(p, prefix) == 0: # was startswith result.append((p, True)) else: result.append((p, False)) except (ImportError, AttributeError): - #python 3k also does not have it - #jython may not have it (depending on how are things configured) - if p.startswith(prefix): #was startswith + # python 3k also does not have it + # jython may not have it (depending on how are things configured) + if p.startswith(prefix): # was startswith result.append((p, True)) else: result.append((p, False)) - + for p, b in result: if b: - sys.stdout.write('|%s%s\n' % (p, 'INS_PATH')) + contents.append(tounicode('%s') % (p,)) else: - sys.stdout.write('|%s%s\n' % (p, 'OUT_PATH')) - - sys.stdout.write('@\n') #no compiled libs - sys.stdout.write('$\n') #the forced libs - + contents.append(tounicode('%s') % (p,)) + + # no compiled libs + # nor forced libs + for builtinMod in sys.builtin_module_names: - sys.stdout.write('|%s\n' % builtinMod) - - + contents.append(tounicode('%s') % tounicode(builtinMod)) + + + contents.append(tounicode('')) + unic = tounicode('\n').join(contents) + inasciixml = toasciimxl(unic) + if IS_PYTHON_3K: + # This is the 'official' way of writing binary output in Py3K (see: http://bugs.python.org/issue4571) + sys.stdout.buffer.write(inasciixml) + else: + sys.stdout.write(inasciixml) + try: sys.stdout.flush() sys.stderr.flush() - #and give some time to let it read things (just in case) + # and give some time to let it read things (just in case) + import time time.sleep(0.1) except: pass - + raise RuntimeError('Ok, this is so that it shows the output (ugly hack for some platforms, so that it releases the output).') diff --git a/python/helpers/pydev/pycompletion.py b/python/helpers/pydev/pycompletion.py index 93dd2e85598c..e706d5410f3d 100644 --- a/python/helpers/pydev/pycompletion.py +++ b/python/helpers/pydev/pycompletion.py @@ -2,10 +2,12 @@ ''' @author Radim Kubacki ''' -import importsTipper +import __builtin__ +import _pydev_imports_tipper import traceback import StringIO import sys +import time import urllib import pycompletionserver @@ -17,7 +19,7 @@ def GetImports(module_name): try: processor = pycompletionserver.Processor() data = urllib.unquote_plus(module_name) - def_file, completions = importsTipper.GenerateTip(data) + def_file, completions = _pydev_imports_tipper.GenerateTip(data) return processor.formatCompletionMessage(def_file, completions) except: s = StringIO.StringIO() diff --git a/python/helpers/pydev/pycompletionserver.py b/python/helpers/pydev/pycompletionserver.py index fc4332f75f0d..2fdd53903fb1 100644 --- a/python/helpers/pydev/pycompletionserver.py +++ b/python/helpers/pydev/pycompletionserver.py @@ -1,20 +1,20 @@ #@PydevCodeAnalysisIgnore ''' -@author Fabio Zadrozny +@author Fabio Zadrozny ''' IS_PYTHON3K = 0 try: import __builtin__ except ImportError: - import builtins as __builtin__ # Python 3.0 + import builtins as __builtin__ # Python 3.0 IS_PYTHON3K = 1 try: - True - False -except NameError: - #If it's not defined, let's define it now. - setattr(__builtin__, 'True', 1) #Python 3.0 does not accept __builtin__.True = 1 in its syntax + True + False +except NameError: + # If it's not defined, let's define it now. + setattr(__builtin__, 'True', 1) # Python 3.0 does not accept __builtin__.True = 1 in its syntax setattr(__builtin__, 'False', 0) import pydevd_constants @@ -23,18 +23,18 @@ try: from java.lang import Thread IS_JYTHON = True SERVER_NAME = 'jycompletionserver' - import jyimportsTipper #as importsTipper #changed to be backward compatible with 1.5 - importsTipper = jyimportsTipper + import _pydev_jy_imports_tipper # as _pydev_imports_tipper #changed to be backward compatible with 1.5 + _pydev_imports_tipper = _pydev_jy_imports_tipper except ImportError: - #it is python + # it is python IS_JYTHON = False SERVER_NAME = 'pycompletionserver' if pydevd_constants.USE_LIB_COPY: from _pydev_threading import Thread else: from threading import Thread - import importsTipper + import _pydev_imports_tipper if pydevd_constants.USE_LIB_COPY: @@ -44,20 +44,20 @@ else: import sys if sys.platform == "darwin": - #See: https://sourceforge.net/projects/pydev/forums/forum/293649/topic/3454227 + # See: https://sourceforge.net/projects/pydev/forums/forum/293649/topic/3454227 try: - import _CF #Don't fail if it doesn't work. + import _CF # Don't fail if it doesn't work -- do it because it must be loaded on the main thread! @UnresolvedImport @UnusedImport except: pass -#initial sys.path +# initial sys.path _sys_path = [] for p in sys.path: - #changed to be compatible with 1.5 + # changed to be compatible with 1.5 _sys_path.append(p) -#initial sys.modules +# initial sys.modules _sys_modules = {} for name, mod in sys.modules.items(): _sys_modules[name] = mod @@ -104,12 +104,10 @@ MSG_INVALID_REQUEST = '@@INVALID_REQUEST' MSG_JYTHON_INVALID_REQUEST = '@@JYTHON_INVALID_REQUEST' MSG_CHANGE_DIR = '@@CHANGE_DIR:' MSG_OK = '@@MSG_OK_END@@' -MSG_BIKE = '@@BIKE' -MSG_PROCESSING = '@@PROCESSING_END@@' -MSG_PROCESSING_PROGRESS = '@@PROCESSING:%sEND@@' MSG_IMPORTS = '@@IMPORTS:' MSG_PYTHONPATH = '@@PYTHONPATH_END@@' MSG_CHANGE_PYTHONPATH = '@@CHANGE_PYTHONPATH:' +MSG_JEDI = '@@MSG_JEDI:' MSG_SEARCH = '@@SEARCH' BUFFER_SIZE = 1024 @@ -118,74 +116,46 @@ BUFFER_SIZE = 1024 currDirModule = None -def CompleteFromDir(dir): +def CompleteFromDir(directory): ''' - This is necessary so that we get the imports from the same dir where the file + This is necessary so that we get the imports from the same directory where the file we are completing is located. ''' global currDirModule if currDirModule is not None: - del sys.path[currDirModule] + if len(sys.path) > 0 and sys.path[0] == currDirModule: + del sys.path[0] - sys.path.insert(0, dir) + currDirModule = directory + sys.path.insert(0, directory) def ChangePythonPath(pythonpath): '''Changes the pythonpath (clears all the previous pythonpath) - + @param pythonpath: string with paths separated by | ''' - + split = pythonpath.split('|') sys.path = [] for path in split: path = path.strip() if len(path) > 0: sys.path.append(path) - -class KeepAliveThread(Thread): - def __init__(self, socket): - Thread.__init__(self) - self.socket = socket - self.processMsgFunc = None - self.lastMsg = None - - def run(self): - time.sleep(0.1) - - def send(s, msg): - if IS_PYTHON3K: - s.send(bytearray(msg, 'utf-8')) - else: - s.send(msg) - - while self.lastMsg == None: - - if self.processMsgFunc != None: - s = MSG_PROCESSING_PROGRESS % quote_plus(self.processMsgFunc()) - sent = send(self.socket, s) - else: - sent = send(self.socket, MSG_PROCESSING) - if sent == 0: - sys.exit(0) #connection broken - time.sleep(0.1) - sent = send(self.socket, self.lastMsg) - if sent == 0: - sys.exit(0) #connection broken - + class Processor: def __init__(self): - # nothing to do - return - + # nothing to do + return + def removeInvalidChars(self, msg): try: msg = str(msg) except UnicodeDecodeError: pass - + if msg: try: return quote_plus(msg) @@ -193,7 +163,7 @@ class Processor: sys.stdout.write('error making quote plus in %s\n' % (msg,)) raise return ' ' - + def formatCompletionMessage(self, defFile, completionsList): ''' Format the completions suggestions in the following format: @@ -203,41 +173,43 @@ class Processor: compMsg.append('%s' % defFile) for tup in completionsList: compMsg.append(',') - + compMsg.append('(') - compMsg.append(str(self.removeInvalidChars(tup[0]))) #token + compMsg.append(str(self.removeInvalidChars(tup[0]))) # token compMsg.append(',') - compMsg.append(self.removeInvalidChars(tup[1])) #description + compMsg.append(self.removeInvalidChars(tup[1])) # description if(len(tup) > 2): compMsg.append(',') - compMsg.append(self.removeInvalidChars(tup[2])) #args - only if function. - + compMsg.append(self.removeInvalidChars(tup[2])) # args - only if function. + if(len(tup) > 3): compMsg.append(',') - compMsg.append(self.removeInvalidChars(tup[3])) #TYPE - + compMsg.append(self.removeInvalidChars(tup[3])) # TYPE + compMsg.append(')') - + return '%s(%s)%s' % (MSG_COMPLETIONS, ''.join(compMsg), MSG_END) - + class T(Thread): - def __init__(self, thisP, serverP): + def __init__(self, port): Thread.__init__(self) - self.thisPort = thisP - self.serverPort = serverP - self.socket = None #socket to send messages. + self.ended = False + self.port = port + self.socket = None # socket to send messages. self.processor = Processor() def connectToServer(self): + import socket + self.socket = s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: - s.connect((HOST, self.serverPort)) + s.connect((HOST, self.port)) except: - sys.stderr.write('Error on connectToServer with parameters: host: %s port: %s\n' % (HOST, self.serverPort)) + sys.stderr.write('Error on connectToServer with parameters: host: %s port: %s\n' % (HOST, self.port)) raise def getCompletionsMessage(self, defFile, completionsList): @@ -245,7 +217,7 @@ class T(Thread): get message with completions. ''' return self.processor.formatCompletionMessage(defFile, completionsList) - + def getTokenAndData(self, data): ''' When we receive this, we have 'token):data' @@ -256,129 +228,168 @@ class T(Thread): token = token + c else: break; - + return token, data.lstrip(token + '):') - + def emulated_sendall(self, msg): + MSGLEN = 1024 * 20 + + totalsent = 0 + while totalsent < MSGLEN: + sent = self.socket.send(msg[totalsent:]) + if sent == 0: + return + totalsent = totalsent + sent + + + def send(self, msg): + if not hasattr(self.socket, 'sendall'): + #Older versions (jython 2.1) + self.emulated_sendall(msg) + else: + if IS_PYTHON3K: + self.socket.sendall(bytearray(msg, 'utf-8')) + else: + self.socket.sendall(msg) + + def run(self): # Echo server program try: import _pydev_log log = _pydev_log.Log() - - dbg(SERVER_NAME + ' creating socket' , INFO1) - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.bind((HOST, self.thisPort)) - except: - sys.stderr.write('Error connecting with parameters: host: %s port: %s\n' % (HOST, self.serverPort)) - raise - s.listen(1) #socket to receive messages. - - - #we stay here until we are connected. - #we only accept 1 client. - #the exit message for the server is @@KILL_SERVER_END@@ - dbg(SERVER_NAME + ' waiting for connection' , INFO1) - conn, addr = s.accept() - time.sleep(0.5) #wait a little before connecting to JAVA server - - dbg(SERVER_NAME + ' waiting to java client' , INFO1) - #after being connected, create a socket as a client. + + dbg(SERVER_NAME + ' connecting to java server on %s (%s)' % (HOST, self.port) , INFO1) + # after being connected, create a socket as a client. self.connectToServer() - - dbg(SERVER_NAME + ' Connected by ' + str(addr), INFO1) - - - while 1: + + dbg(SERVER_NAME + ' Connected to java server', INFO1) + + + while not self.ended: data = '' - returnMsg = '' - keepAliveThread = KeepAliveThread(self.socket) - + while data.find(MSG_END) == -1: - received = conn.recv(BUFFER_SIZE) + received = self.socket.recv(BUFFER_SIZE) if len(received) == 0: - sys.exit(0) #ok, connection ended + sys.exit(0) # ok, connection ended if IS_PYTHON3K: data = data + received.decode('utf-8') else: data = data + received - + try: try: if data.find(MSG_KILL_SERVER) != -1: dbg(SERVER_NAME + ' kill message received', INFO1) - #break if we received kill message. + # break if we received kill message. self.ended = True sys.exit(0) - + dbg(SERVER_NAME + ' starting keep alive thread', INFO2) - keepAliveThread.start() - + if data.find(MSG_PYTHONPATH) != -1: comps = [] for p in _sys_path: comps.append((p, ' ')) - returnMsg = self.getCompletionsMessage(None, comps) - + self.send(self.getCompletionsMessage(None, comps)) + else: data = data[:data.rfind(MSG_END)] - + if data.startswith(MSG_IMPORTS): - data = data.replace(MSG_IMPORTS, '') + data = data[len(MSG_IMPORTS):] data = unquote_plus(data) - defFile, comps = importsTipper.GenerateTip(data, log) - returnMsg = self.getCompletionsMessage(defFile, comps) - + defFile, comps = _pydev_imports_tipper.GenerateTip(data, log) + self.send(self.getCompletionsMessage(defFile, comps)) + elif data.startswith(MSG_CHANGE_PYTHONPATH): - data = data.replace(MSG_CHANGE_PYTHONPATH, '') + data = data[len(MSG_CHANGE_PYTHONPATH):] data = unquote_plus(data) ChangePythonPath(data) - returnMsg = MSG_OK - - elif data.startswith(MSG_SEARCH): - data = data.replace(MSG_SEARCH, '') + self.send(MSG_OK) + + elif data.startswith(MSG_JEDI): + data = data[len(MSG_JEDI):] data = unquote_plus(data) - (f, line, col), foundAs = importsTipper.Search(data) - returnMsg = self.getCompletionsMessage(f, [(line, col, foundAs)]) - + line, column, encoding, path, source = data.split('|', 4) + try: + import jedi # @UnresolvedImport + except: + self.send(self.getCompletionsMessage(None, [('Error on import jedi', 'Error importing jedi', '')])) + else: + script = jedi.Script( + # Line +1 because it expects lines 1-based (and col 0-based) + source=source, + line=int(line) + 1, + column=int(column), + source_encoding=encoding, + path=path, + ) + lst = [] + for completion in script.completions(): + t = completion.type + if t == 'class': + t = '1' + + elif t == 'function': + t = '2' + + elif t == 'import': + t = '0' + + elif t == 'keyword': + continue # Keywords are already handled in PyDev + + elif t == 'statement': + t = '3' + + else: + t = '-1' + + # gen list(tuple(name, doc, args, type)) + lst.append((completion.name, '', '', t)) + self.send(self.getCompletionsMessage('empty', lst)) + + elif data.startswith(MSG_SEARCH): + data = data[len(MSG_SEARCH):] + data = unquote_plus(data) + (f, line, col), foundAs = _pydev_imports_tipper.Search(data) + self.send(self.getCompletionsMessage(f, [(line, col, foundAs)])) + elif data.startswith(MSG_CHANGE_DIR): - data = data.replace(MSG_CHANGE_DIR, '') + data = data[len(MSG_CHANGE_DIR):] data = unquote_plus(data) CompleteFromDir(data) - returnMsg = MSG_OK - - elif data.startswith(MSG_BIKE): - returnMsg = MSG_INVALID_REQUEST #No longer supported. - + self.send(MSG_OK) + else: - returnMsg = MSG_INVALID_REQUEST + self.send(MSG_INVALID_REQUEST) except SystemExit: - returnMsg = self.getCompletionsMessage(None, [('Exit:', 'SystemExit', '')]) - keepAliveThread.lastMsg = returnMsg + self.send(self.getCompletionsMessage(None, [('Exit:', 'SystemExit', '')])) raise + except: dbg(SERVER_NAME + ' exception occurred', ERROR) s = StringIO.StringIO() traceback.print_exc(file=s) - + err = s.getvalue() dbg(SERVER_NAME + ' received error: ' + str(err), ERROR) - returnMsg = self.getCompletionsMessage(None, [('ERROR:', '%s\nLog:%s' % (err, log.GetContents()), '')]) - - + self.send(self.getCompletionsMessage(None, [('ERROR:', '%s\nLog:%s' % (err, log.GetContents()), '')])) + + finally: log.Clear() - keepAliveThread.lastMsg = returnMsg - - conn.close() + + self.socket.close() self.ended = True - sys.exit(0) #connection broken - - + sys.exit(0) # connection broken + + except SystemExit: raise - #No need to log SystemExit error + # No need to log SystemExit error except: s = StringIO.StringIO() exc_info = sys.exc_info() @@ -388,12 +399,13 @@ class T(Thread): dbg(SERVER_NAME + ' received error: ' + str(err), ERROR) raise + + if __name__ == '__main__': - thisPort = int(sys.argv[1]) #this is from where we want to receive messages. - serverPort = int(sys.argv[2])#this is where we want to write messages. - - t = T(thisPort, serverPort) + port = int(sys.argv[1]) # this is from where we want to receive messages. + + t = T(port) dbg(SERVER_NAME + ' will start', INFO1) t.start() time.sleep(5) diff --git a/python/helpers/pydev/pydev_app_engine_debug_startup.py b/python/helpers/pydev/pydev_app_engine_debug_startup.py new file mode 100644 index 000000000000..464f0ddf3464 --- /dev/null +++ b/python/helpers/pydev/pydev_app_engine_debug_startup.py @@ -0,0 +1,21 @@ +if False: + config = None + + +# See: https://docs.google.com/document/d/1CCSaRiIWCLgbD3OwmuKsRoHHDfBffbROWyVWWL0ZXN4/edit +if ':' not in config.version_id: + # The default server version_id does not contain ':' + import json + import os + import sys + + startup = config.python_config.startup_args + if not startup: + raise AssertionError('Expected --python_startup_args to be passed from the pydev debugger.') + + setup = json.loads(startup) + pydevd_path = setup['pydevd'] + sys.path.append(os.path.dirname(pydevd_path)) + + import pydevd + pydevd.settrace(setup['client'], port=setup['port'], suspend=False, trace_only_current_thread=False) diff --git a/python/helpers/pydev/pydev_console_utils.py b/python/helpers/pydev/pydev_console_utils.py index 54a85850c48f..b76e6c662a16 100644 --- a/python/helpers/pydev/pydev_console_utils.py +++ b/python/helpers/pydev/pydev_console_utils.py @@ -283,9 +283,9 @@ class BaseInterpreterInterface: if doc is not None: return doc - import jyimportsTipper + import _pydev_jy_imports_tipper - is_method, infos = jyimportsTipper.ismethod(obj) + is_method, infos = _pydev_jy_imports_tipper.ismethod(obj) ret = '' if is_method: for info in infos: diff --git a/python/helpers/pydev/pydev_imports.py b/python/helpers/pydev/pydev_imports.py index 9dce8c4ec9e4..06858750c97d 100644 --- a/python/helpers/pydev/pydev_imports.py +++ b/python/helpers/pydev/pydev_imports.py @@ -33,4 +33,61 @@ try: else: import Queue as _queue except: - import queue as _queue + import queue as _queue #@UnresolvedImport + +try: + from pydevd_exec import Exec +except: + from pydevd_exec2 import Exec + +try: + from urllib import quote +except: + from urllib.parse import quote #@UnresolvedImport + + +import os +try: + relpath = os.path.relpath +except: + # Only there from 2.6 onwards... let's provide a replacement. + def _split_path(path): + parts = [] + loc = path + + while loc != os.curdir and loc != os.pardir: + prev = loc + loc, child = os.path.split(prev) + if loc == prev: + break + + parts.append(child) + + parts.append(loc) + parts.reverse() + return parts + + def relpath(path, start=None): + if start is None: + start = os.curdir + origin = os.path.abspath(path) + start = os.path.abspath(start) + + orig_list = _split_path(os.path.normcase(origin)) + dest_list = _split_path(start) + + if orig_list[0] != os.path.normcase(dest_list[0]): + return start + + i = 0 + for start_seg, dest_seg in zip(orig_list, dest_list): + if start_seg != os.path.normcase(dest_seg): + break + i += 1 + + segments = [os.pardir] * (len(orig_list) - i) + segments += dest_list[i:] + if len(segments) == 0: + return os.curdir + else: + return os.path.join(*segments) diff --git a/python/helpers/pydev/pydev_ipython_console.py b/python/helpers/pydev/pydev_ipython_console.py index 6a8e0567644e..859157e022ad 100644 --- a/python/helpers/pydev/pydev_ipython_console.py +++ b/python/helpers/pydev/pydev_ipython_console.py @@ -82,7 +82,7 @@ class InterpreterInterface(BaseInterpreterInterface): return ret #Otherwise, use the default PyDev completer (to get nice icons) - from _completer import Completer + from _pydev_completer import Completer completer = Completer(self.getNamespace(), None) completions = completer.complete(act_tok) diff --git a/python/helpers/pydev/pydev_versioncheck.py b/python/helpers/pydev/pydev_versioncheck.py new file mode 100644 index 000000000000..70bf765f47fd --- /dev/null +++ b/python/helpers/pydev/pydev_versioncheck.py @@ -0,0 +1,16 @@ +import sys + +def versionok_for_gui(): + ''' Return True if running Python is suitable for GUI Event Integration and deeper IPython integration ''' + # We require Python 2.6+ ... + if sys.hexversion < 0x02060000: + return False + # Or Python 3.2+ + if sys.hexversion >= 0x03000000 and sys.hexversion < 0x03020000: + return False + # Not supported under Jython nor IronPython + if sys.platform.startswith("java") or sys.platform.startswith('cli'): + return False + + return True + diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py index c0e2eea170a0..e47b3ed1099e 100644 --- a/python/helpers/pydev/pydevconsole.py +++ b/python/helpers/pydev/pydevconsole.py @@ -23,10 +23,7 @@ fix_getpass.fixGetpass() import pydevd_vars -try: - from pydevd_exec import Exec -except: - from pydevd_exec2 import Exec +from pydev_imports import Exec try: if USE_LIB_COPY: @@ -139,7 +136,7 @@ class InterpreterInterface(BaseInterpreterInterface): def getCompletions(self, text, act_tok): try: - from _completer import Completer + from _pydev_completer import Completer completer = Completer(self.namespace, None) return completer.complete(act_tok) @@ -177,7 +174,7 @@ def process_exec_queue(interpreter): if 'IPYTHONENABLE' in os.environ: - IPYTHON = bool(os.environ['IPYTHONENABLE']) + IPYTHON = os.environ['IPYTHONENABLE'] == 'True' else: IPYTHON = True @@ -316,6 +313,8 @@ def get_completions(text, token, globals, locals): return interpreterInterface.getCompletions(text, token) def get_frame(): + interpreterInterface = get_interpreter() + return interpreterInterface.getFrame() def exec_code(code, globals, locals): diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index 5cd96b1232ae..25647ce1f8ea 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -54,7 +54,7 @@ from pydevd_comm import CMD_CHANGE_VARIABLE, \ PydevdLog, \ StartClient, \ StartServer, \ - InternalSetNextStatementThread + InternalSetNextStatementThread, ReloadCodeCommand from pydevd_file_utils import NormFileToServer, GetFilenameAndBase import pydevd_file_utils @@ -65,6 +65,7 @@ import pydevd_tracing import pydevd_io import pydev_monkey from pydevd_additional_thread_info import PyDBAdditionalThreadInfo +from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit if USE_LIB_COPY: import _pydev_time as time @@ -81,50 +82,69 @@ threadingCurrentThread = threading.currentThread DONT_TRACE = { - #commonly used things from the stdlib that we don't want to trace + # commonly used things from the stdlib that we don't want to trace 'threading.py':1, 'Queue.py':1, 'queue.py':1, 'socket.py':1, + 'weakref.py':1, + 'linecache.py':1, + 'threading.py':1, #things from pydev that we don't want to trace + 'pydevd.py':1 , 'pydevd_additional_thread_info.py':1, + 'pydevd_custom_frames.py':1, 'pydevd_comm.py':1, + 'pydevd_console.py':1 , 'pydevd_constants.py':1, 'pydevd_exec.py':1, 'pydevd_exec2.py':1, 'pydevd_file_utils.py':1, 'pydevd_frame.py':1, + 'pydevd_import_class.py':1 , 'pydevd_io.py':1 , + 'pydevd_psyco_stub.py':1, + 'pydevd_reload.py':1 , 'pydevd_resolver.py':1 , + 'pydevd_stackless.py':1 , + 'pydevd_traceproperty.py':1, 'pydevd_tracing.py':1 , 'pydevd_signature.py':1, 'pydevd_utils.py':1, 'pydevd_vars.py':1, 'pydevd_vm_type.py':1, - 'pydevd.py':1 , - 'pydevd_psyco_stub.py':1, '_pydev_execfile.py':1, '_pydev_jython_execfile.py':1 - } + } if IS_PY3K: - #if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716) + # if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716) DONT_TRACE['io.py'] = 1 + # Don't trace common encodings too + DONT_TRACE['cp1252.py'] = 1 + DONT_TRACE['utf_8.py'] = 1 + connected = False bufferStdOutToServer = False bufferStdErrToServer = False remote = False -PyDBUseLocks = True +from _pydev_filesystem_encoding import getfilesystemencoding +file_system_encoding = getfilesystemencoding() def isThreadAlive(t): try: - alive = t.isAlive() + # If thread is not started yet we treat it as alive. + # It is required to debug threads started by start_new_thread in Python 3.4 + if hasattr(t, '_is_stopped'): + alive = not t._is_stopped + else: + alive = not t.__stopped except: - alive = False #Workaround for Python 3.4 http://youtrack.jetbrains.com/issue/PY-12317 + alive = t.isAlive() return alive #======================================================================================================================= @@ -134,6 +154,7 @@ class PyDBCommandThread(PyDBDaemonThread): def __init__(self, pyDb): PyDBDaemonThread.__init__(self) + self._py_db_command_thread_event = pyDb._py_db_command_thread_event self.pyDb = pyDb self.setName('pydevd.CommandThread') @@ -152,7 +173,8 @@ class PyDBCommandThread(PyDBDaemonThread): self.pyDb.processInternalCommands() except: PydevdLog(0, 'Finishing debug communication...(2)') - time.sleep(0.5) + self._py_db_command_thread_event.clear() + self._py_db_command_thread_event.wait(0.5) except: pydev_log.debug(sys.exc_info()[0]) @@ -216,44 +238,38 @@ if getattr(thread, '_original_start_new_thread', None) is None: #======================================================================================================================= class NewThreadStartup: - def __init__(self, original_func, args, kwargs): + def __init__(self, original_func): self.original_func = original_func - self.args = args - self.kwargs = kwargs - def __call__(self): + def __call__(self, *args, **kwargs): global_debugger = GetGlobalDebugger() - global_debugger.SetTrace(global_debugger.trace_dispatch) - self.original_func(*self.args, **self.kwargs) + if global_debugger is not None: + pydevd_tracing.SetTrace(global_debugger.trace_dispatch) + return self.original_func(*args, **kwargs) -thread.NewThreadStartup = NewThreadStartup #======================================================================================================================= -# pydev_start_new_thread +# ClassWithPydevStartNewThread #======================================================================================================================= -def _pydev_start_new_thread(function, args, kwargs={}): - ''' - We need to replace the original thread.start_new_thread with this function so that threads started through - it and not through the threading module are properly traced. - ''' - if USE_LIB_COPY: - import _pydev_thread as thread - else: - try: - import thread - except ImportError: - import _thread as thread #Py3K changed it. +class ClassWithPydevStartNewThread: - return thread._original_start_new_thread(thread.NewThreadStartup(function, args, kwargs), ()) + def pydev_start_new_thread(self, function, args, kwargs={}): + ''' + We need to replace the original thread.start_new_thread with this function so that threads started through + it and not through the threading module are properly traced. + ''' + return _original_start_new_thread(NewThreadStartup(function), args, kwargs) -class PydevStartNewThread(object): - def __get__(self, obj, type=None): - return self +# This is a hack for the situation where the thread.start_new_thread is declared inside a class, such as the one below +# class F(object): +# start_new_thread = thread.start_new_thread +# +# def start_it(self): +# self.start_new_thread(self.function, args, kwargs) +# So, if it's an already bound method, calling self.start_new_thread won't really receive a different 'self' -- it +# does work in the default case because in builtins self isn't passed either. +pydev_start_new_thread = ClassWithPydevStartNewThread().pydev_start_new_thread - def __call__(self, function, args, kwargs={}): - return _pydev_start_new_thread(function, args, kwargs) - -pydev_start_new_thread = PydevStartNewThread() #======================================================================================================================= # PyDB @@ -272,11 +288,6 @@ class PyDB: These are placed on the internal command queue. """ - RUNNING_THREAD_IDS = {} #this is a dict of thread ids pointing to thread ids. Whenever a command - #is passed to the java end that acknowledges that a thread was created, - #the thread id should be passed here -- and if at some time we do not find - #that thread alive anymore, we must remove it from this list and make - #the java side know that the thread was killed. def __init__(self): SetGlobalDebugger(self) @@ -285,7 +296,7 @@ class PyDB: self.writer = None self.quitting = None self.cmdFactory = NetCommandFactory() - self._cmd_queue = {} # the hash of Queues. Key is thread id, value is thread + self._cmd_queue = {} # the hash of Queues. Key is thread id, value is thread self.breakpoints = {} self.django_breakpoints = {} self.exception_set = {} @@ -294,6 +305,8 @@ class PyDB: self.readyToRun = False self._main_lock = threading.Lock() self._lock_running_thread_ids = threading.Lock() + self._py_db_command_thread_event = threading.Event() + CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event self._finishDebuggingSession = False self._terminationEventSent = False self.force_post_mortem_stop = 0 @@ -328,7 +341,7 @@ class PyDB: def initializeNetwork(self, sock): try: - sock.settimeout(None) # infinite, no timeouts from now on - jython does not have it + sock.settimeout(None) # infinite, no timeouts from now on - jython does not have it except: pass self.writer = WriterThread(sock) @@ -336,7 +349,7 @@ class PyDB: self.writer.start() self.reader.start() - time.sleep(0.1) # give threads time to start + time.sleep(0.1) # give threads time to start def connect(self, host, port): if host: @@ -350,6 +363,8 @@ class PyDB: def getInternalQueue(self, thread_id): """ returns internal command queue for a given thread. if new queue is created, notify the RDB about it """ + if thread_id.startswith('__frame__'): + thread_id = thread_id[thread_id.rfind('|') + 1:] try: return self._cmd_queue[thread_id] except KeyError: @@ -359,8 +374,13 @@ class PyDB: def postInternalCommand(self, int_cmd, thread_id): """ if thread_id is *, post to all """ if thread_id == "*": - for k in self._cmd_queue.keys(): - self._cmd_queue[k].put(int_cmd) + threads = threadingEnumerate() + for t in threads: + thread_name = t.getName() + if not thread_name.startswith('pydevd.') or thread_name == 'pydevd.CommandThread': + thread_id = GetThreadId(t) + queue = self.getInternalQueue(thread_id) + queue.put(int_cmd) else: queue = self.getInternalQueue(thread_id) @@ -397,17 +417,15 @@ class PyDB: def processInternalCommands(self): '''This function processes internal commands ''' - curr_thread_id = GetThreadId(threadingCurrentThread()) - program_threads_alive = {} - all_threads = threadingEnumerate() - program_threads_dead = [] - - self._main_lock.acquire() try: self.checkOutputRedirect() + curr_thread_id = GetThreadId(threadingCurrentThread()) + program_threads_alive = {} + all_threads = threadingEnumerate() + program_threads_dead = [] self._lock_running_thread_ids.acquire() try: for t in all_threads: @@ -418,16 +436,16 @@ class PyDB: if not DictContains(self._running_thread_ids, thread_id): if not hasattr(t, 'additionalInfo'): - #see http://sourceforge.net/tracker/index.php?func=detail&aid=1955428&group_id=85796&atid=577329 - #Let's create the additional info right away! + # see http://sourceforge.net/tracker/index.php?func=detail&aid=1955428&group_id=85796&atid=577329 + # Let's create the additional info right away! t.additionalInfo = PyDBAdditionalThreadInfo() self._running_thread_ids[thread_id] = t self.writer.addCommand(self.cmdFactory.makeThreadCreatedMessage(t)) queue = self.getInternalQueue(thread_id) - cmdsToReadd = [] #some commands must be processed by the thread itself... if that's the case, - #we will re-add the commands to the queue after executing. + cmdsToReadd = [] # some commands must be processed by the thread itself... if that's the case, + # we will re-add the commands to the queue after executing. try: while True: int_cmd = queue.get(False) @@ -470,24 +488,30 @@ class PyDB: self._main_lock.release() - def setTracingForUntracedContexts(self): - #Enable the tracing for existing threads (because there may be frames being executed that - #are currently untraced). + def setTracingForUntracedContexts(self, ignore_frame=None, overwrite_prev_trace=False): + # Enable the tracing for existing threads (because there may be frames being executed that + # are currently untraced). threads = threadingEnumerate() - for t in threads: - if not t.getName().startswith('pydevd.'): - #TODO: optimize so that we only actually add that tracing if it's in - #the new breakpoint context. - additionalInfo = None - try: - additionalInfo = t.additionalInfo - except AttributeError: - pass #that's ok, no info currently set + try: + for t in threads: + if not t.getName().startswith('pydevd.'): + # TODO: optimize so that we only actually add that tracing if it's in + # the new breakpoint context. + additionalInfo = None + try: + additionalInfo = t.additionalInfo + except AttributeError: + pass # that's ok, no info currently set - if additionalInfo is not None: - for frame in additionalInfo.IterFrames(): - self.SetTraceForFrameAndParents(frame) - del frame + if additionalInfo is not None: + for frame in additionalInfo.IterFrames(): + if frame is not ignore_frame: + self.SetTraceForFrameAndParents(frame, overwrite_prev_trace=overwrite_prev_trace) + finally: + frame = None + t = None + threads = None + additionalInfo = None def processNetCommand(self, cmd_id, seq, text): @@ -530,14 +554,14 @@ class PyDB: self.postInternalCommand(int_cmd, text) elif cmd_id == CMD_THREAD_SUSPEND: - #Yes, thread suspend is still done at this point, not through an internal command! + # Yes, thread suspend is still done at this point, not through an internal command! t = PydevdFindThreadById(text) if t: additionalInfo = None try: additionalInfo = t.additionalInfo except AttributeError: - pass #that's ok, no info currently set + pass # that's ok, no info currently set if additionalInfo is not None: for frame in additionalInfo.IterFrames(): @@ -545,6 +569,8 @@ class PyDB: del frame self.setSuspend(t, CMD_THREAD_SUSPEND) + elif text.startswith('__frame__:'): + sys.stderr.write("Can't suspend tasklet: %s\n" % (text,)) elif cmd_id == CMD_THREAD_RUN: t = PydevdFindThreadById(text) @@ -553,46 +579,55 @@ class PyDB: int_cmd = InternalRunThread(thread_id) self.postInternalCommand(int_cmd, thread_id) + elif text.startswith('__frame__:'): + sys.stderr.write("Can't make tasklet run: %s\n" % (text,)) + + elif cmd_id == CMD_STEP_INTO or cmd_id == CMD_STEP_OVER or cmd_id == CMD_STEP_RETURN: - #we received some command to make a single step + # we received some command to make a single step t = PydevdFindThreadById(text) if t: thread_id = GetThreadId(t) int_cmd = InternalStepThread(thread_id, cmd_id) self.postInternalCommand(int_cmd, thread_id) + elif text.startswith('__frame__:'): + sys.stderr.write("Can't make tasklet step command: %s\n" % (text,)) + + elif cmd_id == CMD_RUN_TO_LINE or cmd_id == CMD_SET_NEXT_STATEMENT or cmd_id == CMD_SMART_STEP_INTO: - #we received some command to make a single step + # we received some command to make a single step thread_id, line, func_name = text.split('\t', 2) t = PydevdFindThreadById(thread_id) if t: int_cmd = InternalSetNextStatementThread(thread_id, cmd_id, line, func_name) self.postInternalCommand(int_cmd, thread_id) + elif thread_id.startswith('__frame__:'): + sys.stderr.write("Can't set next statement in tasklet: %s\n" % (thread_id,)) elif cmd_id == CMD_RELOAD_CODE: - #we received some command to make a reload of a module + # we received some command to make a reload of a module module_name = text.strip() - from pydevd_reload import xreload - if not DictContains(sys.modules, module_name): - if '.' in module_name: - new_module_name = module_name.split('.')[-1] - if DictContains(sys.modules, new_module_name): - module_name = new_module_name - if not DictContains(sys.modules, module_name): - sys.stderr.write('pydev debugger: Unable to find module to reload: "'+module_name+'".\n') - sys.stderr.write('pydev debugger: This usually means you are trying to reload the __main__ module (which cannot be reloaded).\n') - sys.stderr.flush() + thread_id = '*' # Any thread - else: - sys.stderr.write('pydev debugger: Reloading: '+module_name+'\n') - sys.stderr.flush() - xreload(sys.modules[module_name]) + # Note: not going for the main thread because in this case it'd only do the load + # when we stopped on a breakpoint. + # for tid, t in self._running_thread_ids.items(): #Iterate in copy + # thread_name = t.getName() + # + # print thread_name, GetThreadId(t) + # #Note: if possible, try to reload on the main thread + # if thread_name == 'MainThread': + # thread_id = tid + + int_cmd = ReloadCodeCommand(module_name, thread_id) + self.postInternalCommand(int_cmd, thread_id) elif cmd_id == CMD_CHANGE_VARIABLE: - #the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change + # the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change try: thread_id, frame_id, scope, attr_and_value = text.split('\t', 3) @@ -606,12 +641,12 @@ class PyDB: traceback.print_exc() elif cmd_id == CMD_GET_VARIABLE: - #we received some command to get a variable - #the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes* + # we received some command to get a variable + # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes* try: thread_id, frame_id, scopeattrs = text.split('\t', 2) - if scopeattrs.find('\t') != -1: # there are attributes beyond scope + if scopeattrs.find('\t') != -1: # there are attributes beyond scope scope, attrs = scopeattrs.split('\t', 1) else: scope, attrs = (scopeattrs, None) @@ -623,8 +658,8 @@ class PyDB: traceback.print_exc() elif cmd_id == CMD_GET_COMPLETIONS: - #we received some command to get a variable - #the text is: thread_id\tframe_id\tactivation token + # we received some command to get a variable + # the text is: thread_id\tframe_id\tactivation token try: thread_id, frame_id, scope, act_tok = text.split('\t', 3) @@ -641,23 +676,26 @@ class PyDB: self.postInternalCommand(int_cmd, thread_id) elif cmd_id == CMD_SET_BREAK: - #func name: 'None': match anything. Empty: match global, specified: only method context. + # func name: 'None': match anything. Empty: match global, specified: only method context. - #command to add some breakpoint. + # command to add some breakpoint. # text is file\tline. Add to breakpoints dictionary type, file, line, condition, expression = text.split('\t', 4) + if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. + file = file.encode(file_system_encoding) + if condition.startswith('**FUNC**'): func_name, condition = condition.split('\t', 1) - #We must restore new lines and tabs as done in - #AbstractDebugTarget.breakpointAdded + # We must restore new lines and tabs as done in + # AbstractDebugTarget.breakpointAdded condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\ replace("@_@TAB_CHAR@_@", '\t').strip() func_name = func_name[8:] else: - func_name = 'None' #Match anything if not specified. + func_name = 'None' # Match anything if not specified. file = NormFileToServer(file) @@ -849,13 +887,29 @@ class PyDB: cmd = self.cmdFactory.makeThreadSuspendMessage(GetThreadId(thread), frame, thread.stop_reason, message) self.writer.addCommand(cmd) - info = thread.additionalInfo + CustomFramesContainer.custom_frames_lock.acquire() + try: + from_this_thread = [] + for frame_id, custom_frame in CustomFramesContainer.custom_frames.items(): + if custom_frame.thread_id == thread.ident: + # print >> sys.stderr, 'Frame created: ', frame_id + self.writer.addCommand(self.cmdFactory.makeCustomFrameCreatedMessage(frame_id, custom_frame.name)) + self.writer.addCommand(self.cmdFactory.makeThreadSuspendMessage(frame_id, custom_frame.frame, CMD_THREAD_SUSPEND, "")) + + from_this_thread.append(frame_id) + + finally: + CustomFramesContainer.custom_frames_lock.release() + + + + info = thread.additionalInfo while info.pydev_state == STATE_SUSPEND and not self._finishDebuggingSession: self.processInternalCommands() time.sleep(0.01) - #process any stepping instructions + # process any stepping instructions if info.pydev_step_cmd == CMD_STEP_INTO: info.pydev_step_stop = None info.pydev_smart_step_stop = None @@ -903,13 +957,13 @@ class PyDB: elif info.pydev_step_cmd == CMD_STEP_RETURN: back_frame = frame.f_back if back_frame is not None: - #steps back to the same frame (in a return call it will stop in the 'back frame' for the user) + # steps back to the same frame (in a return call it will stop in the 'back frame' for the user) info.pydev_step_stop = frame self.SetTraceForFrameAndParents(frame) else: - #No back frame?!? -- this happens in jython when we have some frame created from an awt event - #(the previous frame would be the awt event, but this doesn't make part of 'jython', only 'java') - #so, if we're doing a step return in this situation, it's the same as just making it run + # No back frame?!? -- this happens in jython when we have some frame created from an awt event + # (the previous frame would be the awt event, but this doesn't make part of 'jython', only 'java') + # so, if we're doing a step return in this situation, it's the same as just making it run info.pydev_step_stop = None info.pydev_step_cmd = None info.pydev_state = STATE_RUN @@ -918,6 +972,15 @@ class PyDB: cmd = self.cmdFactory.makeThreadRunMessage(GetThreadId(thread), info.pydev_step_cmd) self.writer.addCommand(cmd) + CustomFramesContainer.custom_frames_lock.acquire() + try: + # The ones that remained on last_running must now be removed. + for frame_id in from_this_thread: + # print >> sys.stderr, 'Removing created frame: ', frame_id + self.writer.addCommand(self.cmdFactory.makeThreadKilledMessage(frame_id)) + + finally: + CustomFramesContainer.custom_frames_lock.release() def handle_post_mortem_stop(self, additionalInfo, t): pydev_log.debug("We are stopping in post-mortem\n") @@ -949,7 +1012,6 @@ class PyDB: try: if self._finishDebuggingSession and not self._terminationEventSent: #that was not working very well because jython gave some socket errors - t = threadingCurrentThread() try: threads = threadingEnumerate() for t in threads: @@ -1005,19 +1067,16 @@ class PyDB: if is_file_to_ignore: return None - #each new frame... + # each new frame... return additionalInfo.CreateDbFrame((self, filename, additionalInfo, t, frame)).trace_dispatch(frame, event, arg) except SystemExit: return None - except TypeError: - return None - except Exception: - #Log it + # Log it if traceback is not None: - #This can actually happen during the interpreter shutdown in Python 2.7 + # This can actually happen during the interpreter shutdown in Python 2.7 traceback.print_exc() return None @@ -1030,8 +1089,8 @@ class PyDB: doWaitSuspend = psyco.proxy(doWaitSuspend) getInternalQueue = psyco.proxy(getInternalQueue) except ImportError: - if hasattr(sys, 'exc_clear'): #jython does not have it - sys.exc_clear() #don't keep the traceback (let's keep it clear for when we go to the point of executing client code) + if hasattr(sys, 'exc_clear'): # jython does not have it + sys.exc_clear() # don't keep the traceback (let's keep it clear for when we go to the point of executing client code) if not IS_PY3K and not IS_PY27 and not IS_64_BITS and not sys.platform.startswith("java") and not sys.platform.startswith("cli"): sys.stderr.write("pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)\n") @@ -1039,15 +1098,15 @@ class PyDB: - def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev=False): + def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev_trace=False): dispatch_func = self.trace_dispatch if also_add_to_passed_frame: - self.update_trace(frame, dispatch_func, overwrite_prev) + self.update_trace(frame, dispatch_func, overwrite_prev_trace) frame = frame.f_back while frame: - self.update_trace(frame, dispatch_func, overwrite_prev) + self.update_trace(frame, dispatch_func, overwrite_prev_trace) frame = frame.f_back del frame @@ -1068,17 +1127,49 @@ class PyDB: frame = frame.f_back del frame + def prepareToRun(self): + ''' Shared code to prepare debugging by installing traces and registering threads ''' + + # for completeness, we'll register the pydevd.reader & pydevd.writer threads + net = NetCommand(str(CMD_THREAD_CREATE), 0, '') + self.writer.addCommand(net) + net = NetCommand(str(CMD_THREAD_CREATE), 0, '') + self.writer.addCommand(net) + + pydevd_tracing.SetTrace(self.trace_dispatch) + self.patch_threads() - def run(self, file, globals=None, locals=None): + PyDBCommandThread(self).start() + PyDBCheckAliveThread(debugger).start() + + def patch_threads(self): + try: + # not available in jython! + threading.settrace(self.trace_dispatch) # for all future threads + except: + pass + + try: + thread.start_new_thread = pydev_start_new_thread + thread.start_new = pydev_start_new_thread + except: + pass + + + def run(self, file, globals=None, locals=None, set_trace=True): + if os.path.isdir(file): + new_target = os.path.join(file, '__main__.py') + if os.path.isfile(new_target): + file = new_target if globals is None: - #patch provided by: Scott Schlesier - when script is run, it does not - #use globals from pydevd: - #This will prevent the pydevd script from contaminating the namespace for the script to be debugged + # patch provided by: Scott Schlesier - when script is run, it does not + # use globals from pydevd: + # This will prevent the pydevd script from contaminating the namespace for the script to be debugged - #pretend pydevd is not the main module, and - #convince the file to be debugged that it was loaded as main + # pretend pydevd is not the main module, and + # convince the file to be debugged that it was loaded as main sys.modules['pydevd'] = sys.modules['__main__'] sys.modules['pydevd'].__name__ = 'pydevd' @@ -1093,61 +1184,39 @@ class PyDB: try: globals['__builtins__'] = __builtins__ except NameError: - pass #Not there on Jython... + pass # Not there on Jython... if locals is None: locals = globals - #Predefined (writable) attributes: __name__ is the module's name; - #__doc__ is the module's documentation string, or None if unavailable; - #__file__ is the pathname of the file from which the module was loaded, - #if it was loaded from a file. The __file__ attribute is not present for - #C modules that are statically linked into the interpreter; for extension modules - #loaded dynamically from a shared library, it is the pathname of the shared library file. + if set_trace: + # Predefined (writable) attributes: __name__ is the module's name; + # __doc__ is the module's documentation string, or None if unavailable; + # __file__ is the pathname of the file from which the module was loaded, + # if it was loaded from a file. The __file__ attribute is not present for + # C modules that are statically linked into the interpreter; for extension modules + # loaded dynamically from a shared library, it is the pathname of the shared library file. - #I think this is an ugly hack, bug it works (seems to) for the bug that says that sys.path should be the same in - #debug and run. - if m.__file__.startswith(sys.path[0]): - #print >> sys.stderr, 'Deleting: ', sys.path[0] - del sys.path[0] + # I think this is an ugly hack, bug it works (seems to) for the bug that says that sys.path should be the same in + # debug and run. + if m.__file__.startswith(sys.path[0]): + # print >> sys.stderr, 'Deleting: ', sys.path[0] + del sys.path[0] - #now, the local directory has to be added to the pythonpath - #sys.path.insert(0, os.getcwd()) - #Changed: it's not the local directory, but the directory of the file launched - #The file being run ust be in the pythonpath (even if it was not before) - sys.path.insert(0, os.path.split(file)[0]) + # now, the local directory has to be added to the pythonpath + # sys.path.insert(0, os.getcwd()) + # Changed: it's not the local directory, but the directory of the file launched + # The file being run ust be in the pythonpath (even if it was not before) + sys.path.insert(0, os.path.split(file)[0]) - # for completness, we'll register the pydevd.reader & pydevd.writer threads - net = NetCommand(str(CMD_THREAD_CREATE), 0, '') - self.writer.addCommand(net) - net = NetCommand(str(CMD_THREAD_CREATE), 0, '') - self.writer.addCommand(net) + self.prepareToRun() - pydevd_tracing.SetTrace(self.trace_dispatch) - try: - #not available in jython! - threading.settrace(self.trace_dispatch) # for all future threads - except: - pass + while not self.readyToRun: + time.sleep(0.1) # busy wait until we receive run command - try: - thread.start_new_thread = pydev_start_new_thread - thread.start_new = pydev_start_new_thread - except: - pass - while not self.readyToRun: - time.sleep(0.1) # busy wait until we receive run command - - PyDBCommandThread(debugger).start() - PyDBCheckAliveThread(debugger).start() - - if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON and sys.version_info[1] == 5 and sys.version_info[2] >= 3: - from _pydev_jython_execfile import jython_execfile - jython_execfile(sys.argv) - else: - pydev_imports.execfile(file, globals, locals) #execute the script + pydev_imports.execfile(file, globals, locals) # execute the script def exiting(self): sys.stdout.flush() @@ -1239,27 +1308,79 @@ def initStderrRedirect(): sys.stderrBuf = pydevd_io.IOBuf() sys.stderr = pydevd_io.IORedirector(sys.stderr, sys.stderrBuf) #@UndefinedVariable -def settrace(host='localhost', stdoutToServer=False, stderrToServer=False, port=5678, suspend=True, trace_only_current_thread=False, overwrite_prev_trace=False): +#======================================================================================================================= +# settrace +#======================================================================================================================= +def settrace( + host=None, + stdoutToServer=False, + stderrToServer=False, + port=5678, + suspend=True, + trace_only_current_thread=False, + overwrite_prev_trace=False, + patch_multiprocessing=False, + ): '''Sets the tracing function with the pydev debug function and initializes needed facilities. - @param host: the user may specify another host, if the debug server is not in the same machine + @param host: the user may specify another host, if the debug server is not in the same machine (default is the local + host) + @param stdoutToServer: when this is true, the stdout is passed to the debug server + @param stderrToServer: when this is true, the stderr is passed to the debug server so that they are printed in its console and not in this process console. + @param port: specifies which port to use for communicating with the server (note that the server must be started in the same port). @note: currently it's hard-coded at 5678 in the client + @param suspend: whether a breakpoint should be emulated as soon as this function is called. - @param trace_only_current_thread: determines if only the current thread will be traced or all future threads will also have the tracing enabled. + + @param trace_only_current_thread: determines if only the current thread will be traced or all current and future + threads will also have the tracing enabled. + + @param overwrite_prev_trace: if True we'll reset the frame.f_trace of frames which are already being traced + + @param patch_multiprocessing: if True we'll patch the functions which create new processes so that launched + processes are debugged. ''' _set_trace_lock.acquire() try: - _locked_settrace(host, stdoutToServer, stderrToServer, port, suspend, trace_only_current_thread, overwrite_prev_trace) + _locked_settrace( + host, + stdoutToServer, + stderrToServer, + port, + suspend, + trace_only_current_thread, + overwrite_prev_trace, + patch_multiprocessing, + ) finally: _set_trace_lock.release() + + _set_trace_lock = threading.Lock() -def _locked_settrace(host, stdoutToServer, stderrToServer, port, suspend, trace_only_current_thread, overwrite_prev_trace): +def _locked_settrace( + host, + stdoutToServer, + stderrToServer, + port, + suspend, + trace_only_current_thread, + overwrite_prev_trace, + patch_multiprocessing, + ): + if patch_multiprocessing: + try: + import pydev_monkey #Jython 2.1 can't use it... + except: + pass + else: + pydev_monkey.patch_new_process_functions() + if host is None: import pydev_localhost host = pydev_localhost.get_localhost() @@ -1267,19 +1388,17 @@ def _locked_settrace(host, stdoutToServer, stderrToServer, port, suspend, trace_ global connected global bufferStdOutToServer global bufferStdErrToServer - global remote - - remote = True if not connected : - connected = True - bufferStdOutToServer = stdoutToServer - bufferStdErrToServer = stderrToServer - pydevd_vm_type.SetupType() debugger = PyDB() - debugger.connect(host, port) + debugger.connect(host, port) # Note: connect can raise error. + + # Mark connected only if it actually succeeded. + connected = True + bufferStdOutToServer = stdoutToServer + bufferStdErrToServer = stderrToServer net = NetCommand(str(CMD_THREAD_CREATE), 0, '') debugger.writer.addCommand(net) @@ -1292,7 +1411,16 @@ def _locked_settrace(host, stdoutToServer, stderrToServer, port, suspend, trace_ if bufferStdErrToServer: initStderrRedirect() - debugger.SetTraceForFrameAndParents(GetFrame(), False, overwrite_prev=overwrite_prev_trace) + debugger.SetTraceForFrameAndParents(GetFrame(), False, overwrite_prev_trace=overwrite_prev_trace) + + + CustomFramesContainer.custom_frames_lock.acquire() + try: + for _frameId, custom_frame in CustomFramesContainer.custom_frames.items(): + debugger.SetTraceForFrameAndParents(custom_frame.frame, False) + finally: + CustomFramesContainer.custom_frames_lock.release() + t = threadingCurrentThread() try: @@ -1302,36 +1430,29 @@ def _locked_settrace(host, stdoutToServer, stderrToServer, port, suspend, trace_ t.additionalInfo = additionalInfo while not debugger.readyToRun: - time.sleep(0.1) # busy wait until we receive run command + time.sleep(0.1) # busy wait until we receive run command - if suspend: - debugger.setSuspend(t, CMD_SET_BREAK) - - #note that we do that through pydevd_tracing.SetTrace so that the tracing - #is not warned to the user! + # note that we do that through pydevd_tracing.SetTrace so that the tracing + # is not warned to the user! pydevd_tracing.SetTrace(debugger.trace_dispatch) if not trace_only_current_thread: - #Trace future threads? - try: - #not available in jython! - threading.settrace(debugger.trace_dispatch) # for all future threads - except: - pass + # Trace future threads? + debugger.patch_threads() - try: - thread.start_new_thread = pydev_start_new_thread - thread.start_new = pydev_start_new_thread - except: - pass + # As this is the first connection, also set tracing for any untraced threads + debugger.setTracingForUntracedContexts(ignore_frame=GetFrame(), overwrite_prev_trace=overwrite_prev_trace) sys.exitfunc = exit_hook + #Suspend as the last thing after all tracing is in place. + if suspend: + debugger.setSuspend(t, CMD_SET_BREAK) PyDBCommandThread(debugger).start() PyDBCheckAliveThread(debugger).start() else: - #ok, we're already in debug mode, with all set, so, let's just set the break + # ok, we're already in debug mode, with all set, so, let's just set the break debugger = GetGlobalDebugger() debugger.SetTraceForFrameAndParents(GetFrame(), False) @@ -1346,22 +1467,14 @@ def _locked_settrace(host, stdoutToServer, stderrToServer, port, suspend, trace_ pydevd_tracing.SetTrace(debugger.trace_dispatch) if not trace_only_current_thread: - #Trace future threads? - try: - #not available in jython! - threading.settrace(debugger.trace_dispatch) # for all future threads - except: - pass + # Trace future threads? + debugger.patch_threads() - try: - thread.start_new_thread = pydev_start_new_thread - thread.start_new = pydev_start_new_thread - except: - pass if suspend: debugger.setSuspend(t, CMD_SET_BREAK) + def stoptrace(): global connected if connected: @@ -1447,7 +1560,17 @@ def settrace_forked(): if port is not None: global connected connected = False - settrace(host, port=port, suspend=False, overwrite_prev_trace=True) + + CustomFramesContainerInit() + + settrace( + host, + port=port, + suspend=False, + trace_only_current_thread=False, + overwrite_prev_trace=True, + patch_multiprocessing=True, + ) #======================================================================================================================= # main #======================================================================================================================= @@ -1461,23 +1584,8 @@ if __name__ == '__main__': usage(1) - #as to get here all our imports are already resolved, the psyco module can be - #changed and we'll still get the speedups in the debugger, as those functions - #are already compiled at this time. - try: - import psyco - except ImportError: - if hasattr(sys, 'exc_clear'): #jython does not have it - sys.exc_clear() #don't keep the traceback -- clients don't want to see it - pass #that's ok, no need to mock psyco if it's not available anyways - else: - #if it's available, let's change it for a stub (pydev already made use of it) - import pydevd_psyco_stub - sys.modules['psyco'] = pydevd_psyco_stub - fix_getpass.fixGetpass() - pydev_log.debug("Executing file %s" % setup['file']) pydev_log.debug("arguments: %s"% str(sys.argv)) @@ -1493,6 +1601,8 @@ if __name__ == '__main__': port = setup['port'] host = setup['client'] + f = setup['file'] + fix_app_engine_debug = False if setup['multiproc']: pydev_log.debug("Started in multiproc mode\n") @@ -1523,6 +1633,83 @@ if __name__ == '__main__': pydev_log.error("Error patching process functions\n") traceback.print_exc() + # Only do this patching if we're not running with multiprocess turned on. + if f.find('dev_appserver.py') != -1: + if os.path.basename(f).startswith('dev_appserver.py'): + appserver_dir = os.path.dirname(f) + version_file = os.path.join(appserver_dir, 'VERSION') + if os.path.exists(version_file): + try: + stream = open(version_file, 'r') + try: + for line in stream.read().splitlines(): + line = line.strip() + if line.startswith('release:'): + line = line[8:].strip() + version = line.replace('"', '') + version = version.split('.') + if int(version[0]) > 1: + fix_app_engine_debug = True + + elif int(version[0]) == 1: + if int(version[1]) >= 7: + # Only fix from 1.7 onwards + fix_app_engine_debug = True + break + finally: + stream.close() + except: + traceback.print_exc() + + try: + # In the default run (i.e.: run directly on debug mode), we try to patch stackless as soon as possible + # on a run where we have a remote debug, we may have to be more careful because patching stackless means + # that if the user already had a stackless.set_schedule_callback installed, he'd loose it and would need + # to call it again (because stackless provides no way of getting the last function which was registered + # in set_schedule_callback). + # + # So, ideally, if there's an application using stackless and the application wants to use the remote debugger + # and benefit from stackless debugging, the application itself must call: + # + # import pydevd_stackless + # pydevd_stackless.patch_stackless() + # + # itself to be able to benefit from seeing the tasklets created before the remote debugger is attached. + import pydevd_stackless + pydevd_stackless.patch_stackless() + except: + pass # It's ok not having stackless there... + + if fix_app_engine_debug: + sys.stderr.write("pydev debugger: google app engine integration enabled\n") + curr_dir = os.path.dirname(__file__) + app_engine_startup_file = os.path.join(curr_dir, 'pydev_app_engine_debug_startup.py') + + sys.argv.insert(1, '--python_startup_script=' + app_engine_startup_file) + import json + setup['pydevd'] = __file__ + sys.argv.insert(2, '--python_startup_args=%s' % json.dumps(setup),) + sys.argv.insert(3, '--automatic_restart=no') + sys.argv.insert(4, '--max_module_instances=1') + + debugger = PyDB() + # Run the dev_appserver + debugger.run(setup['file'], None, None, set_trace=False) + + else: + # as to get here all our imports are already resolved, the psyco module can be + # changed and we'll still get the speedups in the debugger, as those functions + # are already compiled at this time. + try: + import psyco + except ImportError: + if hasattr(sys, 'exc_clear'): # jython does not have it + sys.exc_clear() # don't keep the traceback -- clients don't want to see it + pass # that's ok, no need to mock psyco if it's not available anyways + else: + # if it's available, let's change it for a stub (pydev already made use of it) + import pydevd_psyco_stub + sys.modules['psyco'] = pydevd_psyco_stub debugger = PyDB() diff --git a/python/helpers/pydev/pydevd_additional_thread_info.py b/python/helpers/pydev/pydevd_additional_thread_info.py index d2d3fffbce82..1b0fc2cdd633 100644 --- a/python/helpers/pydev/pydevd_additional_thread_info.py +++ b/python/helpers/pydev/pydevd_additional_thread_info.py @@ -118,7 +118,7 @@ class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(AbstractPyDBAdditional try: ret.append(weak_db_frame().frame) except AttributeError: - pass #ok, garbage-collected already + pass # ok, garbage-collected already return ret finally: self._release_lock() @@ -136,13 +136,11 @@ if hasattr(sys, '_current_frames'): PyDBAdditionalThreadInfo = PyDBAdditionalThreadInfoWithCurrentFramesSupport else: try: - import threadframe + import threadframe #@UnresolvedImport sys._current_frames = threadframe.dict - assert sys._current_frames is threadframe.dict #Just check if it was correctly set + assert sys._current_frames is threadframe.dict #Just check if it was correctly set PyDBAdditionalThreadInfo = PyDBAdditionalThreadInfoWithCurrentFramesSupport except: #If all fails, let's use the support without frames PyDBAdditionalThreadInfo = PyDBAdditionalThreadInfoWithoutCurrentFramesSupport - sys.stderr.write("pydev debugger: warning: sys._current_frames is not supported in Python 2.4, it is recommended to install threadframe module\n") - sys.stderr.write("pydev debugger: warning: See http://majid.info/blog/threadframe-multithreaded-stack-frame-extraction-for-python/\n") diff --git a/python/helpers/pydev/pydevd_comm.py b/python/helpers/pydev/pydevd_comm.py index b7505362c0dc..9d4f2e78b94d 100644 --- a/python/helpers/pydev/pydevd_comm.py +++ b/python/helpers/pydev/pydevd_comm.py @@ -89,22 +89,21 @@ else: from socket import SHUT_RD, SHUT_WR try: - from urllib import quote + from urllib import quote, quote_plus, unquote, unquote_plus except: - from urllib.parse import quote #@Reimport @UnresolvedImport - + from urllib.parse import quote, quote_plus, unquote, unquote_plus #@Reimport @UnresolvedImport +import pydevconsole import pydevd_vars import pydevd_tracing import pydevd_vm_type import pydevd_file_utils import traceback -from pydevd_utils import * -from pydevd_utils import quote_smart as quote +from pydevd_utils import quote_smart as quote, compare_object_attrs, cmp_to_key, to_string import pydev_log - +import _pydev_completer from pydevd_tracing import GetExceptionTracebackStr -import pydevconsole + CMD_RUN = 101 @@ -182,6 +181,8 @@ MAX_IO_MSG_SIZE = 1000 #if the io is too big, we'll not send all (could make th VERSION_STRING = "@@BUILD_NUMBER@@" +from _pydev_filesystem_encoding import getfilesystemencoding +file_system_encoding = getfilesystemencoding() #--------------------------------------------------------------------------------------------------- UTILITIES @@ -290,7 +291,11 @@ class ReaderThread(PyDBDaemonThread): if not self.killReceived: self.handleExcept() return #Finished communication. - if IS_PY3K: + + #Note: the java backend is always expected to pass utf-8 encoded strings. We now work with unicode + #internally and thus, we may need to convert to the actual encoding where needed (i.e.: filenames + #on python 2 may need to be converted to the filesystem encoding). + if hasattr(r, 'decode'): r = r.decode('utf-8') buffer += r @@ -375,10 +380,10 @@ class WriterThread(PyDBDaemonThread): out = cmd.getOutgoing() if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: - out_message = 'Sending cmd: ' - out_message += ID_TO_MEANING.get(out[:3], 'UNKNOWN') + out_message = 'sending cmd --> ' + out_message += "%20s" % ID_TO_MEANING.get(out[:3], 'UNKNOWN') out_message += ' ' - out_message += out + out_message += unquote(unquote(out)).replace('\n', ' ') try: sys.stderr.write('%s\n' % (out_message,)) except: @@ -501,6 +506,13 @@ class NetCommandFactory: cmdText = "" + self.threadToXML(thread) + "" return NetCommand(CMD_THREAD_CREATE, 0, cmdText) + + def makeCustomFrameCreatedMessage(self, frameId, frameDescription): + frameDescription = pydevd_vars.makeValidXmlValue(frameDescription) + cmdText = '' % (frameDescription, frameId) + return NetCommand(CMD_THREAD_CREATE, 0, cmdText) + + def makeListThreadsMessage(self, seq): """ returns thread listing as XML """ try: @@ -588,6 +600,10 @@ class NetCommandFactory: filename, base = pydevd_file_utils.GetFilenameAndBase(curFrame) myFile = pydevd_file_utils.NormFileToClient(filename) + if file_system_encoding.lower() != "utf-8" and hasattr(myFile, "decode"): + # myFile is a byte string encoded using the file system encoding + # convert it to utf8 + myFile = myFile.decode(file_system_encoding).encode("utf-8") #print "file is ", myFile #myFile = inspect.getsourcefile(curFrame) or inspect.getfile(frame) @@ -687,6 +703,54 @@ class InternalThreadCommand: def doIt(self, dbg): raise NotImplementedError("you have to override doIt") + +class ReloadCodeCommand(InternalThreadCommand): + + + def __init__(self, module_name, thread_id): + self.thread_id = thread_id + self.module_name = module_name + self.executed = False + self.lock = threading.Lock() + + + def canBeExecutedBy(self, thread_id): + if self.thread_id == '*': + return True #Any thread can execute it! + + return InternalThreadCommand.canBeExecutedBy(self, thread_id) + + + def doIt(self, dbg): + self.lock.acquire() + try: + if self.executed: + return + self.executed = True + finally: + self.lock.release() + + module_name = self.module_name + if not DictContains(sys.modules, module_name): + if '.' in module_name: + new_module_name = module_name.split('.')[-1] + if DictContains(sys.modules, new_module_name): + module_name = new_module_name + + if not DictContains(sys.modules, module_name): + sys.stderr.write('pydev debugger: Unable to find module to reload: "' + module_name + '".\n') + # Too much info... + # sys.stderr.write('pydev debugger: This usually means you are trying to reload the __main__ module (which cannot be reloaded).\n') + + else: + sys.stderr.write('pydev debugger: Start reloading module: "' + module_name + '" ... \n') + import pydevd_reload + if pydevd_reload.xreload(sys.modules[module_name]): + sys.stderr.write('pydev debugger: reload finished\n') + else: + sys.stderr.write('pydev debugger: reload finished without applying any change\n') + + #======================================================================================================================= # InternalTerminateThread #======================================================================================================================= @@ -875,6 +939,49 @@ class InternalEvaluateExpression(InternalThreadCommand): cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc) dbg.writer.addCommand(cmd) +#======================================================================================================================= +# InternalGetCompletions +#======================================================================================================================= +class InternalGetCompletions(InternalThreadCommand): + """ Gets the completions in a given scope """ + + def __init__(self, seq, thread_id, frame_id, act_tok): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.act_tok = act_tok + + + def doIt(self, dbg): + """ Converts request into completions """ + try: + remove_path = None + try: + + frame = pydevd_vars.findFrame(self.thread_id, self.frame_id) + if frame is not None: + + + msg = _pydev_completer.GenerateCompletionsAsXML(frame, self.act_tok) + + cmd = dbg.cmdFactory.makeGetCompletionsMessage(self.sequence, msg) + dbg.writer.addCommand(cmd) + else: + cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "InternalGetCompletions: Frame not found: %s from thread: %s" % (self.frame_id, self.thread_id)) + dbg.writer.addCommand(cmd) + + + finally: + if remove_path is not None: + sys.path.remove(remove_path) + + except: + exc = GetExceptionTracebackStr() + sys.stderr.write('%s\n' % (exc,)) + cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc) + dbg.writer.addCommand(cmd) + + #======================================================================================================================= # InternalConsoleExec #======================================================================================================================= @@ -914,87 +1021,6 @@ class InternalConsoleExec(InternalThreadCommand): sys.stderr.flush() sys.stdout.flush() -#======================================================================================================================= -# InternalGetCompletions -#======================================================================================================================= -class InternalGetCompletions(InternalThreadCommand): - """ Gets the completions in a given scope """ - - def __init__(self, seq, thread_id, frame_id, act_tok): - self.sequence = seq - self.thread_id = thread_id - self.frame_id = frame_id - self.act_tok = act_tok - - - def doIt(self, dbg): - """ Converts request into completions """ - try: - remove_path = None - try: - import _completer - except: - try: - path = os.environ['PYDEV_COMPLETER_PYTHONPATH'] - except : - path = os.path.dirname(__file__) - sys.path.append(path) - remove_path = path - try: - import _completer - except : - pass - - try: - - frame = pydevd_vars.findFrame(self.thread_id, self.frame_id) - if frame is not None: - - #Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329 - #(Names not resolved in generator expression in method) - #See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html - updated_globals = {} - updated_globals.update(frame.f_globals) - updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals - locals = frame.f_locals - else: - updated_globals = {} - locals = {} - - - if pydevconsole.IPYTHON: - completions = pydevconsole.get_completions(self.act_tok, self.act_tok, updated_globals, locals) - else: - try: - completer = _completer.Completer(updated_globals, None) - #list(tuple(name, descr, parameters, type)) - completions = completer.complete(self.act_tok) - except : - completions = [] - - - def makeValid(s): - return pydevd_vars.makeValidXmlValue(pydevd_vars.quote(s, '/>_= \t')) - - msg = "" - - for comp in completions: - msg += '' % (makeValid(comp[0]), makeValid(comp[1]), makeValid(comp[2]), makeValid(comp[3]),) - msg += "" - - cmd = dbg.cmdFactory.makeGetCompletionsMessage(self.sequence, msg) - dbg.writer.addCommand(cmd) - - finally: - if remove_path is not None: - sys.path.remove(remove_path) - - except: - exc = GetExceptionTracebackStr() - sys.stderr.write('%s\n' % (exc,)) - cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error getting completion " + exc) - dbg.writer.addCommand(cmd) - #======================================================================================================================= # PydevdFindThreadById @@ -1004,7 +1030,8 @@ def PydevdFindThreadById(thread_id): # there was a deadlock here when I did not remove the tracing function when thread was dead threads = threading.enumerate() for i in threads: - if thread_id == GetThreadId(i): + tid = GetThreadId(i) + if thread_id == tid or thread_id.endswith('|' + tid): return i sys.stderr.write("Could not find thread %s\n" % thread_id) diff --git a/python/helpers/pydev/pydevd_constants.py b/python/helpers/pydev/pydevd_constants.py index 5e78e15d3a19..71fe4aed2505 100644 --- a/python/helpers/pydev/pydevd_constants.py +++ b/python/helpers/pydev/pydevd_constants.py @@ -59,7 +59,7 @@ try: elif sys.version_info[0] == 2 and sys.version_info[1] == 4: IS_PY24 = True except AttributeError: - pass #Not all versions have sys.version_info + pass #Not all versions have sys.version_info try: IS_64_BITS = sys.maxsize > 2 ** 32 @@ -85,10 +85,7 @@ _nextThreadIdLock = threading.Lock() # Jython? #======================================================================================================================= try: - import org.python.core.PyDictionary #@UnresolvedImport @UnusedImport -- just to check if it could be valid - - def DictContains(d, key): - return d.has_key(key) + DictContains = dict.has_key except: try: #Py3k does not have has_key anymore, and older versions don't have __contains__ @@ -99,6 +96,19 @@ except: except NameError: def DictContains(d, key): return d.has_key(key) +#======================================================================================================================= +# Jython? +#======================================================================================================================= +try: + DictPop = dict.pop +except: + def DictPop(d, key, default=None): + try: + ret = d[key] + del d[key] + return ret + except: + return default try: @@ -193,6 +203,9 @@ class Null: return self def __getattr__(self, mname): + if len(mname) > 4 and mname[:2] == '__' and mname[-2:] == '__': + # Don't pretend to implement special method names. + raise AttributeError(mname) return self def __setattr__(self, name, value): @@ -222,6 +235,30 @@ class Null: def __nonzero__(self): return 0 + def __iter__(self): + return iter(()) + + +def call_only_once(func): + ''' + To be used as a decorator + + @call_only_once + def func(): + print 'Calling func only this time' + + Actually, in PyDev it must be called as: + + func = call_only_once(func) to support older versions of Python. + ''' + def new_func(*args, **kwargs): + if not new_func._called: + new_func._called = True + return func(*args, **kwargs) + + new_func._called = False + return new_func + if __name__ == '__main__': if Null(): sys.stdout.write('here\n') diff --git a/python/helpers/pydev/pydevd_custom_frames.py b/python/helpers/pydev/pydevd_custom_frames.py new file mode 100644 index 000000000000..e259356b8336 --- /dev/null +++ b/python/helpers/pydev/pydevd_custom_frames.py @@ -0,0 +1,121 @@ +from pydevd_constants import * #@UnusedWildImport +from pydevd_file_utils import GetFilenameAndBase +threadingCurrentThread = threading.currentThread + +DEBUG = False + +#======================================================================================================================= +# CustomFramesContainer +#======================================================================================================================= +class CustomFramesContainer: + pass + + +def CustomFramesContainerInit(): #Note: no staticmethod on jython 2.1 (so, use free-function) + + CustomFramesContainer.custom_frames_lock = threading.Lock() + + # custom_frames can only be accessed if properly locked with custom_frames_lock! + # Key is a string identifying the frame (as well as the thread it belongs to). + # Value is a CustomFrame. + # + CustomFramesContainer.custom_frames = {} + + # Only to be used in this module + CustomFramesContainer._next_frame_id = 0 + + # This is the event we must set to release an internal process events. It's later set by the actual debugger + # when we do create the debugger. + CustomFramesContainer._py_db_command_thread_event = Null() + +#Initialize it the first time (it may be reinitialized later on when dealing with a fork). +CustomFramesContainerInit() + + +#======================================================================================================================= +# CustomFrame +#======================================================================================================================= +class CustomFrame: + + def __init__(self, name, frame, thread_id): + # 0 = string with the representation of that frame + self.name = name + + # 1 = the frame to show + self.frame = frame + + # 2 = an integer identifying the last time the frame was changed. + self.mod_time = 0 + + # 3 = the thread id of the given frame + self.thread_id = thread_id + + +def addCustomFrame(frame, name, thread_id): + CustomFramesContainer.custom_frames_lock.acquire() + try: + curr_thread_id = GetThreadId(threadingCurrentThread()) + next_id = CustomFramesContainer._next_frame_id = CustomFramesContainer._next_frame_id + 1 + + # Note: the frame id kept contains an id and thread information on the thread where the frame was added + # so that later on we can check if the frame is from the current thread by doing frame_id.endswith('|'+thread_id). + frame_id = '__frame__:%s|%s' % (next_id, curr_thread_id) + if DEBUG: + sys.stderr.write('addCustomFrame: %s (%s) %s %s\n' % ( + frame_id, GetFilenameAndBase(frame)[1], frame.f_lineno, frame.f_code.co_name)) + + CustomFramesContainer.custom_frames[frame_id] = CustomFrame(name, frame, thread_id) + CustomFramesContainer._py_db_command_thread_event.set() + return frame_id + finally: + CustomFramesContainer.custom_frames_lock.release() + + +def updateCustomFrame(frame_id, frame, thread_id, name=None): + CustomFramesContainer.custom_frames_lock.acquire() + try: + if DEBUG: + sys.stderr.write('updateCustomFrame: %s\n' % frame_id) + try: + old = CustomFramesContainer.custom_frames[frame_id] + if name is not None: + old.name = name + old.mod_time += 1 + old.thread_id = thread_id + except: + sys.stderr.write('Unable to get frame to replace: %s\n' % (frame_id,)) + import traceback;traceback.print_exc() + + CustomFramesContainer._py_db_command_thread_event.set() + finally: + CustomFramesContainer.custom_frames_lock.release() + + +def getCustomFrame(thread_id, frame_id): + ''' + :param thread_id: This should actually be the frame_id which is returned by addCustomFrame. + :param frame_id: This is the actual id() of the frame + ''' + + CustomFramesContainer.custom_frames_lock.acquire() + try: + frame_id = int(frame_id) + f = CustomFramesContainer.custom_frames[thread_id].frame + while f is not None: + if id(f) == frame_id: + return f + f = f.f_back + finally: + f = None + CustomFramesContainer.custom_frames_lock.release() + + +def removeCustomFrame(frame_id): + CustomFramesContainer.custom_frames_lock.acquire() + try: + if DEBUG: + sys.stderr.write('removeCustomFrame: %s\n' % frame_id) + DictPop(CustomFramesContainer.custom_frames, frame_id, None) + CustomFramesContainer._py_db_command_thread_event.set() + finally: + CustomFramesContainer.custom_frames_lock.release() diff --git a/python/helpers/pydev/pydevd_exec.py b/python/helpers/pydev/pydevd_exec.py index 6cffeaf86e27..9a342ee1b015 100644 --- a/python/helpers/pydev/pydevd_exec.py +++ b/python/helpers/pydev/pydevd_exec.py @@ -1,2 +1,5 @@ -def Exec(exp, global_vars, local_vars): - exec exp in global_vars, local_vars \ No newline at end of file +def Exec(exp, global_vars, local_vars=None): + if local_vars is not None: + exec exp in global_vars, local_vars + else: + exec exp in global_vars \ No newline at end of file diff --git a/python/helpers/pydev/pydevd_exec2.py b/python/helpers/pydev/pydevd_exec2.py index 9b234b76344d..ee4f37a6c792 100644 --- a/python/helpers/pydev/pydevd_exec2.py +++ b/python/helpers/pydev/pydevd_exec2.py @@ -1,2 +1,5 @@ -def Exec(exp, global_vars, local_vars): - exec(exp, global_vars, local_vars) \ No newline at end of file +def Exec(exp, global_vars, local_vars=None): + if local_vars is not None: + exec(exp, global_vars, local_vars) + else: + exec(exp, global_vars) \ No newline at end of file diff --git a/python/helpers/pydev/pydevd_frame.py b/python/helpers/pydev/pydevd_frame.py index a418c7e5bcfa..05faaeb77ff2 100644 --- a/python/helpers/pydev/pydevd_frame.py +++ b/python/helpers/pydev/pydevd_frame.py @@ -210,6 +210,7 @@ class PyDBFrame: return self.trace_dispatch except: + traceback.print_exc() raise #step handling. We stop when we hit the right frame diff --git a/python/helpers/pydev/pydevd_import_class.py b/python/helpers/pydev/pydevd_import_class.py index c84b0cee3b61..3c3bec848abd 100644 --- a/python/helpers/pydev/pydevd_import_class.py +++ b/python/helpers/pydev/pydevd_import_class.py @@ -1,4 +1,4 @@ -#Note: code gotten from importsTipper. +#Note: code gotten from _pydev_imports_tipper. import sys diff --git a/python/helpers/pydev/pydevd_io.py b/python/helpers/pydev/pydevd_io.py index ca8c49308daa..a83adc8de2b9 100644 --- a/python/helpers/pydev/pydevd_io.py +++ b/python/helpers/pydev/pydevd_io.py @@ -1,10 +1,14 @@ +import pydevd_constants #@UnusedImport -- defines False and True if not there. + +IS_PY3K = pydevd_constants.IS_PY3K + class IORedirector: '''This class works to redirect the write function to many streams ''' - + def __init__(self, *args): self._redirectTo = args - + def write(self, s): for r in self._redirectTo: try: @@ -13,7 +17,7 @@ class IORedirector: pass def isatty(self): - return False #not really a file + return False def flush(self): for r in self._redirectTo: @@ -33,17 +37,22 @@ class IOBuf: ''' def __init__(self): self.buflist = [] - + import os + self.encoding = os.environ.get('PYTHONIOENCODING', 'utf-8') + def getvalue(self): b = self.buflist self.buflist = [] #clear it return ''.join(b) def write(self, s): + if not IS_PY3K: + if isinstance(s, unicode): + s = s.encode(self.encoding) self.buflist.append(s) def isatty(self): - return False #not really a file + return False def flush(self): pass @@ -88,4 +97,3 @@ def EndRedirect(std='stdout'): stack = getattr(_RedirectionsHolder, '_stack_%s' % std) setattr(sys, std, stack.pop()) - diff --git a/python/helpers/pydev/pydevd_reload.py b/python/helpers/pydev/pydevd_reload.py index 03ca2fdc74ba..1533c8958a88 100644 --- a/python/helpers/pydev/pydevd_reload.py +++ b/python/helpers/pydev/pydevd_reload.py @@ -1,208 +1,453 @@ """ -Copied from the python xreload (available for change) +Based on the python xreload. + +Changes +====================== + +1. we don't recreate the old namespace from new classes. Rather, we keep the existing namespace, +load a new version of it and update only some of the things we can inplace. That way, we don't break +things such as singletons or end up with a second representation of the same class in memory. + +2. If we find it to be a __metaclass__, we try to update it as a regular class. + +3. We don't remove old attributes (and leave them lying around even if they're no longer used). + +4. Reload hooks were changed + +These changes make it more stable, especially in the common case (where in a debug session only the +contents of a function are changed), besides providing flexibility for users that want to extend +on it. + + + +Hooks +====================== + +Classes/modules can be specially crafted to work with the reload (so that it can, for instance, +update some constant which was changed). + +1. To participate in the change of some attribute: + + In a module: + + __xreload_old_new__(namespace, name, old, new) + + in a class: + + @classmethod + __xreload_old_new__(cls, name, old, new) + + A class or module may include a method called '__xreload_old_new__' which is called when we're + unable to reload a given attribute. + + + +2. To do something after the whole reload is finished: + + In a module: + + __xreload_after_reload_update__(namespace): + + In a class: + + @classmethod + __xreload_after_reload_update__(cls): + + + A class or module may include a method called '__xreload_after_reload_update__' which is called + after the reload finishes. + + +Important: when providing a hook, always use the namespace or cls provided and not anything in the global +namespace, as the global namespace are only temporarily created during the reload and may not reflect the +actual application state (while the cls and namespace passed are). + + +Current limitations +====================== + + +- Attributes/constants are added, but not changed (so singletons and the application state is not + broken -- use provided hooks to workaround it). + +- Code using metaclasses may not always work. + +- Functions and methods using decorators (other than classmethod and staticmethod) are not handled + correctly. + +- Renamings are not handled correctly. + +- Dependent modules are not reloaded. + +- New __slots__ can't be added to existing classes. + + +Info +====================== + +Original: http://svn.python.org/projects/sandbox/trunk/xreload/xreload.py +Note: it seems https://github.com/plone/plone.reload/blob/master/plone/reload/xreload.py enhances it (to check later) + +Interesting alternative: https://code.google.com/p/reimport/ Alternative to reload(). -This works by executing the module in a scratch namespace, and then -patching classes, methods and functions in place. This avoids the -need to patch instances. New objects are copied into the target -namespace. +This works by executing the module in a scratch namespace, and then patching classes, methods and +functions in place. This avoids the need to patch instances. New objects are copied into the +target namespace. -Some of the many limitations include: - -- Global mutable objects other than classes are simply replaced, not patched - -- Code using metaclasses is not handled correctly - -- Code creating global singletons is not handled correctly - -- Functions and methods using decorators (other than classmethod and - staticmethod) is not handled correctly - -- Renamings are not handled correctly - -- Dependent modules are not reloaded - -- When a dependent module contains 'from foo import bar', and - reloading foo deletes foo.bar, the dependent module continues to use - the old foo.bar object rather than failing - -- Frozen modules and modules loaded from zip files aren't handled - correctly - -- Classes involving __slots__ are not handled correctly """ import imp +from pydev_imports import Exec +import pydevd_dont_trace import sys +import traceback import types +NO_DEBUG = 0 +LEVEL1 = 1 +LEVEL2 = 2 +DEBUG = NO_DEBUG + +def write(*args): + new_lst = [] + for a in args: + new_lst.append(str(a)) + + msg = ' '.join(new_lst) + sys.stdout.write('%s\n' % (msg,)) + +def write_err(*args): + new_lst = [] + for a in args: + new_lst.append(str(a)) + + msg = ' '.join(new_lst) + sys.stderr.write('pydev debugger: %s\n' % (msg,)) + +def notify_info0(*args): + write_err(*args) + +def notify_info(*args): + if DEBUG >= LEVEL1: + write(*args) + +def notify_info2(*args): + if DEBUG >= LEVEL2: + write(*args) + +def notify_error(*args): + write_err(*args) + + + +#======================================================================================================================= +# code_objects_equal +#======================================================================================================================= +def code_objects_equal(code0, code1): + for d in dir(code0): + if d.startswith('_') or 'lineno' in d: + continue + if getattr(code0, d) != getattr(code1, d): + return False + return True + + +#======================================================================================================================= +# xreload +#======================================================================================================================= def xreload(mod): """Reload a module in place, updating classes, methods and functions. - Args: - mod: a module object + mod: a module object - Returns: - The (updated) input object itself. + Returns a boolean indicating whether a change was done. """ - # Get the module name, e.g. 'foo.bar.whatever' - modname = mod.__name__ - # Get the module namespace (dict) early; this is part of the type check - modns = mod.__dict__ - # Parse it into package name and module name, e.g. 'foo.bar' and 'whatever' - i = modname.rfind(".") - if i >= 0: - pkgname, modname = modname[:i], modname[i+1:] - else: - pkgname = None - # Compute the search path - if pkgname: - # We're not reloading the package, only the module in it - pkg = sys.modules[pkgname] - path = pkg.__path__ # Search inside the package - else: - # Search the top-level module path - pkg = None - path = None # Make find_module() uses the default search path - # Find the module; may raise ImportError - (stream, filename, (suffix, mode, kind)) = imp.find_module(modname, path) - # Turn it into a code object - try: - # Is it Python source code or byte code read from a file? - if kind not in (imp.PY_COMPILED, imp.PY_SOURCE): - # Fall back to built-in reload() - return reload(mod) - if kind == imp.PY_SOURCE: - source = stream.read() - code = compile(source, filename, "exec") - else: - import marshal - code = marshal.load(stream) - finally: - if stream: - stream.close() - # Execute the code. We copy the module dict to a temporary; then - # clear the module dict; then execute the new code in the module - # dict; then swap things back and around. This trick (due to - # Glyph Lefkowitz) ensures that the (readonly) __globals__ - # attribute of methods and functions is set to the correct dict - # object. - tmpns = modns.copy() - modns.clear() - modns["__name__"] = tmpns["__name__"] - exec(code, modns) - # Now we get to the hard part - oldnames = set(tmpns) - newnames = set(modns) - # Update attributes in place - for name in oldnames & newnames: - modns[name] = _update(tmpns[name], modns[name]) - # Done! - return mod + r = Reload(mod) + r.apply() + found_change = r.found_change + r = None + pydevd_dont_trace.clear_trace_filter_cache() + return found_change -def _update(oldobj, newobj): - """Update oldobj, if possible in place, with newobj. - - If oldobj is immutable, this simply returns newobj. - - Args: - oldobj: the object to be updated - newobj: the object used as the source for the update - - Returns: - either oldobj, updated in place, or newobj. - """ - if oldobj is newobj: - # Probably something imported - return newobj - if type(oldobj) is not type(newobj): - # Cop-out: if the type changed, give up - return newobj - if hasattr(newobj, "__reload_update__"): - # Provide a hook for updating - return newobj.__reload_update__(oldobj) - - if hasattr(types, 'ClassType'): - classtype = types.ClassType - else: - classtype = type - - if isinstance(newobj, classtype): - return _update_class(oldobj, newobj) - if isinstance(newobj, types.FunctionType): - return _update_function(oldobj, newobj) - if isinstance(newobj, types.MethodType): - return _update_method(oldobj, newobj) - if isinstance(newobj, classmethod): - return _update_classmethod(oldobj, newobj) - if isinstance(newobj, staticmethod): - return _update_staticmethod(oldobj, newobj) - # Not something we recognize, just give up - return newobj +# This isn't actually used... Initially I planned to reload variables which are immutable on the +# namespace, but this can destroy places where we're saving state, which may not be what we want, +# so, we're being conservative and giving the user hooks if he wants to do a reload. +# +# immutable_types = [int, str, float, tuple] #That should be common to all Python versions +# +# for name in 'long basestr unicode frozenset'.split(): +# try: +# immutable_types.append(__builtins__[name]) +# except: +# pass #Just ignore: not all python versions are created equal. +# immutable_types = tuple(immutable_types) -# All of the following functions have the same signature as _update() +#======================================================================================================================= +# Reload +#======================================================================================================================= +class Reload: + + def __init__(self, mod): + self.mod = mod + self.found_change = False + + def apply(self): + mod = self.mod + self._on_finish_callbacks = [] + try: + # Get the module name, e.g. 'foo.bar.whatever' + modname = mod.__name__ + # Get the module namespace (dict) early; this is part of the type check + modns = mod.__dict__ + # Parse it into package name and module name, e.g. 'foo.bar' and 'whatever' + i = modname.rfind(".") + if i >= 0: + pkgname, modname = modname[:i], modname[i + 1:] + else: + pkgname = None + # Compute the search path + if pkgname: + # We're not reloading the package, only the module in it + pkg = sys.modules[pkgname] + path = pkg.__path__ # Search inside the package + else: + # Search the top-level module path + pkg = None + path = None # Make find_module() uses the default search path + # Find the module; may raise ImportError + (stream, filename, (suffix, mode, kind)) = imp.find_module(modname, path) + # Turn it into a code object + try: + # Is it Python source code or byte code read from a file? + if kind not in (imp.PY_COMPILED, imp.PY_SOURCE): + # Fall back to built-in reload() + notify_error('Could not find source to reload (mod: %s)' % (modname,)) + return + if kind == imp.PY_SOURCE: + source = stream.read() + code = compile(source, filename, "exec") + else: + import marshal + code = marshal.load(stream) + finally: + if stream: + stream.close() + # Execute the code. We copy the module dict to a temporary; then + # clear the module dict; then execute the new code in the module + # dict; then swap things back and around. This trick (due to + # Glyph Lefkowitz) ensures that the (readonly) __globals__ + # attribute of methods and functions is set to the correct dict + # object. + new_namespace = modns.copy() + new_namespace.clear() + new_namespace["__name__"] = modns["__name__"] + Exec(code, new_namespace) + # Now we get to the hard part + oldnames = set(modns) + newnames = set(new_namespace) + + # Create new tokens (note: not deleting existing) + for name in newnames - oldnames: + notify_info0('Added:', name, 'to namespace') + self.found_change = True + modns[name] = new_namespace[name] + + # Update in-place what we can + for name in oldnames & newnames: + self._update(modns, name, modns[name], new_namespace[name]) + + self._handle_namespace(modns) + + for c in self._on_finish_callbacks: + c() + del self._on_finish_callbacks[:] + except: + traceback.print_exc() -def _update_function(oldfunc, newfunc): - """Update a function object.""" - oldfunc.__doc__ = newfunc.__doc__ - oldfunc.__dict__.update(newfunc.__dict__) - - try: - oldfunc.__code__ = newfunc.__code__ - except AttributeError: - oldfunc.func_code = newfunc.func_code - try: - oldfunc.__defaults__ = newfunc.__defaults__ - except AttributeError: - oldfunc.func_defaults = newfunc.func_defaults - - return oldfunc + def _handle_namespace(self, namespace, is_class_namespace=False): + on_finish = None + if is_class_namespace: + xreload_after_update = getattr(namespace, '__xreload_after_reload_update__', None) + if xreload_after_update is not None: + self.found_change = True + on_finish = lambda: xreload_after_update() + + elif '__xreload_after_reload_update__' in namespace: + xreload_after_update = namespace['__xreload_after_reload_update__'] + self.found_change = True + on_finish = lambda: xreload_after_update(namespace) -def _update_method(oldmeth, newmeth): - """Update a method object.""" - # XXX What if im_func is not a function? - _update(oldmeth.im_func, newmeth.im_func) - return oldmeth + if on_finish is not None: + # If a client wants to know about it, give him a chance. + self._on_finish_callbacks.append(on_finish) -def _update_class(oldclass, newclass): - """Update a class object.""" - olddict = oldclass.__dict__ - newdict = newclass.__dict__ - oldnames = set(olddict) - newnames = set(newdict) - for name in newnames - oldnames: - setattr(oldclass, name, newdict[name]) - for name in oldnames - newnames: - delattr(oldclass, name) - for name in oldnames & newnames - set(['__dict__', '__doc__']): - setattr(oldclass, name, _update(olddict[name], newdict[name])) - return oldclass + + def _update(self, namespace, name, oldobj, newobj, is_class_namespace=False): + """Update oldobj, if possible in place, with newobj. + + If oldobj is immutable, this simply returns newobj. + + Args: + oldobj: the object to be updated + newobj: the object used as the source for the update + """ + try: + notify_info2('Updating: ', oldobj) + if oldobj is newobj: + # Probably something imported + return + + if type(oldobj) is not type(newobj): + # Cop-out: if the type changed, give up + notify_error('Type of: %s changed... Skipping.' % (oldobj,)) + return + + if isinstance(newobj, types.FunctionType): + self._update_function(oldobj, newobj) + return + + if isinstance(newobj, types.MethodType): + self._update_method(oldobj, newobj) + return + + if isinstance(newobj, classmethod): + self._update_classmethod(oldobj, newobj) + return + + if isinstance(newobj, staticmethod): + self._update_staticmethod(oldobj, newobj) + return + + if hasattr(types, 'ClassType'): + classtype = (types.ClassType, type) #object is not instance of types.ClassType. + else: + classtype = type + + if isinstance(newobj, classtype): + self._update_class(oldobj, newobj) + return + + # New: dealing with metaclasses. + if hasattr(newobj, '__metaclass__') and hasattr(newobj, '__class__') and newobj.__metaclass__ == newobj.__class__: + self._update_class(oldobj, newobj) + return + + if namespace is not None: + + if oldobj != newobj and str(oldobj) != str(newobj) and repr(oldobj) != repr(newobj): + xreload_old_new = None + if is_class_namespace: + xreload_old_new = getattr(namespace, '__xreload_old_new__', None) + if xreload_old_new is not None: + self.found_change = True + xreload_old_new(name, oldobj, newobj) + + elif '__xreload_old_new__' in namespace: + xreload_old_new = namespace['__xreload_old_new__'] + xreload_old_new(namespace, name, oldobj, newobj) + self.found_change = True + + # Too much information to the user... + # else: + # notify_info0('%s NOT updated. Create __xreload_old_new__(name, old, new) for custom reload' % (name,)) + + except: + notify_error('Exception found when updating %s. Proceeding for other items.' % (name,)) + traceback.print_exc() -def _update_classmethod(oldcm, newcm): - """Update a classmethod update.""" - # While we can't modify the classmethod object itself (it has no - # mutable attributes), we *can* extract the underlying function - # (by calling __get__(), which returns a method object) and update - # it in-place. We don't have the class available to pass to - # __get__() but any object except None will do. - _update(oldcm.__get__(0), newcm.__get__(0)) - return newcm + # All of the following functions have the same signature as _update() -def _update_staticmethod(oldsm, newsm): - """Update a staticmethod update.""" - # While we can't modify the staticmethod object itself (it has no - # mutable attributes), we *can* extract the underlying function - # (by calling __get__(), which returns it) and update it in-place. - # We don't have the class available to pass to __get__() but any - # object except None will do. - _update(oldsm.__get__(0), newsm.__get__(0)) - return newsm + def _update_function(self, oldfunc, newfunc): + """Update a function object.""" + oldfunc.__doc__ = newfunc.__doc__ + oldfunc.__dict__.update(newfunc.__dict__) + + try: + newfunc.__code__ + attr_name = '__code__' + except AttributeError: + newfunc.func_code + attr_name = 'func_code' + + old_code = getattr(oldfunc, attr_name) + new_code = getattr(newfunc, attr_name) + if not code_objects_equal(old_code, new_code): + notify_info0('Updated function code:', oldfunc) + setattr(oldfunc, attr_name, new_code) + self.found_change = True + + try: + oldfunc.__defaults__ = newfunc.__defaults__ + except AttributeError: + oldfunc.func_defaults = newfunc.func_defaults + + return oldfunc + + + def _update_method(self, oldmeth, newmeth): + """Update a method object.""" + # XXX What if im_func is not a function? + if hasattr(oldmeth, 'im_func') and hasattr(newmeth, 'im_func'): + self._update(None, None, oldmeth.im_func, newmeth.im_func) + elif hasattr(oldmeth, '__func__') and hasattr(newmeth, '__func__'): + self._update(None, None, oldmeth.__func__, newmeth.__func__) + return oldmeth + + + def _update_class(self, oldclass, newclass): + """Update a class object.""" + olddict = oldclass.__dict__ + newdict = newclass.__dict__ + + oldnames = set(olddict) + newnames = set(newdict) + + for name in newnames - oldnames: + setattr(oldclass, name, newdict[name]) + notify_info0('Added:', name, 'to', oldclass) + self.found_change = True + + # Note: not removing old things... + # for name in oldnames - newnames: + # notify_info('Removed:', name, 'from', oldclass) + # delattr(oldclass, name) + + for name in (oldnames & newnames) - set(['__dict__', '__doc__']): + self._update(oldclass, name, olddict[name], newdict[name], is_class_namespace=True) + + old_bases = getattr(oldclass, '__bases__', None) + new_bases = getattr(newclass, '__bases__', None) + if str(old_bases) != str(new_bases): + notify_error('Changing the hierarchy of a class is not supported. %s may be inconsistent.' % (oldclass,)) + + self._handle_namespace(oldclass, is_class_namespace=True) + + + def _update_classmethod(self, oldcm, newcm): + """Update a classmethod update.""" + # While we can't modify the classmethod object itself (it has no + # mutable attributes), we *can* extract the underlying function + # (by calling __get__(), which returns a method object) and update + # it in-place. We don't have the class available to pass to + # __get__() but any object except None will do. + self._update(None, None, oldcm.__get__(0), newcm.__get__(0)) + + + def _update_staticmethod(self, oldsm, newsm): + """Update a staticmethod update.""" + # While we can't modify the staticmethod object itself (it has no + # mutable attributes), we *can* extract the underlying function + # (by calling __get__(), which returns it) and update it in-place. + # We don't have the class available to pass to __get__() but any + # object except None will do. + self._update(None, None, oldsm.__get__(0), newsm.__get__(0)) diff --git a/python/helpers/pydev/pydevd_resolver.py b/python/helpers/pydev/pydevd_resolver.py index 114b8494b654..614549f74f37 100644 --- a/python/helpers/pydev/pydevd_resolver.py +++ b/python/helpers/pydev/pydevd_resolver.py @@ -3,6 +3,7 @@ try: except: import io as StringIO import traceback +from os.path import basename try: __setFalse = False @@ -357,9 +358,100 @@ class JyArrayResolver: ret['__len__'] = len(obj) return ret + +#======================================================================================================================= +# NdArrayResolver +#======================================================================================================================= +class NdArrayResolver: + ''' + This resolves a numpy ndarray returning some metadata about the NDArray + ''' + + def resolve(self, obj, attribute): + if attribute == '__internals__': + return defaultResolver.getDictionary(obj) + if attribute == 'min': + return obj.min() + if attribute == 'max': + return obj.max() + if attribute == 'shape': + return obj.shape + if attribute == 'dtype': + return obj.dtype + if attribute == 'size': + return obj.size + return None + + def getDictionary(self, obj): + ret = dict() + ret['__internals__'] = defaultResolver.getDictionary(obj) + if obj.size > 1024 * 1024: + ret['min'] = 'ndarray too big, calculating min would slow down debugging' + ret['max'] = 'ndarray too big, calculating max would slow down debugging' + else: + ret['min'] = obj.min() + ret['max'] = obj.max() + ret['shape'] = obj.shape + ret['dtype'] = obj.dtype + ret['size'] = obj.size + return ret + + +#======================================================================================================================= +# FrameResolver +#======================================================================================================================= +class FrameResolver: + ''' + This resolves a frame. + ''' + + def resolve(self, obj, attribute): + if attribute == '__internals__': + return defaultResolver.getDictionary(obj) + + if attribute == 'stack': + return self.getFrameStack(obj) + + if attribute == 'f_locals': + return obj.f_locals + + return None + + + def getDictionary(self, obj): + ret = dict() + ret['__internals__'] = defaultResolver.getDictionary(obj) + ret['stack'] = self.getFrameStack(obj) + ret['f_locals'] = obj.f_locals + return ret + + + def getFrameStack(self, frame): + ret = [] + if frame is not None: + ret.append(self.getFrameName(frame)) + + while frame.f_back: + frame = frame.f_back + ret.append(self.getFrameName(frame)) + + return ret + + def getFrameName(self, frame): + if frame is None: + return 'None' + try: + name = basename(frame.f_code.co_filename) + return 'frame: %s [%s:%s] id:%s' % (frame.f_code.co_name, name, frame.f_lineno, id(frame)) + except: + return 'frame object' + + defaultResolver = DefaultResolver() dictResolver = DictResolver() tupleResolver = TupleResolver() instanceResolver = InstanceResolver() jyArrayResolver = JyArrayResolver() setResolver = SetResolver() +ndarrayResolver = NdArrayResolver() +frameResolver = FrameResolver() diff --git a/python/helpers/pydev/pydevd_save_locals.py b/python/helpers/pydev/pydevd_save_locals.py new file mode 100644 index 000000000000..2808081a5866 --- /dev/null +++ b/python/helpers/pydev/pydevd_save_locals.py @@ -0,0 +1,58 @@ +""" +Utility for saving locals. +""" +import sys + +def is_save_locals_available(): + try: + if '__pypy__' in sys.builtin_module_names: + import __pypy__ + save_locals = __pypy__.locals_to_fast + return True + except: + pass + + + try: + import ctypes + except: + return False #Not all Python versions have it + + try: + func = ctypes.pythonapi.PyFrame_LocalsToFast + except: + return False + + return True + +def save_locals(frame): + """ + Copy values from locals_dict into the fast stack slots in the given frame. + + Note: the 'save_locals' branch had a different approach wrapping the frame (much more code, but it gives ideas + on how to save things partially, not the 'whole' locals). + """ + try: + if '__pypy__' in sys.builtin_module_names: + import __pypy__ + save_locals = __pypy__.locals_to_fast + save_locals(frame) + return + except: + pass + + + try: + import ctypes + except: + return #Not all Python versions have it + + try: + func = ctypes.pythonapi.PyFrame_LocalsToFast + except: + return + + #parameter 0: don't set to null things that are not in the frame.f_locals (which seems good in the debugger context). + func(ctypes.py_object(frame), ctypes.c_int(0)) + + diff --git a/python/helpers/pydev/pydevd_stackless.py b/python/helpers/pydev/pydevd_stackless.py new file mode 100644 index 000000000000..bd3b306dad63 --- /dev/null +++ b/python/helpers/pydev/pydevd_stackless.py @@ -0,0 +1,412 @@ +from __future__ import nested_scopes +from pydevd_constants import * # @UnusedWildImport +import stackless # @UnresolvedImport +from pydevd_tracing import SetTrace +from pydevd_custom_frames import updateCustomFrame, removeCustomFrame, addCustomFrame +from pydevd_comm import GetGlobalDebugger +import weakref +from pydevd_file_utils import GetFilenameAndBase +from pydevd import DONT_TRACE + + +# Used so that we don't loose the id (because we'll remove when it's not alive and would generate a new id for the +# same tasklet). +class TaskletToLastId: + ''' + So, why not a WeakKeyDictionary? + The problem is that removals from the WeakKeyDictionary will create a new tasklet (as it adds a callback to + remove the key when it's garbage-collected), so, we can get into a recursion. + ''' + + def __init__(self): + self.tasklet_ref_to_last_id = {} + self._i = 0 + + + def get(self, tasklet): + return self.tasklet_ref_to_last_id.get(weakref.ref(tasklet)) + + + def __setitem__(self, tasklet, last_id): + self.tasklet_ref_to_last_id[weakref.ref(tasklet)] = last_id + self._i += 1 + if self._i % 100 == 0: #Collect at each 100 additions to the dict (no need to rush). + for tasklet_ref in list(self.tasklet_ref_to_last_id.keys()): + if tasklet_ref() is None: + del self.tasklet_ref_to_last_id[tasklet_ref] + + +_tasklet_to_last_id = TaskletToLastId() + +#======================================================================================================================= +# _TaskletInfo +#======================================================================================================================= +class _TaskletInfo: + + _last_id = 0 + + def __init__(self, tasklet_weakref, tasklet): + self.frame_id = None + self.tasklet_weakref = tasklet_weakref + + last_id = _tasklet_to_last_id.get(tasklet) + if last_id is None: + _TaskletInfo._last_id += 1 + last_id = _TaskletInfo._last_id + _tasklet_to_last_id[tasklet] = last_id + + self._tasklet_id = last_id + + self.update_name() + + def update_name(self): + tasklet = self.tasklet_weakref() + if tasklet: + if tasklet.blocked: + state = 'blocked' + elif tasklet.paused: + state = 'paused' + elif tasklet.scheduled: + state = 'scheduled' + else: + state = '' + + try: + name = tasklet.name + except AttributeError: + if tasklet.is_main: + name = 'MainTasklet' + else: + name = 'Tasklet-%s' % (self._tasklet_id,) + + thread_id = tasklet.thread_id + if thread_id != -1: + for thread in threading.enumerate(): + if thread.ident == thread_id: + if thread.name: + thread_name = "of %s" % (thread.name,) + else: + thread_name = "of Thread-%s" % (thread.name or str(thread_id),) + break + else: + # should not happen. + thread_name = "of Thread-%s" % (str(thread_id),) + thread = None + else: + # tasklet is no longer bound to a thread, because its thread ended + thread_name = "without thread" + + tid = id(tasklet) + tasklet = None + else: + state = 'dead' + name = 'Tasklet-%s' % (self._tasklet_id,) + thread_name = "" + tid = '-' + self.tasklet_name = '%s %s %s (%s)' % (state, name, thread_name, tid) + + if not hasattr(stackless.tasklet, "trace_function"): + # bug https://bitbucket.org/stackless-dev/stackless/issue/42 + # is not fixed. Stackless releases before 2014 + def update_name(self): + tasklet = self.tasklet_weakref() + if tasklet: + try: + name = tasklet.name + except AttributeError: + if tasklet.is_main: + name = 'MainTasklet' + else: + name = 'Tasklet-%s' % (self._tasklet_id,) + + thread_id = tasklet.thread_id + for thread in threading.enumerate(): + if thread.ident == thread_id: + if thread.name: + thread_name = "of %s" % (thread.name,) + else: + thread_name = "of Thread-%s" % (thread.name or str(thread_id),) + break + else: + # should not happen. + thread_name = "of Thread-%s" % (str(thread_id),) + thread = None + + tid = id(tasklet) + tasklet = None + else: + name = 'Tasklet-%s' % (self._tasklet_id,) + thread_name = "" + tid = '-' + self.tasklet_name = '%s %s (%s)' % (name, thread_name, tid) + +_weak_tasklet_registered_to_info = {} + +#======================================================================================================================= +# get_tasklet_info +#======================================================================================================================= +def get_tasklet_info(tasklet): + return register_tasklet_info(tasklet) + + +#======================================================================================================================= +# register_tasklet_info +#======================================================================================================================= +def register_tasklet_info(tasklet): + r = weakref.ref(tasklet) + info = _weak_tasklet_registered_to_info.get(r) + if info is None: + info = _weak_tasklet_registered_to_info[r] = _TaskletInfo(r, tasklet) + + return info + + +_application_set_schedule_callback = None + +#======================================================================================================================= +# _schedule_callback +#======================================================================================================================= +def _schedule_callback(prev, next): + ''' + Called when a context is stopped or a new context is made runnable. + ''' + try: + if not prev and not next: + return + + current_frame = sys._getframe() + + if next: + register_tasklet_info(next) + + # Ok, making next runnable: set the tracing facility in it. + debugger = GetGlobalDebugger() + if debugger is not None: + next.trace_function = debugger.trace_dispatch + frame = next.frame + if frame is current_frame: + frame = frame.f_back + if hasattr(frame, 'f_trace'): # Note: can be None (but hasattr should cover for that too). + frame.f_trace = debugger.trace_dispatch + + debugger = None + + if prev: + register_tasklet_info(prev) + + try: + for tasklet_ref, tasklet_info in list(_weak_tasklet_registered_to_info.items()): # Make sure it's a copy! + tasklet = tasklet_ref() + if tasklet is None or not tasklet.alive: + # Garbage-collected already! + try: + del _weak_tasklet_registered_to_info[tasklet_ref] + except KeyError: + pass + if tasklet_info.frame_id is not None: + removeCustomFrame(tasklet_info.frame_id) + else: + is_running = stackless.get_thread_info(tasklet.thread_id)[1] is tasklet + if tasklet is prev or (tasklet is not next and not is_running): + # the tasklet won't run after this scheduler action: + # - the tasklet is the previous tasklet + # - it is not the next tasklet and it is not an already running tasklet + frame = tasklet.frame + if frame is current_frame: + frame = frame.f_back + if frame is not None: + _filename, base = GetFilenameAndBase(frame) + # print >>sys.stderr, "SchedCB: %r, %d, '%s', '%s'" % (tasklet, frame.f_lineno, _filename, base) + is_file_to_ignore = DictContains(DONT_TRACE, base) + if not is_file_to_ignore: + tasklet_info.update_name() + if tasklet_info.frame_id is None: + tasklet_info.frame_id = addCustomFrame(frame, tasklet_info.tasklet_name, tasklet.thread_id) + else: + updateCustomFrame(tasklet_info.frame_id, frame, tasklet.thread_id, name=tasklet_info.tasklet_name) + + elif tasklet is next or is_running: + if tasklet_info.frame_id is not None: + # Remove info about stackless suspended when it starts to run. + removeCustomFrame(tasklet_info.frame_id) + tasklet_info.frame_id = None + + + finally: + tasklet = None + tasklet_info = None + frame = None + + except: + import traceback;traceback.print_exc() + + if _application_set_schedule_callback is not None: + return _application_set_schedule_callback(prev, next) + +if not hasattr(stackless.tasklet, "trace_function"): + # Older versions of Stackless, released before 2014 + # This code does not work reliable! It is affected by several + # stackless bugs: Stackless issues #44, #42, #40 + def _schedule_callback(prev, next): + ''' + Called when a context is stopped or a new context is made runnable. + ''' + try: + if not prev and not next: + return + + if next: + register_tasklet_info(next) + + # Ok, making next runnable: set the tracing facility in it. + debugger = GetGlobalDebugger() + if debugger is not None and next.frame: + if hasattr(next.frame, 'f_trace'): + next.frame.f_trace = debugger.trace_dispatch + debugger = None + + if prev: + register_tasklet_info(prev) + + try: + for tasklet_ref, tasklet_info in list(_weak_tasklet_registered_to_info.items()): # Make sure it's a copy! + tasklet = tasklet_ref() + if tasklet is None or not tasklet.alive: + # Garbage-collected already! + try: + del _weak_tasklet_registered_to_info[tasklet_ref] + except KeyError: + pass + if tasklet_info.frame_id is not None: + removeCustomFrame(tasklet_info.frame_id) + else: + if tasklet.paused or tasklet.blocked or tasklet.scheduled: + if tasklet.frame and tasklet.frame.f_back: + f_back = tasklet.frame.f_back + _filename, base = GetFilenameAndBase(f_back) + is_file_to_ignore = DictContains(DONT_TRACE, base) + if not is_file_to_ignore: + if tasklet_info.frame_id is None: + tasklet_info.frame_id = addCustomFrame(f_back, tasklet_info.tasklet_name, tasklet.thread_id) + else: + updateCustomFrame(tasklet_info.frame_id, f_back, tasklet.thread_id) + + elif tasklet.is_current: + if tasklet_info.frame_id is not None: + # Remove info about stackless suspended when it starts to run. + removeCustomFrame(tasklet_info.frame_id) + tasklet_info.frame_id = None + + finally: + tasklet = None + tasklet_info = None + f_back = None + + except: + import traceback;traceback.print_exc() + + if _application_set_schedule_callback is not None: + return _application_set_schedule_callback(prev, next) + + + _original_setup = stackless.tasklet.setup + + #======================================================================================================================= + # setup + #======================================================================================================================= + def setup(self, *args, **kwargs): + ''' + Called to run a new tasklet: rebind the creation so that we can trace it. + ''' + + f = self.tempval + def new_f(old_f, args, kwargs): + + debugger = GetGlobalDebugger() + if debugger is not None: + SetTrace(debugger.trace_dispatch) + + debugger = None + + # Remove our own traces :) + self.tempval = old_f + register_tasklet_info(self) + + # Hover old_f to see the stackless being created and *args and **kwargs to see its parameters. + return old_f(*args, **kwargs) + + # This is the way to tell stackless that the function it should execute is our function, not the original one. Note: + # setting tempval is the same as calling bind(new_f), but it seems that there's no other way to get the currently + # bound function, so, keeping on using tempval instead of calling bind (which is actually the same thing in a better + # API). + + self.tempval = new_f + + return _original_setup(self, f, args, kwargs) + + #======================================================================================================================= + # __call__ + #======================================================================================================================= + def __call__(self, *args, **kwargs): + ''' + Called to run a new tasklet: rebind the creation so that we can trace it. + ''' + + return setup(self, *args, **kwargs) + + + _original_run = stackless.run + + + #======================================================================================================================= + # run + #======================================================================================================================= + def run(*args, **kwargs): + debugger = GetGlobalDebugger() + if debugger is not None: + SetTrace(debugger.trace_dispatch) + debugger = None + + return _original_run(*args, **kwargs) + + + +#======================================================================================================================= +# patch_stackless +#======================================================================================================================= +def patch_stackless(): + ''' + This function should be called to patch the stackless module so that new tasklets are properly tracked in the + debugger. + ''' + global _application_set_schedule_callback + _application_set_schedule_callback = stackless.set_schedule_callback(_schedule_callback) + + def set_schedule_callback(callable): + global _application_set_schedule_callback + old = _application_set_schedule_callback + _application_set_schedule_callback = callable + return old + + def get_schedule_callback(callable): + global _application_set_schedule_callback + return _application_set_schedule_callback + + set_schedule_callback.__doc__ = stackless.set_schedule_callback.__doc__ + if hasattr(stackless, "get_schedule_callback"): + get_schedule_callback.__doc__ = stackless.get_schedule_callback.__doc__ + stackless.set_schedule_callback = set_schedule_callback + stackless.get_schedule_callback = get_schedule_callback + + if not hasattr(stackless.tasklet, "trace_function"): + # Older versions of Stackless, released before 2014 + __call__.__doc__ = stackless.tasklet.__call__.__doc__ + stackless.tasklet.__call__ = __call__ + + setup.__doc__ = stackless.tasklet.setup.__doc__ + stackless.tasklet.setup = setup + + run.__doc__ = stackless.run.__doc__ + stackless.run = run + +patch_stackless = call_only_once(patch_stackless) diff --git a/python/helpers/pydev/pydevd_tracing.py b/python/helpers/pydev/pydevd_tracing.py index 7c197efc2002..1a5a833f6bd0 100644 --- a/python/helpers/pydev/pydevd_tracing.py +++ b/python/helpers/pydev/pydevd_tracing.py @@ -68,6 +68,11 @@ def _InternalSetTrace(tracing_func): TracingFunctionHolder._original_tracing(tracing_func) def SetTrace(tracing_func): + if TracingFunctionHolder._original_tracing is None: + #This may happen before ReplaceSysSetTraceFunc is called. + sys.settrace(tracing_func) + return + TracingFunctionHolder._lock.acquire() try: TracingFunctionHolder._warn = False @@ -75,8 +80,8 @@ def SetTrace(tracing_func): TracingFunctionHolder._warn = True finally: TracingFunctionHolder._lock.release() - - + + def ReplaceSysSetTraceFunc(): if TracingFunctionHolder._original_tracing is None: TracingFunctionHolder._original_tracing = sys.settrace diff --git a/python/helpers/pydev/pydevd_vars.py b/python/helpers/pydev/pydevd_vars.py index b8f95fc62a24..de8c2415fcae 100644 --- a/python/helpers/pydev/pydevd_vars.py +++ b/python/helpers/pydev/pydevd_vars.py @@ -6,6 +6,7 @@ from django_frame import DjangoTemplateFrame from pydevd_constants import * #@UnusedWildImport from types import * #@UnusedWildImport +from pydevd_custom_frames import getCustomFrame from pydevd_xml import * try: @@ -20,11 +21,15 @@ else: import threading import pydevd_resolver import traceback +import pydevd_save_locals +from pydev_imports import Exec, quote, execfile try: - from pydevd_exec import Exec + import types + frame_type = types.FrameType except: - from pydevd_exec2 import Exec + frame_type = None + #-------------------------------------------------------------------------- defining true and false for earlier versions @@ -53,7 +58,7 @@ if USE_PSYCO_OPTIMIZATION: sys.exc_clear() #don't keep the traceback -- clients don't want to see it def iterFrames(initialFrame): - """NO-YIELD VERSION: Iterates through all the frames starting at the specified frame (which will be the first returned item)""" + '''NO-YIELD VERSION: Iterates through all the frames starting at the specified frame (which will be the first returned item)''' #cannot use yield frames = [] @@ -90,65 +95,77 @@ def removeAdditionalFrameById(thread_id): + def findFrame(thread_id, frame_id): """ returns a frame on the thread that has a given frame_id """ - if thread_id != GetThreadId(threading.currentThread()): - raise VariableError("findFrame: must execute on same thread") + try: + curr_thread_id = GetThreadId(threading.currentThread()) + if thread_id != curr_thread_id : + try: + return getCustomFrame(thread_id, frame_id) #I.e.: thread_id could be a stackless frame id + thread_id. + except: + pass - lookingFor = int(frame_id) + raise VariableError("findFrame: must execute on same thread (%s != %s)" % (thread_id, curr_thread_id)) - if AdditionalFramesContainer.additional_frames: - if DictContains(AdditionalFramesContainer.additional_frames, thread_id): - frame = AdditionalFramesContainer.additional_frames[thread_id].get(lookingFor) + lookingFor = int(frame_id) - if frame is not None: - return frame + if AdditionalFramesContainer.additional_frames: + if DictContains(AdditionalFramesContainer.additional_frames, thread_id): + frame = AdditionalFramesContainer.additional_frames[thread_id].get(lookingFor) - curFrame = GetFrame() - if frame_id == "*": - return curFrame # any frame is specified with "*" + if frame is not None: + return frame - frameFound = None + curFrame = GetFrame() + if frame_id == "*": + return curFrame # any frame is specified with "*" + + frameFound = None + + for frame in iterFrames(curFrame): + if lookingFor == id(frame): + frameFound = frame + del frame + break - for frame in iterFrames(curFrame): - if lookingFor == id(frame): - frameFound = frame del frame - break - del frame + #Important: python can hold a reference to the frame from the current context + #if an exception is raised, so, if we don't explicitly add those deletes + #we might have those variables living much more than we'd want to. - #Important: python can hold a reference to the frame from the current context - #if an exception is raised, so, if we don't explicitly add those deletes - #we might have those variables living much more than we'd want to. + #I.e.: sys.exc_info holding reference to frame that raises exception (so, other places + #need to call sys.exc_clear()) + del curFrame - #I.e.: sys.exc_info holding reference to frame that raises exception (so, other places - #need to call sys.exc_clear()) - del curFrame + if frameFound is None: + msgFrames = '' + i = 0 - if frameFound is None: - msgFrames = '' - i = 0 + for frame in iterFrames(GetFrame()): + i += 1 + msgFrames += str(id(frame)) + if i % 5 == 0: + msgFrames += '\n' + else: + msgFrames += ' - ' - for frame in iterFrames(GetFrame()): - i += 1 - msgFrames += str(id(frame)) - if i % 5 == 0: - msgFrames += '\n' - else: - msgFrames += ' - ' + errMsg = '''findFrame: frame not found. + Looking for thread_id:%s, frame_id:%s + Current thread_id:%s, available frames: + %s\n + ''' % (thread_id, lookingFor, curr_thread_id, msgFrames) - errMsg = '''findFrame: frame not found. -Looking for thread_id:%s, frame_id:%s -Current thread_id:%s, available frames: -%s -''' % (thread_id, lookingFor, GetThreadId(threading.currentThread()), msgFrames) + sys.stderr.write(errMsg) + return None - sys.stderr.write(errMsg) + return frameFound + except: + import traceback + traceback.print_exc() return None - return frameFound - def resolveCompoundVariable(thread_id, frame_id, scope, attrs): """ returns the value of the compound variable as a dictionary""" frame = findFrame(thread_id, frame_id) @@ -195,9 +212,9 @@ def resolveVar(var, attrs): def evaluateExpression(thread_id, frame_id, expression, doExec): - """returns the result of the evaluated expression + '''returns the result of the evaluated expression @param doExec: determines if we should do an exec or an eval - """ + ''' frame = findFrame(thread_id, frame_id) if frame is None: return @@ -210,7 +227,7 @@ def evaluateExpression(thread_id, frame_id, expression, doExec): #See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html updated_globals = {} updated_globals.update(frame.f_globals) - updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals + updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals try: if doExec: @@ -220,6 +237,7 @@ def evaluateExpression(thread_id, frame_id, expression, doExec): compiled = compile(expression, '', 'eval') except: Exec(expression, updated_globals, frame.f_locals) + pydevd_save_locals.save_locals(frame) else: result = eval(compiled, updated_globals, frame.f_locals) if result is not None: #Only print if it's not None (as python does) @@ -254,11 +272,11 @@ def evaluateExpression(thread_id, frame_id, expression, doExec): del frame def changeAttrExpression(thread_id, frame_id, attr, expression): - """Changes some attribute in a given frame. + '''Changes some attribute in a given frame. @note: it will not (currently) work if we're not in the topmost frame (that's a python deficiency -- and it appears that there is no way of making it currently work -- will probably need some change to the python internals) - """ + ''' frame = findFrame(thread_id, frame_id) if frame is None: return @@ -269,16 +287,7 @@ def changeAttrExpression(thread_id, frame_id, attr, expression): try: expression = expression.replace('@LINE@', '\n') - #tests (needs proposed patch in python accepted) - # if hasattr(frame, 'savelocals'): - # if attr in frame.f_locals: - # frame.f_locals[attr] = eval(expression, frame.f_globals, frame.f_locals) - # frame.savelocals() - # return - # - # elif attr in frame.f_globals: - # frame.f_globals[attr] = eval(expression, frame.f_globals, frame.f_locals) - # return + if attr[:7] == "Globals": @@ -287,6 +296,11 @@ def changeAttrExpression(thread_id, frame_id, attr, expression): frame.f_globals[attr] = eval(expression, frame.f_globals, frame.f_locals) return frame.f_globals[attr] else: + if pydevd_save_locals.is_save_locals_available(): + frame.f_locals[attr] = eval(expression, frame.f_globals, frame.f_locals) + pydevd_save_locals.save_locals(frame) + return + #default way (only works for changing it in the topmost frame) result = eval(expression, frame.f_globals, frame.f_locals) Exec('%s=%s' % (attr, expression), frame.f_globals, frame.f_locals) diff --git a/python/helpers/pydev/pydevd_xml.py b/python/helpers/pydev/pydevd_xml.py index 73258e6fcc65..ac3f71cd9566 100644 --- a/python/helpers/pydev/pydevd_xml.py +++ b/python/helpers/pydev/pydevd_xml.py @@ -2,12 +2,14 @@ import pydev_log import traceback import pydevd_resolver from pydevd_constants import * #@UnusedWildImport -from types import * #@UnusedWildImport + +from pydev_imports import quote try: - from urllib import quote + import types + frame_type = types.FrameType except: - from urllib.parse import quote #@UnresolvedImport + frame_type = None try: from xml.sax.saxutils import escape @@ -60,9 +62,18 @@ if not sys.platform.startswith("java"): except: pass #not available on all python versions + try: + import numpy + typeMap.append((numpy.ndarray, pydevd_resolver.ndarrayResolver)) + except: + pass #numpy may not be installed + + if frame_type is not None: + typeMap.append((frame_type, pydevd_resolver.frameResolver)) + + else: #platform is java from org.python import core #@UnresolvedImport - typeMap = [ (core.PyNone, None), (core.PyInteger, None), @@ -98,20 +109,21 @@ def getType(o): return 'Unable to get Type', 'Unable to get Type', None try: + if type_name == 'org.python.core.PyJavaInstance': - return type_object, type_name, pydevd_resolver.instanceResolver + return (type_object, type_name, pydevd_resolver.instanceResolver) if type_name == 'org.python.core.PyArray': - return type_object, type_name, pydevd_resolver.jyArrayResolver + return (type_object, type_name, pydevd_resolver.jyArrayResolver) for t in typeMap: if isinstance(o, t[0]): - return type_object, type_name, t[1] + return (type_object, type_name, t[1]) except: traceback.print_exc() #no match return default - return type_object, type_name, pydevd_resolver.defaultResolver + return (type_object, type_name, pydevd_resolver.defaultResolver) def frameVarsToXML(frame_f_locals): """ dumps frame variables to XML diff --git a/python/ide/src/com/jetbrains/python/buildout/BuildoutConfigurable.java b/python/ide/src/com/jetbrains/python/buildout/BuildoutConfigurable.java index 199e9ed5962c..8ece6bc90ad6 100644 --- a/python/ide/src/com/jetbrains/python/buildout/BuildoutConfigurable.java +++ b/python/ide/src/com/jetbrains/python/buildout/BuildoutConfigurable.java @@ -87,7 +87,7 @@ public class BuildoutConfigurable implements Configurable, NonDefaultProjectConf @Nls @Override public String getDisplayName() { - return "Buildout Support"; + return "Buildout"; } @Override diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractConsoleCommunication.java b/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractConsoleCommunication.java index e8fa271c8baf..03598551f826 100644 --- a/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractConsoleCommunication.java +++ b/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractConsoleCommunication.java @@ -43,7 +43,7 @@ public abstract class AbstractConsoleCommunication implements ConsoleCommunicati more = false; errorContents = str; } - return new Pair(errorContents, more); + return Pair.create(errorContents, more); } @Override diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index 4bca6e7c8581..a307c031d380 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -481,13 +481,16 @@ public class RemoteDebugger implements ProcessDebugger { } case AbstractCommand.SUSPEND_THREAD: { final PyThreadInfo event = parseThreadEvent(frame); - final PyThreadInfo thread = myThreads.get(event.getId()); - if (thread != null) { - thread.updateState(PyThreadInfo.State.SUSPENDED, event.getFrames()); - thread.setStopReason(event.getStopReason()); - thread.setMessage(event.getMessage()); - myDebugProcess.threadSuspended(thread); + PyThreadInfo thread = myThreads.get(event.getId()); + if (thread == null) { + LOG.error("Trying to stop on non-existent thread: " + event.getId() + ", " + event.getStopReason() + ", " + event.getMessage()); + myThreads.put(event.getId(), event); + thread = event; } + thread.updateState(PyThreadInfo.State.SUSPENDED, event.getFrames()); + thread.setStopReason(event.getStopReason()); + thread.setMessage(event.getMessage()); + myDebugProcess.threadSuspended(thread); break; } case AbstractCommand.RESUME_THREAD: { diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java index e183aae203d4..3df0a3edf390 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -316,6 +316,6 @@ public class ConvertFormatOperatorToMethodIntention extends BaseIntentionAction if (seeker != null && seeker instanceof PsiWhiteSpace) sb.append(seeker.getText()); else break; } - return new Pair(sb.toString(), seeker); + return Pair.create(sb.toString(), seeker); } } diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/DeclarationConflictChecker.java b/python/src/com/jetbrains/python/codeInsight/intentions/DeclarationConflictChecker.java index 1eb17307a3a2..cac318dc1a51 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/DeclarationConflictChecker.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/DeclarationConflictChecker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -67,7 +67,7 @@ public class DeclarationConflictChecker { if (ignored != null) for (PsiElement ignorable : ignored) { if (result == ignorable) continue REF_LOOP; } - conflicts.add(new Pair(ref.getElement(), result)); + conflicts.add(Pair.create(ref.getElement(), result)); } } return conflicts; diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyStringConcatenationToFormatIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyStringConcatenationToFormatIntention.java index c2624aa941fd..f4fd792fc5b1 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/PyStringConcatenationToFormatIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyStringConcatenationToFormatIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -134,7 +134,7 @@ public class PyStringConcatenationToFormatIntention extends BaseIntentionAction NotNullFunction escaper = StringUtil.escaper(false, "\"\'\\"); StringBuilder stringLiteral = new StringBuilder(); List parameters = new ArrayList(); - Pair quotes = new Pair("\"", "\""); + Pair quotes = Pair.create("\"", "\""); boolean quotesDetected = false; final TypeEvalContext context = TypeEvalContext.userInitiated(file); int paramCount = 0; @@ -163,7 +163,7 @@ public class PyStringConcatenationToFormatIntention extends BaseIntentionAction } } if (quotes == null) - quotes = new Pair("\"", "\""); + quotes = Pair.create("\"", "\""); stringLiteral.insert(0, quotes.getFirst()); if (isUnicode && !quotes.getFirst().toLowerCase().contains("u")) stringLiteral.insert(0, "u"); diff --git a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java index 6af6c133cd33..571ffb5f4100 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -372,7 +372,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl if (commAttempts < MAX_ATTEMPTS) { commAttempts += 1; Thread.sleep(250); - executed = new Pair("", executed.second); + executed = Pair.create("", executed.second); } else { break; diff --git a/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java b/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java index 8b8a095c7f8e..b4e2fe2bc644 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java +++ b/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.debugger; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -42,32 +43,40 @@ public class PyDebuggerEvaluator extends XDebuggerEvaluator { doEvaluate(expression, callback, true); } - private void doEvaluate(String expression, XEvaluationCallback callback, boolean doTrunc) { - expression = expression.trim(); - if (expression.isEmpty()) { - callback.evaluated(NONE); - return; - } + private void doEvaluate(final String expr, final XEvaluationCallback callback, final boolean doTrunc) { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + String expression = expr.trim(); + if (expression.isEmpty()) { + callback.evaluated(NONE); + return; + } - final boolean isExpression = PyDebugSupportUtils.isExpression(myProject, expression); - try { - // todo: think on getting results from EXEC - final PyDebugValue value = myDebugProcess.evaluate(expression, !isExpression, doTrunc); - if (value.isErrorOnEval()) { - callback.errorOccurred("{" + value.getType() + "}" + value.getValue()); + final boolean isExpression = PyDebugSupportUtils.isExpression(myProject, expression); + try { + // todo: think on getting results from EXEC + final PyDebugValue value = myDebugProcess.evaluate(expression, !isExpression, doTrunc); + if (value.isErrorOnEval()) { + callback.errorOccurred("{" + value.getType() + "}" + value.getValue()); + } + else { + callback.evaluated(value); + } + } + catch (PyDebuggerException e) { + callback.errorOccurred(e.getTracebackError()); + } } - else { - callback.evaluated(value); - } - } - catch (PyDebuggerException e) { - callback.errorOccurred(e.getTracebackError()); - } + }); } @Nullable @Override - public TextRange getExpressionRangeAtOffset(final Project project, final Document document, final int offset, boolean sideEffectsAllowed) { + public TextRange getExpressionRangeAtOffset(final Project project, + final Document document, + final int offset, + boolean sideEffectsAllowed) { return PyDebugSupportUtils.getExpressionRangeAtOffset(project, document, offset); } diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java index 4062a692e346..68b74b6c3897 100644 --- a/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -81,7 +81,7 @@ public class PyPropertyAccessInspection extends PyInspection { final PyClass cls = ((PyClassType)type).getPyClass(); final String name = node.getName(); if (name != null) { - final Pair key = new Pair(cls, name); + final Pair key = Pair.create(cls, name); final Property property; if (myPropertyCache.containsKey(key)) { property = myPropertyCache.get(key); diff --git a/python/src/com/jetbrains/python/psi/PsiQuery.java b/python/src/com/jetbrains/python/psi/PsiQuery.java new file mode 100644 index 000000000000..d53469d2dc66 --- /dev/null +++ b/python/src/com/jetbrains/python/psi/PsiQuery.java @@ -0,0 +1,322 @@ +package com.jetbrains.python.psi; + +import com.intellij.openapi.util.Condition; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNamedElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.python.nameResolver.FQNamesProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * JQuery-like tool that makes PSI navigation easier. + * You just "drive" your query filtering results, and no need to check result for null. + * + * @author Ilya.Kazakevich + */ +public class PsiQuery { + private static final PsiQuery EMPTY = new PsiQuery(); + @NotNull + private final PsiElement[] myPsiElements; + + /** + * @param psiElement one or more elements to start + */ + public PsiQuery(@NotNull final PsiElement... psiElement) { + myPsiElements = psiElement.clone(); + } + + + /** + * @param psiElements one or more elements to start + */ + public PsiQuery(@NotNull final List psiElements) { + this(psiElements.toArray(new PsiElement[psiElements.size()])); + } + + /** + * Filter children by name + */ + @NotNull + public PsiQuery childrenNamed(@NotNull final String name) { + return childrenNamed(PsiNamedElement.class, name); + } + + /** + * Filter children by name and class + */ + @NotNull + public PsiQuery childrenNamed(@NotNull final Class clazz, @NotNull final String name) { + final List result = new ArrayList(); + for (final PsiElement element : myPsiElements) { + for (final PsiNamedElement child : PsiTreeUtil.findChildrenOfType(element, clazz)) { + if (name.equals(child.getName())) { + result.add(child); + } + } + } + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } + + + /** + * Filter children by function call + */ + @NotNull + public PsiQuery childrenCall(@NotNull final FQNamesProvider name) { + final List result = new ArrayList(); + for (final PsiElement element : myPsiElements) { + for (final PyCallExpression call : PsiTreeUtil.findChildrenOfType(element, PyCallExpression.class)) { + if (call.isCallee(name)) { + result.add(call); + } + } + } + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } + + /** + * Filter children by class + */ + @NotNull + public PsiQuery children(@NotNull final Class clazz) { + final List result = new ArrayList(); + for (final PsiElement element : myPsiElements) { + result.addAll(PsiTreeUtil.findChildrenOfType(element, clazz)); + } + + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } + + + /** + * Filter parents by name + */ + @NotNull + public PsiQuery parents(@NotNull final String name) { + throw new RuntimeException("Not implemented"); + } + + + /** + * Filter parents by name and class + */ + @NotNull + public PsiQuery parents(@NotNull final Class clazz) { + throw new RuntimeException("Not impl"); + } + + + /** + * Filter parents by condition + */ + @NotNull + public PsiQuery parents(@NotNull final Condition> condition) { + throw new RuntimeException("Not impl"); + } + + + /** + * Filter parents by class and name + */ + @NotNull + public PsiQuery parents(@NotNull final Class clazz, @NotNull final String name) { + throw new RuntimeException("Not impl"); + } + + + /** + * Filter parents by function call + */ + @NotNull + public PsiQuery parents(@NotNull final FQNamesProvider name) { + throw new RuntimeException("Not impl"); + } + + + /** + * Filter siblings by name + */ + @NotNull + public PsiQuery siblings(@NotNull final String name) { + return siblings(PsiNamedElement.class, name); + } + + + /** + * Filter siblings by class + */ + @NotNull + public PsiQuery siblings(@NotNull final Class clazz) { + final List result = new ArrayList(); + for (final PsiElement element : myPsiElements) { + final PsiElement parent = element.getParent(); + for (final PsiElement sibling : PsiTreeUtil.findChildrenOfType(parent, clazz)) { + if ((!sibling.equals(element))) { + result.add(sibling); + } + } + } + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } + + + /** + * Filter siblings by name and class + */ + @NotNull + public PsiQuery siblings(@NotNull final Class clazz, @NotNull final String name) { + final List result = new ArrayList(); + for (final PsiElement element : myPsiElements) { + final PsiElement parent = element.getParent(); + for (final PsiNamedElement namedSibling : PsiTreeUtil.findChildrenOfType(parent, clazz)) { + if ((!namedSibling.equals(element)) && (name.equals(namedSibling.getName()))) { + result.add(namedSibling); + } + } + } + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } + + + /** + * Filter siblings by function call name + */ + @NotNull + public PsiQuery siblings(@NotNull final FQNamesProvider name) { + final List result = new ArrayList(); + for (final PsiElement element : myPsiElements) { + final PsiElement parent = element.getParent(); + for (final PyCallExpression callSibling : PsiTreeUtil.findChildrenOfType(parent, PyCallExpression.class)) { + if ((!callSibling.equals(element)) && (callSibling.isCallee(name))) { + result.add(callSibling); + } + } + } + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } + + + /** + * Get first element from result only + */ + @NotNull + public PsiQuery first() { + return (myPsiElements.length > 0) ? new PsiQuery(myPsiElements[0]) : EMPTY; + } + + + /** + * Get last element from result only + */ + @NotNull + public PsiQuery last() { + return (myPsiElements.length > 0) ? new PsiQuery(myPsiElements[myPsiElements.length - 1]) : EMPTY; + } + + + /** + * Get first element from result only if certain class + */ + @Nullable + public T getFirstElement(@NotNull final Class expectedClass) { + final List elements = getChildrenElements(expectedClass); + if (!elements.isEmpty()) { + return elements.get(0); + } + return null; + } + + + /** + * Get last element from result only if certain class + */ + @Nullable + public T getLastElement(@NotNull final Class expectedClass) { + final List elements = getChildrenElements(expectedClass); + if (!elements.isEmpty()) { + return elements.get(elements.size() - 1); + } + return null; + } + + + /** + * Get children elements filtered by class + */ + @NotNull + public List getChildrenElements(@NotNull final Class expectedClass) { + final List result = new ArrayList(); + for (final PsiElement element : myPsiElements) { + final T typedElement = PyUtil.as(element, expectedClass); + if (typedElement != null) { + result.add(typedElement); + } + else { + final T[] children = PsiTreeUtil.getChildrenOfType(element, expectedClass); + if (children != null) { + Collections.addAll(result, children); + } + } + } + return result; + } + + + /** + * Filter by function call + */ + @NotNull + public PsiQuery filter(@NotNull final FQNamesProvider name) { + final Set result = new HashSet(Arrays.asList(myPsiElements)); + for (final PsiElement element : myPsiElements) { + final PyCallExpression callExpression = PyUtil.as(element, PyCallExpression.class); + if ((callExpression == null) || (!callExpression.isCallee(name))) { + result.remove(element); + } + } + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } + + + /** + * Filter by element name + */ + @NotNull + public PsiQuery filter(@NotNull final String name) { + return filter(PsiNamedElement.class, name); + } + + + /** + * Filter elements by class + */ + @NotNull + public PsiQuery filter(@NotNull final Class clazz) { + final Set result = new HashSet(Arrays.asList(myPsiElements)); + for (final PsiElement element : myPsiElements) { + if (PyUtil.as(element, clazz) == null) { + result.remove(element); + } + } + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } + + + /** + * Filter elements by class and name + */ + @NotNull + public PsiQuery filter(@NotNull final Class clazz, @NotNull final String name) { + final Set result = new HashSet(Arrays.asList(myPsiElements)); + for (final PsiElement element : myPsiElements) { + final PsiNamedElement namedElement = PyUtil.as(element, clazz); + if ((namedElement == null) || (!name.equals(namedElement.getName()))) { + result.remove(element); + } + } + return new PsiQuery(result.toArray(new PsiElement[result.size()])); + } +} diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java index d0c83cc65957..2166c6a396c9 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java @@ -345,7 +345,12 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList final PyExpression[] arguments = getArguments(); if (arguments.length > parameter.getPosition()) { - return arguments[parameter.getPosition()]; + final PyExpression result = arguments[parameter.getPosition()]; + if (result instanceof PyKeywordArgument) { + ((PyKeywordArgument)result).getValueExpression(); + } else { + return result; + } } return null; diff --git a/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java index 9f767985c282..c991266f4522 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -180,7 +180,7 @@ public class PyAssignmentStatementImpl extends PyElementImpl implements PyAssign else if (rhs != null) rhs_one = rhs; // if (lhs_one != null) { // single LHS, single RHS (direct mapping) or multiple RHS (packing) - map.add(new Pair(lhs_one, rhs)); + map.add(Pair.create(lhs_one, rhs)); } else if (lhs_tuple != null && rhs_one != null) { // multiple LHS, single RHS: unpacking // PY-2648, PY-2649 @@ -190,7 +190,7 @@ public class PyAssignmentStatementImpl extends PyElementImpl implements PyAssign for (PyExpression tuple_elt : lhs_tuple.getElements()) { try { final PyExpression expression = elementGenerator.createExpressionFromText(languageLevel, rhs_one.getText() + "[" + counter + "]"); - map.add(new Pair(tuple_elt, expression)); + map.add(Pair.create(tuple_elt, expression)); } catch (IncorrectOperationException e) { // not parsed, no problem diff --git a/python/src/com/jetbrains/python/psi/impl/PyBlockEvaluator.java b/python/src/com/jetbrains/python/psi/impl/PyBlockEvaluator.java index c561eb694182..016bfbedab68 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBlockEvaluator.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBlockEvaluator.java @@ -25,6 +25,8 @@ import org.jetbrains.annotations.Nullable; import java.util.*; /** + * + * @see {@link com.jetbrains.python.psi.impl.PyExpressionEvaluator} (TODO: merge both classes?) * @author yole */ public class PyBlockEvaluator { diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java index a626310beef4..712e8b541a1e 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java +++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -86,7 +86,7 @@ public class PyCallExpressionHelper { PsiElement original = ((PyReferenceExpression)possible_original_ref).getReference().resolve(); if (original instanceof PyFunction) { // pinned down the original; replace our resolved callee with it and add flags. - return new Pair(refname, (PyFunction)original); + return Pair.create(refname, (PyFunction)original); } } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java b/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java index 1c3daa5721dd..a006c2728121 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java +++ b/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java @@ -24,7 +24,7 @@ import com.jetbrains.python.psi.resolve.PyResolveContext; import java.util.*; /** - * TODO: Merge PythonDataflowUtil, {@link com.jetbrains.python.psi.impl.PyConstantExpressionEvaluator} and {@link com.jetbrains.python.psi.impl.PyEvaluator} and all its inheritors and improve Abstract Interpretation + * TODO: Merge {@link com.jetbrains.python.psi.impl.PyExpressionEvaluator}, PythonDataflowUtil, {@link com.jetbrains.python.psi.impl.PyConstantExpressionEvaluator} and {@link com.jetbrains.python.psi.impl.PyEvaluator} and all its inheritors and improve Abstract Interpretation * @author yole */ public class PyEvaluator { @@ -46,7 +46,7 @@ public class PyEvaluator { } myVisited.add(expr); if (expr instanceof PyParenthesizedExpression) { - return evaluate(((PyParenthesizedExpression) expr).getContainedExpression()); + return evaluate(((PyParenthesizedExpression)expr).getContainedExpression()); } if (expr instanceof PySequenceExpression) { PyExpression[] elements = ((PySequenceExpression)expr).getElements(); @@ -94,12 +94,12 @@ public class PyEvaluator { public static Object concatenate(Object lhs, Object rhs) { if (lhs instanceof String && rhs instanceof String) { - return (String) lhs + (String) rhs; + return (String)lhs + (String)rhs; } if (lhs instanceof List && rhs instanceof List) { List result = new ArrayList(); - result.addAll((List) lhs); - result.addAll((List) rhs); + result.addAll((List)lhs); + result.addAll((List)rhs); return result; } return null; @@ -132,7 +132,7 @@ public class PyEvaluator { Object arg1 = evaluate(args[0]); Object arg2 = evaluate(args[1]); if (arg1 instanceof String && arg2 instanceof String) { - return ((String) result).replace((String) arg1, (String) arg2); + return ((String)result).replace((String)arg1, (String)arg2); } } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyExpressionEvaluator.java b/python/src/com/jetbrains/python/psi/impl/PyExpressionEvaluator.java new file mode 100644 index 000000000000..72db93dc0b87 --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/PyExpressionEvaluator.java @@ -0,0 +1,147 @@ +package com.jetbrains.python.psi.impl; + +import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.python.PyTokenTypes; +import com.jetbrains.python.psi.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * Engine to evaluate expressions. + *

+ * Supports references and concatinations (sometimes!) + * + * @author Ilya.Kazakevich + * @see {@link com.jetbrains.python.psi.impl.PyBlockEvaluator} (TODO: merge both classes?) + */ +public final class PyExpressionEvaluator { + private static final int MAX_STEP = 100; + + private PyExpressionEvaluator() { + } + + + /** + * Evaluate expression to string + * + * @param expression expression to evaluate + * @return string (or empty if cant evaluate) + */ + @NotNull + public static String evaluateString(@NotNull final PyExpression expression) { + final List expressions = evaluateRaw(expression, PyStringLiteralExpression.class); + final StringBuilder builder = new StringBuilder(); + for (final PyStringLiteralExpression literalExpression : expressions) { + builder.append(literalExpression.getStringValue()); + } + + return builder.toString(); + } + + /** + * Evaluate expression to long + * + * @param expression expression to evaluate + * @return long (or 0 if cant evaluate) + */ + public static long evaluateLong(@NotNull final PyExpression expression) { + final List expressions = evaluateRaw(expression, PyNumericLiteralExpression.class); + long result = 0L; + for (final PyNumericLiteralExpression numericLiteralExpression : expressions) { + final Long value = numericLiteralExpression.getLongValue(); + result += value != null ? value : 0L; + } + return result; + } + + + /** + * Evaluate expression to pack of elements (some iterables could be evaluated to it) + * + * @param expression expression to evaluate + * @param aClass expected class of elements + * @return pack of elements (or empty if cant evaluate) + */ + @NotNull + public static List evaluateIterable(@NotNull final PyExpression expression, @NotNull final Class aClass) { + final List list = new ArrayList(); + for (final PyElement possibleIterable : evaluateRaw(expression, PyElement.class)) { + if ((possibleIterable instanceof PyParenthesizedExpression) || (possibleIterable instanceof PyListLiteralExpression)) { + list.addAll(PsiTreeUtil.findChildrenOfType(possibleIterable, aClass)); + } + } + return list; + } + + /** + * Evaluates expression to some element + * @param expression expression to evaluate + * @param aClass expected element type + * @param expected element type + * @return element or null if can't evaluate + */ + @Nullable + public static T evaluateOne(@NotNull final PyExpression expression, @NotNull final Class aClass) { + final List list = evaluateRaw(expression, aClass); + if (list.isEmpty()) { + return null; + } + return list.get(0); + } + + + /** + * Evaluates expression to one or more elements (all elements should be concatinated). + * I.e: i = 1 + 2. Evaluating "i" would lead to "1" and "2" separately (and not summed like in {@link #evaluateLong(com.jetbrains.python.psi.PyExpression)} + * @param expression expression to evaluate + * @param aClass expected elements type + * @param expected elements type + * @return a pack of elements to concatinate or empty if can't evaluate + */ + @NotNull + public static List evaluateRaw(@NotNull final PyExpression expression, @NotNull final Class aClass) { + int step = 0; + PyElement currentElement = expression; + final List result = new ArrayList(); + while (step < MAX_STEP) { + PyElement newElement = null; + + // TODO: Use visitor? + if (currentElement instanceof PyReferenceExpression) { + newElement = PyUtil.as(((PyReferenceExpression)currentElement).getReference().resolve(), PyElement.class); + } + else if (currentElement instanceof PyTargetExpression) { + newElement = ((PyTargetExpression)currentElement).findAssignedValue(); + } + else if (currentElement instanceof PyBinaryExpression) { + final PyBinaryExpression newExpression = (PyBinaryExpression)currentElement; + final PyElementType operator = newExpression.getOperator(); + if (PyTokenTypes.PLUS.equals(operator)) { + final PyExpression leftExpression = newExpression.getLeftExpression(); + final PyExpression rightExpression = newExpression.getRightExpression(); + if (leftExpression != null) { + result.addAll(evaluateRaw(leftExpression, aClass)); + } + if (rightExpression != null) { + result.addAll(evaluateRaw(rightExpression, aClass)); + } + } + } + + if (newElement == null) { + break; + } + + currentElement = newElement; + step++; + } + final T elementToAdd = PyUtil.as(currentElement, aClass); + if (elementToAdd != null) { + result.add(elementToAdd); + } + return result; + } +} diff --git a/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java b/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java index 94c2c87fbb62..de5951c37684 100644 --- a/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java +++ b/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java @@ -15,7 +15,6 @@ */ package com.jetbrains.python.psi.impl; -import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.module.Module; @@ -158,44 +157,26 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher updatedSdks = new HashSet(); - final Module[] modules = ModuleManager.getInstance(project).getModules(); - boolean needReparseOpenFiles = false; - for (Module module : modules) { - Sdk newSdk = PythonSdkType.findPythonSdk(module); - if (myModuleSdks.containsKey(module)) { - Sdk oldSdk = myModuleSdks.get(module); - if ((newSdk != null || oldSdk != null) && newSdk != oldSdk) { - needReparseOpenFiles = true; - } - } - myModuleSdks.put(module, newSdk); - if (newSdk != null && !updatedSdks.contains(newSdk)) { - updatedSdks.add(newSdk); - updateSdkLanguageLevel(project, newSdk); - } + Set updatedSdks = new HashSet(); + final Module[] modules = ModuleManager.getInstance(project).getModules(); + boolean needReparseOpenFiles = false; + for (Module module : modules) { + Sdk newSdk = PythonSdkType.findPythonSdk(module); + if (myModuleSdks.containsKey(module)) { + Sdk oldSdk = myModuleSdks.get(module); + if ((newSdk != null || oldSdk != null) && newSdk != oldSdk) { + needReparseOpenFiles = true; } - final boolean finalNeedReparseOpenFiles = needReparseOpenFiles; - application.invokeLater(new Runnable() { - @Override - public void run() { - if (finalNeedReparseOpenFiles) { - FileContentUtil.reparseFiles(project, Collections.emptyList(), true); - } - } - }); } - }; - application.executeOnPooledThread(new Runnable() { - @Override - public void run() { - application.runReadAction(updateLanguageLevel); + myModuleSdks.put(module, newSdk); + if (newSdk != null && !updatedSdks.contains(newSdk)) { + updatedSdks.add(newSdk); + updateSdkLanguageLevel(project, newSdk); } - }); + } + if (needReparseOpenFiles) { + FileContentUtil.reparseFiles(project, Collections.emptyList(), true); + } } private void updateSdkLanguageLevel(Project project, Sdk sdk) { diff --git a/python/src/com/jetbrains/python/toolbox/FP.java b/python/src/com/jetbrains/python/toolbox/FP.java index 148cfe3c328a..2fc2ef592a42 100644 --- a/python/src/com/jetbrains/python/toolbox/FP.java +++ b/python/src/com/jetbrains/python/toolbox/FP.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -238,9 +238,9 @@ public class FP { } public Pair next() { - if (one_iter.hasNext() && two_iter.hasNext()) return new Pair(one_iter.next(), two_iter.next()); - if (fill1 && two_iter.hasNext()) return new Pair(filler1, two_iter.next()); - if (fill2 && one_iter.hasNext()) return new Pair(one_iter.next(), filler2); + if (one_iter.hasNext() && two_iter.hasNext()) return Pair.create(one_iter.next(), two_iter.next()); + if (fill1 && two_iter.hasNext()) return Pair.create(filler1, two_iter.next()); + if (fill2 && one_iter.hasNext()) return Pair.create(one_iter.next(), filler2); throw new NoSuchElementException(); } }; diff --git a/python/testSrc/com/jetbrains/python/PyExpressionEvaluatorTest.java b/python/testSrc/com/jetbrains/python/PyExpressionEvaluatorTest.java new file mode 100644 index 000000000000..f36c5e4c4b9c --- /dev/null +++ b/python/testSrc/com/jetbrains/python/PyExpressionEvaluatorTest.java @@ -0,0 +1,133 @@ +package com.jetbrains.python; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiFile; +import com.jetbrains.python.fixtures.PyTestCase; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyExpressionEvaluator; +import org.hamcrest.Matchers; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; + +import java.util.List; + +/** + * Tests {@link com.jetbrains.python.psi.impl.PyExpressionEvaluator} + * + * @author Ilya.Kazakevich + */ +public class PyExpressionEvaluatorTest extends PyTestCase { + + public void testLiteralReferences() { + final PyTargetExpression myValue = createFileAndExpression("my_value", + "x = 2", + "y = x", + "my_value = y" + ); + final List result = PyExpressionEvaluator.evaluateRaw(myValue, PyNumericLiteralExpression.class); + Assert.assertThat("Expected list of 1 long element", result.size(), Matchers.is(1)); + Assert.assertNotNull("Failed to evaluate chain of literals (got null)", result); + final PyNumericLiteralExpression resultElement = result.get(0); + Assert.assertThat("Evaluated incorrectly", resultElement.getLongValue(), Matchers.equalTo(2L)); + } + + + public void testCall() { + final PyTargetExpression myValue = createFileAndExpression("my_value", + "x = abs(42)", + "y = x", + "my_value = y" + ); + final List result = PyExpressionEvaluator.evaluateRaw(myValue, PyCallExpression.class); + Assert.assertNotNull("Failed to evaluate chain of functions (got null)", result); + Assert.assertThat("Expected list of 1 call element", result.size(), Matchers.is(1)); + final PyExpression callee = result.get(0).getCallee(); + Assert.assertNotNull("Found empty callee", callee); + Assert.assertThat("Evaluated incorrectly", callee.getName(), Matchers.equalTo("abs")); + } + + public void testStringConcat() { + final PyTargetExpression myValue = createFileAndExpression("my_value", + "x = 'go'", + "y = x + ' away'", + "my_value = y" + ); + + final List expressions = PyExpressionEvaluator.evaluateRaw(myValue, PyStringLiteralExpression.class); + Assert.assertThat("Expected list of 2 string elements", expressions.size(), Matchers.is(2)); + Assert.assertThat("Evaluated incorrectly", expressions.get(0).getStringValue(), Matchers.equalTo("go")); + Assert.assertThat("Evaluated incorrectly", expressions.get(1).getStringValue(), Matchers.equalTo(" away")); + } + + public void testNumberConcat() { + final PyTargetExpression myValue = createFileAndExpression("my_value", + "x = 2", + "y = x + 1", + "my_value = y" + ); + + final List expressions = PyExpressionEvaluator.evaluateRaw(myValue, PyNumericLiteralExpression.class); + Assert.assertThat("Expected list of 2 num elements", expressions.size(), Matchers.is(2)); + Assert.assertThat("Evaluated incorrectly", expressions.get(0).getLongValue(), Matchers.equalTo(2L)); + Assert.assertThat("Evaluated incorrectly", expressions.get(1).getLongValue(), Matchers.equalTo(1L)); + } + + public void testNumber() { + final long result = PyExpressionEvaluator.evaluateLong(createFileAndExpression("my_value", "x = 2", " y = 3", "my_value = x + y + 1")); + Assert.assertThat("Error summarizing numbers", result, Matchers.is(6L)); + } + + public void testString() { + final String result = PyExpressionEvaluator.evaluateString(createFileAndExpression("my_value", + "x = 'hello'", + " y = \" there\"", + "my_value = x + y + '!'")); + Assert.assertThat("Error in string concat", result, Matchers.is("hello there!")); + } + + public void testIterableTuples() { + final List value = PyExpressionEvaluator.evaluateIterable(createFileAndExpression("my_value", + "x = ('hello', 'from')", + " y = ('here', '!')", + "my_value = x + y"), + PyStringLiteralExpression.class + ); + Assert.assertThat("Expected list of elements", value.size(), Matchers.is(4)); + Assert.assertThat("Evaluated incorrectly", value.get(0).getStringValue(), Matchers.equalTo("hello")); + Assert.assertThat("Evaluated incorrectly", value.get(1).getStringValue(), Matchers.equalTo("from")); + Assert.assertThat("Evaluated incorrectly", value.get(2).getStringValue(), Matchers.equalTo("here")); + Assert.assertThat("Evaluated incorrectly", value.get(3).getStringValue(), Matchers.equalTo("!")); + } + + public void testIterableLists() { + final List value = PyExpressionEvaluator.evaluateIterable(createFileAndExpression("my_value", + "x = ['hello', 'from']", + " y = ['here'] + ['!']", + "my_value = x + y"), + PyStringLiteralExpression.class + ); + Assert.assertThat("Expected list of elements", value.size(), Matchers.is(4)); + Assert.assertThat("Evaluated incorrectly", value.get(0).getStringValue(), Matchers.equalTo("hello")); + Assert.assertThat("Evaluated incorrectly", value.get(1).getStringValue(), Matchers.equalTo("from")); + Assert.assertThat("Evaluated incorrectly", value.get(2).getStringValue(), Matchers.equalTo("here")); + Assert.assertThat("Evaluated incorrectly", value.get(3).getStringValue(), Matchers.equalTo("!")); + } + + /** + * Create file, fill it with data and return some expression from it + * + * @param varName name of expression to return + * @param lines lines of code + * @return expression + */ + @NotNull + private PyTargetExpression createFileAndExpression(@NotNull final String varName, @NotNull final String... lines) { + final PsiFile file = + PyElementGenerator.getInstance(myFixture.getProject()).createDummyFile(LanguageLevel.PYTHON27, StringUtil.join(lines, "\n")); + assert file instanceof PyFile : "PyElementGenerator created not py file?"; + final PyFile pyFile = (PyFile)file; + final PyTargetExpression result = pyFile.findTopLevelAttribute(varName); + assert result != null : "No var with name " + varName + " found"; + return result; + } +} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index af2be3da50cd..70ba34a504d8 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -518,14 +518,14 @@ + diff --git a/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java b/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java index e6ef0e450433..9cc9ec96ad8f 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -87,7 +87,7 @@ public class DomElementProblemDescriptorImpl implements DomElementProblemDescrip final PsiElement psiElement = getPsiElement(); LOG.assertTrue(psiElement != null, "Problems with explicit text range can't be created for DOM elements without underlying XML element"); assert psiElement.isValid(); - myPair = new Pair(textRange, psiElement); + myPair = Pair.create(textRange, psiElement); } myHighlightType = highlightType; } diff --git a/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilder.java b/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilder.java index 0b86f4365492..41196ae78872 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilder.java +++ b/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilder.java @@ -63,7 +63,7 @@ public class DomStructureViewBuilder extends TreeBasedStructureViewBuilder { return new StructureViewComponent(fileEditor, createStructureViewModel(fileEditor instanceof TextEditor ? ((TextEditor)fileEditor).getEditor() : null), project, true) { @Override public AsyncResult expandPathToElement(final Object element) { - if (element instanceof XmlElement) { + if (element instanceof XmlElement && ((XmlElement)element).isValid()) { final XmlElement xmlElement = (XmlElement)element; XmlTag tag = PsiTreeUtil.getParentOfType(xmlElement, XmlTag.class, false); while (tag != null) { diff --git a/xml/dom-impl/src/com/intellij/util/xml/stubs/StubParentStrategy.java b/xml/dom-impl/src/com/intellij/util/xml/stubs/StubParentStrategy.java index be674fc9acea..e8913607c18f 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/stubs/StubParentStrategy.java +++ b/xml/dom-impl/src/com/intellij/util/xml/stubs/StubParentStrategy.java @@ -15,6 +15,7 @@ */ package com.intellij.util.xml.stubs; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; @@ -30,6 +31,8 @@ import java.util.List; */ public class StubParentStrategy implements DomParentStrategy { + private final static Logger LOG = Logger.getInstance(StubParentStrategy.class); + public static StubParentStrategy createAttributeStrategy(@Nullable AttributeStub stub, @NotNull final DomStub parent) { if (stub == null) { return new Empty(parent); @@ -39,10 +42,14 @@ public class StubParentStrategy implements DomParentStrategy { @Override public XmlElement getXmlElement() { DomInvocationHandler parentHandler = getParentHandler(); - assert parentHandler != null; + if (parentHandler == null) { + LOG.error("no parent handler for " + this); + return null; + } XmlTag tag = parentHandler.getXmlTag(); if (tag == null) { - throw new AssertionError("can't find tag for " + parentHandler); + LOG.error("can't find tag for " + parentHandler); + return null; } return tag.getAttribute(myStub.getName()); } diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPass.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPass.java index 04d7b767ef20..f35bebce3715 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPass.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingPass.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -104,7 +104,7 @@ public class XmlTagTreeHighlightingPass extends TextEditorHighlightingPass { @Nullable private static Pair getTagRanges(XmlTag tag) { final ASTNode tagNode = tag.getNode(); - return new Pair(getStartTagRange(tagNode), getEndTagRange(tagNode)); + return Pair.create(getStartTagRange(tagNode), getEndTagRange(tagNode)); } @Nullable diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewAction.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewAction.java index 578c8615a93e..f7f5fe50d58d 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewAction.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewAction.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.actions.BaseCodeInsightAction; import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.openapi.actionSystem.PopupAction; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; @@ -41,7 +42,7 @@ public class EmmetPreviewAction extends BaseCodeInsightAction implements DumbAwa return; } - EmmetPreviewHint.createHint(editor, templateText, file.getFileType()).showHint(); + EmmetPreviewHint.createHint((EditorEx)editor, templateText, file.getFileType()).showHint(); EmmetPreviewUtil.addEmmetPreviewListeners(editor, file, true); } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewHint.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewHint.java index f625e507d0fe..52c1b6334424 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewHint.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewHint.java @@ -27,13 +27,13 @@ import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.EditorFactoryAdapter; import com.intellij.openapi.editor.event.EditorFactoryEvent; import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.ui.HintHint; import com.intellij.ui.LightweightHint; import com.intellij.ui.components.JBPanel; @@ -59,10 +59,11 @@ public class EmmetPreviewHint extends LightweightHint implements Disposable { myParentEditor = parentEditor; myEditor = editor; + final Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(myParentEditor); EditorFactory.getInstance().addEditorFactoryListener(new EditorFactoryAdapter() { @Override public void editorReleased(@NotNull EditorFactoryEvent event) { - if (event.getEditor() == myParentEditor || event.getEditor() == myEditor) { + if (event.getEditor() == myParentEditor || event.getEditor() == myEditor || event.getEditor() == topLevelEditor) { hide(); } } @@ -139,7 +140,7 @@ public class EmmetPreviewHint extends LightweightHint implements Disposable { } @NotNull - public static EmmetPreviewHint createHint(@NotNull final Editor parentEditor, @NotNull String templateText, @NotNull FileType fileType) { + public static EmmetPreviewHint createHint(@NotNull final EditorEx parentEditor, @NotNull String templateText, @NotNull FileType fileType) { EditorFactory editorFactory = EditorFactory.getInstance(); Document document = editorFactory.createDocument(templateText); final EditorEx previewEditor = (EditorEx)editorFactory.createEditor(document, parentEditor.getProject(), fileType, true); @@ -163,7 +164,7 @@ public class EmmetPreviewHint extends LightweightHint implements Disposable { @Override public Dimension getPreferredSize() { Dimension size = super.getPreferredSize(); - Dimension parentEditorSize = ((EditorImpl)parentEditor).getScrollPane().getSize(); + Dimension parentEditorSize = parentEditor.getScrollPane().getSize(); int maxWidth = (int)parentEditorSize.getWidth() / 3; int maxHeight = (int)parentEditorSize.getHeight() / 2; Dimension contentSize = previewEditor.getContentSize(); diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewTypedHandler.java index 8111bac0fb0b..b17ad8742fd6 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewTypedHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewTypedHandler.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.template.emmet; import com.intellij.application.options.emmet.EmmetOptions; import com.intellij.codeInsight.editorActions.TypedHandlerDelegate; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; @@ -31,7 +32,7 @@ public class EmmetPreviewTypedHandler extends TypedHandlerDelegate { if (existingBalloon == null) { String templateText = EmmetPreviewUtil.calculateTemplateText(editor, file, false); if (StringUtil.isNotEmpty(templateText)) { - EmmetPreviewHint.createHint(editor, templateText, file.getFileType()).showHint(); + EmmetPreviewHint.createHint((EditorEx)editor, templateText, file.getFileType()).showHint(); EmmetPreviewUtil.addEmmetPreviewListeners(editor, file, false); } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewUtil.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewUtil.java index 44be533301f1..4a00c6f5d2fa 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewUtil.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetPreviewUtil.java @@ -19,8 +19,11 @@ import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateEditingListener; import com.intellij.codeInsight.template.emmet.filters.ZenCodingFilter; +import com.intellij.codeInsight.template.emmet.generators.XmlZenCodingGenerator; import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator; import com.intellij.codeInsight.template.impl.TemplateImpl; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.undo.UndoConstants; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.event.CaretAdapter; @@ -51,11 +54,11 @@ public class EmmetPreviewUtil { public static String calculateTemplateText(@NotNull Editor editor, @NotNull PsiFile file, boolean expandPrimitiveAbbreviations) { if (file instanceof XmlFile) { final Ref generatedTemplate = new Ref(); - CustomTemplateCallback callback = createCallback(editor, file, generatedTemplate); PsiDocumentManager.getInstance(file.getProject()).commitDocument(editor.getDocument()); + CustomTemplateCallback callback = createCallback(editor, file, generatedTemplate); PsiElement context = callback.getContext(); ZenCodingGenerator generator = ZenCodingTemplate.findApplicableDefaultGenerator(context, false); - if (generator != null) { + if (generator != null && generator instanceof XmlZenCodingGenerator) { final String templatePrefix = new ZenCodingTemplate().computeTemplateKeyWithoutContextChecking(callback); if (templatePrefix != null) { ZenCodingTemplate.expand(templatePrefix, callback, null, generator, Collections.emptyList(), expandPrimitiveAbbreviations, 0); @@ -100,13 +103,23 @@ public class EmmetPreviewUtil { }); } - private static String reformatTemplateText(@NotNull PsiFile file, @NotNull String templateText) { - PsiFile copy = PsiFileFactory.getInstance(file.getProject()).createFileFromText(file.getName(), file.getFileType(), templateText); + private static String reformatTemplateText(@NotNull final PsiFile file, @NotNull String templateText) { + final PsiFile copy = PsiFileFactory.getInstance(file.getProject()).createFileFromText(file.getName(), file.getFileType(), templateText); VirtualFile vFile = copy.getVirtualFile(); if (vFile != null) { vFile.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE); } - CodeStyleManager.getInstance(file.getProject()).reformat(copy); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { + @Override + public void run() { + CodeStyleManager.getInstance(file.getProject()).reformat(copy); + } + }); + } + }); return copy.getText(); } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java index 6e2d2a12fe67..81716a27bb54 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java @@ -263,10 +263,10 @@ public class XmlEmmetParser extends EmmetParser { final List> attrList = parseSelector(); if (attrList == null) { if (classAttrPosition != -1) { - result.set(classAttrPosition, new Pair(CLASS, classAttrBuilder.toString())); + result.set(classAttrPosition, Pair.create(CLASS, classAttrBuilder.toString())); } if (idAttrPosition != -1) { - result.set(idAttrPosition, new Pair(ID, idAttrBuilder.toString())); + result.set(idAttrPosition, Pair.create(ID, idAttrBuilder.toString())); } return result; } @@ -320,7 +320,7 @@ public class XmlEmmetParser extends EmmetParser { if (!value.isEmpty()) { advance(); } - return Collections.singletonList(new Pair(name, value)); + return Collections.singletonList(Pair.create(name, value)); } return null; @@ -369,7 +369,7 @@ public class XmlEmmetParser extends EmmetParser { advance(); token = getToken(); if (token != ZenCodingTokens.EQ) { - return new Pair(name, ""); + return Pair.create(name, ""); } advance(); @@ -386,6 +386,6 @@ public class XmlEmmetParser extends EmmetParser { } while (token != null && token != ZenCodingTokens.CLOSING_SQ_BRACKET && token != ZenCodingTokens.SPACE && token != ZenCodingTokens.COMMA); - return new Pair(name, attrValueBuilder.toString()); + return Pair.create(name, attrValueBuilder.toString()); } } diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java index 4521f840030d..152a9d925ab8 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -135,7 +135,7 @@ public abstract class XmlFormattingPolicy { public abstract boolean addSpaceIntoEmptyTag(); public void setRootBlock(final ASTNode node, final Block rootBlock) { - myRootToBlockMap.put(new Pair(node.getPsi(), node.getPsi().getLanguage()), rootBlock); + myRootToBlockMap.put(Pair.create(node.getPsi(), node.getPsi().getLanguage()), rootBlock); } public FormattingDocumentModel getDocumentModel() { diff --git a/xml/impl/src/com/intellij/xml/refactoring/XmlTagInplaceRenamer.java b/xml/impl/src/com/intellij/xml/refactoring/XmlTagInplaceRenamer.java index 9585643b775a..828c7faccc4f 100644 --- a/xml/impl/src/com/intellij/xml/refactoring/XmlTagInplaceRenamer.java +++ b/xml/impl/src/com/intellij/xml/refactoring/XmlTagInplaceRenamer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -152,7 +152,7 @@ public class XmlTagInplaceRenamer { : endTagName; final ASTNode other = (selected == startTagName) ? endTagName : startTagName; - return new Pair(selected, other); + return Pair.create(selected, other); } private static Template buildTemplate(@NotNull final XmlTag tag, @NotNull final Pair pair) { diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java index f0067fe38ca0..d78e94172080 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -74,7 +74,7 @@ public class HtmlConditionalCommentInjector implements MultiHostInjector { return null; } final ASTNode endOfEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END)); - return endOfEnd == null ? null : new Pair(conditionalStart, conditionalEnd); + return endOfEnd == null ? null : Pair.create(conditionalStart, conditionalEnd); } public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement host) { diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java index 5d35f0f4ae69..63633af5ed0a 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -459,7 +459,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator pair = new Pair(new QNameKey(name, namespace), rootTag); + final Pair pair = Pair.create(new QNameKey(name, namespace), rootTag); final CachedValue descriptor = myTypesMap.get(pair); if(descriptor != null) { diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java index bfbc4a7bad8c..b82f69bb7ffb 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -1096,7 +1096,7 @@ public class XmlUtil { } } - return new Pair(first, last); + return Pair.create(first, last); } public static boolean isSimpleValue(@NotNull final String unquotedValue, final PsiElement context) {