diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java index e2b97a284a07..b677df25ac71 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java @@ -25,6 +25,7 @@ import com.intellij.ProjectTopics; import com.intellij.compiler.impl.javaCompiler.BackendCompiler; import com.intellij.compiler.impl.javaCompiler.eclipse.EclipseCompiler; import com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler; +import com.intellij.compiler.server.BuildManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.compiler.CompilerBundle; @@ -41,10 +42,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.ui.InputValidator; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Couple; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; @@ -204,7 +202,11 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements } public void setProjectBytecodeTarget(@Nullable String level) { + final String previous = myBytecodeTargetLevel; myBytecodeTargetLevel = level; + if (!myProject.isDefault() && !Comparing.equal(previous, level)) { + BuildManager.getInstance().clearState(myProject); + } } @Override @@ -214,8 +216,12 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements } public void setModulesBytecodeTargetMap(@NotNull Map mapping) { + final boolean shouldNotify = !myProject.isDefault() && !myModuleBytecodeTarget.equals(mapping); myModuleBytecodeTarget.clear(); myModuleBytecodeTarget.putAll(mapping); + if (shouldNotify) { + BuildManager.getInstance().clearState(myProject); + } } public Map getModulesBytecodeTargetMap() { @@ -231,11 +237,12 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements else { previous = myModuleBytecodeTarget.put(module.getName(), level); } - // todo: mark module as dirty in order to rebuild it completely with the new target level - //if (!Comparing.equal(previous, level)) { - // final Project project = module.getProject(); - // - //} + if (!Comparing.equal(previous, level)) { + final Project project = module.getProject(); + if (!project.isDefault()) { + BuildManager.getInstance().clearState(project); + } + } } @Override diff --git a/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java b/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java index 6d2d5fd3835e..299a9e135e3c 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java @@ -139,8 +139,8 @@ public class JavaCompilersTab implements SearchableConfigurable, Configurable.No myCompilerConfiguration.setProjectBytecodeTarget(myTargetLevelComponent.getProjectBytecodeTarget()); myCompilerConfiguration.setModulesBytecodeTargetMap(myTargetLevelComponent.getModulesBytecodeTargetMap()); - myTargetLevelComponent.setProjectBytecodeTargetLevel(myCompilerConfiguration.getProjectBytecodeTarget()); - myTargetLevelComponent.setModuleTargetLevels(myCompilerConfiguration.getModulesBytecodeTargetMap()); + myCompilerConfiguration.setProjectBytecodeTarget(myTargetLevelComponent.getProjectBytecodeTarget()); + myCompilerConfiguration.setModulesBytecodeTargetMap(myCompilerConfiguration.getModulesBytecodeTargetMap()); } public void reset() { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java index f017ad5c61b3..8c6a19b49a81 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java @@ -37,6 +37,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.searches.AllOverridingMethodsSearch; import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.search.searches.FunctionalExpressionSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.PsiUtil; @@ -179,8 +180,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider, DumbAware { } if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return; // It's useless to have overridden markers for object. - PsiClass inheritor = ClassInheritorsSearch.search(aClass, false).findFirst(); - if (inheritor != null) { + if (ClassInheritorsSearch.search(aClass, false).findFirst() != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) { final Icon icon = aClass.isInterface() ? AllIcons.Gutter.ImplementedMethod : AllIcons.Gutter.OverridenMethod; PsiElement range = aClass.getNameIdentifier(); if (range == null) range = aClass; @@ -219,6 +219,17 @@ public class JavaLineMarkerProvider implements LineMarkerProvider, DumbAware { }); } + if (!methods.isEmpty()) { + for (PsiClass aClass : classes) { + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(aClass); + if (interfaceMethod != null) { + if (FunctionalExpressionSearch.search(aClass).findFirst() != null) { + overridden.add(interfaceMethod); + } + } + } + } + for (PsiMethod method : overridden) { ProgressManager.checkCanceled(); boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java index 72e8eca35fa6..e4e6c5c74ecc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java @@ -23,9 +23,7 @@ import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.daemon.DaemonBundle; import com.intellij.codeInsight.daemon.GutterIconNavigationHandler; import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask; -import com.intellij.ide.util.MethodCellRenderer; -import com.intellij.ide.util.PsiClassListCellRenderer; -import com.intellij.ide.util.PsiElementListCellRenderer; +import com.intellij.ide.util.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -36,6 +34,7 @@ import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.PsiElementProcessorAdapter; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.search.searches.FunctionalExpressionSearch; import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.util.PsiUtil; import com.intellij.util.*; @@ -136,7 +135,7 @@ public class MarkerType { } }); - public static String getOverriddenMethodTooltip(PsiMethod method) { + public static String getOverriddenMethodTooltip(final PsiMethod method) { PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5); OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(processor)); @@ -146,8 +145,14 @@ public class MarkerType { return isAbstract ? DaemonBundle.message("method.is.implemented.too.many") : DaemonBundle.message("method.is.overridden.too.many"); } - PsiMethod[] overridings = processor.toArray(new PsiMethod[processor.getCollection().size()]); - if (overridings.length == 0) return null; + PsiMethod[] overridings = processor.toArray(PsiMethod.EMPTY_ARRAY); + if (overridings.length == 0) { + final PsiClass aClass = method.getContainingClass(); + if (aClass != null && FunctionalExpressionSearch.search(aClass).findFirst() != null) { + return "Has functional implementations"; + } + return null; + } Comparator comparator = new MethodCellRenderer(false).getComparator(); Arrays.sort(overridings, comparator); @@ -166,19 +171,33 @@ public class MarkerType { final PsiElementProcessor.CollectElementsWithLimit collectProcessor = new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); + final PsiElementProcessor.CollectElementsWithLimit collectExprProcessor = + new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); + if (collectProcessor.getCollection().isEmpty()) { + final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiClass compute() { + return method.getContainingClass(); + } + }); + if (aClass != null) { + FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter(collectExprProcessor)); + } + } } }, SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) { return; } - PsiMethod[] overridings = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY); + final PsiMethod[] methodOverriders = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY); + NavigatablePsiElement[] overridings = ArrayUtil.mergeArrays(methodOverriders, collectExprProcessor.toArray(PsiFunctionalExpression.EMPTY_ARRAY)); if (overridings.length == 0) return; - boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(overridings); - MethodCellRenderer renderer = new MethodCellRenderer(showMethodNames); + boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(methodOverriders); + MethodOrFunctionalExpressionCellRenderer renderer = new MethodOrFunctionalExpressionCellRenderer(showMethodNames); Arrays.sort(overridings, renderer.getComparator()); final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer); PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), "Overriding methods of " + method.getName(), renderer, methodsUpdater); @@ -214,8 +233,16 @@ public class MarkerType { : DaemonBundle.message("class.is.subclassed.too.many"); } - PsiClass[] subclasses = processor.toArray(new PsiClass[processor.getCollection().size()]); - if (subclasses.length == 0) return null; + PsiClass[] subclasses = processor.toArray(PsiClass.EMPTY_ARRAY); + if (subclasses.length == 0) { + final PsiElementProcessor.CollectElementsWithLimit functionalImplementations = + new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); + FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter(functionalImplementations)); + if (!functionalImplementations.getCollection().isEmpty()) { + return "Has functional implementations"; + } + return null; + } Comparator comparator = new PsiClassListCellRenderer().getComparator(); Arrays.sort(subclasses, comparator); @@ -234,18 +261,23 @@ public class MarkerType { } final PsiElementProcessor.CollectElementsWithLimit collectProcessor = new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); + final PsiElementProcessor.CollectElementsWithLimit collectExprProcessor = new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); + if (collectProcessor.getCollection().isEmpty()) { + FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter(collectExprProcessor)); + } } }, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent)e.getComponent())) { return; } - PsiClass[] inheritors = collectProcessor.toArray(PsiClass.EMPTY_ARRAY); + NavigatablePsiElement[] inheritors = ArrayUtil.mergeArrays(collectProcessor.toArray(PsiClass.EMPTY_ARRAY), + collectExprProcessor.toArray(PsiFunctionalExpression.EMPTY_ARRAY)); if (inheritors.length == 0) return; - final PsiClassListCellRenderer renderer = new PsiClassListCellRenderer(); + final PsiClassOrFunctionalExpressionListCellRenderer renderer = new PsiClassOrFunctionalExpressionListCellRenderer(); final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer); Arrays.sort(inheritors, renderer.getComparator()); PsiElementListNavigator.openTargets(e, inheritors, subclassUpdater.getCaption(inheritors.length), CodeInsightBundle.message("goto.implementation.findUsages.title", aClass.getName()), renderer, subclassUpdater); @@ -276,9 +308,9 @@ public class MarkerType { private static class SubclassUpdater extends ListBackgroundUpdaterTask { private final PsiClass myClass; - private final PsiClassListCellRenderer myRenderer; + private final PsiClassOrFunctionalExpressionListCellRenderer myRenderer; - public SubclassUpdater(PsiClass aClass, PsiClassListCellRenderer renderer) { + public SubclassUpdater(PsiClass aClass, PsiClassOrFunctionalExpressionListCellRenderer renderer) { super(aClass.getProject(), SEARCHING_FOR_OVERRIDDEN_METHODS); myClass = aClass; myRenderer = renderer; @@ -309,6 +341,17 @@ public class MarkerType { return super.process(o); } }); + + FunctionalExpressionSearch.search(myClass).forEach(new CommonProcessors.CollectProcessor() { + @Override + public boolean process(final PsiFunctionalExpression expr) { + if (!updateComponent(expr, myRenderer.getComparator())) { + indicator.cancel(); + } + indicator.checkCanceled(); + return super.process(expr); + } + }); } } @@ -344,6 +387,22 @@ public class MarkerType { return super.process(psiMethod); } }); + final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiClass compute() { + return myMethod.getContainingClass(); + } + }); + FunctionalExpressionSearch.search(psiClass).forEach(new CommonProcessors.CollectProcessor() { + @Override + public boolean process(final PsiFunctionalExpression expr) { + if (!updateComponent(expr, myRenderer.getComparator())) { + indicator.cancel(); + } + indicator.checkCanceled(); + return super.process(expr); + } + }); } } } diff --git a/java/java-impl/src/com/intellij/ide/util/MethodOrFunctionalExpressionCellRenderer.java b/java/java-impl/src/com/intellij/ide/util/MethodOrFunctionalExpressionCellRenderer.java new file mode 100644 index 000000000000..0e8a33a9b111 --- /dev/null +++ b/java/java-impl/src/com/intellij/ide/util/MethodOrFunctionalExpressionCellRenderer.java @@ -0,0 +1,53 @@ +/* + * 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.ide.util; + +import com.intellij.psi.*; +import com.intellij.psi.util.PsiExpressionTrimRenderer; +import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; + +import javax.swing.*; + +public class MethodOrFunctionalExpressionCellRenderer extends PsiElementListCellRenderer { + private final PsiClassListCellRenderer myClassListCellRenderer = new PsiClassListCellRenderer(); + private final MethodCellRenderer myMethodCellRenderer; + + public MethodOrFunctionalExpressionCellRenderer(boolean showMethodNames) { + this(showMethodNames, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS); + } + public MethodOrFunctionalExpressionCellRenderer(boolean showMethodNames, @PsiFormatUtil.FormatMethodOptions int options) { + myMethodCellRenderer = new MethodCellRenderer(showMethodNames, options); + } + + public String getElementText(NavigatablePsiElement element) { + return element instanceof PsiMethod ? myMethodCellRenderer.getElementText((PsiMethod)element) + : PsiExpressionTrimRenderer.render((PsiExpression)element); + } + + protected Icon getIcon(PsiElement element) { + return element instanceof PsiMethod ? myMethodCellRenderer.getIcon(element) : null; + } + + public String getContainerText(final NavigatablePsiElement element, final String name) { + return element instanceof PsiMethod ? myMethodCellRenderer.getContainerText((PsiMethod)element, name) + : PsiClassListCellRenderer.getContainerTextStatic(element); + } + + public int getIconFlags() { + return myClassListCellRenderer.getIconFlags(); + } +} diff --git a/java/java-impl/src/com/intellij/ide/util/PsiClassOrFunctionalExpressionListCellRenderer.java b/java/java-impl/src/com/intellij/ide/util/PsiClassOrFunctionalExpressionListCellRenderer.java new file mode 100644 index 000000000000..eeea2efd734b --- /dev/null +++ b/java/java-impl/src/com/intellij/ide/util/PsiClassOrFunctionalExpressionListCellRenderer.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.ide.util; + +import com.intellij.psi.NavigatablePsiElement; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiExpression; +import com.intellij.psi.presentation.java.ClassPresentationUtil; +import com.intellij.psi.util.PsiExpressionTrimRenderer; + +public class PsiClassOrFunctionalExpressionListCellRenderer extends PsiElementListCellRenderer { + @Override + public String getElementText(NavigatablePsiElement element) { + return element instanceof PsiClass ? ClassPresentationUtil.getNameForClass((PsiClass)element, false) + : PsiExpressionTrimRenderer.render((PsiExpression)element); + } + + @Override + protected String getContainerText(NavigatablePsiElement element, final String name) { + return PsiClassListCellRenderer.getContainerTextStatic(element); + } + + @Override + protected int getIconFlags() { + return 0; + } +} diff --git a/java/java-psi-api/src/com/intellij/psi/PsiFunctionalExpression.java b/java/java-psi-api/src/com/intellij/psi/PsiFunctionalExpression.java index 28290da31342..000848fc1faf 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiFunctionalExpression.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiFunctionalExpression.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.Iconable; import org.jetbrains.annotations.Nullable; public interface PsiFunctionalExpression extends PsiExpression, Iconable, NavigatablePsiElement { + PsiFunctionalExpression[] EMPTY_ARRAY = new PsiFunctionalExpression[0]; /** * @return SAM type the lambda expression corresponds to * null when no SAM type could be found diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiExpressionTrimRenderer.java b/java/java-psi-api/src/com/intellij/psi/util/PsiExpressionTrimRenderer.java index 029e136c373f..964b5fb67ed3 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiExpressionTrimRenderer.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiExpressionTrimRenderer.java @@ -230,6 +230,10 @@ public class PsiExpressionTrimRenderer extends JavaRecursiveElementWalkingVisito public static String render(PsiExpression expression) { StringBuilder buf = new StringBuilder(); expression.accept(new PsiExpressionTrimRenderer(buf)); - return buf.toString(); + final String text = buf.toString(); + int firstNewLinePos = text.indexOf('\n'); + String trimmedText = text.substring(0, firstNewLinePos != -1 ? firstNewLinePos : Math.min(100, text.length())); + if (trimmedText.length() != text.length()) trimmedText += " ..."; + return trimmedText; } } diff --git a/java/testFramework/src/com/intellij/testFramework/CompilerTester.java b/java/testFramework/src/com/intellij/testFramework/CompilerTester.java index 4815d3db8080..ba1519ada136 100644 --- a/java/testFramework/src/com/intellij/testFramework/CompilerTester.java +++ b/java/testFramework/src/com/intellij/testFramework/CompilerTester.java @@ -117,7 +117,7 @@ public class CompilerTester { path.getChildren(); assert path != null; path.refresh(false, true); - return path.findChild(className.replace('.', '/') + ".class"); + return path.findFileByRelativePath(className.replace('.', '/') + ".class"); } public void touch(VirtualFile file) throws IOException { diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbAware.java b/platform/core-api/src/com/intellij/openapi/project/DumbAware.java index 615ba257c5e3..c9cb054463f4 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbAware.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbAware.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. @@ -17,8 +17,8 @@ package com.intellij.openapi.project; /** * A marker interface for the things that are allowed to run in dumb mode (when indices are in background update). - * Implementors must take care of handling and/or not calling non-DumbAware parts of system - * + * Implementors must take care of handling and/or not calling non-DumbAware parts of system. + *

* Known implementors are: *

  • {@link com.intellij.openapi.actionSystem.AnAction}s *
  • {@link com.intellij.openapi.fileEditor.FileEditorProvider}s @@ -34,10 +34,11 @@ package com.intellij.openapi.project; *
  • {@link com.intellij.openapi.wm.ToolWindowFactory}s *
  • {@link com.intellij.lang.injection.MultiHostInjector}s * + * @author peter * @see com.intellij.openapi.project.DumbService * @see com.intellij.openapi.project.DumbAwareRunnable * @see PossiblyDumbAware - * @author peter */ +@SuppressWarnings("JavadocReference") public interface DumbAware { } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/ListBackgroundUpdaterTask.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/ListBackgroundUpdaterTask.java index eb9abc451329..502b830b2fd9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/ListBackgroundUpdaterTask.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/ListBackgroundUpdaterTask.java @@ -23,6 +23,7 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.List; /** @@ -35,12 +36,14 @@ public abstract class ListBackgroundUpdaterTask extends BackgroundUpdaterTask 0) { + String filename = args[0]; + File file = new File(currentDirectory, filename); + + if(file.exists()) { + VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + if (virtualFile != null) { + int line = -1; + if (args.length > 2 && CustomProtocolHandler.LINE_NUMBER_ARG_NAME.equals(args[1])) { + try { + line = Integer.parseInt(args[2]); + } catch (NumberFormatException ex) { + LOG.error("Wrong line number:" + args[2]); + } + } + PlatformProjectOpenProcessor.doOpenProject(virtualFile, null, false, line, null, false); + } + } + throw new IncorrectOperationException("Can't find file:" + file); + } + } + @Override public void main(String[] args) { SystemDock.updateMenu(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index 527125019b49..6221b8867153 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -264,7 +264,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, @Nullable @Override public Caret addCaret(@NotNull VisualPosition pos) { - myEditor.assertIsDispatchThread(); + EditorImpl.assertIsDispatchThread(); CaretImpl caret = new CaretImpl(myEditor); caret.moveToVisualPosition(pos, false); if (addCaret(caret)) { @@ -291,7 +291,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, @Override public boolean removeCaret(@NotNull Caret caret) { - myEditor.assertIsDispatchThread(); + EditorImpl.assertIsDispatchThread(); if (myCarets.size() <= 1 || !(caret instanceof CaretImpl)) { return false; } @@ -307,7 +307,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, @Override public void removeSecondaryCarets() { - myEditor.assertIsDispatchThread(); + EditorImpl.assertIsDispatchThread(); if (!supportsMultipleCarets()) { return; } @@ -329,7 +329,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, @Override public void runForEachCaret(@NotNull final CaretAction action, final boolean reverseOrder) { - myEditor.assertIsDispatchThread(); + EditorImpl.assertIsDispatchThread(); if (!supportsMultipleCarets()) { action.perform(getPrimaryCaret()); return; @@ -358,7 +358,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, @Override public void runBatchCaretOperation(@NotNull Runnable runnable) { - myEditor.assertIsDispatchThread(); + EditorImpl.assertIsDispatchThread(); doWithCaretMerging(runnable); } @@ -442,7 +442,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, @Override public void setCaretsAndSelections(@NotNull final List caretStates, final boolean updateSystemSelection) { - myEditor.assertIsDispatchThread(); + EditorImpl.assertIsDispatchThread(); if (caretStates.isEmpty()) { throw new IllegalArgumentException("At least one caret should exist"); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index e34b067d4977..4e2fd1cc2a48 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -316,6 +316,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse break; } + int annotationSize = myTextAnnotationGutterSizes.get(i); for (int j = startLineNumber; j < endLineNumber; j++) { int logLine = myEditor.visualToLogicalPosition(new VisualPosition(j, 0)).line; String s = gutterProvider.getLineText(logLine, myEditor); @@ -323,7 +324,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse final Color bg = gutterProvider.getBgColor(logLine, myEditor); if (bg != null) { g.setColor(bg); - g.fillRect(x, j * lineHeight, w, lineHeight); + g.fillRect(x, j * lineHeight, annotationSize, lineHeight); } g.setColor(myEditor.getColorsScheme().getColor(gutterProvider.getColor(logLine, myEditor))); g.setFont(myEditor.getColorsScheme().getFont(style)); @@ -332,7 +333,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - x += myTextAnnotationGutterSizes.get(i); + x += annotationSize; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java index 1c51ae3d8938..560fec4fb8a0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java @@ -32,6 +32,7 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; @@ -47,7 +48,7 @@ public class SettingsImpl implements EditorSettings { private SoftWrapAppliancePlaces mySoftWrapAppliancePlace = SoftWrapAppliancePlaces.MAIN_EDITOR; private int myAdditionalLinesCount = 5; private int myAdditionalColumnsCount = 3; - private int myLineCursorWidth = 2; + private int myLineCursorWidth = Registry.intValue("editor.caret.width", 2); private boolean myLineMarkerAreaShown = true; private boolean myAllowSingleLogicalLineFolding = false; diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java index 87668ba25ea0..781a7c4e419d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java @@ -35,7 +35,9 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.FocusWatcher; +import com.intellij.ui.JBColor; import com.intellij.ui.PrevNextActionsDescriptor; +import com.intellij.ui.SideBorder; import com.intellij.ui.TabbedPaneWrapper; import com.intellij.ui.tabs.UiDecorator; import com.intellij.util.SmartList; @@ -350,7 +352,7 @@ public abstract class EditorComposite implements Disposable { if (remove) { container.remove(component.getParent()); } else { - container.add(new TopBottomComponentWrapper(component)); + container.add(new TopBottomComponentWrapper(component, top)); } container.revalidate(); } @@ -466,17 +468,26 @@ public abstract class EditorComposite implements Disposable { @Override public Color getBackground() { Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.GUTTER_BACKGROUND); - return color == null ? Color.gray : color; + return color == null ? EditorColors.GUTTER_BACKGROUND.getDefaultColor() : color; } } private static class TopBottomComponentWrapper extends JPanel { private final JComponent myWrappee; - public TopBottomComponentWrapper(JComponent component) { + public TopBottomComponentWrapper(JComponent component, boolean top) { super(new BorderLayout()); myWrappee = component; setOpaque(false); + + setBorder(new SideBorder(null, top ? SideBorder.BOTTOM : SideBorder.TOP, false) { + @Override + public Color getLineColor() { + Color result = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.TEARLINE_COLOR); + return result == null ? JBColor.BLACK : result; + } + }); + add(component); } diff --git a/platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java b/platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java index e16fa07f808a..2cbcdb9ebdb8 100644 --- a/platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java @@ -28,6 +28,8 @@ import java.util.List; * @author Dennis.Ushakov */ public class CustomProtocolHandler { + public static final String LINE_NUMBER_ARG_NAME = "--line"; + private static final Logger LOG = Logger.getInstance("#com.intellij.ui.CustomProtocolHandler"); public boolean openLink(@NotNull URI uri) { LOG.info("CustomProtocolHandler.openLink"); @@ -57,7 +59,7 @@ public class CustomProtocolHandler { if (file != null) { if (line != null) { - args.add("--line"); + args.add(LINE_NUMBER_ARG_NAME); args.add(line); } args.add(file); diff --git a/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java index 6099561c7283..26d9908c932c 100644 --- a/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java @@ -23,6 +23,7 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; +import javax.swing.table.JTableHeader; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; import java.awt.*; @@ -110,7 +111,8 @@ public class TableExpandableItemsHandler extends AbstractExpandableItemsHandler< public Pair getCellRendererAndBounds(TableCell key) { if (key.row < 0 || key.row >= myComponent.getRowCount() || key.column < 0 || key.column >= myComponent.getColumnCount() || - key.row == myComponent.getEditingRow() && key.column == myComponent.getEditingColumn()) { + key.row == myComponent.getEditingRow() && key.column == myComponent.getEditingColumn() || + hasDraggingOrResizingColumn()) { return null; } @@ -143,4 +145,9 @@ public class TableExpandableItemsHandler extends AbstractExpandableItemsHandler< return new TableCell(rowIndex, columnIndex); } + + private boolean hasDraggingOrResizingColumn() { + JTableHeader header = myComponent.getTableHeader(); + return header != null && (header.getResizingColumn() != null || header.getDraggedColumn() != null); + } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 759d6fb5ca02..57f78e1e1f84 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -478,4 +478,8 @@ ide.transparency.mode.for.windows.description=Allow to add transparency to float ide.new.welcome.screen=true enable.recursive.document.changes=false -enable.recursive.document.changes.description=Enables performing document changes in document event listeners (this breaks undo/redo functionality!) \ No newline at end of file +enable.recursive.document.changes.description=Enables performing document changes in document event listeners (this breaks undo/redo functionality!) + +editor.caret.width=2 +editor.caret.width.description=Caret width +editor.caret.width.restartRequired=true diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootProblemNotifier.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootProblemNotifier.java index c720834fa594..0bae5907771e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootProblemNotifier.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootProblemNotifier.java @@ -37,7 +37,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.event.HyperlinkEvent; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; @@ -83,17 +82,16 @@ public class VcsRootProblemNotifier { return; } - Collection unregisteredRoots = getUnregisteredRoots(errors); - Collection important = getImportantMappings(unregisteredRoots); + Collection importantUnregisteredRoots = getImportantUnregisteredMappings(errors); Collection invalidRoots = getInvalidRoots(errors); - if (invalidRoots.isEmpty() && (important.isEmpty() || myReportedUnregisteredRoots.containsAll(important))) { + if (invalidRoots.isEmpty() && (importantUnregisteredRoots.isEmpty() || myReportedUnregisteredRoots.containsAll(importantUnregisteredRoots))) { return; } - myReportedUnregisteredRoots.addAll(unregisteredRoots); + myReportedUnregisteredRoots.addAll(importantUnregisteredRoots); - String title = makeTitle(unregisteredRoots, invalidRoots); - String description = makeDescription(unregisteredRoots, invalidRoots); + String title = makeTitle(importantUnregisteredRoots, invalidRoots); + String description = makeDescription(importantUnregisteredRoots, invalidRoots); synchronized (NOTIFICATION_LOCK) { expireNotification(); @@ -105,17 +103,6 @@ public class VcsRootProblemNotifier { } } - @NotNull - private List getImportantMappings(@NotNull Collection unregisteredRoots) { - return ContainerUtil.filter(unregisteredRoots, new Condition() { - @Override - public boolean value(VcsRootError error) { - String mapping = error.getMapping(); - return isUnderProjectDir(mapping) && !isIgnored(mapping); - } - }); - } - private boolean isUnderProjectDir(@NotNull String mapping) { return mapping.equals(VcsDirectoryMapping.PROJECT_CONSTANT) || FileUtil.isAncestor(myProject.getBasePath(), mapping, false); } @@ -207,24 +194,24 @@ public class VcsRootProblemNotifier { } @NotNull - private static Collection getUnregisteredRoots(@NotNull Collection errors) { - return filterErrorsByType(errors, VcsRootError.Type.UNREGISTERED_ROOT); + private List getImportantUnregisteredMappings(@NotNull Collection errors) { + return ContainerUtil.filter(errors, new Condition() { + @Override + public boolean value(VcsRootError error) { + String mapping = error.getMapping(); + return error.getType() == VcsRootError.Type.UNREGISTERED_ROOT && isUnderProjectDir(mapping) && !isIgnored(mapping); + } + }); } @NotNull private static Collection getInvalidRoots(@NotNull Collection errors) { - return filterErrorsByType(errors, VcsRootError.Type.EXTRA_MAPPING); - } - - @NotNull - private static Collection filterErrorsByType(@NotNull Collection errors, @NotNull VcsRootError.Type type) { - Collection roots = new ArrayList(); - for (VcsRootError error : errors) { - if (error.getType() == type) { - roots.add(error); + return ContainerUtil.filter(errors, new Condition() { + @Override + public boolean value(VcsRootError error) { + return error.getType() == VcsRootError.Type.EXTRA_MAPPING; } - } - return roots; + }); } private static class MyNotificationListener implements NotificationListener { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/HashImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/HashImpl.java index fd981f54bfbd..82db30cbe613 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/HashImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/HashImpl.java @@ -43,14 +43,15 @@ public class HashImpl implements Hash { int length = inputStr.length(); byte even = (byte)(length % 2); byte[] data = new byte[length / 2 + 1 + even]; + final int base = 16; data[0] = even; try { for (int i = 0; i < length / 2; i++) { - int k = Integer.parseInt(inputStr.substring(2 * i, 2 * i + 2), 16); + int k = Character.digit(inputStr.charAt(2 * i), base) * base + Character.digit(inputStr.charAt(2 * i + 1), base); data[i + 1] = (byte)(k - 128); } if (even == 1) { - int k = Integer.parseInt(inputStr.substring(length - 1), 16); + int k = Character.digit(inputStr.charAt(length - 1), base); data[length / 2 + 1] = (byte)(k - 128); } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml index 3006a8b2c89e..d87acd74aa30 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml @@ -458,10 +458,6 @@ - + #ref#ref() overrides concrete method #loc abstract.method.with.missing.implementations.problem.descriptor=Abstract method #ref() is not implemented in every subclass #loc abstract.method.overrides.abstract.method.problem.descriptor=Abstract method #ref() overrides abstract method #loc -abstract.method.overrides.abstract.method.ignore.different.javadoc.option=Ignore methods with different JavaDoc than their super methods +abstract.method.overrides.abstract.method.ignore.different.javadoc.option=Ignore methods with different Javadoc than their super methods abstract.method.overrides.abstract.method.ignore.different.annotations.option=Ignore methods with different annotations than their super methods abstract.class.extends.concrete.class.problem.descriptor=Class #ref is declared 'abstract', and extends a concrete class #loc static.non.final.field.problem.descriptor='static' non-'final' field #ref #loc @@ -932,7 +932,9 @@ marker.interface.problem.descriptor=Marker interface #ref #loc field.has.setter.but.no.getter.problem.descriptor=Field #ref has setter but no getter #loc abstract.class.never.implemented.problem.descriptor=Abstract class #ref has no concrete subclass #loc interface.never.implemented.problem.descriptor=Interface #ref has no concrete subclass #loc -missing.deprecated.annotation.problem.descriptor=Missing '@Deprecated' annotation on #ref() #loc +missing.deprecated.annotation.problem.descriptor=Missing '@Deprecated' annotation #loc +missing.deprecated.tag.problem.descriptor=Missing '@deprecated' Javadoc tag explanation #loc +missing.deprecated.tag.option=Warn on missing @deprecated Javadoc tag explanation missing.override.annotation.problem.descriptor=Missing '@Override' annotation on #ref() #loc non.thread.safe.lazy.initialization.problem.descriptor=Lazy initialization of 'static' field #ref is not thread-safe #loc empty.catch.block.problem.descriptor=Empty #ref block #loc diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingDeprecatedAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspection.java similarity index 60% rename from plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingDeprecatedAnnotationInspection.java rename to plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspection.java index ec87f2a1ba2b..3a0898245916 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingDeprecatedAnnotationInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.classlayout; +package com.siyeh.ig.javadoc; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; @@ -26,9 +27,14 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; public class MissingDeprecatedAnnotationInspection extends BaseInspection { + @SuppressWarnings("PublicField") public boolean warnOnMissingJavadoc = false; + @Override @NotNull public String getDisplayName() { @@ -38,7 +44,17 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { @Override @NotNull protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message("missing.deprecated.annotation.problem.descriptor"); + final boolean annotationWarning = ((Boolean)infos[0]).booleanValue(); + return annotationWarning + ? InspectionGadgetsBundle.message("missing.deprecated.annotation.problem.descriptor") + : InspectionGadgetsBundle.message("missing.deprecated.tag.problem.descriptor"); + } + + @Nullable + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("missing.deprecated.tag.option"), + this, "warnOnMissingJavadoc"); } @Override @@ -48,6 +64,10 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { @Override protected InspectionGadgetsFix buildFix(Object... infos) { + final boolean annotationWarning = ((Boolean)infos[0]).booleanValue(); + if (!annotationWarning) { + return null; + } return new MissingDeprecatedAnnotationFix(); } @@ -87,7 +107,7 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { return new MissingDeprecatedAnnotationVisitor(); } - private static class MissingDeprecatedAnnotationVisitor extends BaseInspectionVisitor { + private class MissingDeprecatedAnnotationVisitor extends BaseInspectionVisitor { @Override public void visitClass(@NotNull PsiClass aClass) { @@ -95,10 +115,14 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { if (!PsiUtil.isLanguageLevel5OrHigher(aClass)) { return; } - if (!hasDeprecatedComment(aClass) || hasDeprecatedAnnotation(aClass)) { - return; + if (hasDeprecatedAnnotation(aClass)) { + if (warnOnMissingJavadoc && !hasDeprecatedComment(aClass, true)) { + registerClassError(aClass, Boolean.FALSE); + } + } + else if (hasDeprecatedComment(aClass, false)) { + registerClassError(aClass, Boolean.TRUE); } - registerClassError(aClass); } @Override @@ -109,10 +133,14 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { if (method.getNameIdentifier() == null) { return; } - if (!hasDeprecatedComment(method) || hasDeprecatedAnnotation(method)) { - return; + if (hasDeprecatedAnnotation(method)) { + if (warnOnMissingJavadoc && !hasDeprecatedComment(method, true)) { + registerMethodError(method, Boolean.FALSE); + } + } + else if (hasDeprecatedComment(method, false)) { + registerMethodError(method, Boolean.TRUE); } - registerMethodError(method); } @Override @@ -120,28 +148,31 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { if (!PsiUtil.isLanguageLevel5OrHigher(field)) { return; } - if (!hasDeprecatedComment(field) || hasDeprecatedAnnotation(field)) { - return; + if (hasDeprecatedAnnotation(field)) { + if (warnOnMissingJavadoc && !hasDeprecatedComment(field, true)) { + registerFieldError(field, Boolean.FALSE); + } + } + else if (hasDeprecatedComment(field, false)) { + registerFieldError(field, Boolean.TRUE); } - registerFieldError(field); } - private static boolean hasDeprecatedAnnotation(PsiModifierListOwner element) { + private boolean hasDeprecatedAnnotation(PsiModifierListOwner element) { final PsiModifierList modifierList = element.getModifierList(); - if (modifierList == null) { - return false; - } - final PsiAnnotation annotation = modifierList.findAnnotation(CommonClassNames.JAVA_LANG_DEPRECATED); - return annotation != null; + return modifierList != null && modifierList.findAnnotation(CommonClassNames.JAVA_LANG_DEPRECATED) != null; } - private static boolean hasDeprecatedComment(PsiDocCommentOwner element) { + private boolean hasDeprecatedComment(PsiDocCommentOwner element, boolean checkContent) { final PsiDocComment comment = element.getDocComment(); if (comment == null) { return false; } final PsiDocTag deprecatedTag = comment.findTagByName("deprecated"); - return deprecatedTag != null; + if (deprecatedTag == null) { + return false; + } + return !checkContent || deprecatedTag.getValueElement() != null; } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MissingDeprecatedAnnotation.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MissingDeprecatedAnnotation.html index 6ded6180ef1f..85d00c73f1f4 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/MissingDeprecatedAnnotation.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MissingDeprecatedAnnotation.html @@ -7,6 +7,9 @@ This inspection only reports if the project or module is configured to use a language level of 5.0 or higher.

    +Use the checkbox below to warn on symbols annotated with @Deprecated without a corresponding explanation in a +@deprecated Javadoc tag. +

    \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/missing_deprecated_annotation/MissingDeprecatedAnnotation.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/missing_deprecated_annotation/MissingDeprecatedAnnotation.java new file mode 100644 index 000000000000..7a8f181c93c9 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/missing_deprecated_annotation/MissingDeprecatedAnnotation.java @@ -0,0 +1,37 @@ +/** + * @deprecated + */ +public class MissingDeprecatedAnnotation { + + /** + * @deprecated Use {@link #b()} instead + */ + @Deprecated + void a() {} + + /** + * @deprecated + */ + void b() {} + + /** + * @deprecated + */ + String s; + +} +@Deprecated +class Two { + + /** + * @deprecated + */ + @Deprecated + void a() {} + + @Deprecated + void b() {} + + @Deprecated + String s; +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspectionTest.java new file mode 100644 index 000000000000..6b256a2c313d --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspectionTest.java @@ -0,0 +1,39 @@ +/* + * 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.siyeh.ig.javadoc; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import junit.framework.TestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class MissingDeprecatedAnnotationInspectionTest extends LightInspectionTestCase { + + public void testMissingDeprecatedAnnotation() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + final MissingDeprecatedAnnotationInspection inspection = new MissingDeprecatedAnnotationInspection(); + inspection.warnOnMissingJavadoc = true; + return inspection; + } +} \ No newline at end of file diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 4540c3afd0b1..98542511bd57 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -336,7 +336,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { File commonRoot = new File(context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(), "groovyStubs"); for (ModuleBuildTarget target : chunk.getTargets()) { File targetRoot = new File(commonRoot, target.getModule().getName() + File.separator + target.getTargetType().getTypeId()); - if (!FileUtil.delete(targetRoot)) { + if (!FileUtil.deleteWithRenaming(targetRoot)) { throw new IOException("External make cannot clean " + targetRoot.getPath()); } if (!targetRoot.mkdirs()) { diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java index 50bd5c5720ed..98d2f63ab5ab 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java @@ -69,10 +69,14 @@ public class XsltCommandLineState extends CommandLineState { super(environment); myXsltRunConfiguration = xsltRunConfiguration; - myIsDebugger = "Debug".equals(environment.getRunner().getRunnerId()); + myIsDebugger = "Debug".equals(environment.getExecutor().getId()); } - @Override + public boolean isDebugger() { + return myIsDebugger; + } + + @Override @NotNull protected OSProcessHandler startProcess() throws ExecutionException { final OSProcessHandler osProcessHandler = createJavaParameters().createOSProcessHandler(); diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java index 8cf2c67d4bc9..dc090ffbbfbf 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java @@ -144,8 +144,10 @@ public final class XsltRunConfiguration extends LocatableConfigurationBase imple if (myOutputType == OutputType.CONSOLE) { final HighlightingOutputConsole console = new HighlightingOutputConsole(getProject(), myFileType); - boolean consoleTabAdded = false; - for (XsltRunnerExtension extension : XsltRunnerExtension.getExtensions(this, false /* doesn't matter, xslt debugger uses own flag */)) { + XsltCommandLineState state = startedProcess.getUserData(XsltCommandLineState.STATE); + boolean debug = state != null && state.isDebugger(); + boolean consoleTabAdded = false; + for (XsltRunnerExtension extension : XsltRunnerExtension.getExtensions(this, debug)) { if (extension.createTabs(getProject(), manager, console, startedProcess)) { consoleTabAdded = true; } diff --git a/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java b/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java index db1fec1a6ca7..5fbe67f56f1c 100644 --- a/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java +++ b/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java @@ -87,8 +87,9 @@ public class AddImportHelper { } @Nullable - private static PsiElement getInsertPosition(final PsiFile file, @Nullable String nameToImport, @Nullable ImportPriority priority) { - PsiElement feeler = file.getFirstChild(); + private static PsiElement getInsertPosition(final PsiElement insertParent, @Nullable String nameToImport, + @Nullable ImportPriority priority) { + PsiElement feeler = insertParent.getFirstChild(); if (feeler == null) return null; // skip initial comments and whitespace and try to get just below the last import stmt boolean skippedOverImports = false; @@ -97,7 +98,7 @@ public class AddImportHelper { final boolean isInjected = InjectedLanguageManager.getInstance(feeler.getProject()).isInjectedFragment(feeler.getContainingFile()); do { if (feeler instanceof PyImportStatementBase && !isInjected) { - if (nameToImport != null && priority != null && shouldInsertBefore(file, (PyImportStatementBase)feeler, nameToImport, priority)) { + if (nameToImport != null && priority != null && shouldInsertBefore(insertParent, (PyImportStatementBase)feeler, nameToImport, priority)) { break; } seeker = feeler; @@ -109,10 +110,9 @@ public class AddImportHelper { feeler = feeler.getNextSibling(); } // maybe we arrived at the doc comment stmt; skip over it, too - else if (!skippedOverImports && !skippedOverDoc && file instanceof PyFile) { + else if (!skippedOverImports && !skippedOverDoc && insertParent instanceof PyFile) { PsiElement doc_elt = - DocStringUtil - .findDocStringExpression((PyElement)file); // this gives the literal; its parent is the expr seeker may have encountered + DocStringUtil.findDocStringExpression((PyElement)insertParent); // this gives the literal; its parent is the expr seeker may have encountered if (doc_elt != null && doc_elt.getParent() == feeler) { feeler = feeler.getNextSibling(); seeker = feeler; // skip over doc even if there's nothing below it @@ -130,7 +130,8 @@ public class AddImportHelper { return seeker; } - private static boolean shouldInsertBefore(PsiFile file, PyImportStatementBase relativeTo, String nameToImport, ImportPriority priority) { + private static boolean shouldInsertBefore(PsiElement element, PyImportStatementBase relativeTo, String nameToImport, + ImportPriority priority) { QualifiedName relativeToName; PsiElement source; if (relativeTo instanceof PyFromImportStatement) { @@ -161,7 +162,7 @@ public class AddImportHelper { } ImportPriority relativeToPriority = source == null || containingFile == null ? ImportPriority.BUILTIN - : getImportPriority(file, containingFile); + : getImportPriority(element, containingFile); final int rc = priority.compareTo(relativeToPriority); if (rc < 0) { return true; @@ -213,22 +214,32 @@ public class AddImportHelper { * @param from name of the module * @param name imported name * @param asName optional name for 'as' clause + * @param anchor place where the imported name was used */ - public static void addImportFromStatement(PsiFile file, String from, String name, @Nullable String asName, ImportPriority priority) { + public static void addImportFromStatement(PsiFile file, String from, String name, @Nullable String asName, ImportPriority priority, + @Nullable PsiElement anchor) { final PyElementGenerator generator = PyElementGenerator.getInstance(file.getProject()); final LanguageLevel languageLevel = LanguageLevel.forElement(file); final PyFromImportStatement nodeToInsert = generator.createFromImportStatement(languageLevel, from, name, asName); try { + final PyImportStatementBase importStatement = PsiTreeUtil.getParentOfType(anchor, PyImportStatementBase.class, false); + final PsiElement insertParent; + if (importStatement != null && importStatement.getContainingFile() == file) { + insertParent = importStatement.getParent(); + } + else { + insertParent = file; + } if (InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) { - final PsiElement element = file.addBefore(nodeToInsert, getInsertPosition(file, from, priority)); + final PsiElement element = insertParent.addBefore(nodeToInsert, getInsertPosition(insertParent, from, priority)); PsiElement whitespace = element.getNextSibling(); if (!(whitespace instanceof PsiWhiteSpace)) { whitespace = PsiParserFacade.SERVICE.getInstance(file.getProject()).createWhiteSpaceFromText(" >>> "); } - file.addBefore(whitespace, element); + insertParent.addBefore(whitespace, element); } else { - file.addBefore(nodeToInsert, getInsertPosition(file, from, priority)); + insertParent.addBefore(nodeToInsert, getInsertPosition(insertParent, from, priority)); } } catch (IncorrectOperationException e) { @@ -237,7 +248,7 @@ public class AddImportHelper { } public static boolean addImportFrom(PsiFile file, @Nullable PsiElement target, String path, final String name, - @Nullable String asName, ImportPriority priority) { + @Nullable String asName, ImportPriority priority, @Nullable PsiElement anchor) { final List existingImports = ((PyFile)file).getFromImports(); for (PyFromImportStatement existingImport : existingImports) { if (target != null && existingImport.getTextRange().getStartOffset() > target.getTextRange().getStartOffset()) { @@ -259,7 +270,7 @@ public class AddImportHelper { return true; } } - addImportFromStatement(file, path, name, asName, priority); + addImportFromStatement(file, path, name, asName, priority, anchor); return true; } @@ -283,7 +294,7 @@ public class AddImportHelper { element.replace(elementGenerator.createExpressionFromText(LanguageLevel.forElement(target), toImportQName + "." + targetName)); } else { - addImportFrom(file, null, toImportQName.toString(), target.getName(), null, priority); + addImportFrom(file, null, toImportQName.toString(), target.getName(), null, priority, element); } } } diff --git a/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java b/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java index bf1a80690ce6..09eb355e57a3 100644 --- a/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java +++ b/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java @@ -181,7 +181,7 @@ public class ImportFromExistingAction implements QuestionAction { AddImportHelper.addLocalFromImportStatement(myTarget, qualifiedName, myName); } else { - AddImportHelper.addImportFromStatement(file, qualifiedName, myName, null, priority); + AddImportHelper.addImportFromStatement(file, qualifiedName, myName, null, priority, null); } } } diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java index e333e864cfa2..7ab4b1a395a4 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java @@ -59,7 +59,11 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase { @Override public PyType getReferenceType(@NotNull PsiElement referenceTarget, @NotNull TypeEvalContext context, @Nullable PsiElement anchor) { - PyType type = getNamedTupleType(referenceTarget, anchor); + PyType type = getBaseStringType(referenceTarget); + if (type != null) { + return type; + } + type = getNamedTupleType(referenceTarget, anchor); if (type != null) { return type; } @@ -70,6 +74,16 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase { return null; } + @Nullable + private static PyType getBaseStringType(@NotNull PsiElement referenceTarget) { + final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(referenceTarget); + if (referenceTarget instanceof PyElement && builtinCache.isBuiltin(referenceTarget) && + "basestring".equals(((PyElement)referenceTarget).getName())) { + return builtinCache.getStringType(LanguageLevel.forElement(referenceTarget)); + } + return null; + } + @Nullable private static PyType getEnumType(@NotNull PsiElement referenceTarget, @NotNull TypeEvalContext context, @Nullable PsiElement anchor) { diff --git a/python/src/com/jetbrains/python/codeInsight/testIntegration/PyTestCreator.java b/python/src/com/jetbrains/python/codeInsight/testIntegration/PyTestCreator.java index 3ea107f60808..4c13089f40ed 100644 --- a/python/src/com/jetbrains/python/codeInsight/testIntegration/PyTestCreator.java +++ b/python/src/com/jetbrains/python/codeInsight/testIntegration/PyTestCreator.java @@ -85,7 +85,7 @@ public class PyTestCreator implements TestCreator { PsiFile psiFile = PyUtil.getOrCreateFile( dialog.getTargetDir() + "/" + fileName, project); - AddImportHelper.addImportFrom(psiFile, null, "unittest", "TestCase", null, AddImportHelper.ImportPriority.BUILTIN); + AddImportHelper.addImportFrom(psiFile, null, "unittest", "TestCase", null, AddImportHelper.ImportPriority.BUILTIN, null); PyElement createdClass = PyElementGenerator.getInstance(project).createFromText( LanguageLevel.forElement(psiFile), PyClass.class, diff --git a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java index 00793c8ffd0e..0e58f56d5ff3 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java @@ -161,15 +161,33 @@ public class PyBuiltinCache { } @Nullable - static PyType createLiteralCollectionType(final PySequenceExpression sequence, final String name) { - final PyBuiltinCache builtinCache = getInstance(sequence); - final PyClass setClass = builtinCache.getClass(name); - if (setClass != null) { - return new PyLiteralCollectionType(setClass, false, sequence); + public PyType createLiteralCollectionType(final PySequenceExpression sequence, final String name, @NotNull TypeEvalContext context) { + final PyClass cls = getClass(name); + if (cls != null) { + return new PyCollectionTypeImpl(cls, false, getSequenceElementType(sequence, context)); } return null; } + @Nullable + private static PyType getSequenceElementType(@NotNull PySequenceExpression sequence, @NotNull TypeEvalContext context) { + final PyExpression[] elements = sequence.getElements(); + if (elements.length == 0 || elements.length > 10 /* performance */) { + return null; + } + final PyType result = context.getType(elements[0]); + if (result == null) { + return null; + } + for (int i = 1; i < elements.length; i++) { + final PyType elementType = context.getType(elements[i]); + if (elementType == null || !elementType.equals(result)) { + return null; + } + } + return result; + } + @Nullable public PyFile getBuiltinsFile() { return myBuiltinsFile; diff --git a/python/src/com/jetbrains/python/psi/impl/PyDictLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyDictLiteralExpressionImpl.java index b7b73bd91ad9..e6010154cf7c 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyDictLiteralExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyDictLiteralExpressionImpl.java @@ -38,7 +38,7 @@ public class PyDictLiteralExpressionImpl extends PyElementImpl implements PyDict } public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) { - return PyBuiltinCache.createLiteralCollectionType(this, "dict"); + return PyBuiltinCache.getInstance(this).createLiteralCollectionType(this, "dict", context); } @Override diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 59a3afa70b15..2e8e7196a80c 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -270,6 +270,16 @@ public class PyFunctionImpl extends PyBaseElementImpl implements public String getPresentableText() { return notNullize(getName(), PyNames.UNNAMED_ELEMENT) + getParameterList().getPresentableText(true); } + + @Nullable + @Override + public String getLocationString() { + final PyClass containingClass = getContainingClass(); + if (containingClass != null) { + return "(" + containingClass.getName() + " in " + getPackageForFile(getContainingFile()) + ")"; + } + return super.getLocationString(); + } }; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyListLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyListLiteralExpressionImpl.java index 63f4b29c435a..a71519266e48 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyListLiteralExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyListLiteralExpressionImpl.java @@ -86,6 +86,6 @@ public class PyListLiteralExpressionImpl extends PyElementImpl implements PyList } public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) { - return PyBuiltinCache.createLiteralCollectionType(this, "list"); + return PyBuiltinCache.getInstance(this).createLiteralCollectionType(this, "list", context); } } diff --git a/python/src/com/jetbrains/python/psi/impl/PySetLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PySetLiteralExpressionImpl.java index 9d60b576aea2..89c87692748a 100644 --- a/python/src/com/jetbrains/python/psi/impl/PySetLiteralExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PySetLiteralExpressionImpl.java @@ -31,7 +31,7 @@ public class PySetLiteralExpressionImpl extends PyElementImpl implements PySetLi } public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) { - return PyBuiltinCache.createLiteralCollectionType(this, "set"); + return PyBuiltinCache.getInstance(this).createLiteralCollectionType(this, "set", context); } @Override diff --git a/python/src/com/jetbrains/python/psi/types/PyLiteralCollectionType.java b/python/src/com/jetbrains/python/psi/types/PyLiteralCollectionType.java deleted file mode 100644 index 896c9d57d929..000000000000 --- a/python/src/com/jetbrains/python/psi/types/PyLiteralCollectionType.java +++ /dev/null @@ -1,52 +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.jetbrains.python.psi.types; - -import com.jetbrains.python.psi.PyClass; -import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.PySequenceExpression; -import org.jetbrains.annotations.NotNull; - -/** - * @author yole - */ -public class PyLiteralCollectionType extends PyClassTypeImpl implements PyCollectionType { - private final PySequenceExpression mySequence; - - public PyLiteralCollectionType(@NotNull PyClass source, boolean isDefinition, PySequenceExpression sequence) { - super(source, isDefinition); - mySequence = sequence; - } - - @Override - public PyType getElementType(@NotNull TypeEvalContext context) { - final PyExpression[] elements = mySequence.getElements(); - if (elements.length == 0 || elements.length > 10 /* performance */) { - return null; - } - PyType result = context.getType(elements [0]); - if (result == null) { - return null; - } - for (int i = 1; i < elements.length; i++) { - PyType elementType = context.getType(elements[i]); - if (elementType == null || !elementType.equals(result)) { - return null; - } - } - return result; - } -} diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java index f2647bdb3b72..0a07ffaac98d 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java +++ b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java @@ -318,7 +318,7 @@ public final class PyClassRefactoringUtil { } final AddImportHelper.ImportPriority priority = AddImportHelper.getImportPriority(anchor, newFile); if (preferFromImport && !containingQName.getComponents().isEmpty()) { - return AddImportHelper.addImportFrom(file, null, containingQName.toString(), importedName, asName, priority); + return AddImportHelper.addImportFrom(file, null, containingQName.toString(), importedName, asName, priority, anchor); } else { return AddImportHelper.addImportStatement(file, containingQName.append(importedName).toString(), asName, priority); diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java index 1d30e01821be..24b8ec0e3873 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java @@ -163,7 +163,7 @@ class MethodsManager extends MembersManager { */ private static void addImportFromAbc(@NotNull final PsiFile file, @NotNull final String nameToImport) { AddImportHelper.addImportFromStatement(file, ABC_META_PACKAGE, nameToImport, null, - AddImportHelper.ImportPriority.BUILTIN); + AddImportHelper.ImportPriority.BUILTIN, null); } /** diff --git a/python/testData/hierarchy/call/Static/Constructor/Constructor_callee_verification.xml b/python/testData/hierarchy/call/Static/Constructor/Constructor_callee_verification.xml index 1b720a99aee9..100a9c5448a1 100644 --- a/python/testData/hierarchy/call/Static/Constructor/Constructor_callee_verification.xml +++ b/python/testData/hierarchy/call/Static/Constructor/Constructor_callee_verification.xml @@ -1,8 +1,8 @@ - + - + - + \ No newline at end of file diff --git a/python/testData/hierarchy/call/Static/Constructor/Constructor_caller_verification.xml b/python/testData/hierarchy/call/Static/Constructor/Constructor_caller_verification.xml index b872e20e6c7b..8b70d0c1c04b 100644 --- a/python/testData/hierarchy/call/Static/Constructor/Constructor_caller_verification.xml +++ b/python/testData/hierarchy/call/Static/Constructor/Constructor_caller_verification.xml @@ -1,6 +1,6 @@ - + - + - + \ No newline at end of file diff --git a/python/testData/hierarchy/call/Static/Inheritance/Inheritance_callee_verification.xml b/python/testData/hierarchy/call/Static/Inheritance/Inheritance_callee_verification.xml index cf65c63a4d04..8f7c5104f231 100644 --- a/python/testData/hierarchy/call/Static/Inheritance/Inheritance_callee_verification.xml +++ b/python/testData/hierarchy/call/Static/Inheritance/Inheritance_callee_verification.xml @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/python/testData/hierarchy/call/Static/Inheritance/Inheritance_caller_verification.xml b/python/testData/hierarchy/call/Static/Inheritance/Inheritance_caller_verification.xml index a81d537dcc27..a01c0e8c3a71 100644 --- a/python/testData/hierarchy/call/Static/Inheritance/Inheritance_caller_verification.xml +++ b/python/testData/hierarchy/call/Static/Inheritance/Inheritance_caller_verification.xml @@ -1,4 +1,4 @@ - - + + \ No newline at end of file diff --git a/python/testData/hierarchy/call/Static/OverriddenMethod/OverriddenMethod_callee_verification.xml b/python/testData/hierarchy/call/Static/OverriddenMethod/OverriddenMethod_callee_verification.xml index 04af9fdd87ed..66557bd8da18 100644 --- a/python/testData/hierarchy/call/Static/OverriddenMethod/OverriddenMethod_callee_verification.xml +++ b/python/testData/hierarchy/call/Static/OverriddenMethod/OverriddenMethod_callee_verification.xml @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/python/testData/hierarchy/call/Static/OverriddenMethod/OverriddenMethod_caller_verification.xml b/python/testData/hierarchy/call/Static/OverriddenMethod/OverriddenMethod_caller_verification.xml index ddf9369f2766..23bbf44306b1 100644 --- a/python/testData/hierarchy/call/Static/OverriddenMethod/OverriddenMethod_caller_verification.xml +++ b/python/testData/hierarchy/call/Static/OverriddenMethod/OverriddenMethod_caller_verification.xml @@ -1,5 +1,5 @@ - - + + - + \ No newline at end of file diff --git a/python/testData/inspections/PyTypeCheckerInspection/RecursiveDictAttribute.py b/python/testData/inspections/PyTypeCheckerInspection/RecursiveDictAttribute.py new file mode 100644 index 000000000000..72f10ac35f4c --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/RecursiveDictAttribute.py @@ -0,0 +1,5 @@ +class C: + def f(self, x): + self.foo = x + self.foo = {'foo': self.foo} + return self.foo['foo'] + 10 diff --git a/python/testData/refactoring/move/conditionalImport/after/src/mod1.py b/python/testData/refactoring/move/conditionalImport/after/src/mod1.py new file mode 100644 index 000000000000..16b31152f96e --- /dev/null +++ b/python/testData/refactoring/move/conditionalImport/after/src/mod1.py @@ -0,0 +1,6 @@ +if True: + import pkgutil +else: + from pkg1 import mod2 as pkgutil + +print(pkgutil) diff --git a/python/testData/refactoring/move/conditionalImport/after/src/pkg1/__init__.py b/python/testData/refactoring/move/conditionalImport/after/src/pkg1/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/conditionalImport/after/src/pkg1/mod2.py b/python/testData/refactoring/move/conditionalImport/after/src/pkg1/mod2.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/conditionalImport/before/src/mod1.py b/python/testData/refactoring/move/conditionalImport/before/src/mod1.py new file mode 100644 index 000000000000..08f91c02004c --- /dev/null +++ b/python/testData/refactoring/move/conditionalImport/before/src/mod1.py @@ -0,0 +1,6 @@ +if True: + import pkgutil +else: + import mod2 as pkgutil + +print(pkgutil) diff --git a/python/testData/refactoring/move/conditionalImport/before/src/mod2.py b/python/testData/refactoring/move/conditionalImport/before/src/mod2.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/conditionalImport/before/src/pkg1/__init__.py b/python/testData/refactoring/move/conditionalImport/before/src/pkg1/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testSrc/com/jetbrains/python/PyAddImportTest.java b/python/testSrc/com/jetbrains/python/PyAddImportTest.java index f95187aff819..2b64e00064e1 100644 --- a/python/testSrc/com/jetbrains/python/PyAddImportTest.java +++ b/python/testSrc/com/jetbrains/python/PyAddImportTest.java @@ -53,7 +53,7 @@ public class PyAddImportTest extends PyTestCase { new WriteCommandAction(myFixture.getProject(), myFixture.getFile()) { @Override protected void run(Result result) throws Throwable { - AddImportHelper.addImportFrom(myFixture.getFile(), null, path, name, null, AddImportHelper.ImportPriority.BUILTIN); + AddImportHelper.addImportFrom(myFixture.getFile(), null, path, name, null, AddImportHelper.ImportPriority.BUILTIN, null); } }.execute(); myFixture.checkResultByFile("addImport/" + getTestName(true) + ".after.py"); diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java index d4f6acda8fd3..7453e78613a8 100644 --- a/python/testSrc/com/jetbrains/python/PyTypeTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java @@ -505,7 +505,7 @@ public class PyTypeTest extends PyTestCase { // EA-40207 public void testRecursion() { - doTest("list[list]", + doTest("list", "def f():\n" + " return [f()]\n" + "expr = f()\n"); @@ -952,6 +952,14 @@ public class PyTypeTest extends PyTestCase { "print(expr)\n"); } + // PY-11541 + public void testIsInstanceBaseStringCheck() { + doTest("str | unicode", + "def f(x):\n" + + " if isinstance(x, basestring):\n" + + " expr = x\n"); + } + private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) { return TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).withTracing(); } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java index 0b15d89dfddf..65ea0ed75497 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java @@ -237,4 +237,9 @@ public class PyTypeCheckerInspectionTest extends PyTestCase { public void testDefaultTupleParameter() { doTest(); } + + // PY-14222 + public void testRecursiveDictAttribute() { + doTest(); + } } diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java index ab929d572550..b6a1a1f78a88 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java @@ -133,6 +133,11 @@ public class PyMoveTest extends PyTestCase { doMoveSymbolTest("g", "c.py"); } + // PY-13870 + public void testConditionalImport() { + doMoveFileTest("mod2.py", "pkg1"); + } + private void doMoveFileTest(String fileName, String toDirName) { Project project = myFixture.getProject(); PsiManager manager = PsiManager.getInstance(project); diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index e1413b893901..c8ac0924ee37 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -198,6 +198,8 @@ https iconable iife impl +implementor +implementors inbox incrementer indextype