From b8bdd948cdaaf224d424f28f46459ed3777742e5 Mon Sep 17 00:00:00 2001 From: Dennis Kehrig Date: Tue, 19 Mar 2013 16:10:12 +0100 Subject: [PATCH 1/4] Allow extensions to inherit from other extensions (i.e. SVG from XML) --- src/language/LanguageManager.js | 139 +++++++++++++++++++++++------- test/spec/LanguageManager-test.js | 82 +++++++++++++++++- 2 files changed, 187 insertions(+), 34 deletions(-) diff --git a/src/language/LanguageManager.js b/src/language/LanguageManager.js index 04e8c045ac5..a02f07ac4cf 100644 --- a/src/language/LanguageManager.js +++ b/src/language/LanguageManager.js @@ -169,8 +169,9 @@ define(function (require, exports, module) { * @param {!Language} language The language to associate with the mode */ function _setLanguageForMode(mode, language) { - if (_modeToLanguageMap[mode]) { - console.warn("CodeMirror mode \"" + mode + "\" is already used by language " + _modeToLanguageMap[mode]._name + ", won't register for " + language._name); + var mappedLanguage = _modeToLanguageMap[mode]; + if (mappedLanguage && !language.hasAncestor(mappedLanguage)) { + console.warn("CodeMirror mode \"" + mode + "\" is already used by language " + mappedLanguage.getName() + ", won't register for " + language.getName()); return; } @@ -196,10 +197,6 @@ define(function (require, exports, module) { filename = PathUtils.filename(path).toLowerCase(), language = extension ? _fileExtensionToLanguageMap[extension] : _fileNameToLanguageMap[filename]; - if (!language) { - console.log("Called LanguageManager.getLanguageForPath with an unhandled " + (extension ? "file extension" : "file name") + ":", extension || filename); - } - return language || _fallbackLanguage; } @@ -276,6 +273,9 @@ define(function (require, exports, module) { /** @type {string} Human-readable name of this language */ Language.prototype._name = null; + /** @type {?Language} Parent language */ + Language.prototype._parent = null; + /** @type {string} CodeMirror mode for this language */ Language.prototype._mode = null; @@ -288,12 +288,12 @@ define(function (require, exports, module) { /** @type {Array.} Line comment syntax */ Language.prototype._lineCommentSyntax = null; - /** @type {Object.} Which language to use for what CodeMirror mode */ - Language.prototype._modeToLanguageMap = null; - /** @type {{ prefix: string, suffix: string }} Block comment syntax */ Language.prototype._blockCommentSyntax = null; + /** @type {Object.} Which language to use for what CodeMirror mode */ + Language.prototype._modeToLanguageMap = null; + /** * Returns the identifier for this language. * @return {string} The identifier @@ -310,12 +310,38 @@ define(function (require, exports, module) { return this._name; }; + /** + * Set the language this language inherits from + * @param {string|Language} parent The parent language or its ID + */ + Language.prototype._setParent = function (parent) { + if (!(parent instanceof Language)) { + parent = getLanguage(parent); + } + this._parent = parent; + }; + + /** + * Determines whether the language is this language's parent, or the parent's parent, etc. + * @param {Language} The language to test + * @return {boolean} True if language is an ancestor of this language, false otherwise + **/ + Language.prototype.hasAncestor = function (language) { + if (!this._parent) { + return false; + } + if (this._parent === language) { + return true; + } + return this._parent.hasAncestor(language); + }; + /** * Returns the CodeMirror mode for this language. * @return {string} The mode */ Language.prototype.getMode = function () { - return this._mode; + return this._mode || (this._parent && this._parent.getMode()); }; /** @@ -329,6 +355,7 @@ define(function (require, exports, module) { Language.prototype._loadAndSetMode = function (mode) { var result = new $.Deferred(), self = this, + definesOwnMode, mimeMode; // Mode can be an array specifying a mode plus a MIME mode defined by that mode ["clike", "text/x-c++src"] if (Array.isArray(mode)) { @@ -339,11 +366,15 @@ define(function (require, exports, module) { mode = mode[0]; } - // mode must not be empty. Use "null" (the string "null") mode for plain text - _validateNonEmptyString(mode, "mode"); + definesOwnMode = !this._parent || mode; + + if (definesOwnMode) { + // mode must not be empty for root languages. Use "null" (the string "null") mode for plain text + _validateNonEmptyString(mode, "mode"); + } var finish = function () { - if (!CodeMirror.modes[mode]) { + if (definesOwnMode && !CodeMirror.modes[mode]) { result.reject("CodeMirror mode \"" + mode + "\" is not loaded"); return; } @@ -363,15 +394,17 @@ define(function (require, exports, module) { } } - // This mode is now only about what to tell CodeMirror - // The base mode was only necessary to load the proper mode file - self._mode = mimeMode || mode; - self._wasModified(); + if (definesOwnMode) { + // This mode is now only about what to tell CodeMirror + // The base mode was only necessary to load the proper mode file + self._mode = mimeMode || mode; + self._wasModified(); + } result.resolve(self); }; - if (CodeMirror.modes[mode]) { + if (!definesOwnMode || CodeMirror.modes[mode]) { finish(); } else { require(["thirdparty/CodeMirror2/mode/" + mode + "/" + mode], finish); @@ -400,8 +433,6 @@ define(function (require, exports, module) { /** * Adds a file extension to this language. - * Private for now since dependent code would need to by kept in sync with such changes. - * See https://github.com/adobe/brackets/issues/2966 for plans to make this public. * @param {!string} extension A file extension used by this language */ Language.prototype.addFileExtension = function (extension) { @@ -411,10 +442,14 @@ define(function (require, exports, module) { this._fileExtensions.push(extension); var language = _fileExtensionToLanguageMap[extension]; - if (language) { + if (language && !this.hasAncestor(language)) { console.warn("Cannot register file extension \"" + extension + "\" for " + this._name + ", it already belongs to " + language._name); } else { _fileExtensionToLanguageMap[extension] = this; + // Must be an ancestor + if (language) { + language._removeFileExtension(extension); + } } this._wasModified(); @@ -423,10 +458,7 @@ define(function (require, exports, module) { /** * Adds a file name to the language which is used to match files that don't have extensions like "Makefile" for example. - * Private for now since dependent code would need to by kept in sync with such changes. - * See https://github.com/adobe/brackets/issues/2966 for plans to make this public. * @param {!string} extension An extensionless file name used by this language - * @private */ Language.prototype.addFileName = function (name) { name = name.toLowerCase(); @@ -435,22 +467,57 @@ define(function (require, exports, module) { this._fileNames.push(name); var language = _fileNameToLanguageMap[name]; - if (language) { + if (language && !this.hasAncestor(language)) { console.warn("Cannot register file name \"" + name + "\" for " + this._name + ", it already belongs to " + language._name); } else { _fileNameToLanguageMap[name] = this; + // Must be an ancestor + if (language) { + language._removeFileName(name); + } } this._wasModified(); } }; + + /** + * @private + * Removes a file extension from this language + * @param {string} extension File extension to remove + */ + Language.prototype._removeFileExtension = function (extension) { + var index = this._fileExtensions.indexOf(extension); + if (index === -1) { + return; + } + + this._fileExtensions.splice(index, 1); + this._wasModified(); + }; + /** + * @private + * Removes a file name from this language + * @param {string} fileName File name to remove + */ + Language.prototype._removeFileName = function (fileName) { + var index = this._fileNames.indexOf(fileName); + if (index === -1) { + return; + } + + this._fileNames.splice(index, 1); + this._wasModified(); + }; + /** * Returns whether the line comment syntax is defined for this language. * @return {boolean} Whether line comments are supported */ Language.prototype.hasLineCommentSyntax = function () { - return this._lineCommentSyntax.length > 0; + // Cast as Boolean to return false instead of null (i.e. this._parent) + return Boolean(this._lineCommentSyntax.length > 0 || (this._parent && this._parent.hasLineCommentSyntax())); }; /** @@ -458,7 +525,7 @@ define(function (require, exports, module) { * @return {Array.} The prefixes */ Language.prototype.getLineCommentPrefixes = function () { - return this._lineCommentSyntax; + return this._lineCommentSyntax.concat(this._parent ? this._parent.getLineCommentPrefixes() : []); }; /** @@ -488,7 +555,8 @@ define(function (require, exports, module) { * @return {boolean} Whether block comments are supported */ Language.prototype.hasBlockCommentSyntax = function () { - return Boolean(this._blockCommentSyntax); + // Cast as Boolean to return false instead of null (i.e. this._parent) + return Boolean(this._blockCommentSyntax || (this._parent && this._parent.hasBlockCommentSyntax())); }; /** @@ -496,7 +564,7 @@ define(function (require, exports, module) { * @return {string} The prefix */ Language.prototype.getBlockCommentPrefix = function () { - return this._blockCommentSyntax && this._blockCommentSyntax.prefix; + return (this._blockCommentSyntax && this._blockCommentSyntax.prefix) || (this._parent && this._parent.getBlockCommentPrefix()); }; /** @@ -504,7 +572,7 @@ define(function (require, exports, module) { * @return {string} The suffix */ Language.prototype.getBlockCommentSuffix = function () { - return this._blockCommentSyntax && this._blockCommentSyntax.suffix; + return (this._blockCommentSyntax && this._blockCommentSyntax.suffix) || (this._parent && this._parent.getBlockCommentSuffix()); }; /** @@ -527,11 +595,11 @@ define(function (require, exports, module) { * @return {Language} This language if it uses the mode, or whatever {@link LanguageManager#_getLanguageForMode} returns */ Language.prototype.getLanguageForMode = function (mode) { - if (mode === this._mode) { + if (mode === this.getMode()) { return this; } - return this._modeToLanguageMap[mode] || _getLanguageForMode(mode); + return this._modeToLanguageMap[mode] || (this._parent && this._parent.getLanguageForMode(mode)) || _getLanguageForMode(mode); }; /** @@ -542,7 +610,7 @@ define(function (require, exports, module) { * @private */ Language.prototype._setLanguageForMode = function (mode, language) { - if (mode === this._mode && language !== this) { + if (mode === this.getMode() && language !== this) { throw new Error("A language must always map its mode to itself"); } this._modeToLanguageMap[mode] = language; @@ -596,6 +664,11 @@ define(function (require, exports, module) { l, i; + var parent = definition.parent; + if (parent) { + language._setParent(parent); + } + var blockComment = definition.blockComment; if (blockComment) { language.setBlockCommentSyntax(blockComment[0], blockComment[1]); diff --git a/test/spec/LanguageManager-test.js b/test/spec/LanguageManager-test.js index e81004b73b5..4ef3383a0e6 100644 --- a/test/spec/LanguageManager-test.js +++ b/test/spec/LanguageManager-test.js @@ -46,11 +46,18 @@ define(function (require, exports, module) { function defineLanguage(definition) { var def = $.extend({}, definition); + var id = def.id; + delete def.id; + if (def.blockComment) { def.blockComment = [def.blockComment.prefix, def.blockComment.suffix]; } - return LanguageManager.defineLanguage(definition.id, def); + if (def.lineComment) { + def.lineComment = def.lineComment.prefix; + } + + return LanguageManager.defineLanguage(id, def); } function validateLanguage(expected, actual) { @@ -335,6 +342,77 @@ define(function (require, exports, module) { }); }); + describe("when extending a language", function () { + var id = "fakescript", + name = "FakeScript", + fileName = "fakefile", + extension = "fake", + parent = LanguageManager.getLanguage("javascript"), + child, + promise, + didFail, + def, + language; + + + it("should still require a name", function () { + expect(LanguageManager.getLanguage(id)).toBe(undefined); + expect(function () { defineLanguage({ id: id, parent: parent.getId() }); }).toThrow(new Error("name must be a string")); + }); + + it("should allow a minimal definition when extending a language", function () { + runs(function () { + expect(LanguageManager.getLanguage(id)).toBe(undefined); + promise = defineLanguage({ id: id, parent: parent.getId(), name: name }); + promise.done(function (language) { + child = language; + }); + }); + + runs(function () { + waitsForDone(promise, "Defining a language with a name should succeed"); + }); + }); + + it("inherit only mode and comment syntax", function () { + runs(function () { + expect(child.hasAncestor(parent)).toBe(true); + + // Own + expect(child.getId()).toBe(id); + expect(child.getName()).toBe(name); + expect(child.getFileExtensions()).toEqual([]); + + // Inherited + expect(child.getMode()).toBe(parent.getMode()); + + expect(child.hasLineCommentSyntax()).toBe(parent.hasLineCommentSyntax()); + expect(child.getLineCommentPrefixes()).toEqual(parent.getLineCommentPrefixes()); + + expect(child.hasBlockCommentSyntax()).toBe(parent.hasBlockCommentSyntax()); + expect(child.getBlockCommentPrefix()).toBe(parent.getBlockCommentPrefix()); + expect(child.getBlockCommentSuffix()).toBe(parent.getBlockCommentSuffix()); + }); + }); + + it("should take over file names and extension from parent", function () { + parent.addFileExtension(extension); + expect(child.getFileExtensions()).not.toContain(extension); + expect(parent.getFileExtensions()).toContain(extension); + parent.addFileName(fileName); + expect(child.getFileNames()).not.toContain(fileName); + expect(parent.getFileNames()).toContain(fileName); + expect(LanguageManager.getLanguageForPath("file." + extension).getId()).toBe(parent.getId()); + + child.addFileExtension(extension); + expect(child.getFileExtensions()).toContain(extension); + expect(parent.getFileExtensions()).not.toContain(extension); + child.addFileName(fileName); + expect(child.getFileNames()).toContain(fileName); + expect(parent.getFileNames()).not.toContain(fileName); + expect(LanguageManager.getLanguageForPath(fileName).getId()).toBe(child.getId()); + }); + }); }); describe("rename file extension", function () { @@ -404,7 +482,9 @@ define(function (require, exports, module) { // cleanup doc.releaseRef(); }); + }); + describe("adding or modifying languages", function () { it("should update the document's language when a language is added", function () { var unknown, doc, From 458aa28285c16bac8fc0d432a7bb3cae6e396c24 Mon Sep 17 00:00:00 2001 From: Dennis Kehrig Date: Tue, 19 Mar 2013 21:23:54 +0100 Subject: [PATCH 2/4] Removed an unnecessary piece of code --- test/spec/LanguageManager-test.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/spec/LanguageManager-test.js b/test/spec/LanguageManager-test.js index 4ef3383a0e6..20c3b199df6 100644 --- a/test/spec/LanguageManager-test.js +++ b/test/spec/LanguageManager-test.js @@ -53,10 +53,6 @@ define(function (require, exports, module) { def.blockComment = [def.blockComment.prefix, def.blockComment.suffix]; } - if (def.lineComment) { - def.lineComment = def.lineComment.prefix; - } - return LanguageManager.defineLanguage(id, def); } From 7057394e519b8d68e378502311f9e6032ceaabff Mon Sep 17 00:00:00 2001 From: Dennis Kehrig Date: Wed, 15 May 2013 00:19:25 +0200 Subject: [PATCH 3/4] Added methods to compare languages, taking inheritance into account --- src/language/LanguageManager.js | 41 +++++++++++++++++++++++++------ test/spec/LanguageManager-test.js | 31 +++++++++++++++++++++-- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/language/LanguageManager.js b/src/language/LanguageManager.js index ca5afb134e8..408fe731668 100644 --- a/src/language/LanguageManager.js +++ b/src/language/LanguageManager.js @@ -94,6 +94,11 @@ * * If a mode is not shipped with our CodeMirror distribution, you need to first load it yourself. * If the mode is part of our CodeMirror distribution, it gets loaded automatically. + * + * To compare languages, use the following methods: + * - isLanguage (if this language should be the same as the passed one) + * - isBasedOnLanguage (if this language should be a child of the passed one) + * - isInstanceOfLanguage (if this language should be the passed one or a child of it) */ define(function (require, exports, module) { "use strict"; @@ -162,7 +167,7 @@ define(function (require, exports, module) { */ function _setLanguageForMode(mode, language) { var mappedLanguage = _modeToLanguageMap[mode]; - if (mappedLanguage && !language.hasAncestor(mappedLanguage)) { + if (mappedLanguage && !language.isBasedOnLanguage(mappedLanguage)) { console.warn("CodeMirror mode \"" + mode + "\" is already used by language " + mappedLanguage.getName() + ", won't register for " + language.getName()); return; } @@ -367,19 +372,41 @@ define(function (require, exports, module) { return true; }; + /** + * Determines whether the language is this language + * @param {Language|string} The language (or its ID) to test + * @return {boolean} True if this language has the same ID as language, false otherwise + **/ + Language.prototype.isLanguage = function (language) { + if (language.getId) { + language = language.getId(); + } + + return this.getId() === language; + }; + /** * Determines whether the language is this language's parent, or the parent's parent, etc. - * @param {Language} The language to test - * @return {boolean} True if language is an ancestor of this language, false otherwise + * @param {Language} The language (or its ID) to test + * @return {boolean} True if this language is a child of language, false otherwise **/ - Language.prototype.hasAncestor = function (language) { + Language.prototype.isBasedOnLanguage = function (language) { if (!this._parent) { return false; } if (this._parent === language) { return true; } - return this._parent.hasAncestor(language); + return this._parent.isBasedOnLanguage(language); + }; + + /** + * Determines whether the language is this language or based on this language + * @param {Language} The language (or its ID) to test + * @return {boolean} True if this language is an instance of language, false otherwise + **/ + Language.prototype.isInstanceOfLanguage = function (language) { + return this.isLanguage(language) || this.isBasedOnLanguage(language); }; /** @@ -510,7 +537,7 @@ define(function (require, exports, module) { this._fileExtensions.push(extension); var language = _fileExtensionToLanguageMap[extension]; - if (language && !this.hasAncestor(language)) { + if (language && !this.isBasedOnLanguage(language)) { console.warn("Cannot register file extension \"" + extension + "\" for " + this._name + ", it already belongs to " + language._name); } else { _fileExtensionToLanguageMap[extension] = this; @@ -537,7 +564,7 @@ define(function (require, exports, module) { this._fileNames.push(name); var language = _fileNameToLanguageMap[name]; - if (language && !this.hasAncestor(language)) { + if (language && !this.isBasedOnLanguage(language)) { console.warn("Cannot register file name \"" + name + "\" for " + this._name + ", it already belongs to " + language._name); } else { _fileNameToLanguageMap[name] = this; diff --git a/test/spec/LanguageManager-test.js b/test/spec/LanguageManager-test.js index 83bebcb153f..e8f1f7561c1 100644 --- a/test/spec/LanguageManager-test.js +++ b/test/spec/LanguageManager-test.js @@ -414,11 +414,38 @@ define(function (require, exports, module) { waitsForDone(promise, "Defining a language with a name should succeed"); }); }); + + it("make the inheritance chain comprehensible", function () { + // isLanguage + + // Same language: true + expect(child.isLanguage(child)).toBe(true); + expect(parent.isLanguage(parent)).toBe(true); + // Different language: false + expect(child.isLanguage(parent)).toBe(false); + expect(parent.isLanguage(child)).toBe(false); + + // isBasedOnLanguage + + // Same language: false + expect(child.isBasedOnLanguage(child)).toBe(false); + expect(parent.isBasedOnLanguage(parent)).toBe(false); + // Child based on parent: true, parent based on child: false + expect(child.isBasedOnLanguage(parent)).toBe(true); + expect(parent.isBasedOnLanguage(child)).toBe(false); + // isInstanceOfLanguage + + // Same language: true + expect(child.isInstanceOfLanguage(child)).toBe(true); + expect(parent.isInstanceOfLanguage(parent)).toBe(true); + // Child instance of parent: true, parent instance of child: false + expect(child.isInstanceOfLanguage(parent)).toBe(true); + expect(parent.isInstanceOfLanguage(child)).toBe(false); + }); + it("inherit only mode and comment syntax", function () { runs(function () { - expect(child.hasAncestor(parent)).toBe(true); - // Own expect(child.getId()).toBe(id); expect(child.getName()).toBe(name); From c1b06d9e599def94e56045dd2bac70a6905230c9 Mon Sep 17 00:00:00 2001 From: Dennis Kehrig Date: Wed, 15 May 2013 02:07:56 +0200 Subject: [PATCH 4/4] Determine a language match by respecting the inheritance chain --- src/LiveDevelopment/LiveDevelopment.js | 7 +-- src/editor/CSSInlineEditor.js | 2 +- src/editor/CodeHintManager.js | 8 +-- src/extensions/default/JSLint/main.js | 2 +- .../default/JavaScriptCodeHints/HintUtils.js | 4 +- .../JavaScriptCodeHints/ScopeManager.js | 4 +- .../default/JavaScriptCodeHints/Session.js | 2 +- .../default/JavaScriptCodeHints/main.js | 9 ++-- .../default/WebPlatformDocs/main.js | 2 +- src/language/LanguageManager.js | 50 ++++++++++++++++--- src/search/QuickOpen.js | 6 +-- test/spec/LanguageManager-test.js | 48 ++++++++++++++++++ 12 files changed, 113 insertions(+), 31 deletions(-) diff --git a/src/LiveDevelopment/LiveDevelopment.js b/src/LiveDevelopment/LiveDevelopment.js index 48c9cc7ec92..94495bc8c0b 100644 --- a/src/LiveDevelopment/LiveDevelopment.js +++ b/src/LiveDevelopment/LiveDevelopment.js @@ -245,10 +245,11 @@ define(function LiveDevelopment(require, exports, module) { * @param {Document} document */ function _classForDocument(doc) { - switch (doc.getLanguage().getId()) { - case "css": + var language = doc.getLanguage(); + if (language.isInstanceOfLanguage("css")) { return CSSDocument; - case "javascript": + } + if (language.isInstanceOfLanguage("javascript")) { return exports.config.experimental ? JSDocument : null; } diff --git a/src/editor/CSSInlineEditor.js b/src/editor/CSSInlineEditor.js index 01b2dca766d..c196f3581e9 100644 --- a/src/editor/CSSInlineEditor.js +++ b/src/editor/CSSInlineEditor.js @@ -90,7 +90,7 @@ define(function (require, exports, module) { */ function htmlToCSSProvider(hostEditor, pos) { // Only provide a CSS editor when cursor is in HTML content - if (hostEditor.getLanguageForSelection().getId() !== "html") { + if (!hostEditor.getLanguageForSelection().isInstanceOfLanguage("html")) { return null; } diff --git a/src/editor/CodeHintManager.js b/src/editor/CodeHintManager.js index 9649f5a1b6e..fdf3a22c3fa 100644 --- a/src/editor/CodeHintManager.js +++ b/src/editor/CodeHintManager.js @@ -285,11 +285,11 @@ define(function (require, exports, module) { * Return the array of hint providers for the given language id. * This gets called (potentially) on every keypress. So, it should be fast. * - * @param {!string} languageId + * @param {!Language} language * @return {?Array.<{provider: Object, priority: number}>} */ - function _getProvidersForLanguageId(languageId) { - return hintProviders[languageId] || hintProviders.all; + function _getProvidersForLanguage(language) { + return language.findEntryInObject(hintProviders) || hintProviders.all; } /** @@ -375,7 +375,7 @@ define(function (require, exports, module) { function _beginSession(editor) { // Find a suitable provider, if any var language = editor.getLanguageForSelection(), - enabledProviders = _getProvidersForLanguageId(language.getId()); + enabledProviders = _getProvidersForLanguage(language); enabledProviders.some(function (item, index) { if (item.provider.hasHints(editor, lastChar)) { diff --git a/src/extensions/default/JSLint/main.js b/src/extensions/default/JSLint/main.js index 9d1c92d238a..741a6fc2bd9 100644 --- a/src/extensions/default/JSLint/main.js +++ b/src/extensions/default/JSLint/main.js @@ -107,7 +107,7 @@ define(function (require, exports, module) { var language = currentDoc ? LanguageManager.getLanguageForPath(currentDoc.file.fullPath) : ""; - if (_enabled && language && language.getId() === "javascript") { + if (_enabled && language && language.isInstanceOfLanguage("javascript")) { perfTimerLint = PerfUtils.markStart("JSLint linting:\t" + (!currentDoc || currentDoc.file.fullPath)); var text = currentDoc.getText(); diff --git a/src/extensions/default/JavaScriptCodeHints/HintUtils.js b/src/extensions/default/JavaScriptCodeHints/HintUtils.js index 7b8fcc0b961..df0b14d476b 100644 --- a/src/extensions/default/JavaScriptCodeHints/HintUtils.js +++ b/src/extensions/default/JavaScriptCodeHints/HintUtils.js @@ -170,8 +170,8 @@ define(function (require, exports, module) { }); } - function isSupportedLanguage(languageId) { - return SUPPORTED_LANGUAGES.indexOf(languageId) !== -1; + function isSupportedLanguage(language) { + return language.isInstanceOfLanguageInArray(SUPPORTED_LANGUAGES); } var KEYWORD_NAMES = [ "break", "case", "catch", "continue", "debugger", "default", "delete", diff --git a/src/extensions/default/JavaScriptCodeHints/ScopeManager.js b/src/extensions/default/JavaScriptCodeHints/ScopeManager.js index 5de17df2939..c5571cd50a3 100644 --- a/src/extensions/default/JavaScriptCodeHints/ScopeManager.js +++ b/src/extensions/default/JavaScriptCodeHints/ScopeManager.js @@ -200,8 +200,8 @@ define(function (require, exports, module) { if (fileCallback && entry.isFile) { if (file.indexOf(".") > 0) { // ignore .dotfiles - var languageID = LanguageManager.getLanguageForPath(path).getId(); - if (languageID === HintUtils.LANGUAGE_ID) { + var language = LanguageManager.getLanguageForPath(path); + if (language.isInstanceOfLanguage(HintUtils.LANGUAGE_ID)) { fileCallback(path); } } diff --git a/src/extensions/default/JavaScriptCodeHints/Session.js b/src/extensions/default/JavaScriptCodeHints/Session.js index e93e023b40d..967dd1b54d4 100644 --- a/src/extensions/default/JavaScriptCodeHints/Session.js +++ b/src/extensions/default/JavaScriptCodeHints/Session.js @@ -504,7 +504,7 @@ define(function (require, exports, module) { * @return {string} - the "javascript" text that can be sent to Tern. */ Session.prototype.getJavascriptText = function () { - if (LanguageManager.getLanguageForPath(this.editor.document.file.fullPath).getId() === "html") { + if (this.editor.document.getLanguage().isInstanceOfLanguage("html")) { // HTML file - need to send back only the bodies of the //