Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds check for local variable in scope operator check #2227

Merged
merged 8 commits into from
Feb 24, 2025
19 changes: 14 additions & 5 deletions Content.Tests/DMProject/Tests/Operators/scope.dm
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/datum
var/static/datum/three/three
var/text = "hello"

var/static/one = "one"

/datum/three
var/static/datum/four/four
text = "hi"
var/overridden_text = type::text
var/original_text = parent_type::text

/datum/three/proc/typetest()
// initial shorthand, type:: and parent_type::
ASSERT(text == "hi")
Expand All @@ -21,7 +21,7 @@ var/static/one = "one"
ASSERT(src::text == "hi")
ASSERT(src::overridden_text == "hi")
ASSERT(src::original_text == "hello")

// proc reference
ASSERT(__PROC__ == /datum/three::typetest())

Expand All @@ -31,11 +31,17 @@ var/static/one = "one"
/datum/five
var/static/six = "three four five six"

/datum/six
var/toughness = 100
reinforced
toughness = parent_type::toughness + 50

/proc/return_two()
return "two"

/proc/RunTest()
// global vars and procs
var/one = "not one"
ASSERT(::one == "one")
ASSERT(::return_two() == "two")

Expand All @@ -52,10 +58,13 @@ var/static/one = "one"
ASSERT(test::three::four.five::six == "3 4 5 6")
ASSERT(/datum::three::four.five::six == "3 4 5 6")

// this does not compile in BYOND, that is just a bug
// this does not compile in BYOND, that is just a bug
test::three::four.five::six = "7 8 9 10"
ASSERT(test::three::four.five::six == "7 8 9 10")
ASSERT(/datum::three::four.five::six == "7 8 9 10")

var/datum/three/threetest = new
threetest.typetest()

var/datum/six/reinforced/fourtest = new()
ASSERT(fourtest.toughness == 150)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// COMPILE ERROR OD0011

/datum/armor
var/toughness = 100
reinforced
proc/test_proc()
toughness = parent_type::toughness + 50
1 change: 1 addition & 0 deletions DMCompiler/Compiler/CompilerError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public enum WarningCode {

// 2000 - 2999 are reserved for compiler configuration of actual behaviour.
SoftReservedKeyword = 2000, // For keywords that SHOULD be reserved, but don't have to be. 'null' and 'defined', for instance
ScopeOperandNamedType = 2001, // Scope operator is used on a var named type or parent_type, maybe unintentionally
DuplicateVariable = 2100,
DuplicateProcDefinition = 2101,
PointlessParentCall = 2205,
Expand Down
17 changes: 12 additions & 5 deletions DMCompiler/DM/Builders/DMExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -644,11 +644,18 @@
if (scopeIdentifier.Expression is DMASTIdentifier { Identifier: "type" or "parent_type" } identifier) {
// This is the same behaviour as in BYOND, but BYOND simply raises an undefined var error.
// We want to give end users an explanation at least.
if (scopeMode is Normal && ctx.Proc != null)
return BadExpression(WarningCode.BadExpression, identifier.Location,
"Use of \"type::\" and \"parent_type::\" outside of a context is forbidden");

if (identifier.Identifier == "parent_type") {
if (scopeMode is Normal && ctx.Proc != null) {
if (ctx.Proc.GetLocalVariable(identifier.Identifier) != null) {
// actually - it's referring to a local variable named "type" or "parent_type"... just do the usual thing
Compiler.Emit(WarningCode.ScopeOperandNamedType, identifier.Location,
$"Using scope operator :: on a variable named \"type\" or \"parent_type\" is ambiguous. Consider changing the variable name from \"{identifier.Identifier}\".");
expression = BuildExpression(scopeIdentifier.Expression, inferredPath);
} else {
return BadExpression(WarningCode.BadExpression, identifier.Location,
"Use of \"type::\" and \"parent_type::\" inside an object proc is only valid when " +
"there is a local variable named \"type\" or \"parent_type\"");
}
} else if (identifier.Identifier == "parent_type") {
if (ctx.Type.Parent == null)
return BadExpression(WarningCode.ItemDoesntExist, identifier.Location,
$"Type {ctx.Type.Path} does not have a parent");
Expand Down
1 change: 1 addition & 0 deletions DMCompiler/DMStandard/DefaultPragmaConfig.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

//2000-2999
#pragma SoftReservedKeyword error
#pragma ScopeOperandNamedType warning
#pragma DuplicateVariable warning
#pragma DuplicateProcDefinition error
#pragma PointlessParentCall warning
Expand Down
Loading