From aee32cfcadc6dcd28b8fa35505a0ba3acfcf95c2 Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 28 May 2020 19:48:36 +0200 Subject: [PATCH] Warn on unused generic exports --- src/compiler.ts | 20 ++++++++++++++++---- src/diagnosticMessages.generated.ts | 2 ++ src/diagnosticMessages.json | 1 + tests/compiler/export-generic.json | 17 +++++++++++++++++ tests/compiler/export-generic.ts | 14 ++++++++++++++ 5 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 tests/compiler/export-generic.json create mode 100644 tests/compiler/export-generic.ts diff --git a/src/compiler.ts b/src/compiler.ts index e29fc6ecd5..059cf752e4 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -695,8 +695,9 @@ export class Compiler extends DiagnosticEmitter { // traverse instances case ElementKind.FUNCTION_PROTOTYPE: { - let functionInstances = (element).instances; - if (functionInstances) { + let functionPrototype = element; + let functionInstances = functionPrototype.instances; + if (functionInstances !== null && functionInstances.size > 0) { // TODO: for (let instance of instances.values()) { for (let _values = Map_values(functionInstances), i = 0, k = _values.length; i < k; ++i) { let instance = unchecked(_values[i]); @@ -707,12 +708,18 @@ export class Compiler extends DiagnosticEmitter { } this.ensureModuleExport(instanceName, instance, prefix); } + } else if (functionPrototype.is(CommonFlags.GENERIC)) { + this.warning( + DiagnosticCode.Exported_generic_function_or_class_has_no_concrete_instances, + functionPrototype.identifierNode.range + ); } break; } case ElementKind.CLASS_PROTOTYPE: { - let classInstances = (element).instances; - if (classInstances) { + let classPrototype = element; + let classInstances = classPrototype.instances; + if (classInstances !== null && classInstances.size > 0) { // TODO: for (let instance of instances.values()) { for (let _values = Map_values(classInstances), i = 0, k = _values.length; i < k; ++i) { let instance = unchecked(_values[i]); @@ -723,6 +730,11 @@ export class Compiler extends DiagnosticEmitter { } this.ensureModuleExport(instanceName, instance, prefix); } + } else if (classPrototype.is(CommonFlags.GENERIC)) { + this.warning( + DiagnosticCode.Exported_generic_function_or_class_has_no_concrete_instances, + classPrototype.identifierNode.range + ); } break; } diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index e519dde336..f80bf17c68 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -48,6 +48,7 @@ export enum DiagnosticCode { Property_0_only_has_a_setter_and_is_missing_a_getter = 229, _0_keyword_cannot_be_used_here = 230, A_class_with_a_constructor_explicitly_returning_something_else_than_this_must_be_final = 231, + Exported_generic_function_or_class_has_no_concrete_instances = 232, Type_0_is_cyclic_Module_will_include_deferred_garbage_collection = 900, Importing_the_table_disables_some_indirect_call_optimizations = 901, Exporting_the_table_disables_some_indirect_call_optimizations = 902, @@ -221,6 +222,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 229: return "Property '{0}' only has a setter and is missing a getter."; case 230: return "'{0}' keyword cannot be used here."; case 231: return "A class with a constructor explicitly returning something else than 'this' must be '@final'."; + case 232: return "Exported generic function or class has no concrete instances."; case 900: return "Type '{0}' is cyclic. Module will include deferred garbage collection."; case 901: return "Importing the table disables some indirect call optimizations."; case 902: return "Exporting the table disables some indirect call optimizations."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 8a3141ee84..d7a8750a76 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -41,6 +41,7 @@ "Property '{0}' only has a setter and is missing a getter.": 229, "'{0}' keyword cannot be used here.": 230, "A class with a constructor explicitly returning something else than 'this' must be '@final'.": 231, + "Exported generic function or class has no concrete instances.": 232, "Type '{0}' is cyclic. Module will include deferred garbage collection.": 900, "Importing the table disables some indirect call optimizations.": 901, diff --git a/tests/compiler/export-generic.json b/tests/compiler/export-generic.json new file mode 100644 index 0000000000..1b7c4aae33 --- /dev/null +++ b/tests/compiler/export-generic.json @@ -0,0 +1,17 @@ +{ + "asc_flags": [ + "--runtime none" + ], + "stderr": [ + "AS232: Exported generic function or class has no concrete instances.", + "export function testFunction", + "AS232: Exported generic function or class has no concrete instances.", + "export class TestClass", + "AS232: Exported generic function or class has no concrete instances.", + "public testMethod()", + "AS232: Exported generic function or class has no concrete instances.", + "export function testNamespacedFunction", + "AS232: Exported generic function or class has no concrete instances.", + "export class TestNamespacedClass" + ] +} \ No newline at end of file diff --git a/tests/compiler/export-generic.ts b/tests/compiler/export-generic.ts new file mode 100644 index 0000000000..def0f4b67b --- /dev/null +++ b/tests/compiler/export-generic.ts @@ -0,0 +1,14 @@ +export function testFunction(): void {} + +export class TestClass {} + +export class Foo { + public testMethod(): void {} +} + +export namespace test { + export function testNamespacedFunction(): void {} + export class TestNamespacedClass {} +} + +ERROR("EOF");