Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2016-04-11 22:02:49 +02:00
19 changed files with 137 additions and 60 deletions
@@ -20,6 +20,7 @@
package com.intellij.codeInsight;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,6 +47,10 @@ public class ClassUtil {
@Nullable
public static PsiMethod getAnyMethodToImplement(@NotNull PsiClass aClass) {
final PsiClass superClass = aClass instanceof PsiAnonymousClass ? PsiUtil.resolveClassInClassTypeOnly(((PsiAnonymousClass)aClass).getBaseClassType()) : aClass.getSuperClass();
if (superClass != null && !superClass.hasModifierProperty(PsiModifier.ABSTRACT) && aClass.getImplementsListTypes().length == 0) {
return null;
}
Set<PsiMethod> alreadyImplemented = new THashSet<PsiMethod>();
for (HierarchicalMethodSignature signatureHierarchical : aClass.getVisibleSignatures()) {
for (PsiMethod superS : signatureHierarchical.getMethod().findSuperMethods()) {
@@ -688,40 +688,49 @@ public class InferenceSession {
public void registerReturnTypeConstraints(PsiType returnType, PsiType targetType) {
returnType = substituteWithInferenceVariables(returnType);
final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
if (inferenceVariable != null) {
final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor);
final PsiType substitutedReturnType = substitutor.substitute(inferenceVariable);
if (substitutedReturnType != null) {
addConstraint(new TypeCompatibilityConstraint(targetType, PsiUtil.captureToplevelWildcards(substitutedReturnType, myContext)));
if (myErased) {
final InferenceVariable inferenceVariable = getInferenceVariable(returnType);
if (inferenceVariable != null) {
final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor);
returnType = substitutor.substitute(inferenceVariable);
if (returnType == null) return;
}
}
else {
if (FunctionalInterfaceParameterizationUtil.isWildcardParameterized(returnType)) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(returnType);
final PsiClass psiClass = resolveResult.getElement();
if (psiClass != null) {
LOG.assertTrue(returnType instanceof PsiClassType);
PsiClassType substitutedCapture = (PsiClassType)PsiUtil.captureToplevelWildcards(returnType, myContext);
final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
final InferenceVariable[] copy = initBounds(null, typeParameters);
addConstraint(new TypeCompatibilityConstraint(targetType, TypeConversionUtil.erasure(returnType)));
}
else if (FunctionalInterfaceParameterizationUtil.isWildcardParameterized(returnType)) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(returnType);
final PsiClass psiClass = resolveResult.getElement();
if (psiClass != null) {
LOG.assertTrue(returnType instanceof PsiClassType);
PsiClassType substitutedCapture = (PsiClassType)PsiUtil.captureToplevelWildcards(returnType, myContext);
final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
final InferenceVariable[] copy = initBounds(null, typeParameters);
final PsiType[] parameters = substitutedCapture.getParameters();
final PsiType[] newParameters = new PsiType[parameters.length];
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myManager.getProject());
for (int i = 0; i < parameters.length; i++) {
newParameters[i] = parameters[i];
if (parameters[i] instanceof PsiCapturedWildcardType) {
newParameters[i] = elementFactory.createType(copy[i]);
}
final PsiType[] parameters = substitutedCapture.getParameters();
final PsiType[] newParameters = new PsiType[parameters.length];
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myManager.getProject());
for (int i = 0; i < parameters.length; i++) {
newParameters[i] = parameters[i];
if (parameters[i] instanceof PsiCapturedWildcardType) {
newParameters[i] = elementFactory.createType(copy[i]);
}
substitutedCapture = elementFactory.createType(psiClass, newParameters);
myIncorporationPhase.addCapture(copy, (PsiClassType)returnType);
addConstraint(new TypeCompatibilityConstraint(targetType, substitutedCapture));
}
} else {
addConstraint(new TypeCompatibilityConstraint(targetType, myErased ? TypeConversionUtil.erasure(returnType) : returnType));
substitutedCapture = elementFactory.createType(psiClass, newParameters);
myIncorporationPhase.addCapture(copy, (PsiClassType)returnType);
addConstraint(new TypeCompatibilityConstraint(targetType, substitutedCapture));
}
} else {
final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
if (inferenceVariable != null) {
final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor);
final PsiType substitutedReturnType = substitutor.substitute(inferenceVariable);
if (substitutedReturnType != null) {
addConstraint(new TypeCompatibilityConstraint(targetType, PsiUtil.captureToplevelWildcards(substitutedReturnType, myContext)));
}
}
else {
addConstraint(new TypeCompatibilityConstraint(targetType, returnType));
}
}
}
@@ -733,8 +742,7 @@ public class InferenceSession {
return inferenceVariable;
}
if (targetType instanceof PsiClassType) {
if (myErased ||
hasUncheckedBounds(inferenceVariable, (PsiClassType)targetType) ||
if (hasUncheckedBounds(inferenceVariable, (PsiClassType)targetType) ||
hasWildcardParameterization(inferenceVariable, (PsiClassType)targetType)) {
return inferenceVariable;
}
@@ -244,6 +244,7 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements
// 18.5.2
// if unchecked conversion was necessary, then this substitution provides the parameter types of the invocation type,
// while the return type and thrown types are given by the erasure of m's type (without applying θ').
//due to https://bugs.openjdk.java.net/browse/JDK-8135087 erasure is called on substitutedReturnType and not on ret type itself as by spec
return TypeConversionUtil.erasure(substitutedReturnType);
}
@@ -0,0 +1,14 @@
interface I {
void m();
}
<error descr="Class 'A' must either be declared abstract or implement abstract method 'm()' in 'I'">class A implements I</error> {}
class B extends A {}
class U {
{
new B() {};
B b = new B();
}
}
@@ -1,5 +1,5 @@
class Foo<T extends Enum> {
public T bar(Class<? extends T> type, String str) {
<error descr="Incompatible types. Found: 'java.lang.Enum', required: 'T'">return Enum.valueOf(type, str);</error>
return Enum.valueOf(<error descr="'valueOf(java.lang.Class<T>, java.lang.String)' in 'java.lang.Enum' cannot be applied to '(java.lang.Class<capture<? extends T>>, java.lang.String)'">type</error>, str);
}
}
@@ -4,7 +4,7 @@ abstract class Group {
}
public <T extends Category> T get(Key<T> key) {
<error descr="Incompatible types. Found: 'Category', required: 'T'">return getCategory(key);</error>
return getCategory<error descr="'getCategory(Key<R>)' in 'Group' cannot be applied to '(Key<T>)'">(key)</error>;
}
public abstract <R extends Category<R>> R getCategory(Key<R> key);
@@ -0,0 +1,12 @@
import java.util.List;
class Test {
<T> T foo(List<T> l) {
return l.get(0);
}
void m(List l){
<error descr="Incompatible types. Found: 'java.lang.Object', required: 'boolean'">boolean foo = foo(l);</error>
<error descr="Incompatible types. Found: 'java.lang.Object', required: 'java.lang.String'">String s = foo(l);</error>
}
}
@@ -69,4 +69,7 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase {
public void testUnhandledErrorsFromEnumConstructors() {
doTest(true, false);
}
public void testSkipAbstractMethodsIfTheyMustBeDeclaredInNonAbstractSuperclass() {
doTest(false, false);
}
}
@@ -429,6 +429,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
doTest();
}
public void testPrimitiveTypeInReturnConstraintWithUncheckedConversion() throws Exception {
doTest();
}
public void testVariableNamesOfNestedCalls() throws Exception {
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
@@ -32,6 +32,7 @@ import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.FocusChangeListener;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
@@ -632,6 +633,23 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons
final Dimension historySize = history.getContentSize();
final Dimension inputSize = input.getContentSize();
// deal with width
if (isHistoryViewerForceAdditionalColumnsUsage()) {
history.getSoftWrapModel().forceAdditionalColumnsUsage();
int minAdditionalColumns = 2;
// calculate content size without additional columns except minimal amount
int historySpaceWidth = EditorUtil.getPlainSpaceWidth(history);
historySize.width += historySpaceWidth * (minAdditionalColumns - history.getSettings().getAdditionalColumnsCount());
// calculate content size without additional columns except minimal amount
int inputSpaceWidth = EditorUtil.getPlainSpaceWidth(input);
inputSize.width += inputSpaceWidth * (minAdditionalColumns - input.getSettings().getAdditionalColumnsCount());
// calculate additional columns according to the corresponding width
int max = Math.max(historySize.width, inputSize.width);
history.getSettings().setAdditionalColumnsCount(minAdditionalColumns + (max - historySize.width) / historySpaceWidth);
input.getSettings().setAdditionalColumnsCount(minAdditionalColumns + (max - inputSize.width) / inputSpaceWidth);
}
int newInputHeight;
// deal with height, WEB-11122 we cannot trust editor width - it could be 0 in case of soft wrap even if editor has text
if (history.getDocument().getLineCount() == 0) {
@@ -221,9 +221,11 @@ public final class FloatingDecorator extends JDialog {
final Point newPoint=e.getPoint();
SwingUtilities.convertPointToScreen(newPoint,this);
final Rectangle screenBounds=WindowManagerEx.getInstanceEx().getScreenBounds();
int screenMaxX = screenBounds.x + screenBounds.width;
int screenMaxY = screenBounds.y + screenBounds.height;
newPoint.x=Math.min(Math.max(newPoint.x,screenBounds.x),screenBounds.width);
newPoint.y=Math.min(Math.max(newPoint.y,screenBounds.y),screenBounds.height);
newPoint.x = Math.min(Math.max(newPoint.x, screenBounds.x), screenMaxX);
newPoint.y = Math.min(Math.max(newPoint.y, screenBounds.y), screenMaxY);
final Rectangle oldBounds=FloatingDecorator.this.getBounds();
final Rectangle newBounds=new Rectangle(oldBounds);
@@ -248,16 +250,16 @@ public final class FloatingDecorator extends JDialog {
}
if((myMotionMask&ANCHOR_BOTTOM)>0){
newPoint.y=Math.max(newPoint.y,oldBounds.y+2*DIVIDER_WIDTH);
if(newPoint.y>screenBounds.height-DIVIDER_WIDTH){
newPoint.y=screenBounds.height;
if (newPoint.y > screenMaxY - DIVIDER_WIDTH) {
newPoint.y = screenMaxY;
}
final Point offset=new Point(newPoint.x-myLastPoint.x,newPoint.y-myLastPoint.y);
newBounds.height=oldBounds.height+offset.y;
}
if((myMotionMask&ANCHOR_RIGHT)>0){
newPoint.x=Math.max(newPoint.x,oldBounds.x+2*DIVIDER_WIDTH);
if(newPoint.x>screenBounds.width-DIVIDER_WIDTH){
newPoint.x=screenBounds.width;
if (newPoint.x > screenMaxX - DIVIDER_WIDTH) {
newPoint.x = screenMaxX;
}
final Point offset=new Point(newPoint.x-myLastPoint.x,newPoint.y-myLastPoint.y);
newBounds.width=oldBounds.width+offset.x;
@@ -291,7 +291,7 @@ public class UIUtil {
}
@NotNull
static JComponent createCompleteMatchInfo(final Producer<Configuration> configurationProducer) {
public static JComponent createCompleteMatchInfo(final Producer<Configuration> configurationProducer) {
final JLabel completeMatchInfo = new JLabel(AllIcons.RunConfigurations.Variables);
final Point location = completeMatchInfo.getLocation();
final JLabel label = new JLabel(SSRBundle.message("complete.match.variable.tooltip.message",
@@ -242,7 +242,7 @@ public class CoverageConfigurable extends SettingsEditor<RunConfigurationBase> {
final GridBagConstraints gc = new GridBagConstraints(0, GridBagConstraints.RELATIVE,
1, 1, 1, 0,
GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
JBUI.emptyInsets(), 0, 0);
result.add(myRunnerPanel, gc);
@@ -258,6 +258,8 @@ public class CoverageConfigurable extends SettingsEditor<RunConfigurationBase> {
myTrackTestSourcesCb = new JCheckBox("Enable coverage in test folders");
panel.add(myTrackTestSourcesCb, bagConstraints);
gc.weighty = 1;
gc.fill = GridBagConstraints.BOTH;
result.add(panel, gc);
myCoverageNotSupportedLabel = new JLabel(CodeInsightBundle.message("code.coverage.is.not.supported"));
@@ -117,7 +117,8 @@ public class InitializerProcessor {
StructClass cl = wrapper.getClassStruct();
Statement firstData = Statements.findFirstData(root);
if (firstData != null) {
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE);
boolean inlineInitializers = cl.hasModifier(CodeConstants.ACC_INTERFACE) || cl.hasModifier(CodeConstants.ACC_ENUM);
while (!firstData.getExprents().isEmpty()) {
Exprent exprent = firstData.getExprents().get(0);
@@ -131,8 +132,7 @@ public class InitializerProcessor {
cl.hasField(fExpr.getName(), fExpr.getDescriptor().descriptorString)) {
// interfaces fields should always be initialized inline
if (isInterface || isExprentIndependent(assignExpr.getRight(), method)) {
if (inlineInitializers || isExprentIndependent(assignExpr.getRight(), method)) {
String keyField = InterpreterUtil.makeUniqueKey(fExpr.getName(), fExpr.getDescriptor().descriptorString);
if (!wrapper.getStaticFieldInitializers().containsKey(keyField)) {
wrapper.getStaticFieldInitializers().addWithKey(assignExpr.getRight(), keyField);
@@ -6,8 +6,8 @@ public enum TestEnum {
public void m() {
}// 22
},
E3("-"),
E4("+") {
E3("-", TestEnum.Type.ODD),
E4("+", TestEnum.Type.EVEN) {
public void m() {
}// 27
};
@@ -15,14 +15,19 @@ public enum TestEnum {
private String s;
public void m() {
}// 30
}// 32
private TestEnum() {
this("?");// 34
this("?", (TestEnum.Type)null);// 36
}
private TestEnum(@Deprecated String var3) {
this.s = var3;// 35
private TestEnum(@Deprecated String var3, TestEnum.Type var4) {
this.s = var3;// 37
}
private static enum Type {
ODD,
EVEN;
}
}
@@ -46,10 +51,11 @@ class 'pkg/TestEnum' {
method '<init> (Ljava/lang/String;I)V' {
3 20
5 20
8 21
6 20
9 21
}
method '<init> (Ljava/lang/String;ILjava/lang/String;)V' {
method '<init> (Ljava/lang/String;ILjava/lang/String;Lpkg/TestEnum$Type;)V' {
8 24
b 25
}
@@ -58,6 +64,6 @@ class 'pkg/TestEnum' {
Lines mapping:
22 <-> 7
27 <-> 12
30 <-> 18
34 <-> 21
35 <-> 25
32 <-> 18
36 <-> 21
37 <-> 25
@@ -21,16 +21,18 @@ public enum TestEnum {
@Override
public void m() { }
},
E3("-"),
E4("+") {
E3("-", Type.ODD),
E4("+", Type.EVEN) {
@Override
public void m() { }
};
private enum Type {ODD, EVEN}
public void m() { }
private String s;
private TestEnum() { this("?"); }
private TestEnum(@Deprecated String s) { this.s = s; }
private TestEnum() { this("?", null); }
private TestEnum(@Deprecated String s, Type t) { this.s = s; }
}