Render platform name in multiplatform diagnostic tests
Prepend the platform name to the diagnostic in a common module, which is reported when sources of that common module are analyzed as a part of the platform source set: "<!JVM:...!> ... <!>". Fix some existing tests, mostly by adding "impl" to implementations
This commit is contained in:
@@ -34,6 +34,7 @@ import kotlin.Pair;
|
|||||||
import kotlin.TuplesKt;
|
import kotlin.TuplesKt;
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
|
import kotlin.text.StringsKt;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
@@ -48,6 +49,7 @@ import org.jetbrains.kotlin.psi.KtExpression;
|
|||||||
import org.jetbrains.kotlin.psi.KtReferenceExpression;
|
import org.jetbrains.kotlin.psi.KtReferenceExpression;
|
||||||
import org.jetbrains.kotlin.resolve.AnalyzingUtils;
|
import org.jetbrains.kotlin.resolve.AnalyzingUtils;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
|
import org.jetbrains.kotlin.resolve.MultiTargetPlatform;
|
||||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -84,7 +86,7 @@ public class CheckerTestUtil {
|
|||||||
private static final String IGNORE_DIAGNOSTIC_PARAMETER = "IGNORE";
|
private static final String IGNORE_DIAGNOSTIC_PARAMETER = "IGNORE";
|
||||||
private static final String SHOULD_BE_ESCAPED = "\\)\\(;";
|
private static final String SHOULD_BE_ESCAPED = "\\)\\(;";
|
||||||
private static final String DIAGNOSTIC_PARAMETER = "(?:(?:\\\\[" + SHOULD_BE_ESCAPED + "])|[^" + SHOULD_BE_ESCAPED + "])+";
|
private static final String DIAGNOSTIC_PARAMETER = "(?:(?:\\\\[" + SHOULD_BE_ESCAPED + "])|[^" + SHOULD_BE_ESCAPED + "])+";
|
||||||
private static final String INDIVIDUAL_DIAGNOSTIC = "(\\w+)(\\(" + DIAGNOSTIC_PARAMETER + "(;\\s*" + DIAGNOSTIC_PARAMETER + ")*\\))?";
|
private static final String INDIVIDUAL_DIAGNOSTIC = "(\\w+:)?(\\w+)(\\(" + DIAGNOSTIC_PARAMETER + "(;\\s*" + DIAGNOSTIC_PARAMETER + ")*\\))?";
|
||||||
private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("(<!" +
|
private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("(<!" +
|
||||||
INDIVIDUAL_DIAGNOSTIC + "(,\\s*" +
|
INDIVIDUAL_DIAGNOSTIC + "(,\\s*" +
|
||||||
INDIVIDUAL_DIAGNOSTIC + ")*!>)|(<!>)");
|
INDIVIDUAL_DIAGNOSTIC + ")*!>)|(<!>)");
|
||||||
@@ -94,23 +96,57 @@ public class CheckerTestUtil {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static List<ActualDiagnostic> getDiagnosticsIncludingSyntaxErrors(
|
public static List<ActualDiagnostic> getDiagnosticsIncludingSyntaxErrors(
|
||||||
@NotNull BindingContext bindingContext,
|
@NotNull BindingContext bindingContext,
|
||||||
|
@NotNull List<Pair<MultiTargetPlatform, BindingContext>> implementingModulesBindings,
|
||||||
@NotNull PsiElement root,
|
@NotNull PsiElement root,
|
||||||
boolean markDynamicCalls,
|
boolean markDynamicCalls,
|
||||||
@Nullable List<DeclarationDescriptor> dynamicCallDescriptors
|
@Nullable List<DeclarationDescriptor> dynamicCallDescriptors
|
||||||
|
) {
|
||||||
|
List<ActualDiagnostic> result =
|
||||||
|
getDiagnosticsIncludingSyntaxErrors(bindingContext, root, markDynamicCalls, dynamicCallDescriptors, null);
|
||||||
|
|
||||||
|
List<Pair<MultiTargetPlatform, BindingContext>> sortedBindings = CollectionsKt.sortedWith(
|
||||||
|
implementingModulesBindings,
|
||||||
|
new Comparator<Pair<MultiTargetPlatform, BindingContext>>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Pair<MultiTargetPlatform, BindingContext> o1, Pair<MultiTargetPlatform, BindingContext> o2) {
|
||||||
|
return o1.getFirst().compareTo(o2.getFirst());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
for (Pair<MultiTargetPlatform, BindingContext> binding : sortedBindings) {
|
||||||
|
MultiTargetPlatform platform = binding.getFirst();
|
||||||
|
assert platform instanceof MultiTargetPlatform.Specific : "Implementing module must have a specific platform: " + platform;
|
||||||
|
|
||||||
|
result.addAll(getDiagnosticsIncludingSyntaxErrors(
|
||||||
|
binding.getSecond(), root, markDynamicCalls, dynamicCallDescriptors,
|
||||||
|
((MultiTargetPlatform.Specific) platform).getPlatform()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static List<ActualDiagnostic> getDiagnosticsIncludingSyntaxErrors(
|
||||||
|
@NotNull BindingContext bindingContext,
|
||||||
|
@NotNull PsiElement root,
|
||||||
|
boolean markDynamicCalls,
|
||||||
|
@Nullable List<DeclarationDescriptor> dynamicCallDescriptors,
|
||||||
|
@Nullable String platform
|
||||||
) {
|
) {
|
||||||
List<ActualDiagnostic> diagnostics = new ArrayList<ActualDiagnostic>();
|
List<ActualDiagnostic> diagnostics = new ArrayList<ActualDiagnostic>();
|
||||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics().all()) {
|
for (Diagnostic diagnostic : bindingContext.getDiagnostics().all()) {
|
||||||
if (PsiTreeUtil.isAncestor(root, diagnostic.getPsiElement(), false)) {
|
if (PsiTreeUtil.isAncestor(root, diagnostic.getPsiElement(), false)) {
|
||||||
diagnostics.add(new ActualDiagnostic(diagnostic));
|
diagnostics.add(new ActualDiagnostic(diagnostic, platform));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PsiErrorElement errorElement : AnalyzingUtils.getSyntaxErrorRanges(root)) {
|
for (PsiErrorElement errorElement : AnalyzingUtils.getSyntaxErrorRanges(root)) {
|
||||||
diagnostics.add(new ActualDiagnostic(new SyntaxErrorDiagnostic(errorElement)));
|
diagnostics.add(new ActualDiagnostic(new SyntaxErrorDiagnostic(errorElement), platform));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ActualDiagnostic> debugAnnotations = getDebugInfoDiagnostics(root, bindingContext, markDynamicCalls, dynamicCallDescriptors);
|
diagnostics.addAll(getDebugInfoDiagnostics(root, bindingContext, markDynamicCalls, dynamicCallDescriptors, platform));
|
||||||
diagnostics.addAll(debugAnnotations);
|
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +156,8 @@ public class CheckerTestUtil {
|
|||||||
@NotNull PsiElement root,
|
@NotNull PsiElement root,
|
||||||
@NotNull BindingContext bindingContext,
|
@NotNull BindingContext bindingContext,
|
||||||
final boolean markDynamicCalls,
|
final boolean markDynamicCalls,
|
||||||
@Nullable final List<DeclarationDescriptor> dynamicCallDescriptors
|
@Nullable final List<DeclarationDescriptor> dynamicCallDescriptors,
|
||||||
|
@Nullable final String platform
|
||||||
) {
|
) {
|
||||||
final List<ActualDiagnostic> debugAnnotations = new ArrayList<ActualDiagnostic>();
|
final List<ActualDiagnostic> debugAnnotations = new ArrayList<ActualDiagnostic>();
|
||||||
|
|
||||||
@@ -152,7 +189,7 @@ public class CheckerTestUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void newDiagnostic(KtElement element, DebugInfoDiagnosticFactory factory) {
|
private void newDiagnostic(KtElement element, DebugInfoDiagnosticFactory factory) {
|
||||||
debugAnnotations.add(new ActualDiagnostic(new DebugInfoDiagnostic(element, factory)));
|
debugAnnotations.add(new ActualDiagnostic(new DebugInfoDiagnostic(element, factory), platform));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -167,7 +204,7 @@ public class CheckerTestUtil {
|
|||||||
)) {
|
)) {
|
||||||
for (KtExpression expression : bindingContext.getSliceContents(factory.getFirst()).keySet()) {
|
for (KtExpression expression : bindingContext.getSliceContents(factory.getFirst()).keySet()) {
|
||||||
if (PsiTreeUtil.isAncestor(root, expression, false)) {
|
if (PsiTreeUtil.isAncestor(root, expression, false)) {
|
||||||
debugAnnotations.add(new ActualDiagnostic(new DebugInfoDiagnostic(expression, factory.getSecond())));
|
debugAnnotations.add(new ActualDiagnostic(new DebugInfoDiagnostic(expression, factory.getSecond()), platform));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,7 +304,7 @@ public class CheckerTestUtil {
|
|||||||
actualDiagnostics.entrySet(), new Function1<Map.Entry<ActualDiagnostic, TextDiagnostic>, Boolean>() {
|
actualDiagnostics.entrySet(), new Function1<Map.Entry<ActualDiagnostic, TextDiagnostic>, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean invoke(Map.Entry<ActualDiagnostic, TextDiagnostic> entry) {
|
public Boolean invoke(Map.Entry<ActualDiagnostic, TextDiagnostic> entry) {
|
||||||
return expectedDiagnostic.getName().equals(entry.getValue().getName());
|
return expectedDiagnostic.getDescription().equals(entry.getValue().getDescription());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -294,7 +331,7 @@ public class CheckerTestUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean compareTextDiagnostic(@NotNull TextDiagnostic expected, @NotNull TextDiagnostic actual) {
|
private static boolean compareTextDiagnostic(@NotNull TextDiagnostic expected, @NotNull TextDiagnostic actual) {
|
||||||
if (!expected.getName().equals(actual.getName())) return false;
|
if (!expected.getDescription().equals(actual.getDescription())) return false;
|
||||||
|
|
||||||
if (expected.getParameters() == null) return true;
|
if (expected.getParameters() == null) return true;
|
||||||
if (actual.getParameters() == null || expected.getParameters().size() != actual.getParameters().size()) return false;
|
if (actual.getParameters() == null || expected.getParameters().size() != actual.getParameters().size()) return false;
|
||||||
@@ -461,6 +498,10 @@ public class CheckerTestUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (diagnostic.platform != null) {
|
||||||
|
result.append(diagnostic.platform);
|
||||||
|
result.append(":");
|
||||||
|
}
|
||||||
result.append(diagnostic.getName());
|
result.append(diagnostic.getName());
|
||||||
}
|
}
|
||||||
if (iterator.hasNext()) {
|
if (iterator.hasNext()) {
|
||||||
@@ -633,9 +674,11 @@ public class CheckerTestUtil {
|
|||||||
|
|
||||||
public static class ActualDiagnostic {
|
public static class ActualDiagnostic {
|
||||||
public final Diagnostic diagnostic;
|
public final Diagnostic diagnostic;
|
||||||
|
public final String platform;
|
||||||
|
|
||||||
ActualDiagnostic(@NotNull Diagnostic diagnostic) {
|
ActualDiagnostic(@NotNull Diagnostic diagnostic, @Nullable String platform) {
|
||||||
this.diagnostic = diagnostic;
|
this.diagnostic = diagnostic;
|
||||||
|
this.platform = platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -650,18 +693,22 @@ public class CheckerTestUtil {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof ActualDiagnostic)) return false;
|
||||||
|
|
||||||
|
ActualDiagnostic other = (ActualDiagnostic) obj;
|
||||||
// '==' on diagnostics is intentional here
|
// '==' on diagnostics is intentional here
|
||||||
return obj instanceof ActualDiagnostic && ((ActualDiagnostic) obj).diagnostic == diagnostic;
|
return other.diagnostic == diagnostic &&
|
||||||
|
(other.platform == null ? platform == null : other.platform.equals(platform));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return System.identityHashCode(diagnostic);
|
return System.identityHashCode(diagnostic) * 31 + (platform != null ? platform.hashCode() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return diagnostic.toString();
|
return (platform != null ? platform + ":" : "") + diagnostic.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,18 +718,22 @@ public class CheckerTestUtil {
|
|||||||
Matcher matcher = INDIVIDUAL_DIAGNOSTIC_PATTERN.matcher(text);
|
Matcher matcher = INDIVIDUAL_DIAGNOSTIC_PATTERN.matcher(text);
|
||||||
if (!matcher.find())
|
if (!matcher.find())
|
||||||
throw new IllegalArgumentException("Could not parse diagnostic: " + text);
|
throw new IllegalArgumentException("Could not parse diagnostic: " + text);
|
||||||
String name = matcher.group(1);
|
|
||||||
|
|
||||||
String parameters = matcher.group(2);
|
String platformPrefix = matcher.group(1);
|
||||||
|
assert platformPrefix == null || platformPrefix.endsWith(":") : platformPrefix;
|
||||||
|
String platform = platformPrefix == null ? null : StringsKt.substringBeforeLast(platformPrefix, ":", platformPrefix);
|
||||||
|
|
||||||
|
String name = matcher.group(2);
|
||||||
|
String parameters = matcher.group(3);
|
||||||
if (parameters == null) {
|
if (parameters == null) {
|
||||||
return new TextDiagnostic(name, null);
|
return new TextDiagnostic(name, platform, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> parsedParameters = new SmartList<String>();
|
List<String> parsedParameters = new SmartList<String>();
|
||||||
Matcher parametersMatcher = INDIVIDUAL_PARAMETER_PATTERN.matcher(parameters);
|
Matcher parametersMatcher = INDIVIDUAL_PARAMETER_PATTERN.matcher(parameters);
|
||||||
while (parametersMatcher.find())
|
while (parametersMatcher.find())
|
||||||
parsedParameters.add(unescape(parametersMatcher.group().trim()));
|
parsedParameters.add(unescape(parametersMatcher.group().trim()));
|
||||||
return new TextDiagnostic(name, parsedParameters);
|
return new TextDiagnostic(name, platform, parsedParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NotNull String escape(@NotNull String s) {
|
private static @NotNull String escape(@NotNull String s) {
|
||||||
@@ -708,24 +759,32 @@ public class CheckerTestUtil {
|
|||||||
return o != null ? o.toString() : "null";
|
return o != null ? o.toString() : "null";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return new TextDiagnostic(diagnosticName, parameters);
|
return new TextDiagnostic(diagnosticName, actualDiagnostic.platform, parameters);
|
||||||
}
|
}
|
||||||
return new TextDiagnostic(diagnosticName, null);
|
return new TextDiagnostic(diagnosticName, actualDiagnostic.platform, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final String name;
|
private final String name;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
private final String platform;
|
||||||
|
@Nullable
|
||||||
private final List<String> parameters;
|
private final List<String> parameters;
|
||||||
|
|
||||||
public TextDiagnostic(@NotNull String name, @Nullable List<String> parameters) {
|
public TextDiagnostic(@NotNull String name, @Nullable String platform, @Nullable List<String> parameters) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.platform = platform;
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getPlatform() {
|
||||||
|
return platform;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getName() {
|
public String getDescription() {
|
||||||
return name;
|
return (platform != null ? platform + ":" : "") + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -741,6 +800,7 @@ public class CheckerTestUtil {
|
|||||||
TextDiagnostic that = (TextDiagnostic) o;
|
TextDiagnostic that = (TextDiagnostic) o;
|
||||||
|
|
||||||
if (!name.equals(that.name)) return false;
|
if (!name.equals(that.name)) return false;
|
||||||
|
if (platform != null ? !platform.equals(that.platform) : that.platform != null) return false;
|
||||||
if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false;
|
if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -749,20 +809,30 @@ public class CheckerTestUtil {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = name.hashCode();
|
int result = name.hashCode();
|
||||||
|
result = 31 * result + (platform != null ? platform.hashCode() : 0);
|
||||||
result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
|
result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String asString() {
|
public String asString() {
|
||||||
if (parameters == null)
|
StringBuilder result = new StringBuilder();
|
||||||
return name;
|
if (platform != null) {
|
||||||
return name + '(' + StringUtil.join(parameters, new Function<String, String>() {
|
result.append(platform);
|
||||||
@Override
|
result.append(":");
|
||||||
public String fun(String s) {
|
}
|
||||||
return escape(s);
|
result.append(name);
|
||||||
}
|
if (parameters != null) {
|
||||||
}, "; ") + ')';
|
result.append("(");
|
||||||
|
result.append(StringUtil.join(parameters, new Function<String, String>() {
|
||||||
|
@Override
|
||||||
|
public String fun(String s) {
|
||||||
|
return escape(s);
|
||||||
|
}
|
||||||
|
}, "; "));
|
||||||
|
result.append(")");
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,10 +20,19 @@ import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
|
||||||
sealed class MultiTargetPlatform {
|
sealed class MultiTargetPlatform : Comparable<MultiTargetPlatform> {
|
||||||
object Common : MultiTargetPlatform()
|
object Common : MultiTargetPlatform() {
|
||||||
|
override fun compareTo(other: MultiTargetPlatform): Int =
|
||||||
|
if (other is Common) 0 else -1
|
||||||
|
}
|
||||||
|
|
||||||
data class Specific(val platform: String) : MultiTargetPlatform()
|
data class Specific(val platform: String) : MultiTargetPlatform() {
|
||||||
|
override fun compareTo(other: MultiTargetPlatform): Int =
|
||||||
|
when (other) {
|
||||||
|
is Common -> 1
|
||||||
|
is Specific -> platform.compareTo(other.platform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
|
|||||||
+9
-9
@@ -4,15 +4,15 @@
|
|||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
|
|
||||||
header class C1
|
header class C1
|
||||||
header class C2<A>
|
header interface <!JVM:HEADER_WITHOUT_IMPLEMENTATION!>C2<!><A>
|
||||||
header class C3<B>
|
header interface <!JVM:HEADER_WITHOUT_IMPLEMENTATION!>C3<!><B>
|
||||||
header class C4<D, E>
|
header interface C4<D, E>
|
||||||
header class C5<F, G>
|
header interface C5<F, G>
|
||||||
header class C6<H>
|
header interface C6<H>
|
||||||
header class C7<I>
|
header interface C7<I>
|
||||||
header class C8<J>
|
header interface C8<J>
|
||||||
header class C9<K>
|
header interface C9<K>
|
||||||
header class C10<L>
|
header interface C10<L>
|
||||||
|
|
||||||
// MODULE: m2-jvm(m1-common)
|
// MODULE: m2-jvm(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|||||||
+6
-6
@@ -9,16 +9,16 @@ header class Foo {
|
|||||||
|
|
||||||
// MODULE: m2-jvm(m1-common)
|
// MODULE: m2-jvm(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
class Foo {
|
impl class Foo {
|
||||||
val foo: String = "JVM"
|
impl val foo: String = "JVM"
|
||||||
|
|
||||||
fun bar(x: Int): Int = x + 1
|
impl fun bar(x: Int): Int = x + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// MODULE: m3-js(m1-common)
|
// MODULE: m3-js(m1-common)
|
||||||
// FILE: js.kt
|
// FILE: js.kt
|
||||||
class Foo {
|
impl class Foo {
|
||||||
val foo: String = "JS"
|
impl val foo: String = "JS"
|
||||||
|
|
||||||
fun bar(x: Int): Int = x - 1
|
impl fun bar(x: Int): Int = x - 1
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -14,10 +14,10 @@ public final header class Foo {
|
|||||||
// -- Module: <m2-jvm> --
|
// -- Module: <m2-jvm> --
|
||||||
package
|
package
|
||||||
|
|
||||||
public final class Foo {
|
public final impl class Foo {
|
||||||
public constructor Foo()
|
public constructor Foo()
|
||||||
public final val foo: kotlin.String = "JVM"
|
public final val foo: kotlin.String = "JVM"
|
||||||
public final fun bar(/*0*/ x: kotlin.Int): kotlin.Int
|
public final impl fun bar(/*0*/ x: kotlin.Int): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
@@ -27,10 +27,10 @@ public final class Foo {
|
|||||||
// -- Module: <m3-js> --
|
// -- Module: <m3-js> --
|
||||||
package
|
package
|
||||||
|
|
||||||
public final class Foo {
|
public final impl class Foo {
|
||||||
public constructor Foo()
|
public constructor Foo()
|
||||||
public final val foo: kotlin.String = "JS"
|
public final val foo: kotlin.String = "JS"
|
||||||
public final fun bar(/*0*/ x: kotlin.Int): kotlin.Int
|
public final impl fun bar(/*0*/ x: kotlin.Int): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|||||||
+2
-2
@@ -5,8 +5,8 @@ header class Foo
|
|||||||
|
|
||||||
// MODULE: m2-jvm(m1-common)
|
// MODULE: m2-jvm(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
class Foo
|
impl class Foo
|
||||||
|
|
||||||
// MODULE: m3-js(m1-common)
|
// MODULE: m3-js(m1-common)
|
||||||
// FILE: js.kt
|
// FILE: js.kt
|
||||||
class Foo
|
impl class Foo
|
||||||
|
|||||||
+2
-2
@@ -12,7 +12,7 @@ public final header class Foo {
|
|||||||
// -- Module: <m2-jvm> --
|
// -- Module: <m2-jvm> --
|
||||||
package
|
package
|
||||||
|
|
||||||
public final class Foo {
|
public final impl class Foo {
|
||||||
public constructor Foo()
|
public constructor Foo()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
@@ -23,7 +23,7 @@ public final class Foo {
|
|||||||
// -- Module: <m3-js> --
|
// -- Module: <m3-js> --
|
||||||
package
|
package
|
||||||
|
|
||||||
public final class Foo {
|
public final impl class Foo {
|
||||||
public constructor Foo()
|
public constructor Foo()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
|||||||
+2
-2
@@ -10,8 +10,8 @@ header class Foo : I, C, J
|
|||||||
|
|
||||||
// MODULE: m2-jvm(m1-common)
|
// MODULE: m2-jvm(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
class Foo : I, C(), J
|
impl class Foo : I, C(), J
|
||||||
|
|
||||||
// MODULE: m3-js(m1-common)
|
// MODULE: m3-js(m1-common)
|
||||||
// FILE: js.kt
|
// FILE: js.kt
|
||||||
class Foo : I, J, C()
|
impl class Foo : I, J, C()
|
||||||
|
|||||||
+2
-2
@@ -38,7 +38,7 @@ public open class C {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class Foo : I, C, J {
|
public final impl class Foo : I, C, J {
|
||||||
public constructor Foo()
|
public constructor Foo()
|
||||||
public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
@@ -68,7 +68,7 @@ public open class C {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class Foo : I, J, C {
|
public final impl class Foo : I, J, C {
|
||||||
public constructor Foo()
|
public constructor Foo()
|
||||||
public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
|||||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
package common
|
package common
|
||||||
|
|
||||||
header fun foo()
|
<!JS:HEADER_WITHOUT_IMPLEMENTATION, JVM:HEADER_WITHOUT_IMPLEMENTATION!>header fun foo()<!>
|
||||||
|
|
||||||
// MODULE: m2-jvm(m1-common)
|
// MODULE: m2-jvm(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// MODULE: m1-common
|
// MODULE: m1-common
|
||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
|
|
||||||
inline header fun inlineFun()
|
<!JVM:HEADER_WITHOUT_IMPLEMENTATION!>inline header fun inlineFun()<!>
|
||||||
header fun nonInlineFun()
|
header fun nonInlineFun()
|
||||||
|
|
||||||
// MODULE: m2-jvm(m1-common)
|
// MODULE: m2-jvm(m1-common)
|
||||||
|
|||||||
@@ -154,8 +154,17 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
for (testFile in files) {
|
for (testFile in files) {
|
||||||
val module = testFile.module
|
val module = testFile.module
|
||||||
val isCommonModule = modules[module]!!.getMultiTargetPlatform() == MultiTargetPlatform.Common
|
val isCommonModule = modules[module]!!.getMultiTargetPlatform() == MultiTargetPlatform.Common
|
||||||
|
val implementingModules =
|
||||||
|
if (!isCommonModule) emptyList()
|
||||||
|
else modules.entries.filter { (testModule) -> module in testModule?.getDependencies().orEmpty() }
|
||||||
|
val implementingModulesBindings = implementingModules.mapNotNull {
|
||||||
|
(testModule, moduleDescriptor) ->
|
||||||
|
val platform = moduleDescriptor.getCapability(MultiTargetPlatform.CAPABILITY)
|
||||||
|
if (platform is MultiTargetPlatform.Specific) platform to moduleBindings[testModule]!!
|
||||||
|
else null
|
||||||
|
}
|
||||||
ok = ok and testFile.getActualText(
|
ok = ok and testFile.getActualText(
|
||||||
moduleBindings[module]!!, actualText,
|
moduleBindings[module]!!, implementingModulesBindings, actualText,
|
||||||
shouldSkipJvmSignatureDiagnostics(groupedByModule) || isCommonModule
|
shouldSkipJvmSignatureDiagnostics(groupedByModule) || isCommonModule
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -464,7 +473,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
val nameSuffix = moduleName.substringAfterLast("-", "")
|
val nameSuffix = moduleName.substringAfterLast("-", "")
|
||||||
val platform =
|
val platform =
|
||||||
if (nameSuffix.isEmpty()) null
|
if (nameSuffix.isEmpty()) null
|
||||||
else if (nameSuffix == "common") MultiTargetPlatform.Common else MultiTargetPlatform.Specific(nameSuffix)
|
else if (nameSuffix == "common") MultiTargetPlatform.Common else MultiTargetPlatform.Specific(nameSuffix.toUpperCase())
|
||||||
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?> =
|
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?> =
|
||||||
if (platform == null) emptyMap()
|
if (platform == null) emptyMap()
|
||||||
else mapOf(MultiTargetPlatform.CAPABILITY to platform)
|
else mapOf(MultiTargetPlatform.CAPABILITY to platform)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer
|
|||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
@@ -194,13 +195,19 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getActualText(bindingContext: BindingContext, actualText: StringBuilder, skipJvmSignatureDiagnostics: Boolean): Boolean {
|
fun getActualText(
|
||||||
|
bindingContext: BindingContext,
|
||||||
|
implementingModulesBindings: List<Pair<MultiTargetPlatform, BindingContext>>,
|
||||||
|
actualText: StringBuilder,
|
||||||
|
skipJvmSignatureDiagnostics: Boolean
|
||||||
|
): Boolean {
|
||||||
if (this.ktFile == null) {
|
if (this.ktFile == null) {
|
||||||
// TODO: check java files too
|
// TODO: check java files too
|
||||||
actualText.append(this.clearText)
|
actualText.append(this.clearText)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: report JVM signature diagnostics also for implementing modules
|
||||||
val jvmSignatureDiagnostics = if (skipJvmSignatureDiagnostics)
|
val jvmSignatureDiagnostics = if (skipJvmSignatureDiagnostics)
|
||||||
emptySet<ActualDiagnostic>()
|
emptySet<ActualDiagnostic>()
|
||||||
else
|
else
|
||||||
@@ -209,14 +216,14 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
val ok = booleanArrayOf(true)
|
val ok = booleanArrayOf(true)
|
||||||
val diagnostics = ContainerUtil.filter(
|
val diagnostics = ContainerUtil.filter(
|
||||||
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(
|
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(
|
||||||
bindingContext, ktFile, markDynamicCalls, dynamicCallDescriptors
|
bindingContext, implementingModulesBindings, ktFile, markDynamicCalls, dynamicCallDescriptors
|
||||||
) + jvmSignatureDiagnostics,
|
) + jvmSignatureDiagnostics,
|
||||||
{ whatDiagnosticsToConsider.value(it.diagnostic) }
|
{ whatDiagnosticsToConsider.value(it.diagnostic) }
|
||||||
)
|
)
|
||||||
|
|
||||||
val diagnosticToExpectedDiagnostic = CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, object : CheckerTestUtil.DiagnosticDiffCallbacks {
|
val diagnosticToExpectedDiagnostic = CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, object : CheckerTestUtil.DiagnosticDiffCallbacks {
|
||||||
override fun missingDiagnostic(diagnostic: CheckerTestUtil.TextDiagnostic, expectedStart: Int, expectedEnd: Int) {
|
override fun missingDiagnostic(diagnostic: CheckerTestUtil.TextDiagnostic, expectedStart: Int, expectedEnd: Int) {
|
||||||
val message = "Missing " + diagnostic.name + DiagnosticUtils.atLocation(ktFile, TextRange(expectedStart, expectedEnd))
|
val message = "Missing " + diagnostic.description + DiagnosticUtils.atLocation(ktFile, TextRange(expectedStart, expectedEnd))
|
||||||
System.err.println(message)
|
System.err.println(message)
|
||||||
ok[0] = false
|
ok[0] = false
|
||||||
}
|
}
|
||||||
@@ -235,7 +242,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun unexpectedDiagnostic(diagnostic: CheckerTestUtil.TextDiagnostic, actualStart: Int, actualEnd: Int) {
|
override fun unexpectedDiagnostic(diagnostic: CheckerTestUtil.TextDiagnostic, actualStart: Int, actualEnd: Int) {
|
||||||
val message = "Unexpected ${diagnostic.name}${DiagnosticUtils.atLocation(ktFile, TextRange(actualStart, actualEnd))}"
|
val message = "Unexpected ${diagnostic.description}${DiagnosticUtils.atLocation(ktFile, TextRange(actualStart, actualEnd))}"
|
||||||
System.err.println(message)
|
System.err.println(message)
|
||||||
ok[0] = false
|
ok[0] = false
|
||||||
}
|
}
|
||||||
@@ -256,7 +263,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
for (declaration in declarations) {
|
for (declaration in declarations) {
|
||||||
val diagnostics = getJvmSignatureDiagnostics(declaration, bindingContext.diagnostics,
|
val diagnostics = getJvmSignatureDiagnostics(declaration, bindingContext.diagnostics,
|
||||||
GlobalSearchScope.allScope(project)) ?: continue
|
GlobalSearchScope.allScope(project)) ?: continue
|
||||||
jvmSignatureDiagnostics.addAll(diagnostics.forElement(declaration).map { ActualDiagnostic(it) })
|
jvmSignatureDiagnostics.addAll(diagnostics.forElement(declaration).map { ActualDiagnostic(it, null) })
|
||||||
}
|
}
|
||||||
return jvmSignatureDiagnostics
|
return jvmSignatureDiagnostics
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,14 +147,14 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
|
|||||||
|
|
||||||
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(
|
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(
|
||||||
psiFile,
|
psiFile,
|
||||||
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null)
|
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null, null)
|
||||||
).toString();
|
).toString();
|
||||||
|
|
||||||
List<DiagnosedRange> diagnosedRanges = Lists.newArrayList();
|
List<DiagnosedRange> diagnosedRanges = Lists.newArrayList();
|
||||||
CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
|
CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
|
||||||
|
|
||||||
List<ActualDiagnostic> actualDiagnostics =
|
List<ActualDiagnostic> actualDiagnostics =
|
||||||
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null);
|
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null, null);
|
||||||
Collections.sort(actualDiagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
|
Collections.sort(actualDiagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
|
||||||
|
|
||||||
makeTestData(actualDiagnostics, diagnosedRanges);
|
makeTestData(actualDiagnostics, diagnosedRanges);
|
||||||
@@ -165,7 +165,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
|
|||||||
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, actualDiagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
|
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, actualDiagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
|
||||||
@Override
|
@Override
|
||||||
public void missingDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int expectedStart, int expectedEnd) {
|
public void missingDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int expectedStart, int expectedEnd) {
|
||||||
actualMessages.add(missing(diagnostic.getName(), expectedStart, expectedEnd));
|
actualMessages.add(missing(diagnostic.getDescription(), expectedStart, expectedEnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -180,7 +180,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unexpectedDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int actualStart, int actualEnd) {
|
public void unexpectedDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int actualStart, int actualEnd) {
|
||||||
actualMessages.add(unexpected(diagnostic.getName(), actualStart, actualEnd));
|
actualMessages.add(unexpected(diagnostic.getDescription(), actualStart, actualEnd));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class CopyAsDiagnosticTestAction extends AnAction {
|
|||||||
BindingContext bindingContext = ResolutionUtils.analyzeFully((KtFile) psiFile);
|
BindingContext bindingContext = ResolutionUtils.analyzeFully((KtFile) psiFile);
|
||||||
|
|
||||||
List<CheckerTestUtil.ActualDiagnostic> diagnostics =
|
List<CheckerTestUtil.ActualDiagnostic> diagnostics =
|
||||||
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null);
|
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null, null);
|
||||||
String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, diagnostics).toString();
|
String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, diagnostics).toString();
|
||||||
|
|
||||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||||
|
|||||||
Reference in New Issue
Block a user