I feel like these should be UPPER_SNAKE_CASE since they’re constants.
I agree with @pobammer… I love it but am not a fan of the naming. Nothing else aside from data type constructors begin with lowercase letters. I would personally prefer CamelCase
or UPPER_SNAKE_CASE
for these, however the latter breaks conventions too.
Has CamelCase
been considered?
All variants have been considered.
At excruciating length in fact: I actually implemented these 2 months ago, but left them sitting uncommitted until recently because I kept going back and forth internally and with some coworkers over whether the current casing was really the best one to use.
I would disagree considering it follows suit with API such as math.pi
and math.huge
.
Unfortunately not
Tested it on a fresh baseplate to make sure that any PlayerModule customization didn’t get in the way of this, still no good results.
Judging by the FFlag’s name, I believe it’s related to this:
It’s really confusing when you type camelCase in the form of PascalCase. Which one is it you’re referring to?
PascalCase, I got a little mixed up.
Ever since this update, the following require
that I use in most of my scripts has become an unsupported path; no longer autofills and throws a warning:
local MyModule = require(game:GetService("ReplicatedStorage"):WaitForChild("ModuleName"))
Why are you using WaitForChild
there, is ModuleName
a dynamically created object? If not you don’t need to wait for it.
Static objects that exist in the place file at load time are guaranteed to be present before scripts start running, so they don’t need to be waited on (with the obvious exception that scripts in ReplicatedFirst
don’t have any guarantees at all).
I was referring to scripts as a generalised term for LuaSourceContainers. This is also used in (locally required) Modules and LocalScripts, where replication is not a guarantee.
It’s actually the same either way, even LocalScripts (as long as they aren’t in ReplicatedFirst) can rely on the content that was statically loaded from the place file on the server being fully replicated before they run. The best succinct description I know of of the behavior: Can I use game.Loaded to avoid using WaitForChild? - #18 by Anaminus
I’m getting this issue with absolute paths. I mostly notice it on ReplicatedStorage stuff, but that’s primarily since most of my modules don’t live outside of that service.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TypeDefs = require(ReplicatedStorage.CoreData.TypeDefs)
-- Gives me an "unsupported path" warning even though this exists in studio and is
-- not created during runtime.
-- This also occurs if ReplicatedStorage isn't a variable e.g.
-- require(game:GetService("ReplicatedStorage").CoreData.TypeDefs)
-- It does NOT occur if I use game.ReplicatedStorage
-- It only occurs with game:GetService("ReplicatedStorage")
type SomeType = TypeDefs.SomeType -- And this warns for unknown type due to ^
I’ve since renounced that post:
Even disregarding the problems with direct indexing, the complexity behind deciding whether or not a module path is actually safe, combined with the lack of official documentation to guide the decision, is too much. I made that first post trying to frame the problem with locating objects in the game tree, but I believe it falls short. Now, I would only use it to demonstrate the complexity of the problem, and the need for a proper solution.
For modules at least, I feel like the long-term solution will be some sort of feature that handles everything for you (e.g. an analyzer that finds and replicates modules early, or an explicit module registry). Until then, FindFirstChild/WaitForChild/GetService definitely need to be supported by analysis in some capacity. Analysis already assumes that a directly indexed path is correct statically, even if it wont be correct at runtime. I see no reason why the other methods couldn’t be treated the same way.
It seems like everything else in the API is PascalCase
Everything except for constructors like Vector3.new()
and CFrame.lookAt()
. That’s what it comes down to, that these feel closer to the constructors than the rest of the API surface. Though like I note above, there’s advantages to the other casings too, it was a very close decision.
Thanks for taking the time to jump in on this topic. I’d like to note that while the discussion has been focused on my usage of WaitForChild
; both it and FindFirstChild
still seem to be working without issue.
The problem itself seems to be caused by the inline reference to GetService
.
Building on both your post and tnavarts answer, I’d like to point out that during the time that I’ve been a Roblox developer the behaviour as described in your previous, renounced post and by Roblox staff on multiple discussions has always been undocumented.
I believe it to be unfeasible to rely on any behaviour that is not written down, and until such time as the engineering team is willing to nail its trousers to the mast (so they can’t climb down) (props to whomever gets the reference), I’d consider it dangerous to not rely on WaitForChild
for practically everything client-side. Shameless plug for my short post on it.
This is a consequence of a recent change on our side.
Require paths like these are supported, we will revert the change soon and make sure to fix it before the next rollout.
Sorry for the trouble.
Could we get some elaboration on ScriptChangeService
?
Most services are internal ones used by Studio / the game engine, there’s not much more to add.
Are there any plans to introduce methods, that developers can access, regarding the script editor? (Plugin script cursor methods - #4 by Corecii)