Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Continued Language API work #2980

Merged
merged 16 commits into from
Mar 1, 2013
Merged

Continued Language API work #2980

merged 16 commits into from
Mar 1, 2013

Conversation

jasonsanjose
Copy link
Member

Supercedes #2979.

@DennisKehrig I merged with master to resolve #2978

DennisKehrig and others added 7 commits February 27, 2013 14:02
…, 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
}
}

return { promise: promise, language: language };
Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Contributor

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?

Copy link
Member Author

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]+)*$/)) {
Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Contributor

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.

@jasonsanjose
Copy link
Member Author

Addressing the bullets from #2968

  1. We always resolve the promise now, so that addresses my comment. I added error checking for an empty mode string.
  2. Added capital letters. I don't feel strongly about the other restrictions. @DennisKehrig fixed the regex.
  3. @DennisKehrig fixed
  4. Changed to Object.keys
  5. @DennisKehrig fixed
  6. @jasonsanjose fixed
  7. @DennisKehrig updated comment
  8. @DennisKehrig fixed
  9. @DennisKehrig fixed
  10. @DennisKehrig fixed

The additional comments:

  • "rename" event is still not addressed, but I thought you referenced this in another bug earlier today?
  • haxe was fixed by @TomMalbran

@jasonsanjose
Copy link
Member Author

Changes pushed. @peterflynn ready to review.

@DennisKehrig
Copy link
Contributor

@jasonsanjose The rename issue is related to #2961

@jasonsanjose
Copy link
Member Author

@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.
Copy link
Member

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."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@peterflynn
Copy link
Member

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();
Copy link
Member

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?

Copy link
Member Author

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']");
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused var

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@peterflynn
Copy link
Member

@jasonsanjose (CC @DennisKehrig) Done reviewing

…se special null string for plain text mode. Update unit tests.
@jasonsanjose
Copy link
Member Author

@peterflynn ready to review

var extensionLoaderPromise = ExtensionLoader.init(params.get("extensions"));

// Load the initial project after extensions have loaded
extensionLoaderPromise.always(function () {
Copy link
Member

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.

Copy link
Member Author

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?

@peterflynn
Copy link
Member

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 added a commit that referenced this pull request Mar 1, 2013
@peterflynn peterflynn merged commit 4e44a07 into master Mar 1, 2013
@peterflynn peterflynn deleted the jasonsanjose-dk/language-api branch March 1, 2013 22:11
@DennisKehrig
Copy link
Contributor

@peterflynn We could compromise by requiring some modes unconditionally again, the rest will then happen synchronously and therefore reliably. Still not airtight, though.

@peterflynn
Copy link
Member

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants