emit error when proc is defined multiple times (#181)

* emit error when proc is defined multiple times

* simplify

* simpler

Co-authored-by: spookydonut <github@spooksoftware.com>
This commit is contained in:
William Wallace 2020-05-08 17:42:34 +01:00 committed by GitHub
parent c63f9ac567
commit 36313f0915
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 1 deletions

View file

@ -38,6 +38,7 @@ Raised by DreamChecker:
* `protected_var` - `SpacemanDMM_protected` var type
* `must_be_pure` - `SpacemanDMM_should_be_pure` directive
* `must_not_sleep` - `SpacemanDMM_should_not_sleep` directive
* `redefined_proc` - `SpacemanDMM_can_be_redefined` directive
* `ambiguous_in_lhs` - Raised on ambiguous operations on the left hand side of an `in` operation
* `no_typehint_implicit_new` - Raised on the use of `new` where no typehint is avaliable
* `field_access_static_type` - Raised on using `.field_name` on a variable with no typehint

View file

@ -65,6 +65,7 @@ be enabled:
#define SHOULD_BE_PURE(X) set SpacemanDMM_should_be_pure = X
#define PRIVATE_PROC(X) set SpacemanDMM_private_proc = X
#define PROTECTED_PROC(X) set SpacemanDMM_protected_proc = X
#define CAN_BE_REDEFINED(X) set SpacemanDMM_can_be_redefined = X
#define VAR_FINAL var/SpacemanDMM_final
#define VAR_PRIVATE var/SpacemanDMM_private
#define VAR_PROTECTED var/SpacemanDMM_protected
@ -77,6 +78,7 @@ be enabled:
#define SHOULD_BE_PURE(X)
#define PRIVATE_PROC(X)
#define PROTECTED_PROC(X)
#define CAN_BE_REDEFINED(X)
#define VAR_FINAL var
#define VAR_PRIVATE var
#define VAR_PROTECTED var
@ -153,3 +155,8 @@ This also checks to make sure anything using this proc doesn't invoke it without
making use of the return value.
This cannot be disabled by child overrides.
## Proc redefinitions
Multiple definitions of a proc in the same type-path will raise a warning.
Use `set SpacemanDMM_can_be_redefined = 1` to allow a proc to be redefined.

View file

@ -533,6 +533,7 @@ pub struct AnalyzeObjectTree<'o> {
must_not_sleep: ProcDirective<'o>,
sleep_exempt: ProcDirective<'o>,
must_be_pure: ProcDirective<'o>,
can_be_redefined: ProcDirective<'o>,
// Debug(ProcRef) -> KwargInfo
used_kwargs: BTreeMap<String, KwargInfo>,
@ -559,6 +560,7 @@ impl<'o> AnalyzeObjectTree<'o> {
must_not_sleep: ProcDirective::new("SpacemanDMM_should_not_sleep", false, true, true),
sleep_exempt: ProcDirective::new("SpacemanDMM_allowed_to_sleep", false, true, true),
must_be_pure: ProcDirective::new("SpacemanDMM_should_be_pure", false, true, true),
can_be_redefined: ProcDirective::new("SpacemanDMM_can_be_redefined", false, false, false),
used_kwargs: Default::default(),
call_tree: Default::default(),
sleeping_procs: Default::default(),
@ -582,6 +584,7 @@ impl<'o> AnalyzeObjectTree<'o> {
"SpacemanDMM_should_not_sleep" => &mut self.must_not_sleep,
"SpacemanDMM_allowed_to_sleep" => &mut self.sleep_exempt,
"SpacemanDMM_should_be_pure" => &mut self.must_be_pure,
"SpacemanDMM_can_be_redefined" => &mut self.can_be_redefined,
other => {
error(location, format!("unknown linter setting {:?}", directive))
.with_errortype("unknown_linter_setting")
@ -1113,7 +1116,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> {
//println!("purity {}", self.is_pure);
if self.proc_ref.parent_proc().is_some() {
if let Some(parent) = self.proc_ref.parent_proc() {
if let Some((proc, true, location)) = self.env.private.get_self_or_parent(self.proc_ref) {
if proc != self.proc_ref {
error(self.proc_ref.location, format!("proc overrides private parent, prohibited by {}", proc))
@ -1138,6 +1141,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> {
.register(self.context);
}
}
if !parent.is_builtin() && self.proc_ref.ty() == parent.ty()
&& self.env.can_be_redefined.get_self_or_parent(self.proc_ref).is_none() {
error(self.proc_ref.location, format!("redefining proc {}/{}", self.ty, self.proc_ref.name()))
.with_errortype("redefined_proc")
.with_note(parent.location, "previous definition is here")
.register(self.context);
}
}
}

View file

@ -79,3 +79,32 @@ fn no_override_disable() {
"##.trim();
check_errors_match(code, NO_OVERRIDE_DISABLE_ERRORS);
}
#[test]
fn can_be_redefined() {
let code = r##"
/mob/proc/test()
set SpacemanDMM_can_be_redefined = 1
return
/mob/test()
return
"##.trim();
check_errors_match(code, NO_ERRORS);
}
pub const NO_CAN_BE_REDEFINED_ERRORS: &[(u32, u16, &str)] = &[
(4, 10, "redefining proc /mob/test"),
];
#[test]
fn no_can_be_redefined() {
let code = r##"
/mob/proc/test()
return
/mob/test()
return
"##.trim();
check_errors_match(code, NO_CAN_BE_REDEFINED_ERRORS);
}