Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2014-11-10 17:01:28 +01:00
60 changed files with 599 additions and 212 deletions
@@ -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<String, String> mapping) {
final boolean shouldNotify = !myProject.isDefault() && !myModuleBytecodeTarget.equals(mapping);
myModuleBytecodeTarget.clear();
myModuleBytecodeTarget.putAll(mapping);
if (shouldNotify) {
BuildManager.getInstance().clearState(myProject);
}
}
public Map<String, String> 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
@@ -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() {
@@ -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);
@@ -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<PsiMethod> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(5);
OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter<PsiMethod>(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<PsiMethod> comparator = new MethodCellRenderer(false).getComparator();
Arrays.sort(overridings, comparator);
@@ -166,19 +171,33 @@ public class MarkerType {
final PsiElementProcessor.CollectElementsWithLimit<PsiMethod> collectProcessor =
new PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(2, new THashSet<PsiMethod>());
final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> collectExprProcessor =
new PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression>(2, new THashSet<PsiFunctionalExpression>());
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter<PsiMethod>(collectProcessor));
if (collectProcessor.getCollection().isEmpty()) {
final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
@Override
public PsiClass compute() {
return method.getContainingClass();
}
});
if (aClass != null) {
FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(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<PsiFunctionalExpression> functionalImplementations =
new PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression>(2, new THashSet<PsiFunctionalExpression>());
FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(functionalImplementations));
if (!functionalImplementations.getCollection().isEmpty()) {
return "Has functional implementations";
}
return null;
}
Comparator<PsiClass> comparator = new PsiClassListCellRenderer().getComparator();
Arrays.sort(subclasses, comparator);
@@ -234,18 +261,23 @@ public class MarkerType {
}
final PsiElementProcessor.CollectElementsWithLimit<PsiClass> collectProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiClass>(2, new THashSet<PsiClass>());
final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> collectExprProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression>(2, new THashSet<PsiFunctionalExpression>());
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter<PsiClass>(collectProcessor));
if (collectProcessor.getCollection().isEmpty()) {
FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(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<PsiFunctionalExpression>() {
@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<PsiClass>() {
@Override
public PsiClass compute() {
return myMethod.getContainingClass();
}
});
FunctionalExpressionSearch.search(psiClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() {
@Override
public boolean process(final PsiFunctionalExpression expr) {
if (!updateComponent(expr, myRenderer.getComparator())) {
indicator.cancel();
}
indicator.checkCanceled();
return super.process(expr);
}
});
}
}
}
@@ -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<NavigatablePsiElement> {
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();
}
}
@@ -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<NavigatablePsiElement> {
@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;
}
}
@@ -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
@@ -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;
}
}
@@ -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 {
@@ -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.
* <p/>
* Known implementors are:
* <li> {@link com.intellij.openapi.actionSystem.AnAction}s
* <li> {@link com.intellij.openapi.fileEditor.FileEditorProvider}s
@@ -34,10 +34,11 @@ package com.intellij.openapi.project;
* <li> {@link com.intellij.openapi.wm.ToolWindowFactory}s
* <li> {@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 {
}
@@ -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<JB
@Override
protected void paintBusy(final boolean paintBusy) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
final Runnable runnable = new Runnable() {
@Override
public void run() {
myComponent.setPaintBusy(paintBusy);
}
});
};
//ensure start/end order
SwingUtilities.invokeLater(runnable);
}
@Override
@@ -37,12 +37,18 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.SystemDock;
import com.intellij.openapi.wm.impl.WindowManagerImpl;
import com.intellij.openapi.wm.impl.X11UiUtil;
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
import com.intellij.platform.PlatformProjectOpenProcessor;
import com.intellij.ui.CustomProtocolHandler;
import com.intellij.ui.Splash;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -50,6 +56,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.Arrays;
public class IdeaApplication {
@@ -242,6 +249,37 @@ public class IdeaApplication {
}
}
@Override
public boolean canProcessExternalCommandLine() {
return true;
}
@Override
public void processExternalCommandLine(String[] args, @Nullable String currentDirectory) {
LOG.info("Request to open in " + currentDirectory + " with parameters: " + StringUtil.join(args, ","));
if (args.length > 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();
@@ -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<CaretState> caretStates, final boolean updateSystemSelection) {
myEditor.assertIsDispatchThread();
EditorImpl.assertIsDispatchThread();
if (caretStates.isEmpty()) {
throw new IllegalArgumentException("At least one caret should exist");
}
@@ -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;
}
}
@@ -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;
@@ -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);
}
@@ -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);
@@ -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<Component, Rectangle> 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);
}
}
@@ -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!)
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
@@ -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<VcsRootError> unregisteredRoots = getUnregisteredRoots(errors);
Collection<VcsRootError> important = getImportantMappings(unregisteredRoots);
Collection<VcsRootError> importantUnregisteredRoots = getImportantUnregisteredMappings(errors);
Collection<VcsRootError> 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<VcsRootError> getImportantMappings(@NotNull Collection<VcsRootError> unregisteredRoots) {
return ContainerUtil.filter(unregisteredRoots, new Condition<VcsRootError>() {
@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<VcsRootError> getUnregisteredRoots(@NotNull Collection<VcsRootError> errors) {
return filterErrorsByType(errors, VcsRootError.Type.UNREGISTERED_ROOT);
private List<VcsRootError> getImportantUnregisteredMappings(@NotNull Collection<VcsRootError> errors) {
return ContainerUtil.filter(errors, new Condition<VcsRootError>() {
@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<VcsRootError> getInvalidRoots(@NotNull Collection<VcsRootError> errors) {
return filterErrorsByType(errors, VcsRootError.Type.EXTRA_MAPPING);
}
@NotNull
private static Collection<VcsRootError> filterErrorsByType(@NotNull Collection<VcsRootError> errors, @NotNull VcsRootError.Type type) {
Collection<VcsRootError> roots = new ArrayList<VcsRootError>();
for (VcsRootError error : errors) {
if (error.getType() == type) {
roots.add(error);
return ContainerUtil.filter(errors, new Condition<VcsRootError>() {
@Override
public boolean value(VcsRootError error) {
return error.getType() == VcsRootError.Type.EXTRA_MAPPING;
}
}
return roots;
});
}
private static class MyNotificationListener implements NotificationListener {
@@ -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);
}
}
@@ -458,10 +458,6 @@
<localInspection language="JAVA" shortName="MarkerInterface" bundle="com.siyeh.InspectionGadgetsBundle" key="marker.interface.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.class.structure" enabledByDefault="false"
level="WARNING" implementationClass="com.siyeh.ig.classlayout.MarkerInterfaceInspection"/>
<localInspection language="JAVA" shortName="MissingDeprecatedAnnotation" bundle="com.siyeh.InspectionGadgetsBundle"
key="missing.deprecated.annotation.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING" runForWholeFile="true"
implementationClass="com.siyeh.ig.classlayout.MissingDeprecatedAnnotationInspection"/>
<localInspection language="JAVA" shortName="MultipleTopLevelClassesInFile" bundle="com.siyeh.InspectionGadgetsBundle"
key="multiple.top.level.classes.in.file.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
@@ -1231,6 +1227,10 @@
key="html.tag.can.be.javadoc.tag.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.javadoc.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.javadoc.HtmlTagCanBeJavadocTagInspection"/>
<localInspection language="JAVA" shortName="MissingDeprecatedAnnotation" bundle="com.siyeh.InspectionGadgetsBundle"
key="missing.deprecated.annotation.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.javadoc.issues" enabledByDefault="false" level="WARNING" runForWholeFile="true"
implementationClass="com.siyeh.ig.javadoc.MissingDeprecatedAnnotationInspection"/>
<globalInspection language="JAVA" shortName="MissingPackageInfo" bundle="com.siyeh.InspectionGadgetsBundle"
key="missing.package.info.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.javadoc.issues" enabledByDefault="false" level="WARNING"
@@ -913,7 +913,7 @@ utility.class.without.private.constructor.problem.descriptor=Class <code>#ref</c
abstract.method.overrides.concrete.method.problem.descriptor=Abstract method <code>#ref()</code> overrides concrete method #loc
abstract.method.with.missing.implementations.problem.descriptor=Abstract method <code>#ref()</code> is not implemented in every subclass #loc
abstract.method.overrides.abstract.method.problem.descriptor=Abstract method <code>#ref()</code> 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 <code>#ref</code> is declared 'abstract', and extends a concrete class #loc
static.non.final.field.problem.descriptor='static' non-'final' field <code>#ref</code> #loc
@@ -932,7 +932,9 @@ marker.interface.problem.descriptor=Marker interface <code>#ref</code> #loc
field.has.setter.but.no.getter.problem.descriptor=Field <code>#ref</code> has setter but no getter #loc
abstract.class.never.implemented.problem.descriptor=Abstract class <code>#ref</code> has no concrete subclass #loc
interface.never.implemented.problem.descriptor=Interface <code>#ref</code> has no concrete subclass #loc
missing.deprecated.annotation.problem.descriptor=Missing '@Deprecated' annotation on <code>#ref()</code> #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 <code>#ref()</code> #loc
non.thread.safe.lazy.initialization.problem.descriptor=Lazy initialization of 'static' field <code>#ref</code> is not thread-safe #loc
empty.catch.block.problem.descriptor=Empty <code>#ref</code> block #loc
@@ -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;
}
}
}
@@ -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.
<!-- tooltip end -->
<p>
Use the checkbox below to warn on symbols annotated with <b>@Deprecated</b> without a corresponding explanation in a
<b>@deprecated</b> Javadoc tag.
<p>
</body>
</html>
@@ -0,0 +1,37 @@
/**
* @deprecated
*/
public class <warning descr="Missing '@Deprecated' annotation">MissingDeprecatedAnnotation</warning> {
/**
* @deprecated Use {@link #b()} instead
*/
@Deprecated
void a() {}
/**
* @deprecated
*/
void <warning descr="Missing '@Deprecated' annotation">b</warning>() {}
/**
* @deprecated
*/
String <warning descr="Missing '@Deprecated' annotation">s</warning>;
}
@Deprecated
class <warning descr="Missing '@deprecated' Javadoc tag explanation">Two</warning> {
/**
* @deprecated
*/
@Deprecated
void <warning descr="Missing '@deprecated' Javadoc tag explanation">a</warning>() {}
@Deprecated
void <warning descr="Missing '@deprecated' Javadoc tag explanation">b</warning>() {}
@Deprecated
String <warning descr="Missing '@deprecated' Javadoc tag explanation">s</warning>;
}
@@ -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;
}
}
@@ -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()) {
@@ -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();
@@ -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;
}
@@ -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<PyFromImportStatement> 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);
}
}
}
@@ -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);
}
}
}
@@ -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) {
@@ -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,
@@ -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;
@@ -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
@@ -270,6 +270,16 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> 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();
}
};
}
@@ -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);
}
}
@@ -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
@@ -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;
}
}
@@ -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);
@@ -163,7 +163,7 @@ class MethodsManager extends MembersManager<PyFunction> {
*/
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);
}
/**
@@ -1,8 +1,8 @@
<node text="A.__init__(self) (hierarchy.call.Static.Constructor.main)" base="true">
<node text="A.__init__(self) (A in hierarchy.call.Static.Constructor.main)" base="true">
<node text="invoke1(p) (hierarchy.call.Static.Constructor.main)">
<node text="A.method1(self) (hierarchy.call.Static.Constructor.main)"/>
<node text="A.method1(self) (A in hierarchy.call.Static.Constructor.main)"/>
</node>
<node text="invoke2(p) (hierarchy.call.Static.Constructor.main)">
<node text="A.method2(self) (hierarchy.call.Static.Constructor.main)"/>
<node text="A.method2(self) (A in hierarchy.call.Static.Constructor.main)"/>
</node>
</node>
@@ -1,6 +1,6 @@
<node text="A.__init__(self) (hierarchy.call.Static.Constructor.main)" base="true">
<node text="A.__init__(self) (A in hierarchy.call.Static.Constructor.main)" base="true">
<node text="invokeA() (hierarchy.call.Static.Constructor.main)">
<node text="C.bar(self) (hierarchy.call.Static.Constructor.main)"/>
<node text="C.bar(self) (C in hierarchy.call.Static.Constructor.main)"/>
</node>
<node text="C.bar(self) (hierarchy.call.Static.Constructor.main)"/>
<node text="C.bar(self) (C in hierarchy.call.Static.Constructor.main)"/>
</node>
@@ -1 +1 @@
<node text="A.target_func(self) (hierarchy.call.Static.Inheritance.main)" base="true"/>
<node text="A.target_func(self) (A in hierarchy.call.Static.Inheritance.main)" base="true"/>
@@ -1,4 +1,4 @@
<node text="A.target_func(self) (hierarchy.call.Static.Inheritance.main)" base="true">
<node text="C.func(self, a) (hierarchy.call.Static.Inheritance.main)"/>
<node text="A.target_func(self) (A in hierarchy.call.Static.Inheritance.main)" base="true">
<node text="C.func(self, a) (C in hierarchy.call.Static.Inheritance.main)"/>
<node text="foo2(b) (hierarchy.call.Static.Inheritance.main)"/>
</node>
@@ -1,3 +1,3 @@
<node text="B.target_func(self, p) (hierarchy.call.Static.OverriddenMethod.main)" base="true">
<node text="A.another_func(self) (hierarchy.call.Static.OverriddenMethod.file_1)"/>
<node text="B.target_func(self, p) (B in hierarchy.call.Static.OverriddenMethod.main)" base="true">
<node text="A.another_func(self) (A in hierarchy.call.Static.OverriddenMethod.file_1)"/>
</node>
@@ -1,5 +1,5 @@
<node text="B.target_func(self, p) (hierarchy.call.Static.OverriddenMethod.main)" base="true">
<node text="C.func1(self, a) (hierarchy.call.Static.OverriddenMethod.main)"/>
<node text="B.target_func(self, p) (B in hierarchy.call.Static.OverriddenMethod.main)" base="true">
<node text="C.func1(self, a) (C in hierarchy.call.Static.OverriddenMethod.main)"/>
<node text="bar1(a) (hierarchy.call.Static.OverriddenMethod.main)"/>
<node text="C.func2(self) (hierarchy.call.Static.OverriddenMethod.main)"/>
<node text="C.func2(self) (C in hierarchy.call.Static.OverriddenMethod.main)"/>
</node>
@@ -0,0 +1,5 @@
class C:
def f(self, x):
self.foo = x
self.foo = {'foo': self.foo}
return self.foo['foo'] + 10
@@ -0,0 +1,6 @@
if True:
import pkgutil
else:
from pkg1 import mod2 as pkgutil
print(pkgutil)
@@ -0,0 +1,6 @@
if True:
import pkgutil
else:
import mod2 as pkgutil
print(pkgutil)
@@ -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");
@@ -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();
}
@@ -237,4 +237,9 @@ public class PyTypeCheckerInspectionTest extends PyTestCase {
public void testDefaultTupleParameter() {
doTest();
}
// PY-14222
public void testRecursiveDictAttribute() {
doTest();
}
}
@@ -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);
@@ -198,6 +198,8 @@ https
iconable
iife
impl
implementor
implementors
inbox
incrementer
indextype