-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Conversation
…, defineLanguage now returns a promise that resolves once the mode has been loaded and set, instead of returning the language directly. To make things more consistent both within LanguageManager and with the rest of the code base, chaining support has been removed.
…clusively through getters and setters Adjust the unit tests accordingly Added documentation to Language's properties Refined the comment about our special HTML MIME mode Renamed fileExtensionsToLanguageMap to fileExtensionToLanguageMap
Call result.reject in a few places instead of throwing exceptions
Conflicts: test/spec/Editor-test.js
} | ||
} | ||
|
||
return { promise: promise, language: language }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From @DennisKehrig
For convenience, return both a promise and a language.
Maybe this is a good idea for LanguageManager.defineLanguage(), too?
Or maybe we want to go in the opposite direction, i.e. make sure that a language is only registered (via ID, mode or file extensions) once it's fully specified. I.e. we'd wait with registering it until just before we resolve the promise in defineLanguage to make this basically an atomic operation and not have "incomplete" languages lying around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of not registering it at all until the promise is resolved (that is, until the mode is loaded). That would fix #2962 too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I'll write up the fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious on how you will rewrite the unit tests to deal with that, would you just test once that the promise is resolved and then rely on it in later tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. There's a new property ready
promise on LanguageManager that checks when all the default languages are loaded. Each test was also updated to wait for the promise when calling defineLanguage
.
// Hence we use _ instead of "." since this makes it easier to parse a file name containing a language ID | ||
if (!id.match(/^[a-z]+(\.[a-z]+)*$/)) { | ||
// Hence we use "_" instead of "." since the latter often has special meaning | ||
if (!id.match(/^[a-z]+(_[a-z]+)*$/)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't think we should be so strict about ids. We don't even allow capital letters here... For Command ids, we encourage package-style naming but don't enforce anything specific. I'm still unsure why that's not good enough for Language ids too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From @DennisKehrig's comment in the original pull request #2844 (comment), he proposes hypothetical jQuery events on a language. If the language has a dot, it's treated as a namespace, e.g.
$(LanguageManager).on("myLanguageId.myNamespace")
He makes a few other points about restricting the use of a dot. I think capital letters should be ok though. I'll add that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Capital letters are okay, though we lose the ability to convert from foo_bar to FooBar and back, should we ever want/need that.
Addressing the bullets from #2968
The additional comments:
|
Changes pushed. @peterflynn ready to review. |
@jasonsanjose The rename issue is related to #2961 |
@peterflynn ready to review |
* To find out existing MIME modes, search for "CodeMirror.defineMIME" in thirdparty/CodeMirror2/mode | ||
* For instance, C++, C# and Java all use the clike mode. | ||
* To find existing MIME modes, search for "CodeMirror.defineMIME" in thirdparty/CodeMirror2/mode | ||
* For instance, C++, C# and Java all use the clike (C-like) mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be clearer if it read "...all use the "clike" (C-like) mode with different settings and a different MIME name."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Crap, gotta run to dinner -- will finish review in a couple of hours. Sorry about the delay! |
|
||
// Since setting the mode is asynchronous when the mode hasn't been loaded yet, offer a reliable way to wait until it is ready | ||
this._modeReady = new $.Deferred(); | ||
this.modeReady = this._modeReady.promise(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docs above say you can get a Language right away by calling getLanguage() after defineLanguage(), but moving this into the done() handler makes that untrue.
This also makes the if (_languages[id])
check above unreliable -- as long as you can call defineLanguage() for two colliding languages before either one finishes loading, no warning.
So perhaps registering the id should be moved back here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed comment, added _pendingLanguages
to track collisions.
|
||
if (!isPlainText && (!mode || mode === "")) { | ||
result.reject("Mode must be specified as a built-in CodeMirror mode or [\'\', 'text/plain']"); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused var
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@jasonsanjose (CC @DennisKehrig) Done reviewing |
…se special null string for plain text mode. Update unit tests.
@peterflynn ready to review |
var extensionLoaderPromise = ExtensionLoader.init(params.get("extensions")); | ||
|
||
// Load the initial project after extensions have loaded | ||
extensionLoaderPromise.always(function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course thinking about it more, I realized there's a case this doesn't fix :-P The race condition still exists for any new modes added by extensions -- we begin project loading (including opening editors) after the extension itself has loaded but potentially before its mode has... So we should probably still leave #2962 open at a lower priority to try to come up with a more robust fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about I close #2962 and file a new bug specifically for the extension use case?
Looks good to go -- merging. I'd prefer we leave #2962 open though, since the main use case (calling from extensions) isn't fixed yet. But it seems ok to punt it to next sprint. |
@peterflynn We could compromise by requiring some modes unconditionally again, the rest will then happen synchronously and therefore reliably. Still not airtight, though. |
I believe Jason's last commit here guarantees that the only core mode subject to this bug is LESS. The main modes that would be vulnerable to the bug are those added by third-party extensions. |
Supercedes #2979.
@DennisKehrig I merged with master to resolve #2978