Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2015-01-14 12:51:28 +01:00
23 changed files with 378 additions and 266 deletions
@@ -17,6 +17,7 @@ package com.intellij.core;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -83,7 +84,7 @@ public class CoreJavaFileManager implements JavaFileManager {
@Override
public PsiClass findClass(@NotNull String qName, @NotNull GlobalSearchScope scope) {
for (VirtualFile root : roots()) {
final PsiClass psiClass = findClassInClasspathRoot(qName, root, myPsiManager);
final PsiClass psiClass = findClassInClasspathRoot(qName, root, myPsiManager, scope);
if (psiClass != null) {
return psiClass;
}
@@ -92,7 +93,10 @@ public class CoreJavaFileManager implements JavaFileManager {
}
@Nullable
public static PsiClass findClassInClasspathRoot(String qName, VirtualFile root, PsiManager psiManager) {
public static PsiClass findClassInClasspathRoot(@NotNull String qName,
@NotNull VirtualFile root,
@NotNull PsiManager psiManager,
@NotNull GlobalSearchScope scope) {
String pathRest = qName;
VirtualFile cur = root;
@@ -108,77 +112,73 @@ public class CoreJavaFileManager implements JavaFileManager {
cur = child;
}
String className = pathRest.replace('.', '$');
int bucks = className.indexOf('$');
String classNameWithInnerClasses = pathRest;
String topLevelClassName = substringBeforeFirstDot(classNameWithInnerClasses);
String rootClassName;
if (bucks < 0) {
rootClassName = className;
VirtualFile vFile = cur.findChild(topLevelClassName + ".class");
if (vFile == null) vFile = cur.findChild(topLevelClassName + ".java");
if (vFile == null) {
return null;
}
if (!vFile.isValid()) {
LOG.error("Invalid child of valid parent: " + vFile.getPath() + "; " + root.isValid() + " path=" + root.getPath());
return null;
}
if (!scope.contains(vFile)) {
return null;
}
final PsiFile file = psiManager.findFile(vFile);
if (!(file instanceof PsiClassOwner)) {
return null;
}
return findClassInPsiFile(classNameWithInnerClasses, (PsiClassOwner)file);
}
@NotNull
private static String substringBeforeFirstDot(@NotNull String classNameWithInnerClasses) {
int dot = classNameWithInnerClasses.indexOf('.');
if (dot < 0) {
return classNameWithInnerClasses;
}
else {
rootClassName = className.substring(0, bucks);
className = className.substring(bucks + 1);
return classNameWithInnerClasses.substring(0, dot);
}
}
@Nullable
private static PsiClass findClassInPsiFile(@NotNull String classNameWithInnerClassesDotSeparated, @NotNull PsiClassOwner file) {
for (PsiClass topLevelClass : file.getClasses()) {
PsiClass candidate = findClassByTopLevelClass(classNameWithInnerClassesDotSeparated, topLevelClass);
if (candidate != null) {
return candidate;
}
}
return null;
}
@Nullable
private static PsiClass findClassByTopLevelClass(@NotNull String className, @NotNull PsiClass topLevelClass) {
if (className.indexOf('.') < 0) {
return className.equals(topLevelClass.getName()) ? topLevelClass : null;
}
VirtualFile vFile = cur.findChild(rootClassName + ".class");
if (vFile == null) vFile = cur.findChild(rootClassName + ".java");
if (vFile != null) {
if (!vFile.isValid()) {
LOG.error("Invalid child of valid parent: " + vFile.getPath() + "; " + root.isValid() + " path=" + root.getPath());
Iterator<String> segments = StringUtil.split(className, ".").iterator();
if (!segments.hasNext() || !segments.next().equals(topLevelClass.getName())) {
return null;
}
PsiClass curClass = topLevelClass;
while (segments.hasNext()) {
String innerClassName = segments.next();
PsiClass innerClass = curClass.findInnerClassByName(innerClassName, false);
if (innerClass == null) {
return null;
}
final PsiFile file = psiManager.findFile(vFile);
if (file instanceof PsiClassOwner) {
final PsiClass[] classes = ((PsiClassOwner)file).getClasses();
if (classes.length == 1) {
PsiClass curClass = classes[0];
if (bucks > 0) {
Stack<ClassAndOffsets> currentPath = new Stack<ClassAndOffsets>();
currentPath.add(new ClassAndOffsets(curClass, 0, 0));
currentPath.add(currentPath.peek());
while (currentPath.size() > 1) {
ClassAndOffsets classAndOffset = currentPath.pop();
int newComponentStart = classAndOffset.componentStart;
int lookupStart = classAndOffset.lookupStart;
curClass = currentPath.peek().clazz; //owner class
while (lookupStart <= className.length()) {
int bucksIndex = className.indexOf("$", lookupStart);
bucksIndex = bucksIndex < 0 ? className.length(): bucksIndex;
String component = className.substring(newComponentStart, bucksIndex);
PsiClass inner = curClass.findInnerClassByName(component, false);
lookupStart = bucksIndex + 1;
if (inner == null) {
continue;
}
currentPath.add(new ClassAndOffsets(inner, newComponentStart, lookupStart));
newComponentStart = lookupStart;
curClass = inner;
}
if (lookupStart == newComponentStart) {
return curClass;
}
}
return null;
} else {
return curClass;
}
}
}
}
return null;
curClass = innerClass;
}
return curClass;
}
@NotNull
@@ -186,7 +186,7 @@ public class CoreJavaFileManager implements JavaFileManager {
public PsiClass[] findClasses(@NotNull String qName, @NotNull GlobalSearchScope scope) {
List<PsiClass> result = new ArrayList<PsiClass>();
for (VirtualFile file : roots()) {
final PsiClass psiClass = findClassInClasspathRoot(qName, file, myPsiManager);
final PsiClass psiClass = findClassInClasspathRoot(qName, file, myPsiManager, scope);
if (psiClass != null) {
result.add(psiClass);
}
@@ -203,17 +203,4 @@ public class CoreJavaFileManager implements JavaFileManager {
public void addToClasspath(VirtualFile root) {
myClasspath.add(root);
}
private static class ClassAndOffsets {
final PsiClass clazz;
final int componentStart;
final int lookupStart;
ClassAndOffsets(PsiClass clazz, int componentStart, int lookupStart) {
this.clazz = clazz;
this.componentStart = componentStart;
this.lookupStart = lookupStart;
}
}
}
@@ -21,143 +21,186 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.PsiTestCase;
import com.intellij.testFramework.PsiTestUtil;
import java.util.LinkedList;
import java.util.Queue;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
public class CoreJavaFileManagerTest extends PsiTestCase {
private VirtualFile prepareClasses(String clazzName, String clazzData) throws Exception {
public void testCommon() throws Exception {
CoreJavaFileManager manager = configureManager("package foo;\n\n" +
"public class TopLevel {\n" +
"public class Inner {\n" +
" public class Inner {}\n" +
"}\n" +
"\n" +
"}", "TopLevel");
assertCanFind(manager, "foo.TopLevel");
assertCanFind(manager, "foo.TopLevel.Inner");
assertCanFind(manager, "foo.TopLevel.Inner.Inner");
assertCannotFind(manager, "foo.TopLevel$Inner.Inner");
assertCannotFind(manager, "foo.TopLevel.Inner$Inner");
assertCannotFind(manager, "foo.TopLevel.Inner.Inner.Inner");
}
public void testInnerClassesWithDollars() throws Exception {
CoreJavaFileManager manager = configureManager("package foo;\n\n" +
"public class TopLevel {\n" +
"public class I$nner {" +
" public class I$nner{}" +
" public class $Inner{}" +
" public class In$ne$r${}" +
" public class Inner$${}" +
" public class $$$$${}" +
"}\n" +
"public class Inner$ {" +
" public class I$nner{}" +
" public class $Inner{}" +
" public class In$ne$r${}" +
" public class Inner$${}" +
" public class $$$$${}" +
"}\n" +
"public class In$ner$$ {" +
" public class I$nner{}" +
" public class $Inner{}" +
" public class In$ne$r${}" +
" public class Inner$${}" +
" public class $$$$${}" +
"}\n" +
"\n" +
"}", "TopLevel");
assertCanFind(manager, "foo.TopLevel");
assertCanFind(manager, "foo.TopLevel.I$nner");
assertCanFind(manager, "foo.TopLevel.I$nner.I$nner");
assertCanFind(manager, "foo.TopLevel.I$nner.$Inner");
assertCanFind(manager, "foo.TopLevel.I$nner.In$ne$r$");
assertCanFind(manager, "foo.TopLevel.I$nner.Inner$$");
assertCanFind(manager, "foo.TopLevel.I$nner.$$$$$");
assertCannotFind(manager, "foo.TopLevel.I.nner.$$$$$");
assertCanFind(manager, "foo.TopLevel.Inner$");
assertCanFind(manager, "foo.TopLevel.Inner$.I$nner");
assertCanFind(manager, "foo.TopLevel.Inner$.$Inner");
assertCanFind(manager, "foo.TopLevel.Inner$.In$ne$r$");
assertCanFind(manager, "foo.TopLevel.Inner$.Inner$$");
assertCanFind(manager, "foo.TopLevel.Inner$.$$$$$");
assertCannotFind(manager, "foo.TopLevel.Inner..$$$$$");
assertCanFind(manager, "foo.TopLevel.In$ner$$");
assertCanFind(manager, "foo.TopLevel.In$ner$$.I$nner");
assertCanFind(manager, "foo.TopLevel.In$ner$$.$Inner");
assertCanFind(manager, "foo.TopLevel.In$ner$$.In$ne$r$");
assertCanFind(manager, "foo.TopLevel.In$ner$$.Inner$$");
assertCanFind(manager, "foo.TopLevel.In$ner$$.$$$$$");
assertCannotFind(manager, "foo.TopLevel.In.ner$$.$$$$$");
}
public void testTopLevelClassesWithDollars() throws Exception {
CoreJavaFileManager inTheMiddle = configureManager("package foo;\n\n public class Top$Level {}", "Top$Level");
assertCanFind(inTheMiddle, "foo.Top$Level");
CoreJavaFileManager doubleAtTheEnd = configureManager("package foo;\n\n public class TopLevel$$ {}", "TopLevel$$");
assertCanFind(doubleAtTheEnd, "foo.TopLevel$$");
CoreJavaFileManager multiple = configureManager("package foo;\n\n public class Top$Lev$el$ {}", "Top$Lev$el$");
assertCanFind(multiple, "foo.Top$Lev$el$");
assertCannotFind(multiple, "foo.Top.Lev$el$");
CoreJavaFileManager twoBucks = configureManager("package foo;\n\n public class $$ {}", "$$");
assertCanFind(twoBucks, "foo.$$");
}
public void testTopLevelClassWithDollarsAndInners() throws Exception {
CoreJavaFileManager manager = configureManager("package foo;\n\n" +
"public class Top$Level$$ {\n" +
"public class I$nner {" +
" public class I$nner{}" +
" public class In$ne$r${}" +
" public class Inner$$$$${}" +
" public class $Inner{}" +
" public class ${}" +
" public class $$$$${}" +
"}\n" +
"public class Inner {" +
" public class Inner{}" +
"}\n" +
"\n" +
"}", "Top$Level$$");
assertCanFind(manager, "foo.Top$Level$$");
assertCanFind(manager, "foo.Top$Level$$.Inner");
assertCanFind(manager, "foo.Top$Level$$.Inner.Inner");
assertCanFind(manager, "foo.Top$Level$$.I$nner");
assertCanFind(manager, "foo.Top$Level$$.I$nner.I$nner");
assertCanFind(manager, "foo.Top$Level$$.I$nner.In$ne$r$");
assertCanFind(manager, "foo.Top$Level$$.I$nner.Inner$$$$$");
assertCanFind(manager, "foo.Top$Level$$.I$nner.$Inner");
assertCanFind(manager, "foo.Top$Level$$.I$nner.$");
assertCanFind(manager, "foo.Top$Level$$.I$nner.$$$$$");
assertCannotFind(manager, "foo.Top.Level$$.I$nner.$$$$$");
}
public void testDoNotThrowOnMalformedInput() throws Exception {
CoreJavaFileManager fileWithEmptyName = configureManager("package foo;\n\n public class Top$Level {}", "");
assertCannotFind(fileWithEmptyName, "foo.");
assertCannotFind(fileWithEmptyName, ".");
assertCannotFind(fileWithEmptyName, "..");
assertCannotFind(fileWithEmptyName, "");
assertCannotFind(fileWithEmptyName, ".foo");
}
public void testSeveralClassesInOneFile() throws Exception {
CoreJavaFileManager manager = configureManager("package foo;\n\n" +
"public class One {}\n" +
"class Two {}\n" +
"class Three {}", "One");
assertCanFind(manager, "foo.One");
//NOTE: this is unsupported
assertCannotFind(manager, "foo.Two");
assertCannotFind(manager, "foo.Three");
}
public void testScopeCheck() throws Exception {
CoreJavaFileManager manager = configureManager("package foo;\n\n" + "public class Test {}\n", "Test");
assertNotNull("Should find class in all scope", manager.findClass("foo.Test", GlobalSearchScope.allScope(getProject())));
assertNull("Should not find class in empty scope", manager.findClass("foo.Test", GlobalSearchScope.EMPTY_SCOPE));
}
@NotNull
private CoreJavaFileManager configureManager(@Language("JAVA") @NotNull String text, @NotNull String className) throws Exception {
VirtualFile root = PsiTestUtil.createTestProjectStructure(myProject, myModule, myFilesToDelete);
VirtualFile pkg = root.createChildDirectory(this, "foo");
PsiDirectory dir = myPsiManager.findDirectory(pkg);
assertNotNull(dir);
dir.add(PsiFileFactory.getInstance(getProject()).createFileFromText(clazzName + ".java", JavaFileType.INSTANCE, clazzData));
return root;
}
public void testNotNullInnerClass() throws Exception {
String text = "package foo;\n\n" +
"public class Nested {\n" +
"public class InnerGeneral {}\n" +
"public class Inner$ {" +
"}\n" +
"\n" +
"public Inner$ inner() {\n" +
" return new Inner$();\n" +
"}\n" +
"\n" +
"}";
VirtualFile root = prepareClasses("Nested", text);
GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
dir.add(PsiFileFactory.getInstance(getProject()).createFileFromText(className + ".java", JavaFileType.INSTANCE, text));
CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager);
manager.addToClasspath(root);
PsiClass clazz = manager.findClass("foo.Nested", scope);
assertNotNull(clazz);
PsiClass clazzInnerGeneral = manager.findClass("foo.Nested.InnerGeneral", scope);
assertNotNull(clazzInnerGeneral);
PsiClass clazzInner$ = manager.findClass("foo.Nested.Inner$", scope);
assertNotNull(clazzInner$);
PsiClass clazzInner$Wrong1 = manager.findClass("foo.Nested.Inner$X", scope);
assertNull(clazzInner$Wrong1);
PsiClass clazzInner$Wrong2 = manager.findClass("foo.Nested.Inner$$X", scope);
assertNull(clazzInner$Wrong2);
PsiClass clazzInner$Wrong3 = manager.findClass("foo.Nested.Inner$$", scope);
assertNull(clazzInner$Wrong3);
return manager;
}
public void testNotNullInnerClass2() throws Exception {
String text = "package foo;\n\n" +
"public class Nested {\n" +
"public class Inner {" +
" public class XInner{}" +
" public class XInner${}" +
"}\n" +
"public class Inner$ {" +
" public class XInner{}" +
" public class XInner${}" +
"}\n" +
"\n" +
"}";
VirtualFile root = prepareClasses("Nested", text);
GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager);
manager.addToClasspath(root);
PsiClass clazzInner = manager.findClass("foo.Nested.Inner", scope);
assertNotNull(clazzInner);
PsiClass clazzXInner = manager.findClass("foo.Nested.Inner.XInner", scope);
assertNotNull(clazzXInner);
PsiClass clazzXInner$ = manager.findClass("foo.Nested.Inner.XInner$", scope);
assertNotNull(clazzXInner$);
PsiClass clazz$XInner = manager.findClass("foo.Nested.Inner$.XInner", scope);
assertNotNull(clazz$XInner);
PsiClass clazz$XInner$ = manager.findClass("foo.Nested.Inner$.XInner$", scope);
assertNotNull(clazz$XInner$);
private void assertCanFind(@NotNull CoreJavaFileManager manager, @NotNull String qName) {
PsiClass foundClass = manager.findClass(qName, GlobalSearchScope.allScope(getProject()));
assertNotNull("Could not find:" + qName, foundClass);
assertEquals("Found " + foundClass.getQualifiedName() + " instead of " + qName, qName, foundClass.getQualifiedName());
}
public void testNotNullInnerClass3() throws Exception {
String text = "package foo;\n\n" +
"public class NestedX {\n" +
"public class XX {" +
" public class XXX{" +
" public class XXXX{ }" +
" public class XXXX${ }" +
" }" +
" public class XXX${" +
" public class XXXX{ }" +
" public class XXXX${ }" +
" }" +
"}\n" +
"public class XX$ {" +
" public class XXX{" +
" public class XXXX{ }" +
" public class XXXX${ }" +
" }" +
" public class XXX${" +
" public class XXXX{ }" +
" public class XXXX${ }" +
" }" +
"}\n" +
"\n" +
"}";
VirtualFile root = prepareClasses("NestedX", text);
GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager);
manager.addToClasspath(root);
Queue<String> queue = new LinkedList<String>();
queue.add("foo.NestedX");
while(!queue.isEmpty()) {
String head = queue.remove();
PsiClass clazzInner = manager.findClass(head, scope);
assertNotNull(head, clazzInner);
String lastSegment = head.substring(head.lastIndexOf('.'));
String xs = lastSegment.substring(lastSegment.indexOf("X")).replace("$", "");
if (xs.length() < 4) {
queue.add(head + "." + xs + "X");
queue.add(head + "." + xs + "X$");
}
}
private void assertCannotFind(@NotNull CoreJavaFileManager manager, @NotNull String qName) {
PsiClass foundClass = manager.findClass(qName, GlobalSearchScope.allScope(getProject()));
assertNull("Found, but shouldn't have:" + qName, foundClass);
}
}
@@ -22,7 +22,7 @@
</constraints>
<properties>
<selected value="true"/>
<text value="Unlock files"/>
<text value="I want to edit these files anyway"/>
</properties>
</component>
<component id="592c9" class="javax.swing.JRadioButton" binding="myUnlockAllButton" default-binding="true">
@@ -30,7 +30,7 @@
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Unlock all non-project files in current session"/>
<text value="I want to edit any non-project file in the current session"/>
</properties>
</component>
</children>
@@ -38,9 +38,13 @@ public class NonProjectFileWritingAccessDialog extends DialogWrapper {
myFileList.setCellRenderer(new FileListRenderer());
myFileList.setModel(new CollectionListModel<VirtualFile>(nonProjectFiles));
getOKAction().putValue(DEFAULT_ACTION, null);
getCancelAction().putValue(DEFAULT_ACTION, true);
init();
}
@Nullable
@Override
protected JComponent createCenterPanel() {
@@ -54,6 +58,6 @@ public class NonProjectFileWritingAccessDialog extends DialogWrapper {
}
protected String getHelpId() {
return "readOnlyHandler.nonProjectFilesDialog";
return "Non-Project_Files_Access_Dialog";
}
}
@@ -2135,7 +2135,8 @@ utility.class.code.can.be.enum.quickfix=Convert to 'enum'
non.public.clone.display.name='clone()' method not 'public'
non.public.clone.problem.descriptor=<code>#ref()</code> method not 'public' #loc
only.warn.on.public.clone.methods=Only warn on 'public' clone methods
only.warn.on.protected.clone.methods=Only warn on 'protected' clone methods
clone.returns.class.type.display.name='clone()' should have return type equal to the class it contains
clone.returns.class.type.problem.descriptor=''clone()'' should have return type ''{0}'' #loc
clone.returns.class.type.quickfix=Change return type to '{0}'
clone.returns.class.type.quickfix=Change return type to ''{0}''
clone.returns.class.type.family.quickfix=Change return type to class type
@@ -1,5 +1,5 @@
/*
* Copyright 2006-2014 Bas Leijdekkers
* Copyright 2006-2015 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package com.siyeh.ig.abstraction;
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -294,7 +295,7 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
@Override
public void visitMethod(PsiMethod method) {
super.visitMethod(method);
if (isOnTheFly() && !method.hasModifierProperty(PsiModifier.PRIVATE)) {
if (isOnTheFly() && !method.hasModifierProperty(PsiModifier.PRIVATE) && !ApplicationManager.getApplication().isUnitTestMode()) {
// checking methods with greater visibility is too expensive.
// for error checking in the editor
return;
@@ -39,7 +39,7 @@ import javax.swing.*;
public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection {
private boolean onlyWarnOnPublicClone = true;
private boolean onlyWarnOnProtectedClone = true;
@Override
@NotNull
@@ -67,16 +67,16 @@ public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection {
@Nullable
@Override
public JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("only.warn.on.public.clone.methods"),
this, "onlyWarnOnPublicClone");
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("only.warn.on.protected.clone.methods"),
this, "onlyWarnOnProtectedClone");
}
@Override
public void readSettings(@NotNull Element node) throws InvalidDataException {
super.readSettings(node);
for (Element option : node.getChildren("option")) {
if ("onlyWarnOnPublicClone".equals(option.getAttributeValue("name"))) {
onlyWarnOnPublicClone = Boolean.parseBoolean(option.getAttributeValue("value"));
if ("onlyWarnOnProtectedClone".equals(option.getAttributeValue("name"))) {
onlyWarnOnProtectedClone = Boolean.parseBoolean(option.getAttributeValue("value"));
}
}
}
@@ -84,9 +84,9 @@ public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection {
@Override
public void writeSettings(@NotNull Element node) throws WriteExternalException {
super.writeSettings(node);
if (!onlyWarnOnPublicClone) {
node.addContent(new Element("option").setAttribute("name", "onlyWarnOnPublicClone")
.setAttribute("value", String.valueOf(onlyWarnOnPublicClone)));
if (!onlyWarnOnProtectedClone) {
node.addContent(new Element("option").setAttribute("name", "onlyWarnOnProtectedClone")
.setAttribute("value", String.valueOf(onlyWarnOnProtectedClone)));
}
}
@@ -131,7 +131,7 @@ public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection {
if (method.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
if (onlyWarnOnPublicClone && !method.hasModifierProperty(PsiModifier.PUBLIC)) {
if (onlyWarnOnProtectedClone && method.hasModifierProperty(PsiModifier.PUBLIC)) {
return;
}
final PsiClass containingClass = method.getContainingClass();
@@ -1,5 +1,5 @@
/*
* Copyright 2006-2013 Dave Griffith, Bas Leijdekkers
* Copyright 2006-2015 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ public class CyclicClassDependencyInspection extends BaseGlobalInspection {
}
final RefClass refClass = (RefClass)refEntity;
final PsiClass aClass = refClass.getElement();
if (aClass == null || aClass.getContainingClass() != null) {
if (aClass == null || aClass.getContainingClass() != null || aClass instanceof PsiAnonymousClass) {
return null;
}
final Set<RefClass> dependencies = DependencyUtils.calculateTransitiveDependenciesForClass(refClass);
@@ -79,15 +79,8 @@ public class CyclicClassDependencyInspection extends BaseGlobalInspection {
errorString = InspectionGadgetsBundle.message("cyclic.class.dependency.problem.descriptor",
refEntity.getName(), Integer.valueOf(numMutualDependents));
}
final PsiElement anchor;
if (aClass instanceof PsiAnonymousClass) {
final PsiAnonymousClass anonymousClass = (PsiAnonymousClass)aClass;
anchor = anonymousClass.getBaseClassReference();
}
else {
anchor = aClass.getNameIdentifier();
if (anchor == null) return null;
}
final PsiElement anchor = aClass.getNameIdentifier();
if (anchor == null) return null;
return new CommonProblemDescriptor[]{
inspectionManager.createProblemDescriptor(anchor, errorString, (LocalQuickFix)null,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)
@@ -1,5 +1,5 @@
/*
* Copyright 2008-2014 Bas Leijdekkers
* Copyright 2008-2015 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -155,11 +155,17 @@ public class WeakestTypeFinder {
checkClass(javaLangIterableClass, weakestTypeClasses);
}
else if (referenceParent instanceof PsiReturnStatement) {
final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(referenceParent, PsiMethod.class);
if (containingMethod == null) {
final PsiElement owner = PsiTreeUtil.getParentOfType(referenceParent, PsiMethod.class, PsiLambdaExpression.class);
final PsiType type;
if (owner instanceof PsiMethod) {
type = ((PsiMethod)owner).getReturnType();
}
else if (owner instanceof PsiLambdaExpression) {
type = LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)owner);
}
else {
return Collections.emptyList();
}
final PsiType type = containingMethod.getReturnType();
if (!checkType(type, weakestTypeClasses)) {
return Collections.emptyList();
}
@@ -8,9 +8,9 @@ prohibit cloning will not be able to do so in the standard way. This inspection
or <b>clone()</b> methods on <b>final</b> classes.
<!-- tooltip end -->
<p>
Use the checkbox below to indicate if this inspection should only warn on <b>public</b> methods.
Use the checkbox below to indicate if this inspection should only warn on <b>protected</b> methods.
In <i>Effective Java, Second Edition</i> (but not in the first edition) it is recommended to omit the <b>CloneNotSupportedException</b>
declaration, because methods that don't throw checked exceptions are easier to use.
declaration on <b>public</b> methods, because methods that don't throw checked exceptions are easier to use.
<p>
</body>
@@ -0,0 +1,23 @@
package com.siyeh.igtest.abstraction.weaken_type;
import java.util.function.Supplier;
public interface Lambda {
int count();
static Lambda newWeaken(int value) {
return new Lambda() {
@Override
public int count() {
return value;
}
};
}
static Supplier<Lambda> newSupplier() {
return () -> {
return Lambda.newWeaken(0);
};
}
}
@@ -8,7 +8,7 @@ public class CloneDeclaresCloneNonSupportedException implements Cloneable
}
public Object clone()
protected Object <warning descr="'clone()' does not declare 'CloneNotSupportedException'">clone</warning>()
{
try
{
@@ -34,3 +34,13 @@ class Child extends CloneDeclaresCloneNonSupportedException {
return super.clone();
}
}
class NoWarnOnPublic implements Cloneable {
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
}
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>CloneDeclaresCloneNonSupportedException.java</file>
<line>11</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'clone()' does not declare 'CloneNotSupportedException'</problem_class>
<description>&lt;code&gt;clone()&lt;/code&gt; does not declare 'CloneNotSupportedException'</description>
</problem>
</problems>
@@ -1,12 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>Cyclic.java</file>
<line>9</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
<description>Class 'anonymous (java.lang.Object)' is cyclically dependent on 3 other classes</description>
</problem>
<problem>
<file>Cyclic.java</file>
<line>17</line>
@@ -27,3 +27,18 @@ interface FiveOClock {
}
interface Coffee extends FiveOClock {}
enum MyEnum {
ONE {
public int value() {
return 0;
}
},
TWO {
public int value() {
return ONE.value();
}
};
abstract int value();
}
@@ -9,6 +9,7 @@ public class TypeMayBeWeakenedInspectionTest extends LightInspectionTestCase {
public void testTypeMayBeWeakened() { doTest(); }
public void testNumberAdderDemo() { doTest(); }
public void testAutoClosableTest() { doTest(); }
public void testLambda() { doTest(); }
@Override
protected String[] getEnvironmentClasses() {
@@ -33,6 +34,11 @@ public class TypeMayBeWeakenedInspectionTest extends LightInspectionTestCase {
"@FunctionalInterface " +
"public interface Function<T, R> {" +
" R apply(T t);" +
"}",
"package java.util.function;\n" +
"@FunctionalInterface\n" +
"public interface Supplier<T> {\n" +
" T get();\n" +
"}"
};
}
@@ -1,10 +1,18 @@
package com.siyeh.ig.cloneable;
import com.siyeh.ig.IGInspectionTestCase;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.Nullable;
public class CloneDeclaresCloneNotSupportedInspectionTest extends IGInspectionTestCase {
public class CloneDeclaresCloneNotSupportedInspectionTest extends LightInspectionTestCase {
public void test() throws Exception {
doTest("com/siyeh/igtest/cloneable/clone_declares_clone_not_supported", new CloneDeclaresCloneNotSupportedInspection());
public void testCloneDeclaresCloneNonSupportedException() {
doTest();
}
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new CloneDeclaresCloneNotSupportedInspection();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -416,6 +416,7 @@ public class DeadCodeHelper {
if (sameRanges) {
seq.addSequence(next.getSeq());
block.getInstrOldOffsets().addAll(next.getInstrOldOffsets());
next.getSeq().clear();
removeEmptyBlock(graph, next, true);
@@ -16,7 +16,7 @@ public class TestClassLoop {
return;
}
} finally {
System.out.println("1");
System.out.println("1");// 38
}
}
}
@@ -30,7 +30,7 @@ public class TestClassLoop {
System.out.println("1");// 49
break;
} finally {
if(var0) {
if(var0) {// 52
System.out.println("3");// 53
continue;
}
@@ -54,6 +54,9 @@ class 'pkg/TestClassLoop' {
4 10
d 10
f 14
26 18
27 18
2a 18
}
method 'testFinallyContinue ()V' {
@@ -64,6 +67,7 @@ class 'pkg/TestClassLoop' {
e 29
11 29
13 29
26 32
2a 33
2d 33
2f 33
@@ -74,6 +78,8 @@ Lines mapping:
23 <-> 6
29 <-> 11
33 <-> 15
38 <-> 19
45 <-> 25
49 <-> 30
52 <-> 33
53 <-> 34
@@ -22,9 +22,9 @@ public class TestClassSimpleBytecodeMapping {
try {
Integer.parseInt(var1);// 34
} catch (Exception var6) {
System.out.println(var6);
System.out.println(var6);// 36
} finally {
System.out.println("Finally");
System.out.println("Finally");// 38
}
}
@@ -80,6 +80,11 @@ class 'pkg/TestClassSimpleBytecodeMapping' {
method 'test2 (Ljava/lang/String;)V' {
1 22
11 24
15 24
23 26
24 26
27 26
}
method 'run (Ljava/lang/Runnable;)V' {
@@ -114,6 +119,8 @@ Lines mapping:
27 <-> 16
28 <-> 17
34 <-> 23
36 <-> 25
38 <-> 27
44 <-> 44
49 <-> 33
54 <-> 38
@@ -9,7 +9,7 @@ public class TestClassVar {
try {
System.out.println();// 29
} finally {
if(this.field_boolean) {
if(this.field_boolean) {// 32
System.out.println();// 33
}
@@ -46,6 +46,8 @@ class 'pkg/TestClassVar' {
3 7
8 9
b 9
1f 11
20 11
26 12
29 12
}
@@ -73,6 +75,7 @@ class 'pkg/TestClassVar' {
Lines mapping:
26 <-> 8
29 <-> 10
32 <-> 12
33 <-> 13
40 <-> 22
45 <-> 26
@@ -16,6 +16,7 @@ class 'pkg/TestSynchronizedMapping' {
method 'test (I)I' {
3 4
5 5
a 5
}
method 'test2 (Ljava/lang/String;)V' {
@@ -11,7 +11,7 @@ public class TestTryCatchFinally {
;
}
} finally {
System.out.println("finally");
System.out.println("finally");// 34
}
}
@@ -31,9 +31,9 @@ public class TestTryCatchFinally {
int var2 = Integer.parseInt(var1);// 51
return var2;
} catch (Exception var6) {
System.out.println("Error" + var6);
System.out.println("Error" + var6);// 53
} finally {
System.out.println("Finally");
System.out.println("Finally");// 55
}
return -1;
@@ -48,6 +48,9 @@ class 'pkg/TestTryCatchFinally' {
14 8
17 8
19 8
2b 13
2d 13
30 13
}
method 'foo (I)I' {
@@ -63,15 +66,25 @@ class 'pkg/TestTryCatchFinally' {
method 'test (Ljava/lang/String;)I' {
1 30
4 30
10 33
1a 33
23 33
26 33
34 35
35 35
38 35
}
}
Lines mapping:
24 <-> 6
27 <-> 9
34 <-> 14
39 <-> 20
40 <-> 21
41 <-> 22
42 <-> 23
45 <-> 25
51 <-> 31
53 <-> 34
55 <-> 36