Merge remote-tracking branch 'origin/master' into develar/pwd

This commit is contained in:
Vladimir Krivosheev
2016-07-26 11:17:09 +02:00
16 changed files with 115 additions and 60 deletions
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -129,10 +128,10 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
else if (REPLACE_TRIVIAL_FOREACH || !isTrivial(body, statement.getIterationParameter())) {
final List<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>();
fixes.add(new ReplaceWithForeachFix());
fixes.add(new ReplaceWithForeachCallFix("forEach"));
if (extractIfStatement(body) != null) {
//for .stream()
fixes.add(new ReplaceWithForeachOrderedFix());
fixes.add(new ReplaceWithForeachCallFix("forEachOrdered"));
}
holder.registerProblem(iteratedValue, "Can be replaced with foreach call",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
@@ -285,22 +284,12 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
return mapperCall instanceof PsiReferenceExpression && ((PsiReferenceExpression)mapperCall).resolve() == parameter;
}
private static class ReplaceWithForeachFix extends ReplaceWithForeachCallFix {
@Override
protected String getForEachMethodName() {
return "forEach";
}
}
private static class ReplaceWithForeachCallFix implements LocalQuickFix {
private final String myForEachMethodName;
private static class ReplaceWithForeachOrderedFix extends ReplaceWithForeachCallFix {
@Override
protected String getForEachMethodName() {
return "forEachOrdered";
protected ReplaceWithForeachCallFix(String forEachMethodName) {
myForEachMethodName = forEachMethodName;
}
}
private static abstract class ReplaceWithForeachCallFix implements LocalQuickFix {
protected abstract String getForEachMethodName();
@NotNull
@Override
@@ -311,7 +300,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@NotNull
@Override
public String getFamilyName() {
return "Replace with " + getForEachMethodName();
return "Replace with " + myForEachMethodName;
}
@Override
@@ -336,7 +325,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
body = thenBranch;
}
buffer.append(".").append(getForEachMethodName()).append("(");
buffer.append(".").append(myForEachMethodName).append("(");
final String functionalExpressionText = createForEachFunctionalExpressionText(project, body, parameter);
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
@@ -363,7 +363,12 @@ private fun checkSchemes(baseDir: Path, expected: String, ignoreDeleted: Boolean
}
@Tag("scheme")
data class TestScheme(override @field:com.intellij.util.xmlb.annotations.Attribute var name: String = "", @field:com.intellij.util.xmlb.annotations.Attribute var data: String? = null) : ExternalizableScheme {
data class TestScheme(@field:com.intellij.util.xmlb.annotations.Attribute @field:kotlin.jvm.JvmField var name: String = "", @field:com.intellij.util.xmlb.annotations.Attribute var data: String? = null) : ExternalizableScheme {
override fun getName() = name
override fun setName(value: String) {
name = value
}
}
open class TestSchemesProcessor : BaseSchemeProcessor<TestScheme, TestScheme>() {
-1
View File
@@ -24,6 +24,5 @@
</library>
</orderEntry>
<orderEntry type="library" name="CGLIB" level="project" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
</component>
</module>
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.options;
import org.jetbrains.annotations.NotNull;
public interface Scheme {
@NotNull
String getName();
}
@@ -27,7 +27,6 @@ import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.ColorKey;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
@@ -61,26 +61,14 @@ public class LocalQuickFixWrapper extends QuickFixAction {
@Nullable
private QuickFix getWorkingQuickFix(@NotNull QuickFix[] fixes) {
final QuickFix exactResult = getWorkingQuickFix(fixes, true);
return exactResult != null ? exactResult : getWorkingQuickFix(fixes, false);
}
@Nullable
private QuickFix getWorkingQuickFix(@NotNull QuickFix[] fixes, boolean exact) {
for (QuickFix fix : fixes) {
if (!checkFix(exact, myFix, fix)) continue;
if (myFix instanceof IntentionWrapper && fix instanceof IntentionWrapper) {
if (!checkFix(exact, ((IntentionWrapper)myFix).getAction(), ((IntentionWrapper)fix).getAction())) continue;
if (fix.getFamilyName().equals(myFix.getFamilyName())) {
return fix;
}
return fix;
}
return null;
}
private static <T> boolean checkFix(boolean exact, T thisFix, T fix) {
return exact ? thisFix.getClass() == fix.getClass() : thisFix.getClass().isInstance(fix);
}
@Override
protected boolean applyFix(@NotNull RefEntity[] refElements) {
return true;
@@ -25,7 +25,6 @@ import com.intellij.openapi.options.NonLazySchemeProcessor;
import com.intellij.openapi.options.SchemeManager;
import com.intellij.openapi.options.SchemeManagerFactory;
import com.intellij.openapi.project.Project;
import com.intellij.util.ThrowableConvertor;
import gnu.trove.THashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@@ -94,7 +93,7 @@ public class QuickListsManager implements ExportableApplicationComponent {
public void initComponent() {
for (BundledQuickListsProvider provider : BundledQuickListsProvider.EP_NAME.getExtensions()) {
for (final String path : provider.getBundledListsRelativePaths()) {
mySchemeManager.loadBundledScheme(path, provider, element -> createItem(element));
mySchemeManager.loadBundledScheme(path, provider, QuickListsManager::createItem);
}
}
mySchemeManager.loadSchemes();
@@ -9,6 +9,6 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="core-api" exported="" />
<orderEntry type="module" module-name="jps-model-api" exported="" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
</component>
</module>
</module>
@@ -21,12 +21,8 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.WriteExternalException
import org.jdom.Parent
interface Scheme {
val name: String
}
interface ExternalizableScheme : Scheme {
override var name: String
fun setName(value: String)
}
abstract class SchemeManagerFactory {
@@ -20,7 +20,13 @@ import org.jdom.Element
import kotlin.properties.Delegates
abstract class ExternalizableSchemeAdapter : ExternalizableScheme {
override var name: String by Delegates.notNull()
private var myName: String by Delegates.notNull()
override fun getName() = myName
override fun setName(value: String) {
myName = value
}
override fun toString() = name
}
@@ -17,9 +17,13 @@ package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInspection.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.AreaInstance;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,6 +37,11 @@ import java.util.Set;
public class QuickFixGetFamilyNameViolationInspection extends DevKitInspectionBase {
private final static Logger LOG = Logger.getInstance(QuickFixGetFamilyNameViolationInspection.class);
private final static Set<String> BASE_CONTEXT_AWARE_CLASSES = ContainerUtil.newHashSet(PsiElement.class.getName(),
Navigatable.class.getName(),
AreaInstance.class.getName(),
VirtualFile.class.getName());
@Nullable
@Override
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
@@ -55,28 +64,35 @@ public class QuickFixGetFamilyNameViolationInspection extends DevKitInspectionBa
if (!processed.add(method) || method.hasModifierProperty(PsiModifier.STATIC)) return false;
final PsiCodeBlock body = method.getBody();
if (body == null) return false;
if (isContextDependentType(method.getReturnType())) {
return true;
}
final Collection<PsiJavaCodeReferenceElement> referenceIterator =
PsiTreeUtil.findChildrenOfType(body, PsiJavaCodeReferenceElement.class);
for (PsiJavaCodeReferenceElement reference : referenceIterator) {
final PsiElement resolved = reference.resolve();
if (resolved instanceof PsiVariable) {
if ((resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter) && !PsiTreeUtil.isAncestor(body, resolved, false)) {
return true;
}
if (resolved instanceof PsiField && !((PsiField)resolved).hasModifierProperty(PsiModifier.STATIC)) {
if (!(resolved instanceof PsiField && ((PsiField)resolved).hasModifierProperty(PsiModifier.STATIC)) && isContextDependentType(((PsiVariable)resolved).getType())) {
return true;
}
}
if (resolved instanceof PsiMethod && !((PsiMethod)resolved).hasModifierProperty(PsiModifier.STATIC)) {
final PsiClass resolvedContainingClass = ((PsiMethod)resolved).getContainingClass();
if (resolved instanceof PsiMethod) {
final PsiMethod resolvedMethod = (PsiMethod)resolved;
final PsiClass resolvedContainingClass = resolvedMethod.getContainingClass();
//if (resolvedMethod.getName().equals("getName") &&
// resolvedMethod.getParameterList().getParametersCount() == 0 &&
// !resolvedMethod.hasModifierProperty(PsiModifier.STATIC) &&
// InheritanceUtil.isInheritor(resolvedContainingClass, QuickFix.class.getName())) {
// return true;
//}
final PsiClass methodContainingClass = method.getContainingClass();
if (resolvedContainingClass != null &&
methodContainingClass != null &&
(methodContainingClass == resolvedContainingClass ||
methodContainingClass.isInheritor(resolvedContainingClass, true))) {
if (doesMethodViolate((PsiMethod)resolved, processed)) {
if (doesMethodViolate(resolvedMethod, processed)) {
return true;
}
}
@@ -84,4 +100,16 @@ public class QuickFixGetFamilyNameViolationInspection extends DevKitInspectionBa
}
return false;
}
private static boolean isContextDependentType(@Nullable PsiType type) {
if (type == null) return false;
for (String aClass : BASE_CONTEXT_AWARE_CLASSES) {
if (InheritanceUtil.isInheritor(type, aClass)) {
return true;
}
}
return false;
}
}
@@ -8,7 +8,7 @@ class A {
return "some name";
};
public String <warning descr="QuickFix's getFamilyName() implementation must not depend on a specific context">getFamilyName</warning>() {
public String getFamilyName() {
return someParameter + "123";
};
};
@@ -8,7 +8,7 @@ class MyQuickFix implements QuickFix {
return "some name";
};
public String <warning descr="QuickFix's getFamilyName() implementation must not depend on a specific context">getFamilyName</warning>() {
public String getFamilyName() {
return someField + getName() + "123";
};
@@ -0,0 +1,16 @@
import com.intellij.codeInspection.QuickFix;
class MyQuickFix implements QuickFix {
String someField;
public String getName() {
return someField;
};
public String getFamilyName() {
return getName() + "123";
};
}
@@ -1,16 +1,17 @@
import com.intellij.codeInspection.QuickFix;
import com.intellij.psi.PsiElement;
class MyQuickFix implements QuickFix {
String someField;
PsiElement myElement;
public String getName() {
return someField;
};
public String <warning descr="QuickFix's getFamilyName() implementation must not depend on a specific context">getFamilyName</warning>() {
return getName() + "123";
return "error is here: " + String.valueOf(myElement);
};
}
@@ -39,17 +39,19 @@ public class QuickFixGetFamilyNameViolationInspectionTest extends JavaCodeInsigh
" String getName();" +
" String getFamilyName();" +
"}");
myFixture.addClass("package com.intellij.psi;" +
"public interface PsiElement {}");
}
public void testViolationByField() {
public void testNotViolatedByField() {
myFixture.testHighlighting(getTestName(false) + ".java");
}
public void testViolationByGetName() {
public void testNotViolatedByGetName() {
myFixture.testHighlighting(getTestName(false) + ".java");
}
public void testViolationByExternalParameter() {
public void testNotViolatedByExternalParameter() {
myFixture.testHighlighting(getTestName(false) + ".java");
}
@@ -64,4 +66,8 @@ public class QuickFixGetFamilyNameViolationInspectionTest extends JavaCodeInsigh
public void testNotViolatedGetNameMethod() {
myFixture.testHighlighting(getTestName(false) + ".java");
}
public void testViolationByPsiElementFieldUsage() {
myFixture.testHighlighting(getTestName(false) + ".java");
}
}