Merge remote-tracking branch 'origin/master'

This commit is contained in:
Mikhail Golubev
2013-10-10 20:53:22 +04:00
312 changed files with 20279 additions and 11722 deletions
+2
View File
@@ -31,6 +31,8 @@
<module name="groovy_rt" target="1.5" />
<module name="java-runtime" target="1.3" />
<module name="javac2" target="1.5" />
<module name="jps-launcher" target="1.6" />
<module name="junit_rt" target="1.3" />
</bytecodeTargetLevel>
</component>
<component name="EclipseCompilerSettings">
+11
View File
@@ -0,0 +1,11 @@
<component name="libraryTable">
<library name="ForkJoin">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/jsr166e.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/jsr166e_src.jar!/" />
</SOURCES>
</library>
</component>
@@ -100,8 +100,7 @@ import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.incremental.Utils;
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -890,7 +889,8 @@ public class
launcherCp.add(ClasspathBootstrap.getResourcePath(launcherClass));
launcherCp.add(compilerPath);
ClasspathBootstrap.appendJavaCompilerClasspath(launcherCp);
// this will disable standard extensions to ensure javac is loaded from the right tools.jar
cmdLine.addParameter("-Djava.ext.dirs=");
cmdLine.addParameter("-classpath");
cmdLine.addParameter(classpathToString(launcherCp));
@@ -170,6 +170,8 @@ public class FrameVariablesTree extends DebuggerTree {
final DebuggerTreeNodeImpl variableNode = myNodeManager.createNode(descriptor, evaluationContext);
myChildren.add(variableNode);
}
myChildren.add(myNodeManager.createMessageNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE));
// trying to collect values from variable slots
final List<DecompiledLocalVariable> decompiled = collectVariablesFromBytecode(frame, argValues.size());
if (!decompiled.isEmpty()) {
try {
@@ -185,7 +187,6 @@ public class FrameVariablesTree extends DebuggerTree {
LOG.info(ex);
}
}
myChildren.add(myNodeManager.createMessageNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE));
}
else {
throw e;
@@ -70,47 +70,12 @@ public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{
final PsiCodeBlock body = method.getBody();
if (body != null) {
final StringBuilder nameBuilder = new StringBuilder();
nameBuilder.append(myDefaultName);
try {
final int startSlot = params.getParametersCount() + (method.hasModifierProperty(PsiModifier.STATIC)? 0 : 1);
body.accept(new JavaRecursiveElementVisitor() {
private int myCurrentSlotIndex = startSlot;
private final Stack<Integer> myIndexStack = new Stack<Integer>();
@Override
public void visitCodeBlock(PsiCodeBlock block) {
myIndexStack.push(myCurrentSlotIndex);
try {
super.visitCodeBlock(block);
}
finally {
myCurrentSlotIndex = myIndexStack.pop();
}
}
@Override
public void visitLocalVariable(PsiLocalVariable variable) {
if (myCurrentSlotIndex == myIndex) {
if (nameBuilder.length() == myDefaultName.length()) {
nameBuilder.append(": ");
}
else {
nameBuilder.append("|");
}
nameBuilder.append(variable.getName());
}
final PsiType varType = variable.getType();
myCurrentSlotIndex += (varType == PsiType.DOUBLE || varType == PsiType.LONG)? 2 : 1;
}
@Override
public void visitClass(PsiClass aClass) {
// skip local and anonymous classes
}
});
body.accept(new LocalVariableNameFinder(startSlot, nameBuilder));
}
finally {
myName = nameBuilder.toString();
myName = nameBuilder.length() > 0? myDefaultName + ": " + nameBuilder.toString() : myDefaultName;
}
}
}
@@ -141,4 +106,90 @@ public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{
throw new EvaluateException(DebuggerBundle.message("error.invalid.local.variable.name", getName()), e);
}
}
private class LocalVariableNameFinder extends JavaRecursiveElementVisitor {
private final int myStartSlot;
private final StringBuilder myNameBuilder;
private int myCurrentSlotIndex;
private final Stack<Integer> myIndexStack;
public LocalVariableNameFinder(int startSlot, StringBuilder nameBuilder) {
myStartSlot = startSlot;
myNameBuilder = nameBuilder;
myCurrentSlotIndex = myStartSlot;
myIndexStack = new Stack<Integer>();
}
@Override
public void visitLocalVariable(PsiLocalVariable variable) {
if (myCurrentSlotIndex == myIndex) {
if (myNameBuilder.length() != 0) {
myNameBuilder.append("|");
}
myNameBuilder.append(variable.getName());
}
final PsiType varType = variable.getType();
myCurrentSlotIndex += (varType == PsiType.DOUBLE || varType == PsiType.LONG)? 2 : 1;
}
@Override
public void visitCodeBlock(PsiCodeBlock block) {
myIndexStack.push(myCurrentSlotIndex);
try {
super.visitCodeBlock(block);
}
finally {
myCurrentSlotIndex = myIndexStack.pop();
}
}
@Override
public void visitForStatement(PsiForStatement statement) {
myIndexStack.push(myCurrentSlotIndex);
try {
super.visitForStatement(statement);
}
finally {
myCurrentSlotIndex = myIndexStack.pop();
}
}
@Override
public void visitForeachStatement(PsiForeachStatement statement) {
myIndexStack.push(myCurrentSlotIndex);
try {
super.visitForeachStatement(statement);
}
finally {
myCurrentSlotIndex = myIndexStack.pop();
}
}
@Override
public void visitCatchSection(PsiCatchSection section) {
myIndexStack.push(myCurrentSlotIndex);
try {
super.visitCatchSection(section);
}
finally {
myCurrentSlotIndex = myIndexStack.pop();
}
}
@Override
public void visitResourceList(PsiResourceList resourceList) {
myIndexStack.push(myCurrentSlotIndex);
try {
super.visitResourceList(resourceList);
}
finally {
myCurrentSlotIndex = myIndexStack.pop();
}
}
@Override
public void visitClass(PsiClass aClass) {
// skip local and anonymous classes
}
}
}
@@ -19,21 +19,24 @@ import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.junit2.info.MethodLocation;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.PsiClassUtil;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.components.JBList;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.*;
/**
* User: anna
@@ -68,7 +71,7 @@ public class InheritorChooser {
ClassInheritorsSearch.search(containingClass).forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass aClass) {
if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
if (PsiClassUtil.isRunnableClass(aClass, true, true)) {
classes.add(aClass);
}
return true;
@@ -84,6 +87,19 @@ public class InheritorChooser {
return true;
}
if (classes.isEmpty()) return false;
final FileEditor fileEditor = PlatformDataKeys.FILE_EDITOR.getData(context.getDataContext());
if (fileEditor instanceof TextEditor) {
final Document document = ((TextEditor)fileEditor).getEditor().getDocument();
final PsiFile containingFile = PsiDocumentManager.getInstance(context.getProject()).getPsiFile(document);
if (containingFile instanceof PsiClassOwner) {
final List<PsiClass> psiClasses = new ArrayList<PsiClass>(Arrays.asList(((PsiClassOwner)containingFile).getClasses()));
psiClasses.retainAll(classes);
if (psiClasses.size() == 1) {
runForClass(psiClasses.get(0), psiMethod, context, performRunnable);
return true;
}
}
}
final PsiClassListCellRenderer renderer = new PsiClassListCellRenderer() {
@Override
protected boolean customizeNonPsiElementLeftRenderer(ColoredListCellRenderer renderer,
@@ -15,19 +15,14 @@
*/
package com.intellij.ide.projectWizard;
import com.intellij.framework.FrameworkGroup;
import com.intellij.ide.util.frameworkSupport.FrameworkRole;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Arrays;
import java.util.Map;
/**
* @author Dmitry Avdeev
@@ -69,11 +64,6 @@ public abstract class ProjectCategory {
return new FrameworkRole[] {createModuleBuilder().getDefaultAcceptableRole()};
}
@Nullable
public FrameworkGroup getAssociatedFrameworkGroup() {
return null;
}
@NotNull
public String[] getAssociatedFrameworkIds() {
return ArrayUtil.EMPTY_STRING_ARRAY;
@@ -83,15 +73,4 @@ public abstract class ProjectCategory {
public String toString() {
return getDisplayName();
}
private static Map<String, ProjectCategory> map = ContainerUtil.newMapFromValues(Arrays.asList(EXTENSION_POINT_NAME.getExtensions()).iterator(), new Convertor<ProjectCategory, String>() {
@Override
public String convert(ProjectCategory o) {
return o.getId();
}
});
public static ProjectCategory findById(String id) {
return map.get(id);
}
}
@@ -276,7 +276,9 @@ public class GenericsHighlightUtil {
return checkExtendsWildcardCaptureFailure((PsiWildcardType)type, bound);
}
else if (((PsiWildcardType)type).isSuper()) {
return checkNotAssignable(bound, ((PsiWildcardType)type).getSuperBound(), false);
final PsiType superBound = ((PsiWildcardType)type).getSuperBound();
if (PsiUtil.resolveClassInType(superBound) instanceof PsiTypeParameter) return TypesDistinctProver.provablyDistinct(type, bound);
return checkNotAssignable(bound, superBound, false);
}
}
else if (type instanceof PsiArrayType) {
@@ -0,0 +1,96 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.dependencyViolation;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInspection.*;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.packageDependencies.DependenciesBuilder;
import com.intellij.packageDependencies.DependencyRule;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class DependencyInspectionBase extends AbstractBaseJavaLocalInspectionTool {
private static final String GROUP_DISPLAY_NAME = "";
private static final String DISPLAY_NAME = InspectionsBundle.message("illegal.package.dependencies");
@NonNls private static final String SHORT_NAME = "Dependency";
@Override
public boolean isEnabledByDefault() {
return true;
}
@Override
@NotNull
public String getGroupDisplayName() {
return GROUP_DISPLAY_NAME;
}
@Override
@NotNull
public String getDisplayName() {
return DISPLAY_NAME;
}
@Override
@NotNull
public String getShortName() {
return SHORT_NAME;
}
@Override
@Nullable
public ProblemDescriptor[] checkFile(@NotNull final PsiFile file, @NotNull final InspectionManager manager, final boolean isOnTheFly) {
if (file.getViewProvider().getPsi(JavaLanguage.INSTANCE) == null) return null;
final DependencyValidationManager validationManager = DependencyValidationManager.getInstance(file.getProject());
if (!validationManager.hasRules()) return null;
if (validationManager.getApplicableRules(file).length == 0) return null;
final List<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
DependenciesBuilder.analyzeFileDependencies(file, new DependenciesBuilder.DependencyProcessor() {
@Override
public void process(PsiElement place, PsiElement dependency) {
PsiFile dependencyFile = dependency.getContainingFile();
if (dependencyFile != null && dependencyFile.isPhysical() && dependencyFile.getVirtualFile() != null) {
final DependencyRule[] rule = validationManager.getViolatorDependencyRules(file, dependencyFile);
for (DependencyRule dependencyRule : rule) {
problems.add(manager.createProblemDescriptor(place, InspectionsBundle
.message("inspection.dependency.violator.problem.descriptor", dependencyRule.getDisplayText()), isOnTheFly,
createEditDependencyFixes(dependencyRule),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING));
}
}
}
});
return problems.isEmpty() ? null : problems.toArray(new ProblemDescriptor[problems.size()]);
}
protected LocalQuickFix[] createEditDependencyFixes(DependencyRule dependencyRule) {
return null;
}
@Override
@NotNull
public HighlightDisplayLevel getDefaultLevel() {
return HighlightDisplayLevel.ERROR;
}
}
@@ -0,0 +1,262 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.javaDoc;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInspection.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class JavaDocReferenceInspectionBase extends AbstractBaseJavaLocalInspectionTool {
@NonNls private static final String SHORT_NAME = "JavadocReference";
private static ProblemDescriptor createDescriptor(@NotNull PsiElement element, String template, InspectionManager manager,
boolean onTheFly) {
return manager.createProblemDescriptor(element, template, onTheFly, null, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
public void visitRefInDocTag(final PsiDocTag tag,
final JavadocManager manager,
final PsiElement context,
final List<ProblemDescriptor> problems,
final InspectionManager inspectionManager,
final boolean onTheFly) {
final String tagName = tag.getName();
final PsiDocTagValue value = tag.getValueElement();
if (value == null) return;
final JavadocTagInfo info = manager.getTagInfo(tagName);
if (info != null && !info.isValidInContext(context)) return;
final String message = info == null || !info.isInline() ? null : info.checkTagValue(value);
if (message != null){
problems.add(createDescriptor(value, message, inspectionManager, onTheFly));
}
final PsiReference reference = value.getReference();
if (reference == null) return;
final PsiElement element = reference.resolve();
if (element != null) return;
final int textOffset = value.getTextOffset();
if (textOffset == value.getTextRange().getEndOffset()) return;
final PsiDocTagValue valueElement = tag.getValueElement();
if (valueElement == null) return;
final CharSequence paramName = value.getContainingFile().getViewProvider().getContents().subSequence(textOffset, value.getTextRange().getEndOffset());
final String params = "<code>" + paramName + "</code>";
final List<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>();
if (onTheFly && "param".equals(tagName)) {
final PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(tag, PsiDocCommentOwner.class);
if (commentOwner instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)commentOwner;
final PsiParameter[] parameters = method.getParameterList().getParameters();
final PsiDocTag[] tags = tag.getContainingComment().getTags();
final Set<String> unboundParams = new HashSet<String>();
for (PsiParameter parameter : parameters) {
if (!JavaDocLocalInspectionBase.isFound(tags, parameter)) {
unboundParams.add(parameter.getName());
}
}
if (!unboundParams.isEmpty()) {
fixes.add(createRenameReferenceQuickFix(unboundParams));
}
}
}
fixes.add(new RemoveTagFix(tagName, paramName));
problems.add(inspectionManager.createProblemDescriptor(valueElement, reference.getRangeInElement(), cannotResolveSymbolMessage(params),
ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, onTheFly,
fixes.toArray(new LocalQuickFix[fixes.size()])));
}
protected LocalQuickFix createRenameReferenceQuickFix(Set<String> unboundParams) {
return null;
}
private static String cannotResolveSymbolMessage(String params) {
return InspectionsBundle.message("inspection.javadoc.problem.cannot.resolve", params);
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@Nullable
@Override
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
if (!PsiPackage.PACKAGE_INFO_FILE.equals(file.getName()) || !(file instanceof PsiJavaFile)) {
return null;
}
final PsiDocComment docComment = PsiTreeUtil.getChildOfType(file, PsiDocComment.class);
final PsiJavaFile javaFile = (PsiJavaFile)file;
final String packageName = javaFile.getPackageName();
final PsiPackage aPackage = JavaPsiFacade.getInstance(file.getProject()).findPackage(packageName);
return checkComment(docComment, aPackage, manager, isOnTheFly);
}
@Override
@Nullable
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod psiMethod, @NotNull InspectionManager manager, boolean isOnTheFly) {
return checkMember(psiMethod, manager, isOnTheFly);
}
@Override
@Nullable
public ProblemDescriptor[] checkField(@NotNull PsiField field, @NotNull InspectionManager manager, boolean isOnTheFly) {
return checkMember(field, manager, isOnTheFly);
}
@Override
@Nullable
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
return checkMember(aClass, manager, isOnTheFly);
}
@Nullable
private ProblemDescriptor[] checkMember(final PsiDocCommentOwner docCommentOwner, final InspectionManager manager, final boolean isOnTheFly) {
return checkComment(docCommentOwner.getDocComment(), docCommentOwner, manager, isOnTheFly);
}
private ProblemDescriptor[] checkComment(PsiDocComment docComment, PsiElement context, InspectionManager manager, boolean isOnTheFly) {
if (docComment == null) return null;
final List<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
final Set<PsiJavaCodeReferenceElement> references = new HashSet<PsiJavaCodeReferenceElement>();
docComment.accept(getVisitor(references, context, problems, manager, isOnTheFly));
for (PsiJavaCodeReferenceElement reference : references) {
final PsiElement referenceNameElement = reference.getReferenceNameElement();
problems.add(manager.createProblemDescriptor(referenceNameElement != null ? referenceNameElement : reference,
cannotResolveSymbolMessage("<code>" + reference.getText() + "</code>"),
!isOnTheFly ? null : createAddQualifierFix(reference),
ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, isOnTheFly));
}
return problems.isEmpty() ? null : problems.toArray(new ProblemDescriptor[problems.size()]);
}
protected LocalQuickFix createAddQualifierFix(PsiJavaCodeReferenceElement reference) {
return null;
}
private PsiElementVisitor getVisitor(final Set<PsiJavaCodeReferenceElement> references,
final PsiElement context,
final List<ProblemDescriptor> problems,
final InspectionManager manager,
final boolean onTheFly) {
return new JavaElementVisitor() {
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
visitElement(expression);
}
@Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
JavaResolveResult result = reference.advancedResolve(false);
if (result.getElement() == null && !result.isPackagePrefixPackageReference()) {
references.add(reference);
}
}
@Override public void visitDocTag(PsiDocTag tag) {
super.visitDocTag(tag);
final JavadocManager javadocManager = JavadocManager.SERVICE.getInstance(tag.getProject());
final JavadocTagInfo info = javadocManager.getTagInfo(tag.getName());
if (info == null || !info.isInline()) {
visitRefInDocTag(tag, javadocManager, context, problems, manager, onTheFly);
}
}
@Override public void visitInlineDocTag(PsiInlineDocTag tag) {
super.visitInlineDocTag(tag);
final JavadocManager javadocManager = JavadocManager.SERVICE.getInstance(tag.getProject());
visitRefInDocTag(tag, javadocManager, context, problems, manager, onTheFly);
}
@Override public void visitElement(PsiElement element) {
PsiElement[] children = element.getChildren();
for (PsiElement child : children) {
//do not visit method javadoc twice
if (!(child instanceof PsiDocCommentOwner)) {
child.accept(this);
}
}
}
};
}
@Override
@NotNull
public String getDisplayName() {
return InspectionsBundle.message("inspection.javadoc.ref.display.name");
}
@Override
@NotNull
public String getGroupDisplayName() {
return InspectionsBundle.message("group.names.javadoc.issues");
}
@Override
@NotNull
public String getShortName() {
return SHORT_NAME;
}
@Override
@NotNull
public HighlightDisplayLevel getDefaultLevel() {
return HighlightDisplayLevel.ERROR;
}
private static class RemoveTagFix implements LocalQuickFix {
private final String myTagName;
private final CharSequence myParamName;
public RemoveTagFix(String tagName, CharSequence paramName) {
myTagName = tagName;
myParamName = paramName;
}
@Override
@NotNull
public String getName() {
return "Remove @" + myTagName + " " + myParamName;
}
@Override
@NotNull
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiDocTag myTag = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiDocTag.class);
if (myTag == null) return;
if (!FileModificationService.getInstance().preparePsiElementForWrite(myTag)) return;
myTag.delete();
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -85,7 +85,8 @@ class TypeArgumentCompletionProvider extends CompletionProvider<CompletionParame
PsiElement context,
final PsiClass actualClass,
final int index,
PsiClassType.ClassResolveResult expectedType, TailType globalTail) {
PsiClassType.ClassResolveResult expectedType,
TailType globalTail) {
final PsiClass expectedClass = expectedType.getElement();
if (!InheritanceUtil.isInheritorOrSelf(actualClass, expectedClass, true)) return;
@@ -26,6 +26,8 @@ import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.*;
@@ -261,12 +263,12 @@ public class GenerateMembersUtil {
try {
final PsiMethod resultMethod = createMethod(factory, sourceMethod, target);
copyDocComment(sourceMethod, resultMethod, factory);
copyModifiers(sourceMethod.getModifierList(), resultMethod.getModifierList());
final PsiSubstitutor collisionResolvedSubstitutor =
substituteTypeParameters(factory, target, sourceMethod.getTypeParameterList(), resultMethod.getTypeParameterList(), substitutor, sourceMethod);
substituteReturnType(PsiManager.getInstance(project), resultMethod, sourceMethod.getReturnType(), collisionResolvedSubstitutor);
substituteParameters(factory, codeStyleManager, sourceMethod.getParameterList(), resultMethod.getParameterList(), collisionResolvedSubstitutor, target);
copyDocComment(sourceMethod, resultMethod, factory);
final List<PsiClassType> thrownTypes = ExceptionUtil.collectSubstituted(collisionResolvedSubstitutor, sourceMethod.getThrowsList().getReferencedTypes());
if (target instanceof PsiClass) {
final PsiClass[] supers = ((PsiClass)target).getSupers();
@@ -435,6 +437,18 @@ public class GenerateMembersUtil {
target.addAfter(factory.createDocCommentFromText(docComment.getText()), null);
}
}
final PsiParameter[] sourceParameters = source.getParameterList().getParameters();
final PsiParameterList targetParameterList = target.getParameterList();
RefactoringUtil.fixJavadocsForParams(target, new HashSet<PsiParameter>(Arrays.asList(targetParameterList.getParameters())), new Condition<Pair<PsiParameter, String>>() {
@Override
public boolean value(Pair<PsiParameter, String> pair) {
final int parameterIndex = targetParameterList.getParameterIndex(pair.first);
if (parameterIndex >= 0 && parameterIndex < sourceParameters.length) {
return Comparing.strEqual(pair.second, sourceParameters[parameterIndex].getName());
}
return false;
}
});
}
@NotNull
@@ -18,9 +18,9 @@ package com.intellij.codeInsight.generation.surroundWith;
import com.intellij.lang.Language;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.PsiElement;
/**
* @author yole
@@ -65,6 +65,8 @@ public class XmlSurroundWithRangeAdjuster implements SurroundWithRangeAdjuster {
lang2 = getLanguage(element2);
if(lang1 != lang2) return null;
TextRange.assertProperRange(startOffset, endOffset, "Wrong offsets for " + selectedRange.substring(file.getText()));
return new TextRange(startOffset, endOffset);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,60 +15,33 @@
*/
package com.intellij.codeInspection.dependencyViolation;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.BaseLocalInspectionTool;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.ide.DataManager;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.packageDependencies.DependenciesBuilder;
import com.intellij.packageDependencies.DependencyRule;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.packageDependencies.ForwardDependenciesBuilder;
import com.intellij.packageDependencies.ui.DependencyConfigurable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
/**
* User: anna
* Date: Feb 6, 2005
*/
public class DependencyInspection extends BaseLocalInspectionTool {
public static final String GROUP_DISPLAY_NAME = "";
public static final String DISPLAY_NAME = InspectionsBundle.message("illegal.package.dependencies");
@NonNls public static final String SHORT_NAME = "Dependency";
public class DependencyInspection extends DependencyInspectionBase {
@Override
@NotNull
public String getGroupDisplayName() {
return DependencyInspection.GROUP_DISPLAY_NAME;
}
@Override
@NotNull
public String getDisplayName() {
return DependencyInspection.DISPLAY_NAME;
}
@Override
@NotNull
public String getShortName() {
return DependencyInspection.SHORT_NAME;
protected LocalQuickFix[] createEditDependencyFixes(DependencyRule dependencyRule) {
return new LocalQuickFix[]{
new EditDependencyRulesAction(dependencyRule)};
}
@Override
@@ -88,42 +61,6 @@ public class DependencyInspection extends BaseLocalInspectionTool {
return depPanel;
}
@Override
@Nullable
public ProblemDescriptor[] checkFile(@NotNull final PsiFile file, @NotNull final InspectionManager manager, final boolean isOnTheFly) {
if (file == null) return null;
if (file.getViewProvider().getPsi(StdLanguages.JAVA) == null) return null;
final DependencyValidationManager validationManager = DependencyValidationManager.getInstance(file.getProject());
if (!validationManager.hasRules()) return null;
if (validationManager.getApplicableRules(file).length == 0) return null;
final ArrayList<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
ForwardDependenciesBuilder builder = new ForwardDependenciesBuilder(file.getProject(), new AnalysisScope(file));
DependenciesBuilder.analyzeFileDependencies(file, new DependenciesBuilder.DependencyProcessor() {
@Override
public void process(PsiElement place, PsiElement dependency) {
PsiFile dependencyFile = dependency.getContainingFile();
if (dependencyFile != null && dependencyFile.isPhysical() && dependencyFile.getVirtualFile() != null) {
final DependencyRule[] rule = validationManager.getViolatorDependencyRules(file, dependencyFile);
for (DependencyRule dependencyRule : rule) {
StringBuffer message = new StringBuffer();
message
.append(InspectionsBundle.message("inspection.dependency.violator.problem.descriptor", dependencyRule.getDisplayText()));
problems.add(manager.createProblemDescriptor(place, message.toString(), isOnTheFly,
new LocalQuickFix[]{new EditDependencyRulesAction(dependencyRule)},
ProblemHighlightType.GENERIC_ERROR_OR_WARNING));
}
}
}
});
return problems.isEmpty() ? null : problems.toArray(new ProblemDescriptor[problems.size()]);
}
@Override
@NotNull
public HighlightDisplayLevel getDefaultLevel() {
return HighlightDisplayLevel.ERROR;
}
private static class EditDependencyRulesAction implements LocalQuickFix {
private final DependencyRule myRule;
public EditDependencyRulesAction(DependencyRule rule) {
@@ -146,7 +83,5 @@ public class DependencyInspection extends BaseLocalInspectionTool {
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
ShowSettingsUtil.getInstance().editConfigurable(project, new DependencyConfigurable(project));
}
}
}
@@ -139,6 +139,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
}
}
});
restartAnalysis(project, scope);
}
}
else if (Messages.showOkCancelDialog(project, "Infer Nullity Annotations requires that the nullity annotations" +
@@ -163,12 +164,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
}
}
}.execute();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
analyze(project, scope);
}
});
restartAnalysis(project, scope);
}
}
});
@@ -228,6 +224,15 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
SwingUtilities.invokeLater(applyRunnable);
}
private void restartAnalysis(final Project project, final AnalysisScope scope) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
analyze(project, scope);
}
});
}
@Override
protected JComponent getAdditionalActionSettings(Project project, BaseAnalysisActionDialog dialog) {
@@ -15,15 +15,14 @@
*/
package com.intellij.codeInspection.javaDoc;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.BaseLocalInspectionTool;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemDescriptorBase;
import com.intellij.ide.DataManager;
import com.intellij.ide.util.FQNameCellRenderer;
import com.intellij.openapi.actionSystem.CommonDataKeys;
@@ -36,203 +35,75 @@ import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.*;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.proximity.PsiProximityComparator;
import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class JavaDocReferenceInspection extends BaseLocalInspectionTool {
@NonNls public static final String SHORT_NAME = "JavadocReference";
private static ProblemDescriptor createDescriptor(@NotNull PsiElement element, String template, InspectionManager manager,
boolean onTheFly) {
return manager.createProblemDescriptor(element, template, onTheFly, null, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
@Nullable
public class JavaDocReferenceInspection extends JavaDocReferenceInspectionBase {
@Override
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
if (!PsiPackage.PACKAGE_INFO_FILE.equals(file.getName()) || !(file instanceof PsiJavaFile)) {
return null;
}
final PsiDocComment docComment = PsiTreeUtil.getChildOfType(file, PsiDocComment.class);
final PsiJavaFile javaFile = (PsiJavaFile)file;
final String packageName = javaFile.getPackageName();
final PsiPackage aPackage = JavaPsiFacade.getInstance(file.getProject()).findPackage(packageName);
return checkComment(docComment, aPackage, manager, isOnTheFly);
protected LocalQuickFix createAddQualifierFix(PsiJavaCodeReferenceElement reference) {
List<PsiClass> classesToImport = new ImportClassFix(reference).getClassesToImport();
return classesToImport.isEmpty() ? null : new JavaDocReferenceInspection.AddQualifierFix(classesToImport);
}
@Override
@Nullable
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod psiMethod, @NotNull InspectionManager manager, boolean isOnTheFly) {
return checkMember(psiMethod, manager, isOnTheFly);
protected RenameReferenceQuickFix createRenameReferenceQuickFix(Set<String> unboundParams) {
return new RenameReferenceQuickFix(unboundParams);
}
@Override
@Nullable
public ProblemDescriptor[] checkField(@NotNull PsiField field, @NotNull InspectionManager manager, boolean isOnTheFly) {
return checkMember(field, manager, isOnTheFly);
}
private static class RenameReferenceQuickFix implements LocalQuickFix {
private final Set<String> myUnboundParams;
@Override
@Nullable
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
return checkMember(aClass, manager, isOnTheFly);
}
@Nullable
private ProblemDescriptor[] checkMember(final PsiDocCommentOwner docCommentOwner, final InspectionManager manager, final boolean isOnTheFly) {
return checkComment(docCommentOwner.getDocComment(), docCommentOwner, manager, isOnTheFly);
}
private ProblemDescriptor[] checkComment(PsiDocComment docComment, PsiElement context, InspectionManager manager, boolean isOnTheFly) {
if (docComment == null) return null;
final ArrayList<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
final Set<PsiJavaCodeReferenceElement> references = new HashSet<PsiJavaCodeReferenceElement>();
docComment.accept(getVisitor(references, context, problems, manager, isOnTheFly));
for (PsiJavaCodeReferenceElement reference : references) {
final List<PsiClass> classesToImport = new ImportClassFix(reference).getClassesToImport();
final PsiElement referenceNameElement = reference.getReferenceNameElement();
problems.add(manager.createProblemDescriptor(referenceNameElement != null ? referenceNameElement : reference,
cannotResolveSymbolMessage("<code>" + reference.getText() + "</code>"),
!isOnTheFly || classesToImport.isEmpty() ? null : new AddQualifierFix(classesToImport),
ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, isOnTheFly));
public RenameReferenceQuickFix(Set<String> unboundParams) {
myUnboundParams = unboundParams;
}
return problems.isEmpty() ? null : problems.toArray(new ProblemDescriptor[problems.size()]);
}
@Override
@NotNull
public String getName() {
return "Change to ...";
}
private PsiElementVisitor getVisitor(final Set<PsiJavaCodeReferenceElement> references,
final PsiElement context,
final ArrayList<ProblemDescriptor> problems,
final InspectionManager manager,
final boolean onTheFly) {
return new JavaElementVisitor() {
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
visitElement(expression);
}
@Override
@NotNull
public String getFamilyName() {
return getName();
}
@Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
JavaResolveResult result = reference.advancedResolve(false);
if (result.getElement() == null && !result.isPackagePrefixPackageReference()) {
references.add(reference);
}
}
@Override
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
final AsyncResult<DataContext> asyncResult = DataManager.getInstance().getDataContextFromFocus();
asyncResult.doWhenDone(new AsyncResult.Handler<DataContext>() {
@Override
public void run(DataContext dataContext) {
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
assert editor != null;
final TextRange textRange = ((ProblemDescriptorBase)descriptor).getTextRange();
editor.getSelectionModel().setSelection(textRange.getStartOffset(), textRange.getEndOffset());
@Override public void visitDocTag(PsiDocTag tag) {
super.visitDocTag(tag);
final JavadocManager javadocManager = JavadocManager.SERVICE.getInstance(tag.getProject());
final JavadocTagInfo info = javadocManager.getTagInfo(tag.getName());
if (info == null || !info.isInline()) {
visitRefInDocTag(tag, javadocManager, context, problems, manager, onTheFly);
}
}
final String word = editor.getSelectionModel().getSelectedText();
@Override public void visitInlineDocTag(PsiInlineDocTag tag) {
super.visitInlineDocTag(tag);
final JavadocManager javadocManager = JavadocManager.SERVICE.getInstance(tag.getProject());
visitRefInDocTag(tag, javadocManager, context, problems, manager, onTheFly);
}
@Override public void visitElement(PsiElement element) {
PsiElement[] children = element.getChildren();
for (PsiElement child : children) {
//do not visit method javadoc twice
if (!(child instanceof PsiDocCommentOwner)) {
child.accept(this);
if (word == null || StringUtil.isEmptyOrSpaces(word)) {
return;
}
}
}
};
}
public static void visitRefInDocTag(final PsiDocTag tag,
final JavadocManager manager,
final PsiElement context,
final ArrayList<ProblemDescriptor> problems,
final InspectionManager inspectionManager,
final boolean onTheFly) {
final String tagName = tag.getName();
final PsiDocTagValue value = tag.getValueElement();
if (value == null) return;
final JavadocTagInfo info = manager.getTagInfo(tagName);
if (info != null && !info.isValidInContext(context)) return;
final String message = info == null || !info.isInline() ? null : info.checkTagValue(value);
if (message != null){
problems.add(createDescriptor(value, message, inspectionManager, onTheFly));
}
final PsiReference reference = value.getReference();
if (reference == null) return;
final PsiElement element = reference.resolve();
if (element != null) return;
final int textOffset = value.getTextOffset();
if (textOffset == value.getTextRange().getEndOffset()) return;
final PsiDocTagValue valueElement = tag.getValueElement();
if (valueElement == null) return;
final CharSequence paramName = value.getContainingFile().getViewProvider().getContents().subSequence(textOffset, value.getTextRange().getEndOffset());
final String params = "<code>" + paramName + "</code>";
final List<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>();
if (onTheFly && "param".equals(tagName)) {
final PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(tag, PsiDocCommentOwner.class);
if (commentOwner instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)commentOwner;
final PsiParameter[] parameters = method.getParameterList().getParameters();
final PsiDocTag[] tags = tag.getContainingComment().getTags();
final Set<String> unboundParams = new HashSet<String>();
for (PsiParameter parameter : parameters) {
if (!JavaDocLocalInspection.isFound(tags, parameter)) {
unboundParams.add(parameter.getName());
final List<LookupElement> items = new ArrayList<LookupElement>();
for (String variant : myUnboundParams) {
items.add(LookupElementBuilder.create(variant));
}
LookupManager.getInstance(project).showLookup(editor, items.toArray(new LookupElement[items.size()]));
}
if (!unboundParams.isEmpty()) {
fixes.add(new RenameReferenceQuickFix(unboundParams));
}
}
});
}
fixes.add(new RemoveTagFix(tagName, paramName));
problems.add(inspectionManager.createProblemDescriptor(valueElement, reference.getRangeInElement(), cannotResolveSymbolMessage(params),
ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, onTheFly,
fixes.toArray(new LocalQuickFix[fixes.size()])));
}
private static String cannotResolveSymbolMessage(String params) {
return InspectionsBundle.message("inspection.javadoc.problem.cannot.resolve", params);
}
@Override
@NotNull
public String getDisplayName() {
return InspectionsBundle.message("inspection.javadoc.ref.display.name");
}
@Override
@NotNull
public String getGroupDisplayName() {
return InspectionsBundle.message("group.names.javadoc.issues");
}
@Override
@NotNull
public String getShortName() {
return SHORT_NAME;
}
@Override
@NotNull
public HighlightDisplayLevel getDefaultLevel() {
return HighlightDisplayLevel.ERROR;
}
private class AddQualifierFix implements LocalQuickFix{
@@ -294,79 +165,4 @@ public class JavaDocReferenceInspection extends BaseLocalInspectionTool {
}
}
}
private static class RenameReferenceQuickFix implements LocalQuickFix {
private final Set<String> myUnboundParams;
public RenameReferenceQuickFix(Set<String> unboundParams) {
myUnboundParams = unboundParams;
}
@Override
@NotNull
public String getName() {
return "Change to ...";
}
@Override
@NotNull
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
final AsyncResult<DataContext> asyncResult = DataManager.getInstance().getDataContextFromFocus();
asyncResult.doWhenDone(new AsyncResult.Handler<DataContext>() {
@Override
public void run(DataContext dataContext) {
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
assert editor != null;
final TextRange textRange = ((ProblemDescriptorBase)descriptor).getTextRange();
editor.getSelectionModel().setSelection(textRange.getStartOffset(), textRange.getEndOffset());
final String word = editor.getSelectionModel().getSelectedText();
if (word == null || StringUtil.isEmptyOrSpaces(word)) {
return;
}
final List<LookupElement> items = new ArrayList<LookupElement>();
for (String variant : myUnboundParams) {
items.add(LookupElementBuilder.create(variant));
}
LookupManager.getInstance(project).showLookup(editor, items.toArray(new LookupElement[items.size()]));
}
});
}
}
private static class RemoveTagFix implements LocalQuickFix {
private final String myTagName;
private final CharSequence myParamName;
public RemoveTagFix(String tagName, CharSequence paramName) {
myTagName = tagName;
myParamName = paramName;
}
@Override
@NotNull
public String getName() {
return "Remove @" + myTagName + " " + myParamName;
}
@Override
@NotNull
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiDocTag myTag = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiDocTag.class);
if (myTag == null) return;
if (!FileModificationService.getInstance().preparePsiElementForWrite(myTag)) return;
myTag.delete();
}
}
}
@@ -72,7 +72,16 @@ public class TypesDistinctProver {
proveArrayTypeDistinct(((PsiWildcardType)type1).getManager().getProject(), (PsiArrayType)superBound, type2)) return true;
final PsiClass boundClass1 = PsiUtil.resolveClassInType(superBound);
if (boundClass1 == null || boundClass1 instanceof PsiTypeParameter) return false;
if (boundClass1 == null) return false;
if (boundClass1 instanceof PsiTypeParameter) {
final PsiClassType[] extendsListTypes = boundClass1.getExtendsListTypes();
for (PsiClassType classType : extendsListTypes) {
final PsiClass psiClass = classType.resolve();
if (InheritanceUtil.isInheritorOrSelf(psiClass, psiClass2, true) || InheritanceUtil.isInheritorOrSelf(psiClass2, psiClass, true)) return false;
}
return extendsListTypes.length > 0;
}
return !InheritanceUtil.isInheritorOrSelf(boundClass1, psiClass2, true);
}
@@ -579,12 +579,18 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
return false;
}
int leftStart = accessor.getParameterList().getTextRange().getEndOffset();
int leftEnd = statement.getTextRange().getStartOffset();
int rightStart = statement.getTextRange().getEndOffset();
int rightEnd = body.getTextRange().getEndOffset();
if (leftEnd <= leftStart + 1 || rightEnd <= rightStart + 1) {
return false;
}
FoldingGroup group = FoldingGroup.newGroup("simple property accessor");
int paramListEnd = accessor.getParameterList().getTextRange().getEndOffset();
int statementStart = statement.getTextRange().getStartOffset();
PsiJavaToken lBrace = body.getLBrace();
assert lBrace != null;
descriptorList.add(new FoldingDescriptor(lBrace.getNode(), new TextRange(paramListEnd, statementStart), group) {
descriptorList.add(new FoldingDescriptor(lBrace.getNode(), new TextRange(leftStart, leftEnd), group) {
@Nullable
@Override
public String getPlaceholderText() {
@@ -592,10 +598,9 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
}
});
int statementEnd = statement.getTextRange().getEndOffset();
PsiJavaToken rBrace = body.getRBrace();
assert rBrace != null;
descriptorList.add(new FoldingDescriptor(rBrace.getNode(), new TextRange(statementEnd, body.getTextRange().getEndOffset()), group) {
descriptorList.add(new FoldingDescriptor(rBrace.getNode(), new TextRange(rightStart, rightEnd), group) {
@Nullable
@Override
public String getPlaceholderText() {
@@ -898,7 +898,8 @@ public class ControlFlowUtil {
@Override
public Boolean getResult() {
return !maybeUnassigned[0];
final int variableDeclarationOffset = flow.getStartOffset(variable.getParent());
return !maybeUnassigned[variableDeclarationOffset > -1 ? variableDeclarationOffset : 0];
}
}
if (flow.getSize() == 0) return false;
@@ -28,6 +28,7 @@ import com.intellij.util.ArrayUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.util.*;
/**
@@ -439,7 +440,7 @@ public class InferenceSession {
if (lub != null) {
inferenceVariable.setInstantiation(lub instanceof PsiCapturedWildcardType ? ((PsiCapturedWildcardType)lub).getWildcard() : lub);
}
else if (acceptObject || upperBounds.size() > 1) {
else if (acceptObject || upperBounds.size() > 1 || !upperBounds.get(0).equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
PsiType glb = null;
for (PsiType upperBound : upperBounds) {
upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound, substitutor);
@@ -77,7 +77,8 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList();
if (argumentList != null) {
final Pair<PsiMethod,PsiSubstitutor> pair = MethodCandidateInfo.getCurrentMethod(argumentList);
final PsiMethod method = pair != null ? pair.first : ((PsiCallExpression)myExpression).resolveMethod();
if (pair != null) return true;
final PsiMethod method = ((PsiCallExpression)myExpression).resolveMethod();
PsiType returnType = null;
InferenceSession callSession = null;
if (method != null) {
@@ -0,0 +1,3 @@
class A<T> {
class B extends A<<error descr="B is not accessible in current context">B.B</error>>{}
}
@@ -0,0 +1,6 @@
class A<T extends B.C>
{
interface C {}
}
class B extends A<<error descr="C is not accessible in current context">B.C</error>>{}
@@ -243,4 +243,14 @@ class IDEA89640 {
boolean flag = a != b;
System.out.println(flag);
}
}
}
interface Parametrized<<warning descr="Type parameter 'T' is never used">T</warning> extends Number> {
class Bug1<T extends java.io.Serializable> {
void bug1(Parametrized<? super T> <warning descr="Parameter 'param' is never used">param</warning>) {}
}
class Bug2<T extends String> {
void bug1(Parametrized<<error descr="Type parameter '? super T' is not within its bound; should extend 'java.lang.Number'">? super T</error>> <warning descr="Parameter 'param' is never used">param</warning>) {}
}
}
@@ -114,4 +114,17 @@ class ParameterIsEffectivelyFinal {
return 0;
};
}
}
}
class IDEA114737 {
private void on(String propertyName) {
if (!"taskServices".equals(propertyName)) {
return;
}
java.util.List<String> newList = null;
Comparable<String> c1 = o -> {
System.out.println(newList);
return 0;
};
}
}
@@ -0,0 +1,17 @@
import java.util.*;
abstract class IX<T> {
/**
* @param t the param
*/
abstract void foo(T t){}
}
class XXC extends IX<List<String>> {
/**
* @param strings the param
*/
@Override
void foo(List<String> strings) {
}
}
@@ -0,0 +1,11 @@
import java.util.*;
abstract class IX<T> {
/**
* @param t the param
*/
abstract void foo(T t){}
}
class XXC extends IX<List<String>> {
<caret>
}
@@ -51,6 +51,7 @@ public class OverrideImplementTest extends LightCodeInsightTestCase {
public void testSimple() { doTest(true); }
public void testAnnotation() { doTest(true); }
public void testJavadocForChangedParamName() { doTest(true); }
public void testIncomplete() { doTest(false); }
public void testSubstitutionInTypeParametersList() { doTest(false); }
public void testTestMissed() { doTest(false); }
@@ -23,8 +23,12 @@ import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.codeInsight.lookup.PsiTypeLookupItem
import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.codeInsight.template.JavaCodeContextType
import com.intellij.codeInsight.template.LiveTemplateTest
import com.intellij.codeInsight.template.Template
import com.intellij.codeInsight.template.TemplateContextType
import com.intellij.codeInsight.template.TemplateManager
import com.intellij.codeInsight.template.impl.TemplateImpl
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.ide.DataManager
import com.intellij.ide.ui.UISettings
@@ -49,6 +53,7 @@ import com.intellij.psi.PsiFile
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.statistics.StatisticsManager
import com.intellij.psi.statistics.impl.StatisticsManagerImpl
import com.intellij.util.containers.ContainerUtil
/**
* @author peter
*/
@@ -1520,4 +1525,28 @@ class X extends Foo {
assert lookup
}
public void "test live template without description"() {
final TemplateManager manager = TemplateManager.getInstance(getProject());
final Template template = manager.createTemplate("tpl", "user", null);
final JavaCodeContextType contextType =
ContainerUtil.findInstance(TemplateContextType.EP_NAME.getExtensions(), JavaCodeContextType.Statement);
((TemplateImpl)template).getTemplateContext().setEnabled(contextType, true);
LiveTemplateTest.addTemplate(template, testRootDisposable)
myFixture.configureByText 'a.java', '''
class Foo {
int tplMn;
{ <caret> }
}
'''
type 'tpl'
myFixture.assertPreferredCompletionItems 0, 'tplMn', 'tpl'
LookupElementPresentation p = LookupElementPresentation.renderElement(myFixture.lookupElements[1])
assert p.itemText == 'tpl'
assert !p.tailText
assert p.typeText == ' [Tab] '
}
}
@@ -5,12 +5,8 @@ import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.template.SmartCompletionContextType;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateContextType;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.*;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.codeInsight.template.impl.TemplateSettings;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.Condition;
@@ -650,13 +646,8 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
final SmartCompletionContextType completionContextType =
ContainerUtil.findInstance(TemplateContextType.EP_NAME.getExtensions(), SmartCompletionContextType.class);
((TemplateImpl)template).getTemplateContext().setEnabled(completionContextType, true);
TemplateSettings.getInstance().addTemplate(template);
try {
doTest();
}
finally {
TemplateSettings.getInstance().removeTemplate(template);
}
LiveTemplateTest.addTemplate(template, myTestRootDisposable);
doTest();
}
public void testInThisExpression() throws Throwable { doTest(); }
@@ -316,6 +316,8 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA87860() throws Exception { doTest5(false); }
public void testIDEA67584() throws Exception { doTest5(false); }
public void testIDEA113225() throws Exception { doTest5(false); }
public void testIDEA67518() throws Exception { doTest5(false); }
public void testIDEA57252() throws Exception { doTest5(false); }
public void testJavaUtilCollections_NoVerify() throws Exception {
PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));
@@ -0,0 +1,285 @@
/*
* Copyright 2000-2013 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.
*/
/*
* Created by IntelliJ IDEA.
* User: cdr
* Date: Jul 31, 2007
* Time: 2:39:56 PM
*/
package com.intellij.codeInsight.daemon;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class HighlightStressTest extends LightDaemonAnalyzerTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
if ("RandomEditingForUnused".equals(getTestName(false))) {
return new LocalInspectionTool[]{new UnusedSymbolLocalInspection(), new UnusedImportLocalInspection(),};
}
List<InspectionToolWrapper> all = InspectionToolRegistrar.getInstance().createTools();
List<LocalInspectionTool> locals = new ArrayList<LocalInspectionTool>();
for (InspectionToolWrapper tool : all) {
if (tool instanceof LocalInspectionToolWrapper) {
LocalInspectionTool e = ((LocalInspectionToolWrapper)tool).getTool();
locals.add(e);
}
}
return locals.toArray(new LocalInspectionTool[locals.size()]);
}
@NonNls private static final String text = "import java.util.*; class X { void f ( ) { "
+ "List < String > ls = new ArrayList < String > ( 1 ) ; ls . toString ( ) ; \n"
+ "List < Integer > is = new ArrayList < Integer > ( 1 ) ; is . toString ( ) ; \n"
+ "List i = new ArrayList ( 1 ) ; i . toString ( ) ; \n"
+ "Collection < Number > l2 = new ArrayList < Number > ( 10 ) ; l2 . toString ( ) ; \n"
+ "Collection < Number > l22 = new ArrayList < Number > ( ) ; l22 . toString ( ) ; \n"
+ "Map < Number , String > l3 = new HashMap < Number , String > ( 10 ) ; l3 . toString ( ) ; \n"
+ "Map < String , String > m = new HashMap < String , String > ( ) ; m . toString ( ) ; \n"
+ "Map < String , String > m1 = new HashMap < String , String > ( ) ; m1 . toString ( ) ; \n"
+ "Map < String , String > m2 = new HashMap < String , String > ( ) ; m2 . toString ( ) ; \n"
+ "Map < String , String > m3 = new HashMap < String , String > ( ) ; m3 . toString ( ) ; \n"
+ "Map < String , String > mi = new HashMap < String , String > ( 1 ) ; mi . toString ( ) ; \n"
+ "Map < String , String > mi1 = new HashMap < String , String > ( 1 ) ; mi1 . toString ( ) ; \n"
+ "Map < String , String > mi2 = new HashMap < String , String > ( 1 ) ; mi2 . toString ( ) ; \n"
+ "Map < String , String > mi3 = new HashMap < String , String > ( 1 ) ; mi3 . toString ( ) ; \n"
+ "Map < Number , String > l4 = new HashMap < Number , String > ( ) ; l4 . toString ( ) ; \n"
+ "Map < Number , String > l5 = new HashMap < Number , String > ( l4 ) ; l5 . toString ( ) ; \n"
+ "HashMap < Number , String > l6 = new HashMap < Number , String > ( ) ; l6 . toString ( ) ; \n"
+ "Map < List < Integer > , Map < String , List < String > > > l7 = new HashMap ( 1 ) ; l7 . toString ( ) ; \n"
+ "java . util . Map < java . util . List < Integer > , java . util . Map < String , java . util . List < String > > > l77 = new java . util . HashMap ( 1 ) ; l77 . toString ( ) ; \n"
+ " } } ";
public void testAllTheseConcurrentThreadsDoNotCrashAnything() throws Exception {
long time = System.currentTimeMillis();
for (int i = 0; i < 20/*00000*/; i++) {
//System.out.println("i = " + i);
getPsiManager().dropResolveCaches();
((PsiManagerEx)getPsiManager()).getFileManager().cleanupForNextTest();
DaemonCodeAnalyzer.getInstance(getProject()).restart();
configureFromFileText("Stress.java", text);
List<HighlightInfo> infos = doHighlighting();
assertEmpty(DaemonAnalyzerTestCase.filter(infos, HighlightSeverity.ERROR));
UIUtil.dispatchAllInvocationEvents();
FileEditorManagerEx.getInstanceEx(getProject()).closeAllFiles();
}
System.out.println(System.currentTimeMillis() - time+"ms");
}
public void _testHugeFile() throws Exception {
@NonNls String filePath = "/psi/resolve/Thinlet.java";
configureByFile(filePath);
doHighlighting();
int N = 42;
long[] time = new long[N];
for (int i = 0; i < N; i++) {
DaemonCodeAnalyzer.getInstance(getProject()).restart();
long start = System.currentTimeMillis();
doHighlighting();
long end = System.currentTimeMillis();
time[i] = end - start;
System.out.println("i = " + i + "; time= "+(end-start));
UIUtil.dispatchAllInvocationEvents();
}
System.out.println("Average among the N/3 median times: " + PlatformTestUtil.averageAmongMedians(time, 3) + "ms");
//System.out.println("JobLauncher.COUNT = " + JobLauncher.COUNT);
//System.out.println("JobLauncher.TINY = " + JobLauncher.TINY_COUNT);
//System.out.println("JobLauncher.LENGTH = " + JobLauncher.LENGTH);
//System.out.println("JobLauncher.ELAPSED = " + JobLauncher.ELAPSED);
//System.out.println("Ave length : "+(JobLauncher.LENGTH.get()/1.0/JobLauncher.COUNT.get()));
//System.out.println("Ave elapsed: "+(JobLauncher.ELAPSED.get()/1.0/JobLauncher.COUNT.get()));
//
//JobLauncher.lengths.sort();
//System.out.println("Lengths: "+JobLauncher.lengths);
}
public void testRandomEditingPerformance() throws Exception {
configureFromFileText("Stress.java", text);
List<HighlightInfo> list = doHighlighting();
int warnings = list.size();
Random random = new Random();
DaemonCodeAnalyzer.getInstance(getProject()).restart();
int N = 20;
long[] time = new long[N];
for (int i = 0; i < N; i++) {
long start = System.currentTimeMillis();
System.out.println("i = " + i);
String s = myFile.getText();
int offset;
while (true) {
offset = random.nextInt(s.length());
if (s.charAt(offset) == ' ') break;
}
myEditor.getCaretModel().moveToOffset(offset);
type("/*--*/");
Collection<HighlightInfo> infos = doHighlighting();
if (warnings != infos.size()) {
list = new ArrayList<HighlightInfo>(list);
Collections.sort(list, new Comparator<HighlightInfo>() {
@Override
public int compare(HighlightInfo o1, HighlightInfo o2) {
if (o1.equals(o2)) return 0;
if (o1.getActualStartOffset() != o2.getActualStartOffset()) return o1.getActualStartOffset() - o2.getActualStartOffset();
return (o1.getText() + o1.getDescription()).compareTo(o2.getText() + o2.getDescription());
}
});
infos = new ArrayList<HighlightInfo>(infos);
Collections.sort((ArrayList<HighlightInfo>)infos, new Comparator<HighlightInfo>() {
@Override
public int compare(HighlightInfo o1, HighlightInfo o2) {
if (o1.equals(o2)) return 0;
if (o1.getActualStartOffset() != o2.getActualStartOffset()) return o1.getActualStartOffset() - o2.getActualStartOffset();
return (o1.getText() + o1.getDescription()).compareTo(o2.getText() + o2.getDescription());
}
});
System.out.println(">--------------------");
for (HighlightInfo info : list) {
System.out.println(info);
}
System.out.println("---------------------");
for (HighlightInfo info : infos) {
System.out.println(info);
}
System.out.println("<--------------------");
}
assertEquals(infos.toString(), warnings, infos.size());
for (HighlightInfo info : infos) {
assertNotSame(info + "", HighlightSeverity.ERROR, info.getSeverity());
}
UIUtil.dispatchAllInvocationEvents();
long end = System.currentTimeMillis();
time[i] = end - start;
}
FileEditorManagerEx.getInstanceEx(getProject()).closeAllFiles();
System.out.println("Average among the N/3 median times: " + PlatformTestUtil.averageAmongMedians(time, 3) + "ms");
}
public void testRandomEditingForUnused() throws Exception {
configureFromFileText("Stress.java", "class X {<caret>}");
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(getProject());
String[] names = cache.getAllClassNames();
final StringBuilder imports = new StringBuilder();
final StringBuilder usages = new StringBuilder();
int v = 0;
List<PsiClass> aclasses = new ArrayList<PsiClass>();
for (String name : names) {
PsiClass[] classes = cache.getClassesByName(name, GlobalSearchScope.allScope(getProject()));
if (classes.length == 0) continue;
PsiClass aClass = classes[0];
if (!aClass.hasModifierProperty(PsiModifier.PUBLIC)) continue;
if (aClass.getSuperClass() == null) continue;
PsiClassType[] superTypes = aClass.getSuperTypes();
if (superTypes.length == 0 || superTypes[0].resolve() == null) continue;
String qualifiedName = aClass.getQualifiedName();
if (qualifiedName.startsWith("java.lang.invoke")) continue; // java.lang.invoke.MethodHandle has weird access attributes in recent rt.jar which causes spurious highlighting errors
imports.append("import " + qualifiedName + ";\n");
usages.append("/**/ "+aClass.getName() + " var" + v + " = null; var" + v + ".toString();\n");
aclasses.add(aClass);
v++;
if (v>100) break;
}
final String text = imports + "\n class X {{\n" + usages + "}}";
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
getEditor().getDocument().setText(text);
}
});
List<HighlightInfo> errors = DaemonAnalyzerTestCase.filter(doHighlighting(), HighlightSeverity.WARNING);
assertEmpty(errors);
Random random = new Random();
int unused = 0;
for (int i = 0; i < 100; i++) {
String s = myFile.getText();
int offset;
while (true) {
offset = random.nextInt(s.length());
if (CharArrayUtil.regionMatches(s, offset, "/**/") || CharArrayUtil.regionMatches(s, offset, "//")) break;
}
char next = offset < s.length()-1 ? s.charAt(offset+1) : 0;
if (next == '/') {
myEditor.getCaretModel().moveToOffset(offset + 1);
type("**");
unused--;
}
else if (next == '*') {
myEditor.getCaretModel().moveToOffset(offset + 1);
delete();
delete();
unused++;
}
else {
continue;
}
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
getFile().accept(new PsiRecursiveElementVisitor() {
@Override
public void visitElement(PsiElement element) {
assertTrue(element.toString(), element.isValid());
super.visitElement(element);
}
});
System.out.println("i = " + i + " " + next + " at "+offset);
List<HighlightInfo> infos = doHighlighting();
errors = DaemonAnalyzerTestCase.filter(infos, HighlightSeverity.ERROR);
assertEmpty(errors);
List<HighlightInfo> warns = DaemonAnalyzerTestCase.filter(infos, HighlightSeverity.WARNING);
if (unused != warns.size()) {
assertEquals(warns.toString(), unused, warns.size());
}
}
FileEditorManagerEx.getInstanceEx(getProject()).closeAllFiles();
}
}
@@ -0,0 +1,295 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.daemon;
import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
import com.intellij.concurrency.JobLauncher;
import com.intellij.concurrency.JobSchedulerImpl;
import com.intellij.concurrency.SensitiveProgressWrapper;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.util.Processor;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class JobUtilTest extends PlatformTestCase {
@Override
protected boolean isRunInWriteAction() {
return false;
}
public void testUnbalancedTaskJobUtilPerformance() {
List<Integer> things = new ArrayList<Integer>(Collections.<Integer>nCopies(10000, null));
int sum = 0;
for (int i = 0; i < things.size(); i++) {
int v = i < 9950 ? 1 : 1000;
things.set(i, v);
sum += things.get(i);
}
assertEquals(59950, sum);
long start = System.currentTimeMillis();
boolean b = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(things, new ProgressIndicatorBase(), false, false, new Processor<Integer>() {
@Override
public boolean process(Integer o) {
busySleep(o);
return true;
}
});
assertTrue(b);
long elapsed = System.currentTimeMillis() - start;
int expected = 2 * (9950 + 50 * 1000) / JobSchedulerImpl.CORES_COUNT;
String message = "Elapsed: " + elapsed + "; expected: " + expected;
System.out.println(message);
assertTrue(message, elapsed < expected);
}
private static final AtomicInteger COUNT = new AtomicInteger();
private static int busySleep(int ms) {
long end = System.currentTimeMillis() + ms;
while (System.currentTimeMillis() < end);
return COUNT.incrementAndGet();
}
public void testJobUtilFinishes() throws Exception {
COUNT.set(0);
int N = 100000;
List<String> list = Collections.nCopies(N, null);
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
final AtomicBoolean finished = new AtomicBoolean();
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(list, null, false, new Processor<String>() {
@Override
public boolean process(String name) {
try {
if (finished.get()) {
throw new RuntimeException();
}
for (int i = 0; i < 1000; i++) {
new BigDecimal(i).multiply(new BigDecimal(1));
}
busySleep(1);
if (finished.get()) {
throw new RuntimeException();
}
}
catch (Exception e) {
exception.set(e);
}
return true;
}
});
finished.set(true);
Thread.sleep(1000);
if (exception.get() != null) throw exception.get();
assertEquals(N, COUNT.get());
}
public void testJobUtilProcessesAllItems() throws Exception {
List<String> list = Collections.nCopies(10000, null);
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
for (int i=0; i<10; i++) {
long start = System.currentTimeMillis();
COUNT.set(0);
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(list, null, false, new Processor<String>() {
@Override
public boolean process(String name) {
busySleep(1);
return true;
}
});
if (exception.get() != null) throw exception.get();
long finish = System.currentTimeMillis();
System.out.println("Elapsed: "+(finish-start)+"ms");
assertEquals(list.size(), COUNT.get());
}
}
public void testJobUtilRecursive() throws Exception {
final List<String> list = Collections.nCopies(100, null);
for (int i=0; i<10; i++) {
COUNT.set(0);
long start = System.currentTimeMillis();
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(list, null, false, new Processor<String>() {
@Override
public boolean process(String name) {
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(list, null, false, new Processor<String>() {
@Override
public boolean process(String name) {
busySleep(1);
return true;
}
});
return true;
}
});
long finish = System.currentTimeMillis();
System.out.println("Elapsed: "+(finish-start)+"ms");
assertEquals(list.size()*list.size(), COUNT.get());
}
}
public void testCorrectProgressAndReadAction() throws Throwable {
checkProgressAndReadAction(Collections.singletonList(null), new DaemonProgressIndicator(), true);
checkProgressAndReadAction(Collections.singletonList(null), new DaemonProgressIndicator(), false);
checkProgressAndReadAction(Collections.emptyList(), new DaemonProgressIndicator(), true);
checkProgressAndReadAction(Collections.emptyList(), new DaemonProgressIndicator(), false);
checkProgressAndReadAction(Arrays.asList(new Object(), new Object()), new DaemonProgressIndicator(), true);
checkProgressAndReadAction(Arrays.asList(new Object(), new Object()), new DaemonProgressIndicator(), false);
checkProgressAndReadAction(Arrays.asList(new Object(), new Object()), null, false);
}
private static void checkProgressAndReadAction(final List<Object> objects,
final DaemonProgressIndicator progress,
final boolean runInReadAction) throws Throwable {
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(objects, progress, runInReadAction, new Processor<Object>() {
@Override
public boolean process(Object o) {
try {
if (objects.size() <= 1 || JobSchedulerImpl.CORES_COUNT <= 2) {
assertTrue(ApplicationManager.getApplication().isDispatchThread());
}
else {
// generally we know nothing about current thread since FJP can help others task to execute while in current context
}
ProgressIndicator actualIndicator = ProgressManager.getInstance().getProgressIndicator();
if (progress == null) {
assertNotNull(actualIndicator);
assertTrue(actualIndicator instanceof ProgressIndicatorBase);
}
else {
assertTrue(actualIndicator instanceof SensitiveProgressWrapper);
ProgressIndicator original = ((SensitiveProgressWrapper)actualIndicator).getOriginalProgressIndicator();
assertSame(progress, original);
}
// there can be read access even if we didn't ask for it (e.g. when task under read action steals others work)
assertTrue(!runInReadAction || ApplicationManager.getApplication().isReadAccessAllowed());
}
catch (Throwable e) {
exception.set(e);
}
return true;
}
});
if (exception.get() != null) throw exception.get();
}
public void testExceptionalCompletion() throws Throwable {
final List<Object> objects = Collections.nCopies(100000000, null);
COUNT.set(0);
try {
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(objects, null, true, new Processor<Object>() {
@Override
public boolean process(Object o) {
if (COUNT.incrementAndGet() == 100000) {
System.out.println("PCE");
throw new ProcessCanceledException();
}
return true;
}
});
fail("PCE must have been thrown");
}
catch (ProcessCanceledException e) {
// caught OK
}
}
public void testNotNormalCompletion() throws Throwable {
final List<Object> objects = Collections.nCopies(100000000, null);
COUNT.set(0);
boolean success = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(objects, null, true, new Processor<Object>() {
@Override
public boolean process(Object o) {
if (COUNT.incrementAndGet() == 100000) {
System.out.println("PCE");
return false;
}
return true;
}
});
assertFalse(success);
}
public void testJobUtilCompletesEvenIfCannotGrabReadAction() throws Throwable {
final List<Object> objects = Collections.nCopies(1000000, null);
COUNT.set(0);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
boolean success = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(objects, null, true, false, new Processor<Object>() {
@Override
public boolean process(Object o) {
COUNT.incrementAndGet();
return true;
}
});
assertTrue(success);
assertEquals(objects.size(), COUNT.get());
}
});
}
public void testJobUtilRecursiveCancel() throws Exception {
final List<String> list = Collections.nCopies(100, "");
final List<Integer> ilist = Collections.nCopies(100, 0);
for (int i=0; i<1/*0*/; i++) {
COUNT.set(0);
long start = System.currentTimeMillis();
boolean success = false;
try {
success = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(list, null, false, new Processor<String>() {
@Override
public boolean process(String name) {
boolean nestedSuccess = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(ilist, null, false, new Processor<Integer>() {
@Override
public boolean process(Integer integer) {
if (busySleep(1) == 1000) {
System.out.println("PCE");
throw new RuntimeException("xxx");
}
return true;
}
});
System.out.println("nestedSuccess = " + nestedSuccess);
return true;
}
});
}
catch (ProcessCanceledException e) {
// OK
}
catch (RuntimeException e) {
assertEquals("xxx", e.getMessage());
}
long finish = System.currentTimeMillis();
System.out.println("Elapsed: "+(finish-start)+"ms");
//assertEquals(list.size()*list.size(), COUNT.get());
assertFalse(success);
}
}
}
@@ -434,6 +434,7 @@ class Test {
public void "test simple property accessors in one line"() {
configure """class Foo {
int field;
int field2;
int getField()
{
@@ -443,11 +444,13 @@ class Test {
void setField(int f) {
field = f;
}
void setField2(int f){field2=f;}
}"""
PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
assert regions.size() == 4
assert regions.size() == 5
Closure checkAccessorFolding = { FoldRegion region1, FoldRegion region2, PsiMethod method ->
assert region1.startOffset == method.parameterList.textRange.endOffset
@@ -463,6 +466,7 @@ class Test {
checkAccessorFolding(regions[0], regions[1], fooClass.methods[0])
checkAccessorFolding(regions[2], regions[3], fooClass.methods[1])
assert regions[4].placeholderText == '{...}'
}
private def changeFoldRegions(Closure op) {
@@ -1,31 +1,32 @@
/*
* Copyright (c) 2005 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.codeInsight.template;
package com.intellij.codeInsight.template
import com.intellij.JavaTestUtil
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.codeInsight.lookup.impl.LookupManagerImpl
import com.intellij.codeInsight.template.impl.*
import com.intellij.codeInsight.template.macro.ClassNameCompleteMacro
import com.intellij.codeInsight.template.macro.CompleteMacro
import com.intellij.codeInsight.template.macro.MethodReturnTypeMacro
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.AccessToken
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.impl.DocumentImpl
import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.annotations.NotNull
import com.intellij.codeInsight.template.impl.*
import static com.intellij.codeInsight.template.Template.Property.*
import static com.intellij.codeInsight.template.Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE
/**
* @author spleaner
@@ -65,19 +66,11 @@ public class LiveTemplateTest extends LightCodeInsightFixtureTestCase {
final TemplateContextType contextType =
ContainerUtil.findInstance(TemplateContextType.EP_NAME.getExtensions(), JavaCodeContextType.class);
((TemplateImpl)template).getTemplateContext().setEnabled(contextType, true);
TemplateSettings settings = TemplateSettings.getInstance();
try {
settings.addTemplate(template);
final Editor editor = getEditor();
addTemplate(template, testRootDisposable)
final Editor editor = getEditor();
manager.startTemplate(editor, settings.getDefaultShortcutChar());
checkResultByText(expected);
}
finally {
if (settings.getTemplate(template.getKey(), group) != null) {
settings.removeTemplate(template);
}
}
manager.startTemplate(editor, (char)'\t');
checkResultByText(expected);
}
public void testTemplateWithArg1() throws IOException {
@@ -559,15 +552,15 @@ class Foo {
myFixture.configureByText("a.java", "class A { void f() { Stri<selection>ng s = \"tpl</selection><caret>\"; } }")
addTemplate(template, testRootDisposable)
myFixture.type '\t'
myFixture.checkResult 'class A { void f() { Stri "; } }'
}
static void addTemplate(Template template, Disposable parentDisposable) {
def settings = TemplateSettings.getInstance()
settings.addTemplate(template);
try {
myFixture.type '\t'
myFixture.checkResult 'class A { void f() { Stri "; } }'
}
finally {
settings.removeTemplate(template);
}
Disposer.register(parentDisposable, { settings.removeTemplate(template) } as Disposable)
}
public void "test expand current live template on no suggestions in lookup"() {
@@ -109,8 +109,8 @@ class DependencyContext {
myEnumerator.force();
}
public Logger<Integer> getLogger(final com.intellij.openapi.diagnostic.Logger log) {
return new Logger<Integer>() {
public LoggerWrapper<Integer> getLogger(final com.intellij.openapi.diagnostic.Logger log) {
return new LoggerWrapper<Integer>() {
@Override
public void debug(String comment, Integer s) {
if (log.isDebugEnabled()) {
@@ -19,7 +19,7 @@ package org.jetbrains.jps.builders.java.dependencyView;
* @author: db
* Date: 20.01.12
*/
public interface Logger<T> {
public interface LoggerWrapper<T> {
void debug(String comment, T t);
void debug(String comment, String t);
void debug(String comment, boolean t);
@@ -72,7 +72,7 @@ public class Mappings {
private final int myInitName;
private final int myEmptyName;
private final int myObjectClassName;
private org.jetbrains.jps.builders.java.dependencyView.Logger<Integer> myDebugS;
private LoggerWrapper<Integer> myDebugS;
private IntIntMultiMaplet myClassToSubclasses;
@@ -24,8 +24,10 @@ import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.incremental.LineOutputWriter;
import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -71,7 +73,17 @@ public class JavacMain {
if (compiler == null) {
compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "System Java Compiler was not found in classpath"));
String message = "System Java Compiler was not found in classpath";
// trying to obtain additional diagnostic for the case when compiler.jar is present, but there were problems with compiler class loading:
try {
Class.forName("com.sun.tools.javac.api.JavacTool", false, JavacMain.class.getClassLoader());
}
catch (Throwable ex) {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
ex.printStackTrace(new PrintStream(out));
message = message + ":\n" + out.toString();
}
diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message));
return false;
}
nowUsingJavac = true;
@@ -86,6 +86,9 @@ public class JavacServerBootstrap {
appendParam(cmdLine, "-D" + JavacServer.USE_ECLIPSE_COMPILER_PROPERTY);
}
// this will disable standard extensions to ensure javac is loaded from the right tools.jar
appendParam(cmdLine, "-Djava.ext.dirs=");
for (String option : vmOptions) {
appendParam(cmdLine, option);
}
BIN
View File
Binary file not shown.
+11 -10
View File
@@ -2,12 +2,13 @@ asm-commons.jar
asm.jar
asm4-all.jar
automaton.jar
cli-parser-1.1.jar
cglib-2.2.2.jar
cli-parser-1.1.jar
commons-codec-1.3.jar
commons-httpclient-3.1-patched.jar
commons-logging-1.1.1.jar
commons-net-3.1.jar
ecj-4.2.1.jar
groovy-all-2.0.6.jar
gson-2.2.3.jar
guava-14.0.1.jar
@@ -15,29 +16,34 @@ jaxen-1.1.3.jar
jayatana-1.2.4.jar
jcip-annotations.jar
jdom.jar
jgoodies-common-1.2.1.jar
jgoodies-forms.jar
jgoodies-looks-2.4.2.jar
jh.jar
jna-utils.jar
jna.jar
jsch-0.1.50.jar
jsr166e.jar
jsr173_1.0_api.jar
junit.jar
junit-4.10.jar
junit.jar
log4j.jar
jgoodies-common-1.2.1.jar
jgoodies-looks-2.4.2.jar
markdownj-core-0.4.2-SNAPSHOT.jar
microba.jar
miglayout-swing.jar
nanoxml-2.2.3.jar
nekohtml-1.9.14.jar
ecj-4.2.1.jar
netty-all.jar
oromatcher.jar
picocontainer.jar
protobuf-2.5.0.jar
proxy-vole_20120920.jar
resolver.jar
rhino-js-1_7R4.jar
sanselan-0.98-snapshot.jar
serviceMessages.jar
snappy-java-1.0.5.jar
swingx-core-1.6.2.jar
trove4j.jar
velocity.jar
winp-1.17-patched.jar
@@ -46,8 +52,3 @@ xerces.jar
xmlrpc-2.0.jar
xpp3-1.1.4-min.jar
xstream-1.4.3.jar
swingx-core-1.6.2.jar
netty-all.jar
protobuf-2.5.0.jar
rhino-js-1_7R4.jar
proxy-vole_20120920.jar
Binary file not shown.
@@ -24,7 +24,7 @@ public class DaemonCodeAnalyzerSettings {
return ServiceManager.getService(DaemonCodeAnalyzerSettings.class);
}
public boolean NEXT_ERROR_ACTION_GOES_TO_ERRORS_FIRST = false;
public boolean NEXT_ERROR_ACTION_GOES_TO_ERRORS_FIRST = true;
public int AUTOREPARSE_DELAY = 300;
public boolean SHOW_ADD_IMPORT_HINTS = true;
@NonNls public String NO_AUTO_IMPORT_PATTERN = "[a-z].?";
@@ -19,6 +19,7 @@ import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
@@ -46,10 +47,7 @@ public class InconsistentLineSeparatorsInspection extends LocalInspectionTool {
}
final Project project = holder.getProject();
final String projectLineSeparator = CodeStyleFacade.getInstance(project).getLineSeparator();
if (projectLineSeparator == null) {
return;
}
final String projectLineSeparator = FileDocumentManager.getInstance().getLineSeparator(null, project);
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null || !AbstractConvertLineSeparatorsAction.shouldProcess(virtualFile, project)) {
@@ -88,10 +86,7 @@ public class InconsistentLineSeparatorsInspection extends LocalInspectionTool {
return;
}
final String lineSeparator = CodeStyleFacade.getInstance(project).getLineSeparator();
if (lineSeparator == null) {
return;
}
final String lineSeparator = FileDocumentManager.getInstance().getLineSeparator(null, project);
final VirtualFile virtualFile = ((PsiFile)psiElement).getVirtualFile();
if (virtualFile != null) {
@@ -40,13 +40,18 @@ public class Main {
private static final String AWT_HEADLESS = "java.awt.headless";
private static final String PLATFORM_PREFIX_PROPERTY = "idea.platform.prefix";
private static final String[] NO_ARGS = {};
private static boolean isHeadless;
private static boolean isCommandLine;
private Main() { }
public static void main(final String[] args) {
public static void main(String[] args) {
if (args.length == 1 && "%f".equals(args[0])) {
args = NO_ARGS;
}
setFlags(args);
if (isHeadless()) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,10 +19,13 @@
*/
package com.intellij.concurrency;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
public interface Job<T> {
// the lower the priority the more important the task is
@@ -46,6 +49,7 @@ public interface Job<T> {
boolean isDone();
void waitForCompletion(int millis) throws InterruptedException, ExecutionException, TimeoutException;
@NotNull
Job NULL_JOB = new Job() {
@@ -54,6 +58,11 @@ public interface Job<T> {
return true;
}
@Override
public void waitForCompletion(int millis) {
}
@Override
public void cancel() {
}
@@ -65,32 +74,32 @@ public interface Job<T> {
@Override
public void addTask(@NotNull Callable task) {
throw new IncorrectOperationException();
}
@Override
public void addTask(@NotNull Runnable task, Object result) {
throw new IncorrectOperationException();
}
@Override
public void addTask(@NotNull Runnable task) {
throw new IncorrectOperationException();
}
@Override
public List scheduleAndWaitForResults() throws Throwable {
return null;
throw new IncorrectOperationException();
}
@Override
public boolean isCanceled() {
return false;
return true;
}
@Override
public void schedule() {
throw new IncorrectOperationException();
}
};
@@ -27,6 +27,7 @@ import com.intellij.util.Function;
import com.intellij.util.PathUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.DistinctRootsCollection;
import com.intellij.util.io.URLUtil;
import com.intellij.util.text.StringFactory;
@@ -550,4 +551,27 @@ public class VfsUtilCore {
return VfsUtilCore.isAncestor(ancestor, virtualFile, false);
}
}
public static void processFilesRecursively(@NotNull VirtualFile root,
@NotNull Processor<VirtualFile> processor,
@NotNull Convertor<VirtualFile, Boolean> directoryFilter) {
if (!processor.process(root)) return;
if (root.isDirectory() && directoryFilter.convert(root)) {
final LinkedList<VirtualFile[]> queue = new LinkedList<VirtualFile[]>();
queue.add(root.getChildren());
do {
final VirtualFile[] files = queue.removeFirst();
for (VirtualFile file : files) {
if (!processor.process(file)) return;
if (file.isDirectory() && directoryFilter.convert(file)) {
queue.add(file.getChildren());
}
}
} while (!queue.isEmpty());
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable;
public class ProgressWrapper extends AbstractProgressIndicatorBase {
private final ProgressIndicator myOriginal;
private ProgressWrapper(@NotNull ProgressIndicator original) {
protected ProgressWrapper(@NotNull ProgressIndicator original) {
myOriginal = original;
}
@@ -21,12 +21,12 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.LineSeparator;
import com.intellij.util.Processor;
@@ -40,14 +40,13 @@ import java.io.IOException;
* @author Nikolai Matveev
*/
public abstract class AbstractConvertLineSeparatorsAction extends AnAction {
private static Logger LOG = Logger.getInstance("#com.intellij.codeStyle.AbstractConvertLineSeparatorsAction");
private static final Logger LOG = Logger.getInstance("#com.intellij.codeStyle.AbstractConvertLineSeparatorsAction");
@NotNull
private final String mySeparator;
protected AbstractConvertLineSeparatorsAction(@Nullable String text, @NotNull LineSeparator separator) {
this(separator.toString() + " - " + text, separator.getSeparatorString());
this(separator + " - " + text, separator.getSeparatorString());
}
protected AbstractConvertLineSeparatorsAction(@Nullable String text, @NotNull String separator) {
@@ -98,9 +97,9 @@ public abstract class AbstractConvertLineSeparatorsAction extends AnAction {
projectVirtualDirectory = null;
}
final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
final FileTypeRegistry fileTypeManager = FileTypeRegistry.getInstance();
for (VirtualFile file : virtualFiles) {
VfsUtil.processFilesRecursively(
VfsUtilCore.processFilesRecursively(
file,
new Processor<VirtualFile>() {
@Override
@@ -115,7 +114,7 @@ public abstract class AbstractConvertLineSeparatorsAction extends AnAction {
@Override
public Boolean convert(VirtualFile dir) {
return !dir.equals(projectVirtualDirectory)
&& !fileTypeManager.isFileIgnored(dir.getName()); // Exclude files like '.git'
&& !fileTypeManager.isFileIgnored(dir); // Exclude files like '.git'
}
}
);
@@ -125,7 +124,7 @@ public abstract class AbstractConvertLineSeparatorsAction extends AnAction {
public static boolean shouldProcess(@NotNull VirtualFile file, @NotNull Project project) {
if (file.isDirectory()
|| !file.isWritable()
|| FileTypeManager.getInstance().isFileIgnored(file)
|| FileTypeRegistry.getInstance().isFileIgnored(file)
|| file.getFileType().isBinary()
|| file.equals(project.getProjectFile())
|| file.equals(project.getWorkspaceFile()))
@@ -38,9 +38,9 @@ public abstract class IdFilter {
ContentIterator iterator = new ContentIterator() {
@Override
public boolean processFile(VirtualFile fileOrDir) {
idSet.set(
((VirtualFileWithId)fileOrDir).getId()
);
int id = ((VirtualFileWithId)fileOrDir).getId();
if (id < 0) id = -id; // workaround for encountering invalid files, see EA-49915, EA-50599
idSet.set(id);
ProgressManager.checkCanceled();
return true;
}
@@ -54,6 +54,7 @@ public interface FormattingDocumentModel {
*/
int getTextLength();
@NotNull
Document getDocument();
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ public class CommonCodeStyleSettings {
private ArrangementSettings myArrangementSettings;
private CodeStyleSettings myRootSettings;
private IndentOptions myIndentOptions;
private FileType myFileType;
private final FileType myFileType;
private boolean myForceArrangeMenuAvailable;
@NonNls private static final String INDENT_OPTIONS_TAG = "indentOptions";
@@ -61,10 +61,7 @@ public class CommonCodeStyleSettings {
}
public CommonCodeStyleSettings(Language language) {
myLanguage = language;
if (language != null) {
myFileType = language.getAssociatedFileType();
}
this(language, language == null ? null : language.getAssociatedFileType());
}
void setRootSettings(@NotNull CodeStyleSettings rootSettings) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.HighlightingPass;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.concurrency.Job;
import com.intellij.concurrency.JobImpl;
import com.intellij.concurrency.JobLauncher;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.openapi.Disposable;
@@ -47,7 +46,6 @@ import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
import java.util.concurrent.*;
@@ -79,17 +77,17 @@ public abstract class PassExecutorService implements Disposable {
submittedPass.cancel();
}
if (waitForTermination) {
for (Job<Void> job : mySubmittedPasses.values()) {
try {
if (job instanceof JobImpl) {
JobImpl ji = (JobImpl)job;
if (!job.isDone()) ji.waitForTermination();
}
}
catch (Throwable throwable) {
LOG.error(throwable);
try {
while (!waitFor(50)) {
int i = 0;
}
}
catch (ProcessCanceledException ignored) {
}
catch (Throwable throwable) {
LOG.error(throwable);
}
}
mySubmittedPasses.clear();
}
@@ -360,7 +358,9 @@ public abstract class PassExecutorService implements Disposable {
catch (ProcessCanceledException e) {
log(myUpdateProgress, myPass, "Canceled ");
myUpdateProgress.cancel(e); //in case when some smart asses throw PCE just for fun
if (!myUpdateProgress.isCanceled()) {
myUpdateProgress.cancel(e); //in case when some smart asses throw PCE just for fun
}
}
catch (RuntimeException e) {
myUpdateProgress.cancel(e);
@@ -518,20 +518,23 @@ public abstract class PassExecutorService implements Disposable {
return indicator.getUserData(THROWABLE_KEY);
}
@TestOnly
public void waitFor(int millis) throws Exception {
// return true if terminated
public boolean waitFor(int millis) throws Throwable {
ApplicationManager.getApplication().assertIsDispatchThread();
try {
for (Job<Void> job : mySubmittedPasses.values()) {
if (!job.isDone()) {
for (FutureTask task : ((JobImpl)job).getTasks()) {
task.get(millis, TimeUnit.MILLISECONDS);
}
}
job.waitForCompletion(millis);
}
return true;
}
catch (TimeoutException ignored) {
return false;
}
catch (InterruptedException e) {
return true;
}
catch (ExecutionException e) {
throw e.getCause();
}
}
}
@@ -108,8 +108,9 @@ public class AutoHardWrapHandler {
int line = document.getLineNumber(caretOffset);
int startOffset = document.getLineStartOffset(line);
int endOffset = document.getLineEndOffset(line);
final String endOfString = document.getText().substring(caretOffset, endOffset);
final boolean endsWithSpaces = StringUtil.isEmptyOrSpaces(endOfString);
final CharSequence endOfString = document.getCharsSequence().subSequence(caretOffset, endOffset);
final boolean endsWithSpaces = StringUtil.isEmptyOrSpaces(String.valueOf(endOfString));
// Check if right margin is exceeded.
int margin = editor.getSettings().getRightMargin(project);
if (margin <= 0) {
@@ -185,14 +186,16 @@ public class AutoHardWrapHandler {
caretOffsetDiff[0] += event.getNewLength() - event.getOldLength();
}
if (event.getNewLength() <= event.getOldLength() && endsWithSpaces) {
// There is a possible case that document fragment is removed because of auto-formatting.
// We don't want to process such events in case of current string ends with spaces.
if (autoFormatted(event)) {
return;
}
wrapIntroducedSymbolsNumber[0] += event.getNewLength() - event.getOldLength();
}
private boolean autoFormatted(DocumentEvent event) {
return event.getNewLength() <= event.getOldLength() && endsWithSpaces;
}
@Override
public void documentChanged(DocumentEvent event) {
}
@@ -65,7 +65,10 @@ public class LiveTemplateLookupElement extends LookupElement {
}
presentation.setTypeText(" [" + KeyEvent.getKeyText(shortcutChar) + "] ");
}
presentation.setTailText(" (" + myTemplate.getDescription() + ")", true);
String description = myTemplate.getDescription();
if (description != null) {
presentation.setTailText(" (" + description + ")", true);
}
} else {
presentation.setTypeText(myTemplate.getDescription());
@@ -22,7 +22,6 @@
*/
package com.intellij.codeInspection;
import com.intellij.codeStyle.CodeStyleFacade;
import com.intellij.ide.DataManager;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.lang.properties.charset.Native2AsciiCharset;
@@ -153,7 +152,7 @@ public class LossyEncodingInspection extends LocalInspectionTool {
if (separator == null) {
separator = documentManager.isDocumentUnsaved(document) ?
FileDocumentManagerImpl.getLineSeparator(document, virtualFile) :
CodeStyleFacade.getInstance(project).getLineSeparator();
FileDocumentManager.getInstance().getLineSeparator(null, project);
}
String toSave = StringUtil.convertLineSeparators(text, separator);
byte[] bom = virtualFile.getBOM();
@@ -163,6 +163,7 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor {
entriesPanel.add(new ToolbarPanel(myScrollPane, group), BorderLayout.CENTER);
final Splitter splitter = new Splitter(false);
splitter.setProportion(0.4f);
splitter.setHonorComponentsMinimumSize(true);
mainPanel.add(splitter, BorderLayout.CENTER);
@@ -39,14 +39,14 @@ import org.jetbrains.annotations.Nullable;
public class DocumentBasedFormattingModel implements FormattingModel {
private final Block myRootBlock;
private final FormattingDocumentModel myDocumentModel;
private final Document myDocument;
@NotNull private final Document myDocument;
private final Project myProject;
private final CodeStyleSettings mySettings;
private final FileType myFileType;
private final PsiFile myFile;
public DocumentBasedFormattingModel(final Block rootBlock,
final Document document,
@NotNull final Document document,
final Project project,
final CodeStyleSettings settings,
final FileType fileType,
@@ -221,6 +221,7 @@ public class DocumentBasedFormattingModel implements FormattingModel {
return mySettings.getIndentOptions(myFileType);
}
@NotNull
public Document getDocument() {
return myDocument;
}
@@ -38,13 +38,13 @@ public class FormattingDocumentModelImpl implements FormattingDocumentModel {
private final WhiteSpaceFormattingStrategy myWhiteSpaceStrategy;
//private final CharBuffer myBuffer = CharBuffer.allocate(1);
private final Document myDocument;
@NotNull private final Document myDocument;
private final PsiFile myFile;
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.FormattingDocumentModelImpl");
private final CodeStyleSettings mySettings;
public FormattingDocumentModelImpl(final Document document, PsiFile file) {
public FormattingDocumentModelImpl(@NotNull final Document document, PsiFile file) {
myDocument = document;
myFile = file;
if (file != null) {
@@ -117,6 +117,7 @@ public class FormattingDocumentModelImpl implements FormattingDocumentModel {
return myDocument.getTextLength();
}
@NotNull
@Override
public Document getDocument() {
return myDocument;
@@ -175,6 +175,7 @@ public class CodeFormatterFacade {
if (builder != null) {
if (file.getTextLength() > 0) {
LOG.assertTrue(document != null);
try {
final PsiElement startElement = file.findElementAt(textRanges.get(0).getTextRange().getStartOffset());
final PsiElement endElement = file.findElementAt(textRanges.get(textRanges.size() - 1).getTextRange().getEndOffset() - 1);
@@ -567,28 +567,6 @@ public class VfsUtil extends VfsUtilCore {
});
}
public static void processFilesRecursively(@NotNull VirtualFile root, @NotNull Processor<VirtualFile> processor,
@NotNull Convertor<VirtualFile, Boolean> directoryFilter) {
if (!processor.process(root)) return;
if (root.isDirectory() && directoryFilter.convert(root)) {
final LinkedList<VirtualFile[]> queue = new LinkedList<VirtualFile[]>();
queue.add(root.getChildren());
do {
final VirtualFile[] files = queue.removeFirst();
for (VirtualFile file : files) {
if (!processor.process(file)) return;
if (file.isDirectory() && directoryFilter.convert(file)) {
queue.add(file.getChildren());
}
}
} while (!queue.isEmpty());
}
}
@Nullable
public static <T> T processInputStream(@NotNull final VirtualFile file, @NotNull Function<InputStream, T> function) {
InputStream stream = null;
@@ -598,7 +576,8 @@ public class VfsUtil extends VfsUtilCore {
}
catch (IOException e) {
LOG.error(e);
} finally {
}
finally {
try {
if (stream != null) {
stream.close();
@@ -0,0 +1,231 @@
/*
* Copyright 2000-2013 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.concurrency;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.util.Processor;
import jsr166e.CountedCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* Executes processor on array elements in range from lo (inclusive) to hi (exclusive).
* To do this it starts executing processor on first array items and, if it takes too much time, splits the work and forks the right half.
* The series of splits lead to linked list of forked sub tasks, each of which is a CountedCompleter of its own,
* having this task as its parent.
* After the first pass on the array, this task attempts to steal work from the recently forked off sub tasks,
* by traversing the linked subtasks list, unforking each subtask and calling execAndForkSubTasks() on each recursively.
* After that, the task completes itself.
* The process of completing traverses task parent hierarchy, decrementing each pending count until it either
* decrements not-zero pending count and stops or
* reaches the top, in which case it invokes {@link jsr166e.ForkJoinTask#quietlyComplete()} which causes the top level task to wake up and join successfully.
* The exceptions from the sub tasks bubble up to the top and saved in {@link #throwable}.
*/
public class ApplierCompleter extends CountedCompleter<Void> {
private final boolean runInReadAction;
private final ProgressIndicator progressIndicator;
@NotNull
private final List array;
@NotNull
private final Processor processor;
private final int lo;
private final int hi;
private final ApplierCompleter next; // keeps track of right-hand-side tasks
volatile Throwable throwable;
// if not null, the read action has failed and this list contains unfinished subtasks
private List<ApplierCompleter> failedSubTasks;
//private final List<ApplierCompleter> children = new ArrayList<ApplierCompleter>();
ApplierCompleter(ApplierCompleter parent,
boolean runInReadAction,
@NotNull ProgressIndicator progressIndicator,
@NotNull List array,
@NotNull Processor processor,
int lo,
int hi,
ApplierCompleter next) {
super(parent);
this.runInReadAction = runInReadAction;
this.progressIndicator = progressIndicator;
this.array = array;
this.processor = processor;
this.lo = lo;
this.hi = hi;
this.next = next;
}
@Override
public void compute() {
compute(new Runnable() {
@Override
public void run() {
execAndForkSubTasks();
}
});
}
private void compute(@NotNull final Runnable process) {
Runnable toRun = runInReadAction ? new Runnable() {
@Override
public void run() {
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(process)) {
failedSubTasks = new ArrayList<ApplierCompleter>();
failedSubTasks.add(ApplierCompleter.this);
doComplete(throwable);
}
}
} : process;
ProgressIndicator existing = ProgressManager.getInstance().getProgressIndicator();
if (existing == progressIndicator) {
toRun.run();
}
else {
ProgressManager.getInstance().executeProcessUnderProgress(toRun, progressIndicator);
}
}
static class ComputationAbortedException extends RuntimeException {}
// executes tasks one by one and forks right halves if it takes too much time
// returns the linked list of forked halves - they all need to be joined; null means all tasks have been executed, nothing was forked
@Nullable
private ApplierCompleter execAndForkSubTasks() {
int hi = this.hi;
long start = System.currentTimeMillis();
ApplierCompleter right = null;
Throwable throwable = null;
try {
for (int i = lo; i < hi; ++i) {
progressIndicator.checkCanceled();
if (!processor.process(array.get(i))) throw new ComputationAbortedException();
long finish = System.currentTimeMillis();
long elapsed = finish - start;
if (elapsed > 10 && hi - i >= 2 && getSurplusQueuedTaskCount() <= JobSchedulerImpl.CORES_COUNT) {
int mid = i + hi >>> 1;
right = new ApplierCompleter(this, runInReadAction, progressIndicator, array, processor, mid, hi, right);
//children.add(right);
addToPendingCount(1);
right.fork();
hi = mid;
start = finish;
}
}
// traverse the list looking for a task available for stealing
if (right != null) {
right.tryToExecAllList();
}
}
catch (Throwable e) {
cancelProgress();
throwable = e;
}
finally {
doComplete(throwable == null ? this.throwable : throwable);
}
return right;
}
private void doComplete(Throwable throwable) {
ApplierCompleter a = this;
ApplierCompleter child = a;
while (true) {
if (throwable != null) {
a.throwable = throwable;
}
if (a.getPendingCount() == 0) {
if (throwable == null) {
a.onCompletion(child);
}
else {
a.throwable = throwable;
// currently avoid using onExceptionalCompletion since it leaks exceptions via jsr166e.ForkJoinTask.exceptionTable
a.onCompletion(child);
//a.onExceptionalCompletion(throwable, child);
}
child = a;
a = (ApplierCompleter)a.getCompleter();
if (a == null) {
if (throwable == null) {
child.quietlyComplete();
}
else {
child.throwable = throwable;
// currently avoid using completeExceptionally since it leaks exceptions via jsr166e.ForkJoinTask.exceptionTable
child.quietlyComplete();
//child.completeExceptionally(throwable);
}
break;
}
}
else if (a.decrementPendingCountUnlessZero() != 0) {
break;
}
}
}
private void cancelProgress() {
if (!progressIndicator.isCanceled()) {
progressIndicator.cancel();
}
}
// tries to unfork, execute and re-link subtasks
private void tryToExecAllList() {
ApplierCompleter right = this;
while (right != null) {
if (right.tryUnfork()) {
right.execAndForkSubTasks();
}
right = right.next;
}
}
boolean completeTaskWhichFailToAcquireReadAction() {
if (failedSubTasks == null) {
return true;
}
final boolean[] result = {true};
// these tasks could not be executed in the other thread; do them here
for (final ApplierCompleter task : failedSubTasks) {
task.failedSubTasks = null;
task.compute(new Runnable() {
@Override
public void run() {
for (int i = task.lo; i < task.hi; ++i) {
if (!task.processor.process(task.array.get(i))) {
result[0] = false;
break;
}
}
}
});
assert task.failedSubTasks == null;
}
return result[0];
}
@Override
public String toString() {
return System.identityHashCode(this) + " ("+lo+"-"+hi+")";
}
}
@@ -1,245 +0,0 @@
/*
* Copyright 2000-2009 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.
*/
/*
* @author max
*/
package com.intellij.concurrency;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class JobImpl<T> implements Job<T> {
private static volatile long ourJobsCounter = 0;
private final long myJobIndex = ourJobsCounter++;
private final int myPriority;
private final List<PrioritizedFutureTask<T>> myFutures = new ArrayList<PrioritizedFutureTask<T>>();
private volatile boolean canceled = false;
private final AtomicInteger runningTasks = new AtomicInteger();
private volatile boolean scheduled;
private final boolean myFailFastOnAcquireReadAction;
JobImpl(int priority, boolean failFastOnAcquireReadAction) {
myPriority = priority;
myFailFastOnAcquireReadAction = failFastOnAcquireReadAction;
}
@Override
public String getTitle() {
return null;
}
@Override
public void addTask(@NotNull Callable<T> task) {
addTask(task, null);
}
@Override
public void addTask(@NotNull Runnable task, T result) {
addTask(Executors.callable(task, result));
}
@Override
public void addTask(@NotNull Runnable task) {
addTask(Executors.callable(task, (T)null));
}
public void addTask(@NotNull Callable<T> callable, final Consumer<Future> onDoneCallback) {
checkNotScheduled();
PrioritizedFutureTask<T> future =
new PrioritizedFutureTask<T>(callable, this, myJobIndex, JobSchedulerImpl.currentTaskIndex(), myPriority, myFailFastOnAcquireReadAction){
@Override
protected void done() {
super.done();
if (onDoneCallback != null) {
onDoneCallback.consume(this);
}
//TODO[cdr]: consider clearing thread locals: ReflectionUtil.resetThreadlocals();
}
};
synchronized (myFutures) {
myFutures.add(future);
}
runningTasks.incrementAndGet();
}
@Override
public List<T> scheduleAndWaitForResults() throws Throwable {
checkCanSchedule();
final Application application = ApplicationManager.getApplication();
boolean callerHasReadAccess = application != null && application.isReadAccessAllowed();
scheduleAndWaitForResults(callerHasReadAccess);
return null;
}
public void scheduleAndWaitForResults(boolean runInReadAction) throws Throwable {
// Don't bother scheduling if we only have one processor or only one task
boolean reallySchedule;
PrioritizedFutureTask[] tasks = getTasks();
synchronized (myFutures) {
reallySchedule = JobSchedulerImpl.CORES_COUNT >= 2 && myFutures.size() >= 2;
}
scheduled = true;
if (!reallySchedule) {
for (PrioritizedFutureTask future : tasks) {
future.run();
}
return;
}
submitTasks(tasks, runInReadAction, false);
// in case of imbalanced tasks one huge task can stuck running and we would fall to waitForTermination instead of doing useful work
//// http://gafter.blogspot.com/2006/11/thread-pool-puzzler.html
//for (PrioritizedFutureTask task : tasks) {
// task.run();
//}
//
while (!isDone()) {
Runnable task = JobSchedulerImpl.stealTask();
if (task == null) break;
task.run();
}
waitForTermination();
}
public void waitForTermination() throws Throwable {
Throwable ex = null;
PrioritizedFutureTask[] tasks = getTasks();
for (PrioritizedFutureTask f : tasks) {
try {
// this loop is for workaround of mysterious bug
// when sometimes future hangs inside parkAndCheckForInterrupt() during unbounded get()
while(true) {
try {
f.get(10, TimeUnit.MILLISECONDS);
break;
}
catch (TimeoutException e) {
if (f.isDone()) {
f.get(); // does awaitTermination(), and there is no chance to hang
break;
}
}
}
}
catch (CancellationException ignore) {
// already cancelled
cancel();
}
catch (ExecutionException e) {
cancel();
Throwable cause = e.getCause();
if (cause != null) {
ex = cause;
}
}
}
if (ex != null) {
throw ex;
}
}
@Override
public void cancel() {
checkScheduled();
if (canceled) return;
canceled = true;
PrioritizedFutureTask[] tasks = getTasks();
for (PrioritizedFutureTask future : tasks) {
future.cancel(false);
}
runningTasks.set(0);
}
@Override
public boolean isCanceled() {
checkScheduled();
return canceled;
}
@Override
public void schedule() {
checkCanSchedule();
scheduled = true;
PrioritizedFutureTask[] tasks = getTasks();
submitTasks(tasks, false, true);
}
@NotNull
public PrioritizedFutureTask[] getTasks() {
PrioritizedFutureTask[] tasks;
synchronized (myFutures) {
tasks = myFutures.toArray(new PrioritizedFutureTask[myFutures.size()]);
}
return tasks;
}
@Override
public boolean isDone() {
checkScheduled();
return runningTasks.get() <= 0;
}
private void checkCanSchedule() {
checkNotScheduled();
synchronized (myFutures) {
if (myFutures.isEmpty()) {
throw new IllegalStateException("No tasks added. You can't schedule a job which has no tasks");
}
}
}
private void checkNotScheduled() {
if (scheduled) {
throw new IllegalStateException("Already running. You can't call this method for a job which is already scheduled");
}
}
private void checkScheduled() {
if (!scheduled) {
throw new IllegalStateException("Cannot call this method for not yet started job");
}
}
private static void submitTasks(@NotNull PrioritizedFutureTask[] tasks, boolean runInReadAction, boolean reportExceptions) {
for (final PrioritizedFutureTask future : tasks) {
JobSchedulerImpl.submitTask(future, runInReadAction, reportExceptions);
}
}
void taskDone() {
runningTasks.decrementAndGet();
}
}
@@ -19,67 +19,90 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.util.ProgressWrapper;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import jsr166e.ForkJoinPool;
import jsr166e.ForkJoinTask;
import jsr166e.ForkJoinWorkerThread;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author cdr
*/
public class JobLauncherImpl extends JobLauncher {
private static <T> boolean invokeConcurrentlyForAll(@NotNull final List<? extends T> things,
boolean runInReadAction,
boolean failFastOnAcquireReadAction,
@NotNull final Processor<T> thingProcessor,
final ProgressWrapper wrapper) throws ProcessCanceledException {
final JobImpl<String> job = new JobImpl<String>(Job.DEFAULT_PRIORITY, failFastOnAcquireReadAction);
final int chunkSize = Math.max(1, things.size() / Math.max(1, JobSchedulerImpl.CORES_COUNT / 2));
for (int i = 0; i < things.size(); i += chunkSize) {
// this job chunk is i..i+chunkSize-1
final int finalI = i;
job.addTask(new Runnable() {
private static final AtomicLong bits = new AtomicLong();
private static final ForkJoinPool.ForkJoinWorkerThreadFactory FACTORY = new ForkJoinPool.ForkJoinWorkerThreadFactory() {
@Override
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
final int n = addThread();
ForkJoinWorkerThread thread = new ForkJoinWorkerThread(pool) {
@Override
public void run() {
ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
@Override
public void run() {
try {
for (int k = finalI; k < finalI + chunkSize && k < things.size(); k++) {
T thing = things.get(k);
if (!thingProcessor.process(thing)) {
job.cancel();
break;
}
}
}
catch (ProcessCanceledException e) {
job.cancel();
throw e;
}
}
}, wrapper);
protected void onTermination(Throwable exception) {
finishThread(n);
super.onTermination(exception);
}
});
};
thread.setName("JobScheduler FJ pool "+ n +"/"+ JobSchedulerImpl.CORES_COUNT);
return thread;
}
private int addThread() {
boolean set;
int n;
do {
long l = bits.longValue();
long next = (l + 1) | l;
n = Long.numberOfTrailingZeros(l + 1);
set = bits.compareAndSet(l, next);
} while (!set);
return n;
}
private void finishThread(int n) {
boolean set;
do {
long l = bits.get();
long next = l & ~(1L << n);
set = bits.compareAndSet(l, next);
} while (!set);
}
};
private static final ForkJoinPool pool = new ForkJoinPool(JobSchedulerImpl.CORES_COUNT, FACTORY, null, false);
private static <T> boolean invokeConcurrentlyForAll(@NotNull final List<T> things,
boolean runInReadAction,
@NotNull final Processor<? super T> thingProcessor,
@NotNull ProgressIndicator wrapper) throws ProcessCanceledException {
ApplierCompleter applier = new ApplierCompleter(null, runInReadAction, wrapper, things, thingProcessor, 0, things.size(), null);
try {
job.scheduleAndWaitForResults(runInReadAction);
pool.invoke(applier);
if (applier.throwable != null) throw applier.throwable;
}
catch (ApplierCompleter.ComputationAbortedException e) {
return false;
}
catch (RuntimeException e) {
job.cancel();
assert wrapper.isCanceled();
throw e;
}
catch (Throwable throwable) {
job.cancel();
throw new ProcessCanceledException(throwable);
catch (Error e) {
assert wrapper.isCanceled();
throw e;
}
return !job.isCanceled();
catch (Throwable e) {
assert wrapper.isCanceled();
throw new RuntimeException(e);
}
assert applier.isDone();
return applier.completeTaskWhichFailToAcquireReadAction();
}
@Override
@@ -92,22 +115,34 @@ public class JobLauncherImpl extends JobLauncher {
}
@Override
public <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
public <T> boolean invokeConcurrentlyUnderProgress(@NotNull final List<? extends T> things,
ProgressIndicator progress,
boolean runInReadAction,
boolean failFastOnAcquireReadAction,
@NotNull Processor<T> thingProcessor) {
if (things.isEmpty()) {
return true;
}
if (things.size() == 1) {
T t = things.get(0);
return thingProcessor.process(t);
@NotNull final Processor<T> thingProcessor) throws ProcessCanceledException {
if (things.isEmpty()) return true;
// supply our own indicator even if we haven't given one - to support cancellation
final ProgressIndicator wrapper = progress == null ? new ProgressIndicatorBase() : new SensitiveProgressWrapper(progress);
if (things.size() <= 1 || JobSchedulerImpl.CORES_COUNT <= 2) {
final AtomicBoolean result = new AtomicBoolean(true);
ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
@Override
public void run() {
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < things.size(); i++) {
T thing = things.get(i);
if (!thingProcessor.process(thing)) {
result.set(false);
break;
}
}
}
}, wrapper);
return result.get();
}
// can be already wrapped
final ProgressWrapper wrapper = progress instanceof ProgressWrapper ? (ProgressWrapper)progress : ProgressWrapper.wrap(progress);
return invokeConcurrentlyForAll(things, runInReadAction, failFastOnAcquireReadAction, thingProcessor, wrapper);
return invokeConcurrentlyForAll(things, runInReadAction, thingProcessor, wrapper);
}
// This implementation is not really async
@@ -130,22 +165,92 @@ public class JobLauncherImpl extends JobLauncher {
@NotNull
@Override
public Job<Void> submitToJobThread(int priority, @NotNull final Runnable action, Consumer<Future> onDoneCallback) {
final JobImpl<Void> job = new JobImpl<Void>(priority, false);
Callable<Void> callable = new Callable<Void>() {
@Override
public Void call() throws Exception {
try {
action.run();
}
catch (ProcessCanceledException ignored) {
// since it's the only task in the job, nothing to cancel
}
return null;
public Job<Void> submitToJobThread(int priority, @NotNull final Runnable action, final Consumer<Future> onDoneCallback) {
VoidForkJoinTask task = new VoidForkJoinTask(action, onDoneCallback);
pool.submit(task);
return task;
}
private static class VoidForkJoinTask extends ForkJoinTask<Void> implements Job<Void> {
private final Runnable myAction;
private final Consumer<Future> myOnDoneCallback;
public VoidForkJoinTask(@NotNull Runnable action, @Nullable Consumer<Future> onDoneCallback) {
myAction = action;
myOnDoneCallback = onDoneCallback;
}
@Override
public Void getRawResult() {
return null;
}
@Override
protected void setRawResult(Void value) {
}
@Override
protected boolean exec() {
try {
myAction.run();
complete(null); // complete manually before calling callback
}
};
job.addTask(callable, onDoneCallback);
job.schedule();
return job;
catch (Throwable throwable) {
completeExceptionally(throwable);
}
finally {
if (myOnDoneCallback != null) {
myOnDoneCallback.consume(this);
}
}
return true;
}
//////////////// Job
@Override
public String getTitle() {
throw new IncorrectOperationException();
}
@Override
public boolean isCanceled() {
return isCancelled();
}
@Override
public void addTask(@NotNull Callable<Void> task) {
throw new IncorrectOperationException();
}
@Override
public void addTask(@NotNull Runnable task, Void result) {
throw new IncorrectOperationException();
}
@Override
public void addTask(@NotNull Runnable task) {
throw new IncorrectOperationException();
}
@Override
public List<Void> scheduleAndWaitForResults() throws Throwable {
throw new IncorrectOperationException();
}
@Override
public void cancel() {
cancel(true);
}
@Override
public void schedule() {
throw new IncorrectOperationException();
}
@Override
public void waitForCompletion(int millis) throws InterruptedException, ExecutionException, TimeoutException {
get(millis, TimeUnit.MILLISECONDS);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,66 +19,6 @@
*/
package com.intellij.concurrency;
import com.intellij.openapi.Disposable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@NonNls
public class JobSchedulerImpl extends JobScheduler implements Disposable {
public static final int CORES_COUNT = /*1;//*/ Runtime.getRuntime().availableProcessors();
private static final ThreadFactory WORKERS_FACTORY = new ThreadFactory() {
private int threadSeq;
@NotNull
@Override
public synchronized Thread newThread(@NotNull final Runnable r) {
@NonNls String name = "JobScheduler pool " + threadSeq + "/" + CORES_COUNT;
final Thread thread = new Thread(r, name);
thread.setPriority(Thread.NORM_PRIORITY);
threadSeq++;
return thread;
}
};
private static final PriorityBlockingQueue<Runnable> ourQueue = new PriorityBlockingQueue<Runnable>();
private static final MyExecutor ourExecutor = new MyExecutor();
static int currentTaskIndex() {
return ourQueue.size();
}
@Override
public void dispose() {
((ThreadPoolExecutor)getScheduler()).getQueue().clear();
}
static Runnable stealTask() {
return ourQueue.poll();
}
static void submitTask(@NotNull PrioritizedFutureTask future, boolean runInReadAction, boolean reportExceptions) {
future.beforeRun(runInReadAction, reportExceptions);
ourExecutor.executeTask(future);
}
private static class MyExecutor extends ThreadPoolExecutor {
private MyExecutor() {
super(CORES_COUNT, Integer.MAX_VALUE, 60 * 10, TimeUnit.SECONDS, ourQueue, WORKERS_FACTORY);
}
private void executeTask(@NotNull PrioritizedFutureTask task) {
super.execute(task);
}
@Override
public void execute(@NotNull Runnable command) {
throw new IllegalStateException("Use executeTask() to submit PrioritizedFutureTasks only");
}
}
public abstract class JobSchedulerImpl {
public static final int CORES_COUNT = Runtime.getRuntime().availableProcessors();
}
@@ -1,126 +0,0 @@
/*
* Copyright 2000-2009 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.
*/
/*
* @author max
*/
package com.intellij.concurrency;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class PrioritizedFutureTask<T> extends FutureTask<T> implements Comparable<PrioritizedFutureTask> {
private static final Logger LOG = Logger.getInstance("#com.intellij.concurrency.PrioritizedFutureTask");
private final JobImpl<T> myJob;
private final long myJobIndex;
private final int myTaskIndex;
private final int myPriority;
private final boolean myFailFastOnAcquireReadAction;
private volatile boolean myRunInReadAction;
private volatile boolean myReportExceptions;
PrioritizedFutureTask(final Callable<T> callable,
JobImpl<T> job,
long jobIndex,
int taskIndex,
int priority,
boolean failFastOnAcquireReadAction) {
super(callable);
myJob = job;
myJobIndex = jobIndex;
myTaskIndex = taskIndex;
myPriority = priority;
myFailFastOnAcquireReadAction = failFastOnAcquireReadAction;
}
public void beforeRun(boolean runInReadAction, boolean reportExceptions) {
myRunInReadAction = runInReadAction;
myReportExceptions = reportExceptions;
}
@Override
public void run() {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
if (myJob.isCanceled()) {
//set(null);
cancel(false); //todo cancel or set?
}
else {
PrioritizedFutureTask.super.run();
}
}
finally {
try {
if (myReportExceptions) {
// let exceptions during execution manifest themselves
PrioritizedFutureTask.super.get();
}
}
catch (CancellationException ignored) {
}
catch (InterruptedException e) {
LOG.error(e);
}
catch (ExecutionException e) {
LOG.error(e);
}
finally {
myJob.taskDone();
}
}
}
};
if (myRunInReadAction) {
// have to start "real" read action so that we cannot start write action until we are finished here
if (myFailFastOnAcquireReadAction) {
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(runnable)) {
myJob.cancel();
}
}
else {
// cannot run readaction here because of possible deadlock when writeaction in the queue
boolean old = ApplicationImpl.setExceptionalThreadWithReadAccessFlag(true);
try {
runnable.run();
}
finally {
ApplicationImpl.setExceptionalThreadWithReadAccessFlag(old);
}
}
}
else {
runnable.run();
}
}
@Override
public int compareTo(@NotNull final PrioritizedFutureTask o) {
int priorityDelta = myPriority - o.myPriority;
if (priorityDelta != 0) return priorityDelta;
if (myJobIndex != o.myJobIndex) return myJobIndex < o.myJobIndex ? -1 : 1;
return myTaskIndex - o.myTaskIndex;
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2000-2013 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.concurrency;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.util.ProgressWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Progress indicator wrapper which reacts to its own cancellation in addition to the cancellation of its wrappee.
*/
public class SensitiveProgressWrapper extends ProgressWrapper {
public SensitiveProgressWrapper(@NotNull ProgressIndicator indicator) {
super(indicator);
}
@Override
public boolean isCanceled() {
return super.isCanceled() || getOriginalProgressIndicator().isCanceled();
}
}
@@ -21,7 +21,6 @@ import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -643,7 +642,9 @@ public class EditorWindow {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
myTabbedPane.setSelectedIndex(index, focusEditor);
if (myTabbedPane != null) {
myTabbedPane.setSelectedIndex(index, focusEditor);
}
}
});
}
@@ -377,13 +377,13 @@ public class FileWatcher {
if (fastPath && !changedPaths.isEmpty()) break;
for (String root : flatWatchRoots) {
if (FileUtil.pathsEqual(path, root)) {
if (FileUtil.namesEqual(path, root)) {
changedPaths.add(path);
continue ext;
}
if (isExact) {
String parentPath = new File(path).getParent();
if (parentPath != null && FileUtil.pathsEqual(parentPath, root)) {
if (parentPath != null && FileUtil.namesEqual(parentPath, root)) {
changedPaths.add(path);
continue ext;
}
@@ -397,7 +397,7 @@ public class FileWatcher {
}
if (!isExact) {
String parentPath = new File(root).getParent();
if (parentPath != null && FileUtil.pathsEqual(path, parentPath)) {
if (parentPath != null && FileUtil.namesEqual(path, parentPath)) {
changedPaths.add(root);
continue ext;
}
@@ -70,7 +70,7 @@ ide.appIcon.progress=true
ide.appIcon.badge=true
ide.appIcon.requestAttention=true
ide.windowSystem.hScrollChars=15
ide.windowSystem.hScrollChars=5
ide.windowSystem.vScrollChars=5
ide.windowSystem.focusAppOnStartup=true
ide.windowSystem.autoShowProcessPopup=false
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ public interface Convertor<Src, Dst> {
IntoSelf SELF = new IntoSelf();
class IntoSelf<Src> implements Convertor<Src, Src> {
@Override
public Src convert(Src o) {
return o;
}
+1
View File
@@ -23,6 +23,7 @@
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="library" name="CGLIB" level="project" />
<orderEntry type="library" name="asm" level="project" />
<orderEntry type="library" exported="" name="ForkJoin" level="project" />
</component>
<component name="copyright">
<Base>
@@ -0,0 +1,179 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.booleanIsAlwaysInverted;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.reference.*;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public class BooleanMethodIsAlwaysInvertedInspectionBase extends GlobalJavaBatchInspectionTool {
private static final Key<Boolean> ALWAYS_INVERTED = Key.create("ALWAYS_INVERTED_METHOD");
private static boolean hasNonInvertedCalls(final RefMethod refMethod) {
final Boolean alwaysInverted = refMethod.getUserData(ALWAYS_INVERTED);
if (alwaysInverted == null) return true;
if (refMethod.isExternalOverride()) return true;
if (refMethod.isReferenced() && !alwaysInverted.booleanValue()) return true;
final Collection<RefMethod> superMethods = refMethod.getSuperMethods();
for (RefMethod superMethod : superMethods) {
if (hasNonInvertedCalls(superMethod)) return true;
}
return false;
}
private static void traverseSuperMethods(RefMethod refMethod,
GlobalJavaInspectionContext globalContext,
GlobalJavaInspectionContext.UsagesProcessor processor) {
final Collection<RefMethod> superMethods = refMethod.getSuperMethods();
for (RefMethod superMethod : superMethods) {
traverseSuperMethods(superMethod, globalContext, processor);
}
globalContext.enqueueMethodUsagesProcessor(refMethod, processor);
}
private static void checkMethodCall(RefElement refWhat, final PsiElement element) {
if (!(refWhat instanceof RefMethod)) return;
final RefMethod refMethod = (RefMethod)refWhat;
final PsiElement psiElement = refMethod.getElement();
if (!(psiElement instanceof PsiMethod)) return;
final PsiMethod psiMethod = (PsiMethod)psiElement;
if (!PsiType.BOOLEAN.equals(psiMethod.getReturnType())) return;
element.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression call) {
super.visitMethodCallExpression(call);
final PsiReferenceExpression methodExpression = call.getMethodExpression();
if (methodExpression.isReferenceTo(psiMethod)) {
if (isInvertedMethodCall(methodExpression)) return;
refMethod.putUserData(ALWAYS_INVERTED, Boolean.FALSE);
}
}
});
}
private static boolean isInvertedMethodCall(final PsiReferenceExpression methodExpression) {
final PsiPrefixExpression prefixExpression = PsiTreeUtil.getParentOfType(methodExpression, PsiPrefixExpression.class);
if (methodExpression.getQualifierExpression() instanceof PsiSuperExpression) return true; //don't flag super calls
if (prefixExpression != null) {
final IElementType tokenType = prefixExpression.getOperationTokenType();
if (tokenType.equals(JavaTokenType.EXCL)) {
return true;
}
}
return false;
}
@Override
@NotNull
public String getDisplayName() {
return InspectionsBundle.message("boolean.method.is.always.inverted.display.name");
}
@Override
@NotNull
public String getGroupDisplayName() {
return GroupNames.DATA_FLOW_ISSUES;
}
@Override
@NotNull
@NonNls
public String getShortName() {
return "BooleanMethodIsAlwaysInverted";
}
@Override
@Nullable
public RefGraphAnnotator getAnnotator(@NotNull final RefManager refManager) {
return new BooleanInvertedAnnotator();
}
@Override
public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity,
@NotNull AnalysisScope scope,
@NotNull final InspectionManager manager,
@NotNull final GlobalInspectionContext globalContext) {
if (refEntity instanceof RefMethod) {
RefMethod refMethod = (RefMethod)refEntity;
if (!refMethod.isReferenced()) return null;
if (hasNonInvertedCalls(refMethod)) return null;
if (!refMethod.getSuperMethods().isEmpty()) return null;
final PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
final PsiIdentifier psiIdentifier = psiMethod.getNameIdentifier();
if (psiIdentifier != null) {
return new ProblemDescriptor[]{manager.createProblemDescriptor(psiIdentifier,
InspectionsBundle
.message("boolean.method.is.always.inverted.problem.descriptor"),
(LocalQuickFix)getQuickFix(null),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)};
}
}
return null;
}
@Override
protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager,
@NotNull final GlobalJavaInspectionContext context,
@NotNull final ProblemDescriptionsProcessor descriptionsProcessor) {
manager.iterate(new RefJavaVisitor() {
@Override
public void visitMethod(@NotNull final RefMethod refMethod) {
if (descriptionsProcessor.getDescriptions(refMethod) != null) { //suspicious method -> need to check external usages
final GlobalJavaInspectionContext.UsagesProcessor usagesProcessor = new GlobalJavaInspectionContext.UsagesProcessor() {
@Override
public boolean process(PsiReference psiReference) {
final PsiElement psiReferenceExpression = psiReference.getElement();
if (psiReferenceExpression instanceof PsiReferenceExpression &&
!isInvertedMethodCall((PsiReferenceExpression)psiReferenceExpression)) {
descriptionsProcessor.ignoreElement(refMethod);
}
return false;
}
};
traverseSuperMethods(refMethod, context, usagesProcessor);
}
}
});
return false;
}
private static class BooleanInvertedAnnotator extends RefGraphAnnotator {
@Override
public void onInitialize(RefElement refElement) {
if (refElement instanceof RefMethod) {
final PsiElement element = refElement.getElement();
if (!(element instanceof PsiMethod)) return;
if (((PsiMethod)element).getReturnType() != PsiType.BOOLEAN) return;
refElement.putUserData(ALWAYS_INVERTED, Boolean.TRUE); //initial mark boolean methods
}
}
@Override
public void onMarkReferenced(RefElement refWhat, RefElement refFrom, boolean referencedFromClassInitializer) {
checkMethodCall(refWhat, refFrom.getElement());
}
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.bugs;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameterList;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class MisspelledCompareToInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"misspelled.compareto.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"misspelled.compareto.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new MisspelledCompareToVisitor();
}
private static class MisspelledCompareToVisitor
extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
//note: no call to super
@NonNls final String methodName = method.getName();
if (!"compareto".equals(methodName)) {
return;
}
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 1) {
return;
}
registerMethodError(method);
}
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.bugs;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameterList;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class MisspelledEqualsInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"misspelled.equals.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"misspelled.equals.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new MisspelledEqualsVisitor();
}
private static class MisspelledEqualsVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
//note: no call to super
@NonNls final String methodName = method.getName();
if (!"equal".equals(methodName)) {
return;
}
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 1) {
return;
}
registerMethodError(method);
}
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.bugs;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameterList;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class MisspelledHashcodeInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"misspelled.hashcode.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"misspelled.hashcode.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new MisspelledHashcodeVisitor();
}
private static class MisspelledHashcodeVisitor
extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
//note: no call to super
@NonNls final String methodName = method.getName();
if (!"hashcode".equals(methodName)) {
return;
}
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 0) {
return;
}
registerMethodError(method);
}
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.bugs;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameterList;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class MisspelledToStringInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"misspelled.tostring.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"misspelled.tostring.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new MisspelledToStringVisitor();
}
private static class MisspelledToStringVisitor
extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
//note: no call to super
@NonNls final String methodName = method.getName();
if (!"tostring".equals(methodName)) {
return;
}
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 0) {
return;
}
registerMethodError(method);
}
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiAnonymousClass;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiEnumConstantInitializer;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NotNull;
public class AnonymousInnerClassInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"anonymous.inner.class.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"anonymous.inner.class.problem.descriptor");
}
@Override
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
return true;
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new AnonymousInnerClassVisitor();
}
private static class AnonymousInnerClassVisitor
extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
//no call to super here, to avoid double counting
}
@Override
public void visitAnonymousClass(@NotNull PsiAnonymousClass aClass) {
super.visitAnonymousClass(aClass);
if (aClass instanceof PsiEnumConstantInitializer) {
return;
}
registerClassError(aClass);
}
}
}
@@ -0,0 +1,81 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.util.FileTypeUtils;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
public class ClassInTopLevelPackageInspectionBase extends BaseInspection {
@Override
@NotNull
public String getID() {
return "ClassWithoutPackageStatement";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"class.in.top.level.package.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"class.in.top.level.package.problem.descriptor");
}
@Override
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
return true;
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ClassInTopLevelPackageVisitor();
}
private static class ClassInTopLevelPackageVisitor
extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (FileTypeUtils.isInServerPageFile(aClass)) {
return;
}
if (ClassUtils.isInnerClass(aClass)) {
return;
}
final PsiFile file = aClass.getContainingFile();
if (!(file instanceof PsiJavaFile)) {
return;
}
if (((PsiJavaFile)file).getPackageStatement() != null) {
return;
}
registerClassError(aClass);
}
}
}
@@ -0,0 +1,78 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.util.FileTypeUtils;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NotNull;
public class ClassNameDiffersFromFileNameInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"class.name.differs.from.file.name.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"class.name.differs.from.file.name.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ClassNameDiffersFromFileNameVisitor();
}
private static class ClassNameDiffersFromFileNameVisitor
extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (FileTypeUtils.isInServerPageFile(aClass)) {
return;
}
final PsiElement parent = aClass.getParent();
if (!(parent instanceof PsiJavaFile)) {
return;
}
final PsiJavaFile file = (PsiJavaFile)parent;
final String className = aClass.getName();
if (className == null) {
return;
}
final String fileName = file.getName();
final int prefixIndex = fileName.indexOf((int)'.');
if (prefixIndex < 0) {
return;
}
final String filenameWithoutPrefix =
fileName.substring(0, prefixIndex);
if (className.equals(filenameWithoutPrefix)) {
return;
}
registerClassError(aClass, file);
}
}
}
@@ -0,0 +1,172 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.FileTypeUtils;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.AddToIgnoreIfAnnotatedByListQuickFix;
import com.siyeh.ig.ui.ExternalizableStringSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class EmptyClassInspectionBase extends BaseInspection {
@SuppressWarnings({"PublicField"})
public final ExternalizableStringSet ignorableAnnotations = new ExternalizableStringSet();
@SuppressWarnings({"PublicField"})
public boolean ignoreClassWithParameterization = false;
@SuppressWarnings({"PublicField"})
public boolean ignoreThrowables = true;
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("empty.class.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
final Object element = infos[0];
if (element instanceof PsiAnonymousClass) {
return InspectionGadgetsBundle.message("empty.anonymous.class.problem.descriptor");
}
else if (element instanceof PsiClass) {
return InspectionGadgetsBundle.message("empty.class.problem.descriptor");
}
else {
return InspectionGadgetsBundle.message("empty.class.file.without.class.problem.descriptor");
}
}
@NotNull
@Override
protected InspectionGadgetsFix[] buildFixes(Object... infos) {
final Object info = infos[0];
if (!(info instanceof PsiModifierListOwner)) {
return InspectionGadgetsFix.EMPTY_ARRAY;
}
return AddToIgnoreIfAnnotatedByListQuickFix.build((PsiModifierListOwner)info, ignorableAnnotations);
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new EmptyClassVisitor();
}
private class EmptyClassVisitor extends BaseInspectionVisitor {
@Override
public void visitFile(PsiFile file) {
if (!(file instanceof PsiJavaFile)) {
return;
}
final PsiJavaFile javaFile = (PsiJavaFile)file;
if (javaFile.getClasses().length != 0) {
return;
}
@NonNls final String fileName = javaFile.getName();
if ("package-info.java".equals(fileName)) {
return;
}
registerError(file, file);
}
@Override
public void visitClass(@NotNull PsiClass aClass) {
//don't call super, to prevent drilldown
if (FileTypeUtils.isInServerPageFile(aClass.getContainingFile())) {
return;
}
if (aClass.isInterface() || aClass.isEnum() || aClass.isAnnotationType()) {
return;
}
if (aClass instanceof PsiTypeParameter) {
return;
}
final PsiMethod[] constructors = aClass.getConstructors();
if (constructors.length > 0) {
return;
}
final PsiMethod[] methods = aClass.getMethods();
if (methods.length > 0) {
return;
}
final PsiField[] fields = aClass.getFields();
if (fields.length > 0) {
return;
}
final PsiClassInitializer[] initializers = aClass.getInitializers();
if (initializers.length > 0) {
return;
}
if (ignoreClassWithParameterization && isSuperParametrization(aClass)) {
return;
}
if (AnnotationUtil.isAnnotated(aClass, ignorableAnnotations)) {
return;
}
if (ignoreThrowables && InheritanceUtil.isInheritor(aClass, "java.lang.Throwable")) {
return;
}
registerClassError(aClass, aClass);
}
private boolean hasTypeArguments(PsiReferenceList extendsList) {
if (extendsList == null) {
return false;
}
final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
if (parameterList == null) {
continue;
}
final PsiType[] typeArguments = parameterList.getTypeArguments();
if (typeArguments.length != 0) {
return true;
}
}
return false;
}
private boolean isSuperParametrization(PsiClass aClass) {
if (!(aClass instanceof PsiAnonymousClass)) {
final PsiReferenceList extendsList = aClass.getExtendsList();
final PsiReferenceList implementsList = aClass.getImplementsList();
return hasTypeArguments(extendsList) || hasTypeArguments(implementsList);
}
final PsiAnonymousClass anonymousClass = (PsiAnonymousClass)aClass;
final PsiJavaCodeReferenceElement reference = anonymousClass.getBaseClassReference();
final PsiReferenceParameterList parameterList = reference.getParameterList();
if (parameterList == null) {
return false;
}
final PsiTypeElement[] elements = parameterList.getTypeParameterElements();
for (PsiTypeElement element : elements) {
if (element != null) {
return true;
}
}
return false;
}
}
}
@@ -0,0 +1,94 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiAnonymousClass;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiTypeParameter;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NotNull;
public class InnerClassOnInterfaceInspectionBase extends BaseInspection {
/**
* @noinspection PublicField
*/
public boolean m_ignoreInnerInterfaces = false;
@Override
@NotNull
public String getID() {
return "InnerClassOfInterface";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"inner.class.on.interface.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
final PsiClass parentInterface = (PsiClass)infos[0];
final String interfaceName = parentInterface.getName();
return InspectionGadgetsBundle.message(
"inner.class.on.interface.problem.descriptor", interfaceName);
}
@Override
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
return true;
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new InnerClassOnInterfaceVisitor();
}
private class InnerClassOnInterfaceVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (!aClass.isInterface() || aClass.isAnnotationType()) {
return;
}
final PsiClass[] innerClasses = aClass.getInnerClasses();
for (final PsiClass innerClass : innerClasses) {
if (isInnerClass(innerClass)) {
registerClassError(innerClass, aClass);
}
}
}
private boolean isInnerClass(PsiClass innerClass) {
if (innerClass.isEnum()) {
return false;
}
if (innerClass.isAnnotationType()) {
return false;
}
if (innerClass instanceof PsiTypeParameter ||
innerClass instanceof PsiAnonymousClass) {
return false;
}
return !(innerClass.isInterface() && m_ignoreInnerInterfaces);
}
}
}
@@ -0,0 +1,60 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDeclarationStatement;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NotNull;
public class LimitedScopeInnerClassInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"limited.scope.inner.class.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"limited.scope.inner.class.problem.descriptor");
}
@Override
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
return true;
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new LimitedScopeInnerClassVisitor();
}
private static class LimitedScopeInnerClassVisitor
extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
if (aClass.getParent() instanceof PsiDeclarationStatement) {
registerClassError(aClass);
}
}
}
}
@@ -0,0 +1,77 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaFile;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NotNull;
public class MultipleTopLevelClassesInFileInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"multiple.top.level.classes.in.file.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"multiple.top.level.classes.in.file.problem.descriptor");
}
@Override
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
return true;
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new MultipleTopLevelClassesInFileVisitor();
}
private static class MultipleTopLevelClassesInFileVisitor
extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (!(aClass.getParent() instanceof PsiJavaFile)) {
return;
}
final PsiJavaFile file = (PsiJavaFile)aClass.getParent();
if (file == null) {
return;
}
int numClasses = 0;
final PsiElement[] children = file.getChildren();
for (final PsiElement child : children) {
if (child instanceof PsiClass) {
numClasses++;
}
}
if (numClasses <= 1) {
return;
}
registerClassError(aClass);
}
}
}
@@ -0,0 +1,61 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.UtilityClassUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class NonFinalUtilityClassInspectionBase extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("non.final.utility.class.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("non.final.utility.class.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new NonFinalUtilityClassVisitor();
}
private static class NonFinalUtilityClassVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (!UtilityClassUtil.isUtilityClass(aClass)) {
return;
}
if (aClass.hasModifierProperty(PsiModifier.FINAL) ||
aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
registerClassError(aClass, aClass);
}
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.MethodUtils;
import org.jetbrains.annotations.NotNull;
public class ProtectedMemberInFinalClassInspectionBase extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("protected.member.in.final.class.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("protected.member.in.final.class.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ProtectedMemberInFinalClassVisitor();
}
private static class ProtectedMemberInFinalClassVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
if (!method.hasModifierProperty(PsiModifier.PROTECTED)) {
return;
}
final PsiClass containingClass = method.getContainingClass();
if (containingClass == null || !containingClass.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
if (MethodUtils.hasSuper(method)) {
return;
}
registerModifierError(PsiModifier.PROTECTED, method, PsiModifier.PROTECTED);
}
@Override
public void visitField(@NotNull PsiField field) {
if (!field.hasModifierProperty(PsiModifier.PROTECTED)) {
return;
}
final PsiClass containingClass = field.getContainingClass();
if (containingClass == null || !containingClass.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
registerModifierError(PsiModifier.PROTECTED, field, PsiModifier.PROTECTED);
}
}
}
@@ -0,0 +1,101 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiParameterList;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.SerializationUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class PublicConstructorInspectionBase extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("public.constructor.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
if (((Boolean)infos[0]).booleanValue()) {
return InspectionGadgetsBundle.message("public.default.constructor.problem.descriptor");
}
else {
return InspectionGadgetsBundle.message("public.constructor.problem.descriptor");
}
}
@Override
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
return true;
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new PublicConstructorVisitor();
}
private static class PublicConstructorVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(PsiMethod method) {
super.visitMethod(method);
if (!method.isConstructor()) {
return;
}
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
return;
}
final PsiClass aClass = method.getContainingClass();
if (aClass == null || aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
if (SerializationUtils.isExternalizable(aClass)) {
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() == 0) {
return;
}
}
registerMethodError(method, Boolean.FALSE);
}
@Override
public void visitClass(PsiClass aClass) {
super.visitClass(aClass);
if (aClass.isInterface() || aClass.isEnum()) {
return;
}
if (!aClass.hasModifierProperty(PsiModifier.PUBLIC) || aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
final PsiMethod[] constructors = aClass.getConstructors();
if (constructors.length > 0) {
return;
}
if (SerializationUtils.isExternalizable(aClass)) {
return;
}
registerClassError(aClass, Boolean.TRUE);
}
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifierListOwner;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.AddToIgnoreIfAnnotatedByListQuickFix;
import com.siyeh.ig.psiutils.UtilityClassUtil;
import com.siyeh.ig.ui.ExternalizableStringSet;
import org.jetbrains.annotations.NotNull;
public class UtilityClassInspectionBase extends BaseInspection {
@SuppressWarnings({"PublicField"})
public final ExternalizableStringSet ignorableAnnotations = new ExternalizableStringSet();
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("utility.class.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"utility.class.problem.descriptor");
}
@NotNull
@Override
protected InspectionGadgetsFix[] buildFixes(Object... infos) {
return AddToIgnoreIfAnnotatedByListQuickFix.build((PsiModifierListOwner)infos[0], ignorableAnnotations);
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new UtilityClassVisitor();
}
private class UtilityClassVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (!UtilityClassUtil.isUtilityClass(aClass)) {
return;
}
if (AnnotationUtil.isAnnotated(aClass, ignorableAnnotations)) {
return;
}
registerClassError(aClass, aClass);
}
}
}
@@ -0,0 +1,151 @@
/*
* Copyright 2000-2013 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.classlayout;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.util.Query;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.UtilityClassUtil;
import com.siyeh.ig.ui.ExternalizableStringSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class UtilityClassWithoutPrivateConstructorInspectionBase extends BaseInspection {
@SuppressWarnings({"PublicField"})
public final ExternalizableStringSet ignorableAnnotations = new ExternalizableStringSet();
@SuppressWarnings({"PublicField"})
public boolean ignoreClassesWithOnlyMain = false;
@Nullable
static PsiMethod getNullArgConstructor(PsiClass aClass) {
final PsiMethod[] constructors = aClass.getConstructors();
for (final PsiMethod constructor : constructors) {
final PsiParameterList params = constructor.getParameterList();
if (params.getParametersCount() == 0) {
return constructor;
}
}
return null;
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("utility.class.without.private.constructor.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("utility.class.without.private.constructor.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new UtilityClassWithoutPrivateConstructorVisitor();
}
private class UtilityClassWithoutPrivateConstructorVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
if (!UtilityClassUtil.isUtilityClass(aClass)) {
return;
}
if (ignoreClassesWithOnlyMain && hasOnlyMain(aClass)) {
return;
}
if (hasPrivateConstructor(aClass)) {
return;
}
if (AnnotationUtil.isAnnotated(aClass, ignorableAnnotations)) {
return;
}
if (aClass.hasModifierProperty(PsiModifier.PRIVATE) && aClass.getConstructors().length == 0) {
return;
}
final SearchScope scope = GlobalSearchScope.projectScope(aClass.getProject());
final Query<PsiClass> query = ClassInheritorsSearch.search(aClass, scope, true, true);
final PsiClass subclass = query.findFirst();
if (subclass != null) {
return;
}
registerClassError(aClass, aClass);
}
private boolean hasOnlyMain(PsiClass aClass) {
final PsiMethod[] methods = aClass.getMethods();
if (methods.length == 0) {
return false;
}
for (PsiMethod method : methods) {
if (method.isConstructor()) {
continue;
}
if (!method.hasModifierProperty(PsiModifier.STATIC)) {
return false;
}
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
continue;
}
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
return false;
}
final String name = method.getName();
if (!name.equals(HardcodedMethodConstants.MAIN)) {
return false;
}
final PsiType returnType = method.getReturnType();
if (!PsiType.VOID.equals(returnType)) {
return false;
}
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 1) {
return false;
}
final PsiParameter[] parameters = parameterList.getParameters();
final PsiParameter parameter = parameters[0];
final PsiType type = parameter.getType();
if (!type.equalsToText("java.lang.String[]")) {
return false;
}
}
return true;
}
boolean hasPrivateConstructor(PsiClass aClass) {
final PsiMethod[] constructors = aClass.getConstructors();
for (final PsiMethod constructor : constructors) {
if (constructor.hasModifierProperty(PsiModifier.PRIVATE)) {
return true;
}
}
return false;
}
}
}
@@ -0,0 +1,112 @@
/*
* Copyright 2000-2013 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.errorhandling;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiCatchSection;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.ui.ExternalizableStringSet;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class BadExceptionCaughtInspectionBase extends BaseInspection {
/**
* @noinspection PublicField
*/
public final ExternalizableStringSet exceptions =
new ExternalizableStringSet(
"java.lang.NullPointerException",
"java.lang.IllegalMonitorStateException",
"java.lang.ArrayIndexOutOfBoundsException"
);
/**
* @noinspection PublicField
*/
public String exceptionsString = "";
public BadExceptionCaughtInspectionBase() {
if (!exceptionsString.isEmpty()) {
exceptions.clear();
final List<String> strings = StringUtil.split(exceptionsString, ",");
for (String string : strings) {
exceptions.add(string);
}
exceptionsString = "";
}
}
@Override
@NotNull
public String getID() {
return "ProhibitedExceptionCaught";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("bad.exception.caught.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("bad.exception.caught.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new BadExceptionCaughtVisitor();
}
private class BadExceptionCaughtVisitor extends BaseInspectionVisitor {
@Override
public void visitCatchSection(PsiCatchSection section) {
super.visitCatchSection(section);
final PsiParameter parameter = section.getParameter();
if (parameter == null) {
return;
}
final PsiTypeElement typeElement = parameter.getTypeElement();
if (typeElement == null) {
return;
}
final PsiTypeElement[] childTypeElements = PsiTreeUtil.getChildrenOfType(typeElement, PsiTypeElement.class);
if (childTypeElements != null) {
for (PsiTypeElement childTypeElement : childTypeElements) {
checkTypeElement(childTypeElement);
}
}
else {
checkTypeElement(typeElement);
}
}
private void checkTypeElement(PsiTypeElement typeElement) {
final PsiType type = typeElement.getType();
if (exceptions.contains(type.getCanonicalText())) {
registerError(typeElement);
}
}
}
}
@@ -0,0 +1,118 @@
/*
* Copyright 2000-2013 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.errorhandling;
import com.intellij.codeInsight.TestFrameworks;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.LibraryUtil;
import com.siyeh.ig.ui.ExternalizableStringSet;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class BadExceptionDeclaredInspectionBase extends BaseInspection {
/**
* @noinspection PublicField
*/
public final ExternalizableStringSet exceptions =
new ExternalizableStringSet(
"java.lang.Throwable",
"java.lang.Exception",
"java.lang.Error",
"java.lang.RuntimeException",
"java.lang.NullPointerException",
"java.lang.ClassCastException",
"java.lang.ArrayIndexOutOfBoundsException"
);
/**
* @noinspection PublicField
*/
public String exceptionsString = "";
/**
* @noinspection PublicField
*/
public boolean ignoreTestCases = false;
public boolean ignoreLibraryOverrides = false;
public BadExceptionDeclaredInspectionBase() {
if (!exceptionsString.isEmpty()) {
exceptions.clear();
final List<String> strings = StringUtil.split(exceptionsString, ",");
for (String string : strings) {
exceptions.add(string);
}
exceptionsString = "";
}
}
@Override
@NotNull
public String getID() {
return "ProhibitedExceptionDeclared";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("bad.exception.declared.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("bad.exception.declared.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new BadExceptionDeclaredVisitor();
}
private class BadExceptionDeclaredVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
super.visitMethod(method);
if (ignoreTestCases) {
final PsiClass containingClass = method.getContainingClass();
final TestFrameworks testFrameworks = TestFrameworks.getInstance();
if (containingClass != null && testFrameworks.isTestOrConfig(containingClass)) {
return;
}
}
if (ignoreLibraryOverrides && LibraryUtil.isOverrideOfLibraryMethod(method)) {
return;
}
final PsiReferenceList throwsList = method.getThrowsList();
final PsiJavaCodeReferenceElement[] references = throwsList.getReferenceElements();
for (PsiJavaCodeReferenceElement reference : references) {
final PsiElement element = reference.resolve();
if (!(element instanceof PsiClass)) {
continue;
}
final PsiClass thrownClass = (PsiClass)element;
final String qualifiedName = thrownClass.getQualifiedName();
if (qualifiedName != null && exceptions.contains(qualifiedName)) {
registerError(reference);
}
}
}
}
}
@@ -0,0 +1,105 @@
/*
* Copyright 2000-2013 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.errorhandling;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiThrowStatement;
import com.intellij.psi.PsiType;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.ui.ExternalizableStringSet;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class BadExceptionThrownInspectionBase extends BaseInspection {
@SuppressWarnings("PublicField")
public final ExternalizableStringSet exceptions =
new ExternalizableStringSet(
"java.lang.Throwable",
"java.lang.Exception",
"java.lang.Error",
"java.lang.RuntimeException",
"java.lang.NullPointerException",
"java.lang.ClassCastException",
"java.lang.ArrayIndexOutOfBoundsException"
);
/**
* @noinspection PublicField
*/
public String exceptionsString = "";
public BadExceptionThrownInspectionBase() {
if (!exceptionsString.isEmpty()) {
exceptions.clear();
final List<String> strings =
StringUtil.split(exceptionsString, ",");
for (String string : strings) {
exceptions.add(string);
}
exceptionsString = "";
}
}
@Override
@NotNull
public String getID() {
return "ProhibitedExceptionThrown";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"bad.exception.thrown.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
final PsiType type = (PsiType)infos[0];
final String exceptionName = type.getPresentableText();
return InspectionGadgetsBundle.message(
"bad.exception.thrown.problem.descriptor", exceptionName);
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new BadExceptionThrownVisitor();
}
private class BadExceptionThrownVisitor extends BaseInspectionVisitor {
@Override
public void visitThrowStatement(PsiThrowStatement statement) {
super.visitThrowStatement(statement);
final PsiExpression exception = statement.getException();
if (exception == null) {
return;
}
final PsiType type = exception.getType();
if (type == null) {
return;
}
final String text = type.getCanonicalText();
if (exceptions.contains(text)) {
registerStatementError(statement, type);
}
}
}
}
@@ -0,0 +1,66 @@
/*
* Copyright 2000-2013 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.errorhandling;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class ThrowsRuntimeExceptionInspectionBase extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("throws.runtime.exception.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("throws.runtime.exception.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ThrowsRuntimeExceptionVisitor();
}
private static class ThrowsRuntimeExceptionVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(PsiMethod method) {
super.visitMethod(method);
final PsiReferenceList throwsList = method.getThrowsList();
final PsiJavaCodeReferenceElement[] referenceElements = throwsList.getReferenceElements();
for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
final PsiElement target = referenceElement.resolve();
if (!(target instanceof PsiClass)) {
continue;
}
final PsiClass aClass = (PsiClass)target;
if (!InheritanceUtil.isInheritor(aClass, "java.lang.RuntimeException")) {
continue;
}
final String className = aClass.getName();
registerError(referenceElement, className, referenceElement);
}
}
}
}
@@ -0,0 +1,182 @@
/*
* Copyright 2000-2013 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.errorhandling;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ExceptionUtils;
import com.siyeh.ig.psiutils.TestUtils;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class TooBroadCatchInspectionBase extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean onlyWarnOnRootExceptions = false;
@SuppressWarnings("PublicField")
public boolean ignoreInTestCode = false;
@SuppressWarnings("PublicField")
public boolean ignoreThrown = false;
protected static TextRange getRangeToSelect(PsiCodeBlock block) {
PsiElement first = block.getFirstBodyElement();
if (first instanceof PsiWhiteSpace) {
first = first.getNextSibling();
}
if (first == null) {
final int offset = block.getTextRange().getStartOffset() + 1;
return new TextRange(offset, offset);
}
PsiElement last = block.getLastBodyElement();
if (last instanceof PsiWhiteSpace) {
last = last.getPrevSibling();
}
final TextRange textRange;
if (last == null) {
textRange = first.getTextRange();
}
else {
textRange = last.getTextRange();
}
return new TextRange(first.getTextRange().getStartOffset(), textRange.getEndOffset());
}
@Override
@NotNull
public String getID() {
return "OverlyBroadCatchBlock";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("too.broad.catch.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
final List<PsiClass> typesMasked = (List<PsiClass>)infos[0];
String typesMaskedString = typesMasked.get(0).getName();
if (typesMasked.size() == 1) {
return InspectionGadgetsBundle.message("too.broad.catch.problem.descriptor", typesMaskedString);
}
else {
//Collections.sort(typesMasked);
final int lastTypeIndex = typesMasked.size() - 1;
for (int i = 1; i < lastTypeIndex; i++) {
typesMaskedString += ", ";
typesMaskedString += typesMasked.get(i).getName();
}
final String lastTypeString = typesMasked.get(lastTypeIndex).getName();
return InspectionGadgetsBundle.message("too.broad.catch.problem.descriptor1", typesMaskedString, lastTypeString);
}
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new TooBroadCatchVisitor();
}
private class TooBroadCatchVisitor extends BaseInspectionVisitor {
@Override
public void visitTryStatement(@NotNull PsiTryStatement statement) {
super.visitTryStatement(statement);
final PsiCodeBlock tryBlock = statement.getTryBlock();
if (tryBlock == null) {
return;
}
if (ignoreInTestCode && TestUtils.isInTestCode(statement)) {
return;
}
final Set<PsiClassType> thrownTypes = ExceptionUtils.calculateExceptionsThrown(tryBlock);
final Set<PsiType> caughtTypes = new HashSet<PsiType>(thrownTypes.size());
final PsiCatchSection[] catchSections = statement.getCatchSections();
for (final PsiCatchSection catchSection : catchSections) {
final PsiParameter parameter = catchSection.getParameter();
if (parameter == null) {
continue;
}
final PsiType caughtType = parameter.getType();
if (caughtType instanceof PsiDisjunctionType) {
final PsiDisjunctionType disjunctionType = (PsiDisjunctionType)caughtType;
final List<PsiType> types = disjunctionType.getDisjunctions();
for (PsiType type : types) {
check(thrownTypes, caughtTypes, parameter, type);
}
}
else {
if (thrownTypes.isEmpty()) {
if (CommonClassNames.JAVA_LANG_EXCEPTION.equals(caughtType.getCanonicalText())) {
final PsiTypeElement typeElement = parameter.getTypeElement();
if (typeElement == null) {
continue;
}
final PsiClass runtimeExceptionClass = ClassUtils.findClass(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, parameter);
registerError(typeElement, Collections.singletonList(runtimeExceptionClass));
}
}
else {
check(thrownTypes, caughtTypes, parameter, caughtType);
}
}
}
}
private void check(Set<PsiClassType> thrownTypes, Set<PsiType> caughtTypes, PsiParameter parameter, PsiType caughtType) {
final List<PsiClass> maskedExceptions = findMaskedExceptions(thrownTypes, caughtTypes, caughtType);
if (maskedExceptions.isEmpty()) {
return;
}
final PsiTypeElement typeElement = parameter.getTypeElement();
if (typeElement == null) {
return;
}
registerError(typeElement, maskedExceptions);
}
private List<PsiClass> findMaskedExceptions(Set<PsiClassType> thrownTypes, Set<PsiType> caughtTypes, PsiType caughtType) {
if (thrownTypes.contains(caughtType)) {
if (ignoreThrown) {
return Collections.emptyList();
}
caughtTypes.add(caughtType);
thrownTypes.remove(caughtType);
}
if (onlyWarnOnRootExceptions) {
if (!ExceptionUtils.isGenericExceptionClass(caughtType)) {
return Collections.emptyList();
}
}
final List<PsiClass> maskedTypes = new ArrayList();
for (PsiClassType typeThrown : thrownTypes) {
if (!caughtTypes.contains(typeThrown) && caughtType.isAssignableFrom(typeThrown)) {
caughtTypes.add(typeThrown);
final PsiClass aClass = typeThrown.resolve();
if (aClass != null) {
maskedTypes.add(aClass);
}
}
}
return maskedTypes;
}
}
}
@@ -0,0 +1,126 @@
/*
* Copyright 2000-2013 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.errorhandling;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.TestUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class UnusedCatchParameterInspectionBase extends BaseInspection {
/**
* @noinspection PublicField
*/
public boolean m_ignoreCatchBlocksWithComments = false;
/**
* @noinspection PublicField
*/
public boolean m_ignoreTestCases = false;
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"unused.catch.parameter.display.name");
}
@Override
public JComponent createOptionsPanel() {
final MultipleCheckboxOptionsPanel optionsPanel =
new MultipleCheckboxOptionsPanel(this);
optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
"unused.catch.parameter.ignore.catch.option"),
"m_ignoreCatchBlocksWithComments");
optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
"unused.catch.parameter.ignore.empty.option"),
"m_ignoreTestCases");
return optionsPanel;
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
final boolean namedIgnoreButUsed = ((Boolean)infos[0]).booleanValue();
if (namedIgnoreButUsed) {
return InspectionGadgetsBundle.message(
"used.catch.parameter.named.ignore.problem.descriptor"
);
}
return InspectionGadgetsBundle.message(
"unused.catch.parameter.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new UnusedCatchParameterVisitor();
}
private class UnusedCatchParameterVisitor extends BaseInspectionVisitor {
@Override
public void visitTryStatement(@NotNull PsiTryStatement statement) {
super.visitTryStatement(statement);
if (m_ignoreTestCases && TestUtils.isInTestCode(statement)) {
return;
}
final PsiCatchSection[] catchSections = statement.getCatchSections();
for (PsiCatchSection catchSection : catchSections) {
checkCatchSection(catchSection);
}
}
private void checkCatchSection(PsiCatchSection section) {
final PsiParameter parameter = section.getParameter();
if (parameter == null) {
return;
}
@NonNls final String parameterName = parameter.getName();
final PsiCodeBlock block = section.getCatchBlock();
if (block == null) {
return;
}
if (m_ignoreCatchBlocksWithComments) {
final PsiElement[] children = block.getChildren();
for (final PsiElement child : children) {
if (child instanceof PsiComment) {
return;
}
}
}
final CatchParameterUsedVisitor visitor =
new CatchParameterUsedVisitor(parameter);
block.accept(visitor);
final boolean namedIgnore = PsiUtil.isIgnoredName(parameterName);
if (visitor.isUsed()) {
if (namedIgnore) {
registerVariableError(parameter, Boolean.TRUE);
}
return;
}
else if (namedIgnore) {
return;
}
registerVariableError(parameter, Boolean.FALSE);
}
}
}
@@ -0,0 +1,317 @@
/*
* Copyright 2000-2013 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.imports;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.FileTypeUtils;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.OrderedSet;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.StringUtils;
import com.siyeh.ig.psiutils.TestUtils;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StaticImportInspectionBase extends BaseInspection {
@SuppressWarnings({"PublicField"}) public boolean ignoreSingleFieldImports = false;
@SuppressWarnings({"PublicField"}) public boolean ignoreSingeMethodImports = false;
@SuppressWarnings("PublicField") public boolean ignoreInTestCode = false;
@SuppressWarnings("PublicField") public OrderedSet<String> allowedClasses = new OrderedSet<String>();
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("static.import.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"static.import.problem.descriptor");
}
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
return new StaticImportFix();
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new StaticImportVisitor();
}
private static class StaticImportFix extends InspectionGadgetsFix {
@Override
@NotNull
public String getName() {
return InspectionGadgetsBundle.message("static.import.replace.quickfix");
}
@Override
@NotNull
public String getFamilyName() {
return getName();
}
@Override
public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
final PsiImportStaticStatement importStatement = (PsiImportStaticStatement)descriptor.getPsiElement();
final PsiJavaCodeReferenceElement importReference = importStatement.getImportReference();
if (importReference == null) {
return;
}
final JavaResolveResult[] importTargets = importReference.multiResolve(false);
if (importTargets.length == 0) {
return;
}
final boolean onDemand = importStatement.isOnDemand();
final StaticImportFix.StaticImportReferenceCollector
referenceCollector = new StaticImportFix.StaticImportReferenceCollector(importTargets, onDemand);
final PsiJavaFile file = (PsiJavaFile)importStatement.getContainingFile();
file.accept(referenceCollector);
final List<PsiJavaCodeReferenceElement> references = referenceCollector.getReferences();
final Map<PsiJavaCodeReferenceElement, PsiMember> referenceTargetMap = new HashMap<PsiJavaCodeReferenceElement, PsiMember>();
for (PsiJavaCodeReferenceElement reference : references) {
final PsiElement target = reference.resolve();
if (target instanceof PsiMember) {
final PsiMember member = (PsiMember)target;
referenceTargetMap.put(reference, member);
}
}
importStatement.delete();
for (Map.Entry<PsiJavaCodeReferenceElement, PsiMember> entry : referenceTargetMap.entrySet()) {
removeReference(entry.getKey(), entry.getValue());
}
}
private static void removeReference(PsiJavaCodeReferenceElement reference, PsiMember target) {
final PsiManager manager = reference.getManager();
final Project project = manager.getProject();
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
final PsiElementFactory factory = psiFacade.getElementFactory();
final PsiClass aClass = target.getContainingClass();
if (aClass == null) {
return;
}
final String qualifiedName = aClass.getQualifiedName();
final String text = reference.getText();
final String referenceText = qualifiedName + '.' + text;
if (reference instanceof PsiReferenceExpression) {
final PsiExpression newReference = factory.createExpressionFromText(referenceText, reference);
final PsiElement insertedElement = reference.replace(newReference);
JavaCodeStyleManager.getInstance(project).shortenClassReferences(insertedElement);
}
else {
final PsiJavaCodeReferenceElement referenceElement =
factory.createReferenceElementByFQClassName(referenceText, reference.getResolveScope());
final PsiElement insertedElement = reference.replace(referenceElement);
JavaCodeStyleManager.getInstance(project).shortenClassReferences(insertedElement);
}
}
static class StaticImportReferenceCollector extends JavaRecursiveElementVisitor {
private final JavaResolveResult[] importTargets;
private final boolean onDemand;
private final List<PsiJavaCodeReferenceElement> references = new ArrayList<PsiJavaCodeReferenceElement>();
StaticImportReferenceCollector(@NotNull JavaResolveResult[] importTargets, boolean onDemand) {
this.importTargets = importTargets;
this.onDemand = onDemand;
}
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
if (isFullyQualifiedReference(reference)) {
return;
}
PsiElement parent = reference.getParent();
if (parent instanceof PsiImportStatementBase) {
return;
}
while (parent instanceof PsiJavaCodeReferenceElement) {
parent = parent.getParent();
if (parent instanceof PsiImportStatementBase) {
return;
}
}
checkStaticImportReference(reference);
}
private void checkStaticImportReference(PsiJavaCodeReferenceElement reference) {
if (reference.isQualified()) {
return;
}
final PsiElement target = reference.resolve();
if (!(target instanceof PsiMethod) && !(target instanceof PsiClass) && !(target instanceof PsiField)) {
return;
}
final PsiMember member = (PsiMember)target;
for (JavaResolveResult importTarget : importTargets) {
final PsiElement targetElement = importTarget.getElement();
if (targetElement instanceof PsiMethod || targetElement instanceof PsiField) {
if (member.equals(targetElement)) {
addReference(reference);
}
}
else if (targetElement instanceof PsiClass) {
if (onDemand) {
final PsiClass containingClass = member.getContainingClass();
if (InheritanceUtil.isInheritorOrSelf((PsiClass)targetElement, containingClass, true)) {
addReference(reference);
}
}
else {
if (targetElement.equals(member)) {
addReference(reference);
}
}
}
}
}
private void addReference(PsiJavaCodeReferenceElement reference) {
references.add(reference);
}
public List<PsiJavaCodeReferenceElement> getReferences() {
return references;
}
public static boolean isFullyQualifiedReference(PsiJavaCodeReferenceElement reference) {
if (!reference.isQualified()) {
return false;
}
final PsiElement directParent = reference.getParent();
if (directParent instanceof PsiMethodCallExpression ||
directParent instanceof PsiAssignmentExpression ||
directParent instanceof PsiVariable) {
return false;
}
final PsiElement parent =
PsiTreeUtil.getParentOfType(reference, PsiImportStatementBase.class, PsiPackageStatement.class, JavaCodeFragment.class);
if (parent != null) {
return false;
}
final PsiElement target = reference.resolve();
if (!(target instanceof PsiClass)) {
return false;
}
final PsiClass aClass = (PsiClass)target;
final String fqName = aClass.getQualifiedName();
if (fqName == null) {
return false;
}
final String text =
StringUtils.stripAngleBrackets(reference.getText());
return text.equals(fqName);
}
}
}
private class StaticImportVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
final PsiElement parent = aClass.getParent();
if (!(parent instanceof PsiJavaFile)) {
return;
}
final PsiJavaFile file = (PsiJavaFile)parent;
if (FileTypeUtils.isInServerPageFile(file)) {
return;
}
if (!file.getClasses()[0].equals(aClass)) {
return;
}
final PsiImportList importList = file.getImportList();
if (importList == null) {
return;
}
if (ignoreInTestCode && TestUtils.isTest(aClass)) {
return;
}
final PsiImportStaticStatement[] importStatements = importList.getImportStaticStatements();
for (PsiImportStaticStatement importStatement : importStatements) {
if (shouldReportImportStatement(importStatement)) {
registerError(importStatement);
}
}
}
private boolean shouldReportImportStatement(PsiImportStaticStatement importStatement) {
final PsiJavaCodeReferenceElement importReference = importStatement.getImportReference();
if (importReference == null) {
return false;
}
PsiClass targetClass = importStatement.resolveTargetClass();
boolean checked = false;
while (targetClass != null) {
final String qualifiedName = targetClass.getQualifiedName();
if (allowedClasses.contains(qualifiedName)) {
return false;
}
if (checked) {
break;
}
targetClass = targetClass.getContainingClass();
checked = true;
}
if (importStatement.isOnDemand()) {
return true;
}
if (ignoreSingleFieldImports || ignoreSingeMethodImports) {
boolean field = false;
boolean method = false;
// in the presence of method overloading the plain resolve() method returns null
final JavaResolveResult[] results = importReference.multiResolve(false);
for (JavaResolveResult result : results) {
final PsiElement element = result.getElement();
if (element instanceof PsiField) {
field = true;
} else if (element instanceof PsiMethod) {
method = true;
}
}
if (field && !method) {
if (ignoreSingleFieldImports) {
return false;
}
}
else if (method && !field) {
if (ignoreSingeMethodImports) {
return false;
}
}
}
return true;
}
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2000-2013 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.inheritance;
import com.intellij.psi.PsiAnonymousClass;
import com.intellij.psi.PsiClass;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.CollectionUtils;
import org.jetbrains.annotations.NotNull;
public class ExtendsConcreteCollectionInspectionBase extends BaseInspection {
@Override
@NotNull
public String getID() {
return "ClassExtendsConcreteCollection";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"extends.concrete.collection.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
final PsiClass superClass = (PsiClass)infos[0];
final PsiClass aClass = (PsiClass)infos[1];
if (aClass instanceof PsiAnonymousClass) {
return InspectionGadgetsBundle.message("anonymous.extends.concrete.collection.problem.descriptor", superClass.getQualifiedName());
} else {
return InspectionGadgetsBundle.message("extends.concrete.collection.problem.descriptor", superClass.getQualifiedName());
}
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ExtendsConcreteCollectionVisitor();
}
private static class ExtendsConcreteCollectionVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
if (aClass.isInterface() || aClass.isAnnotationType() || aClass.isEnum()) {
return;
}
final PsiClass superClass = aClass.getSuperClass();
if (superClass == null) {
return;
}
if (!CollectionUtils.isCollectionClass(superClass)) {
return;
}
registerClassError(aClass, superClass, aClass);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -23,31 +23,28 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.GuiUtils;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.intellij.util.ui.UIUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
/**
* User: cdr
*/
class StaticInheritanceFix extends InspectionGadgetsFix {
private static final Logger LOG = Logger.getInstance("#com.siyeh.ig.inheritance.StaticInheritanceFix");
private final boolean myReplaceInWholeProject;
StaticInheritanceFix(boolean replaceInWholeProject) {
@@ -101,13 +98,20 @@ class StaticInheritanceFix extends InspectionGadgetsFix {
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)reference;
if (!myReplaceInWholeProject) {
PsiClass aClass = PsiTreeUtil.getParentOfType(referenceExpression, PsiClass.class);
boolean isInheritor = false;
while (aClass != null) {
isInheritor = InheritanceUtil.isInheritorOrSelf(aClass, implementingClass, true);
if (isInheritor) break;
aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class);
}
boolean isInheritor =
ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
boolean isInheritor = false;
PsiClass aClass = PsiTreeUtil.getParentOfType(referenceExpression, PsiClass.class);
while (aClass != null) {
isInheritor = InheritanceUtil.isInheritorOrSelf(aClass, implementingClass, true);
if (isInheritor) break;
aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class);
}
return isInheritor;
}
});
if (!isInheritor) continue;
}
final Runnable runnable = new Runnable() {
@@ -144,24 +148,16 @@ class StaticInheritanceFix extends InspectionGadgetsFix {
}
private static void invokeWriteAction(final Runnable runnable, final PsiFile file) {
try {
GuiUtils.runOrInvokeAndWait(new Runnable() {
@Override
public void run() {
new WriteCommandAction(file.getProject(), file) {
@Override
protected void run(Result result) throws Throwable {
runnable.run();
}
}.execute();
}
});
}
catch (InvocationTargetException e) {
LOG.error(e);
}
catch (InterruptedException e) {
LOG.error(e);
}
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
new WriteCommandAction(file.getProject(), file) {
@Override
protected void run(Result result) throws Throwable {
runnable.run();
}
}.execute();
}
});
}
}

Some files were not shown because too many files have changed in this diff Show More