Improve diagnostic message for UNSUPPORTED_FEATURE

Render lowercase words separated by spaces instead of CamelCase in the
diagnostic message
This commit is contained in:
Alexander Udalov
2016-10-03 12:29:23 +03:00
parent 73652f309f
commit df680305ba
8 changed files with 56 additions and 8 deletions
@@ -31,6 +31,10 @@ enum class LanguageFeature(val sinceVersion: LanguageVersion) {
DestructuringLambdaParameters(KOTLIN_1_1),
;
val presentableText: String
// E.g. "DestructuringLambdaParameters" -> ["Destructuring", "Lambda", "Parameters"] -> "destructuring lambda parameters"
get() = name.split("(?<!^)(?=[A-Z])".toRegex()).joinToString(separator = " ", transform = String::toLowerCase)
companion object {
@JvmStatic
fun fromString(str: String) = values().find { it.name == str }
@@ -21,6 +21,7 @@ import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
import org.jetbrains.kotlin.diagnostics.Errors;
@@ -505,7 +506,13 @@ public class DefaultErrorMessages {
MAP.put(UNSAFE_IMPLICIT_INVOKE_CALL, "Reference has a nullable type ''{0}'', use explicit ''?.invoke()'' to make a function-like call instead", RENDER_TYPE);
MAP.put(AMBIGUOUS_LABEL, "Ambiguous label");
MAP.put(UNSUPPORTED, "Unsupported [{0}]", STRING);
MAP.put(UNSUPPORTED_FEATURE, "{0} are unsupported at this language level", TO_STRING);
MAP.put(UNSUPPORTED_FEATURE, "The feature is only available since Kotlin {0}", new DiagnosticParameterRenderer<LanguageFeature>() {
@NotNull
@Override
public String render(LanguageFeature feature, @NotNull RenderingContext renderingContext) {
return feature.getSinceVersion().getVersionString() + ": " + feature.getPresentableText();
}
});
MAP.put(EXCEPTION_FROM_ANALYZER, "Internal Error occurred while analyzing this expression:\n{0}", THROWABLE);
MAP.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE);
MAP.put(UNEXPECTED_SAFE_CALL, "Safe-call is not allowed here");
@@ -65,7 +65,11 @@ object JvmResolveUtil {
@JvmStatic
fun analyze(files: Collection<KtFile>, environment: KotlinCoreEnvironment): AnalysisResult =
analyze(environment.project, files, environment.configuration) { scope ->
analyze(files, environment, environment.configuration)
@JvmStatic
fun analyze(files: Collection<KtFile>, environment: KotlinCoreEnvironment, configuration: CompilerConfiguration): AnalysisResult =
analyze(environment.project, files, configuration) { scope ->
JvmPackagePartProvider(environment, scope)
}
+7
View File
@@ -0,0 +1,7 @@
// !DIAGNOSTICS_NUMBER: 1
// !DIAGNOSTICS: UNSUPPORTED_FEATURE
// LANGUAGE_VERSION: 1.0
fun test() {
mapOf("1" to "2").forEach { (key, value) -> }
}
@@ -0,0 +1,2 @@
<!-- unsupportedFeature1 -->
The feature is only available since Kotlin 1.1: destructuring lambda parameters
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.LanguageVersion;
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS;
import org.jetbrains.kotlin.js.config.JSConfigurationKeys;
@@ -45,8 +47,8 @@ public abstract class AbstractDiagnosticMessageJsTest extends AbstractDiagnostic
@NotNull
@Override
protected AnalysisResult analyze(@NotNull KtFile file) {
return TopDownAnalyzerFacadeForJS.analyzeFiles(singletonList(file), getConfig());
protected AnalysisResult analyze(@NotNull KtFile file, @Nullable LanguageVersion explicitLanguageVersion) {
return TopDownAnalyzerFacadeForJS.analyzeFiles(singletonList(file), getConfig(explicitLanguageVersion));
}
@NotNull
@@ -62,12 +64,15 @@ public abstract class AbstractDiagnosticMessageJsTest extends AbstractDiagnostic
}
@NotNull
private JsConfig getConfig() {
private JsConfig getConfig(@Nullable LanguageVersion explicitLanguageVersion) {
CompilerConfiguration configuration = getEnvironment().getConfiguration().copy();
configuration.put(CommonConfigurationKeys.MODULE_NAME, KotlinTestUtils.TEST_MODULE_NAME);
configuration.put(JSConfigurationKeys.LIBRARY_FILES, LibrarySourcesConfig.JS_STDLIB);
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, true);
configuration.put(JSConfigurationKeys.UNIT_TEST_CONFIG, true);
if (explicitLanguageVersion != null) {
configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, new LanguageVersionSettingsImpl(explicitLanguageVersion));
}
return new LibrarySourcesConfig(getProject(), configuration);
}
}
@@ -24,6 +24,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.LanguageVersion;
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
import org.jetbrains.kotlin.diagnostics.Errors;
@@ -35,11 +39,13 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm;
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -73,8 +79,12 @@ public abstract class AbstractDiagnosticMessageTest extends KotlinTestWithEnviro
}
@NotNull
protected AnalysisResult analyze(@NotNull KtFile file) {
return JvmResolveUtil.analyze(file, getEnvironment());
protected AnalysisResult analyze(@NotNull KtFile file, @Nullable LanguageVersion explicitLanguageVersion) {
CompilerConfiguration configuration = getEnvironment().getConfiguration();
if (explicitLanguageVersion != null) {
configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, new LanguageVersionSettingsImpl(explicitLanguageVersion));
}
return JvmResolveUtil.analyze(Collections.singleton(file), getEnvironment(), configuration);
}
public void doTest(String filePath) throws Exception {
@@ -87,8 +97,11 @@ public abstract class AbstractDiagnosticMessageTest extends KotlinTestWithEnviro
final Set<DiagnosticFactory<?>> diagnosticFactories = getDiagnosticFactories(directives);
MessageType messageType = getMessageTypeDirective(directives);
String explicitLanguageVersion = InTextDirectivesUtils.findStringWithPrefixes(fileData, "// LANGUAGE_VERSION:");
LanguageVersion version = explicitLanguageVersion == null ? null : LanguageVersion.fromVersionString(explicitLanguageVersion);
KtFile psiFile = KotlinTestUtils.createFile(fileName, KotlinTestUtils.doLoadFile(getTestDataPath(), fileName), getProject());
AnalysisResult analysisResult = analyze(psiFile);
AnalysisResult analysisResult = analyze(psiFile, version);
BindingContext bindingContext = analysisResult.getBindingContext();
List<Diagnostic> diagnostics = ContainerUtil.filter(bindingContext.getDiagnostics().all(), new Condition<Diagnostic>() {
@@ -269,6 +269,12 @@ public class DiagnosticMessageTestGenerated extends AbstractDiagnosticMessageTes
doTest(fileName);
}
@TestMetadata("unsupportedFeature.kt")
public void testUnsupportedFeature() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/unsupportedFeature.kt");
doTest(fileName);
}
@TestMetadata("unusedParameter.kt")
public void testUnusedParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/unusedParameter.kt");