diff --git a/source/rock/frontend/BuildParams.ooc b/source/rock/frontend/BuildParams.ooc index 812442c9..f3de28df 100644 --- a/source/rock/frontend/BuildParams.ooc +++ b/source/rock/frontend/BuildParams.ooc @@ -196,6 +196,9 @@ BuildParams: class { // More debug messages veryVerbose := false + // Give a warning when `this` is added implicitly + explicitThis := false + // Debugging purposes debugLoop := false debugLibcache := false diff --git a/source/rock/frontend/CommandLine.ooc b/source/rock/frontend/CommandLine.ooc index 3e862a9c..e216b5db 100644 --- a/source/rock/frontend/CommandLine.ooc +++ b/source/rock/frontend/CommandLine.ooc @@ -328,6 +328,10 @@ CommandLine: class { params verboser = true params veryVerbose = true + } else if (option == "explicitThis") { + + params explicitThis = true + } else if (option == "stats") { if(!longOption) warnUseLong("stats") diff --git a/source/rock/middle/Addon.ooc b/source/rock/middle/Addon.ooc index 3fe805a8..a69f0016 100644 --- a/source/rock/middle/Addon.ooc +++ b/source/rock/middle/Addon.ooc @@ -1,4 +1,5 @@ import structs/[ArrayList, HashMap, MultiMap] +import ../frontend/BuildParams import Node, Type, TypeDecl, FunctionDecl, FunctionCall, Visitor, VariableAccess, PropertyDecl, ClassDecl, CoverDecl import tinker/[Trail, Resolver, Response, Errors] @@ -155,9 +156,16 @@ Addon: class extends Node { } if (call suggest(fDecl, res, trail)) { - if (fDecl hasThis() && !call getExpr()) { - // add `this` if needed. - call setExpr(VariableAccess new("this", call token)) + if (!call getExpr()) { + if (fDecl hasThis()) { + // add `this` if needed. + call setExpr(VariableAccess new("this", call token)) + } + // Not yet tested + if (res params explicitThis) { + name := fDecl hasThis() ? "this" : "This" + call token printMessage("Implicit " + name + " detected for call to " + fDecl name + "!") + } } } ) diff --git a/source/rock/middle/TypeDecl.ooc b/source/rock/middle/TypeDecl.ooc index 008bfd24..566fb280 100644 --- a/source/rock/middle/TypeDecl.ooc +++ b/source/rock/middle/TypeDecl.ooc @@ -1253,6 +1253,29 @@ TypeDecl: abstract class extends Declaration { varAcc := VariableAccess new("this", access token) varAcc reverseExpr = access access expr = varAcc + if (res params explicitThis) { + mustBeExplicit := true + + // Generic variables do not require explicit this + if (vDecl getType()) { + if (vDecl getType() toString() == "Class") { + mustBeExplicit = false + } + } + + // Access to a variable from within its own declaration does not have to be explicit + depth := trail getSize() - 1 + while (depth >= 0) { + if (trail get(depth) == vDecl) { + mustBeExplicit = false + } + depth -= 1 + } + + if (mustBeExplicit) { + access token printMessage("Implicit this detected for variable access of " + vDecl name + "!") + } + } } return 0 } @@ -1360,8 +1383,14 @@ TypeDecl: abstract class extends Declaration { if (fDecl) { if (call debugCondition()) " \\o/ Found fDecl for %s, it's %s" format(call name, fDecl toString()) println() if (call suggest(fDecl, res, trail)) { - if (fDecl hasThis() && !call getExpr()) { - call setExpr(VariableAccess new("this", call token)) + if (!call getExpr()) { + if (fDecl hasThis()) { + call setExpr(VariableAccess new("this", call token)) + } + if (res params explicitThis && fDecl name != "init" && fDecl name != ClassDecl DEFAULTS_FUNC_NAME) { + name := fDecl hasThis() ? "this" : "This" + call token printMessage("Implicit " + name + " detected for call to " + fDecl name + "!") + } } return 0 } @@ -1391,6 +1420,9 @@ TypeDecl: abstract class extends Declaration { // if the variable is static, use class scope not instance name := vDecl isStatic() ? "This" : "this" call setExpr(VariableAccess new(name, call token)) + if (res params explicitThis) { + call token printMessage("Implicit " + name + " detected for call to " + vDecl name + "!") + } } } }