Skip to content

Commit 30f9c2a

Browse files
authored
Extend pedantic diagnostics (#1075)
1 parent f80c33c commit 30f9c2a

File tree

5 files changed

+59
-5
lines changed

5 files changed

+59
-5
lines changed

src/compiler.ts

+23-4
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ export class Compiler extends DiagnosticEmitter {
428428
if (cyclicClasses.size) {
429429
if (options.pedantic) {
430430
for (let classInstance of cyclicClasses) {
431-
this.info(
431+
this.pedantic(
432432
DiagnosticCode.Type_0_is_cyclic_Module_will_include_deferred_garbage_collection,
433433
classInstance.identifierNode.range, classInstance.internalName
434434
);
@@ -504,7 +504,7 @@ export class Compiler extends DiagnosticEmitter {
504504
if (options.importTable) {
505505
module.addTableImport("0", "env", "table");
506506
if (options.pedantic && options.willOptimize) {
507-
this.warning(
507+
this.pedantic(
508508
DiagnosticCode.Importing_the_table_disables_some_indirect_call_optimizations,
509509
null
510510
);
@@ -513,7 +513,7 @@ export class Compiler extends DiagnosticEmitter {
513513
if (options.exportTable) {
514514
module.addTableExport("0", ExportNames.table);
515515
if (options.pedantic && options.willOptimize) {
516-
this.warning(
516+
this.pedantic(
517517
DiagnosticCode.Exporting_the_table_disables_some_indirect_call_optimizations,
518518
null
519519
);
@@ -5578,6 +5578,12 @@ export class Compiler extends DiagnosticEmitter {
55785578
assert(indexedSet.signature.parameterTypes.length == 2); // parser must guarantee this
55795579
targetType = indexedSet.signature.parameterTypes[1]; // 2nd parameter is the element
55805580
if (indexedSet.hasDecorator(DecoratorFlags.UNSAFE)) this.checkUnsafe(expression);
5581+
if (!isUnchecked && this.options.pedantic) {
5582+
this.pedantic(
5583+
DiagnosticCode.Indexed_access_may_involve_bounds_checking,
5584+
expression.range
5585+
);
5586+
}
55815587
break;
55825588
}
55835589
default: {
@@ -7220,11 +7226,18 @@ export class Compiler extends DiagnosticEmitter {
72207226
if (targetType.is(TypeFlags.REFERENCE)) {
72217227
let classReference = targetType.classReference;
72227228
if (classReference) {
7223-
let indexedGet = classReference.lookupOverload(OperatorKind.INDEXED_GET, this.currentFlow.is(FlowFlags.UNCHECKED_CONTEXT));
7229+
let isUnchecked = this.currentFlow.is(FlowFlags.UNCHECKED_CONTEXT);
7230+
let indexedGet = classReference.lookupOverload(OperatorKind.INDEXED_GET, isUnchecked);
72247231
if (indexedGet) {
72257232
let thisArg = this.compileExpression(targetExpression, classReference.type,
72267233
Constraints.CONV_IMPLICIT
72277234
);
7235+
if (!isUnchecked && this.options.pedantic) {
7236+
this.pedantic(
7237+
DiagnosticCode.Indexed_access_may_involve_bounds_checking,
7238+
expression.range
7239+
);
7240+
}
72287241
return this.compileCallDirect(indexedGet, [
72297242
expression.elementExpression
72307243
], expression, thisArg, constraints);
@@ -7671,6 +7684,12 @@ export class Compiler extends DiagnosticEmitter {
76717684
], expression)
76727685
);
76737686
flow.freeTempLocal(temp);
7687+
if (this.options.pedantic) {
7688+
this.pedantic(
7689+
DiagnosticCode.Expression_compiles_to_a_dynamic_check_at_runtime,
7690+
expression.range
7691+
);
7692+
}
76747693
return ret;
76757694
} else {
76767695
this.error(

src/diagnosticMessages.generated.ts

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export enum DiagnosticCode {
4040
Type_0_is_cyclic_Module_will_include_deferred_garbage_collection = 900,
4141
Importing_the_table_disables_some_indirect_call_optimizations = 901,
4242
Exporting_the_table_disables_some_indirect_call_optimizations = 902,
43+
Expression_compiles_to_a_dynamic_check_at_runtime = 903,
44+
Indexed_access_may_involve_bounds_checking = 904,
4345
Unterminated_string_literal = 1002,
4446
Identifier_expected = 1003,
4547
_0_expected = 1005,
@@ -187,6 +189,8 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
187189
case 900: return "Type '{0}' is cyclic. Module will include deferred garbage collection.";
188190
case 901: return "Importing the table disables some indirect call optimizations.";
189191
case 902: return "Exporting the table disables some indirect call optimizations.";
192+
case 903: return "Expression compiles to a dynamic check at runtime.";
193+
case 904: return "Indexed access may involve bounds checking.";
190194
case 1002: return "Unterminated string literal.";
191195
case 1003: return "Identifier expected.";
192196
case 1005: return "'{0}' expected.";

src/diagnosticMessages.json

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
"Type '{0}' is cyclic. Module will include deferred garbage collection.": 900,
3535
"Importing the table disables some indirect call optimizations.": 901,
3636
"Exporting the table disables some indirect call optimizations.": 902,
37+
"Expression compiles to a dynamic check at runtime.": 903,
38+
"Indexed access may involve bounds checking.": 904,
3739

3840
"Unterminated string literal.": 1002,
3941
"Identifier expected.": 1003,

src/diagnostics.ts

+29
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export {
2424

2525
/** Indicates the category of a {@link DiagnosticMessage}. */
2626
export enum DiagnosticCategory {
27+
/** Overly pedantic message. */
28+
PEDANTIC,
2729
/** Informatory message. */
2830
INFO,
2931
/** Warning message. */
@@ -35,6 +37,7 @@ export enum DiagnosticCategory {
3537
/** Returns the string representation of the specified diagnostic category. */
3638
export function diagnosticCategoryToString(category: DiagnosticCategory): string {
3739
switch (category) {
40+
case DiagnosticCategory.PEDANTIC: return "PEDANTIC";
3841
case DiagnosticCategory.INFO: return "INFO";
3942
case DiagnosticCategory.WARNING: return "WARNING";
4043
case DiagnosticCategory.ERROR: return "ERROR";
@@ -51,12 +54,15 @@ export const COLOR_BLUE: string = "\u001b[96m";
5154
export const COLOR_YELLOW: string = "\u001b[93m";
5255
/** ANSI escape sequence for red foreground. */
5356
export const COLOR_RED: string = "\u001b[91m";
57+
/** ANSI escape sequence for magenta foreground. */
58+
export const COLOR_MAGENTA: string = "\u001b[95m";
5459
/** ANSI escape sequence to reset the foreground color. */
5560
export const COLOR_RESET: string = "\u001b[0m";
5661

5762
/** Returns the ANSI escape sequence for the specified category. */
5863
export function diagnosticCategoryToColor(category: DiagnosticCategory): string {
5964
switch (category) {
65+
case DiagnosticCategory.PEDANTIC: return COLOR_MAGENTA;
6066
case DiagnosticCategory.INFO: return COLOR_BLUE;
6167
case DiagnosticCategory.WARNING: return COLOR_YELLOW;
6268
case DiagnosticCategory.ERROR: return COLOR_RED;
@@ -275,6 +281,29 @@ export abstract class DiagnosticEmitter {
275281
// console.log(<string>new Error("stack").stack);
276282
}
277283

284+
/** Emits an overly pedantic diagnostic message. */
285+
pedantic(
286+
code: DiagnosticCode,
287+
range: Range | null,
288+
arg0: string | null = null,
289+
arg1: string | null = null,
290+
arg2: string | null = null
291+
): void {
292+
this.emitDiagnostic(code, DiagnosticCategory.PEDANTIC, range, null, arg0, arg1, arg2);
293+
}
294+
295+
/** Emits an overly pedantic diagnostic message with a related range. */
296+
pedanticRelated(
297+
code: DiagnosticCode,
298+
range: Range,
299+
relatedRange: Range,
300+
arg0: string | null = null,
301+
arg1: string | null = null,
302+
arg2: string | null = null
303+
): void {
304+
this.emitDiagnostic(code, DiagnosticCategory.PEDANTIC, range, relatedRange, arg0, arg1, arg2);
305+
}
306+
278307
/** Emits an informatory diagnostic message. */
279308
info(
280309
code: DiagnosticCode,

tests/compiler/instanceof.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ assert(!(I instanceof A));
1515
assert(!(f instanceof A));
1616
assert(!(F instanceof A));
1717

18-
// assert(!(a instanceof B)); // dynamic upcast, checked in runtime/instanceof
18+
// assert(!(a instanceof B)); // dynamic upcast, checked in rt/instanceof
1919
assert( b instanceof B );
2020
assert(!(i instanceof B));
2121
assert(!(I instanceof B));

0 commit comments

Comments
 (0)