c9-core/plugins/c9.ide.language.javascript..../tern.js

266 wiersze
9.7 KiB
JavaScript

define(function(require, exports, module) {
main.consumes = [
"Plugin", "language",
"language.tern.architect_resolver", // implicit worker-side dependency
"settings"
];
main.provides = ["language.tern"];
return main;
function main(options, imports, register) {
var Plugin = imports.Plugin;
var language = imports.language;
var settings = imports.settings;
var builtinDefs = JSON.parse(require("text!lib/tern_from_ts/defs/__list.json")).defs;
var builtinTrusted = [
"meteor"
];
var builtinsBroken = [
/mocha.*/, /jquery.*/, /[\.-]/
];
var plugin = new Plugin("Ajax.org", main.consumes);
var emit = plugin.getEmitter();
var defaultPlugins = options.plugins;
var defaultDefs = options.defs || [];
var defs = {};
var preferenceDefs = {};
var loaded = false;
function load() {
if (loaded) return false;
loaded = true;
language.registerLanguageHandler("plugins/c9.ide.language.javascript.tern/worker/tern_worker");
for (var def in builtinDefs) {
if (builtinsBroken.some(function(b) {
return b.test(def);
}))
continue;
registerDef(
def,
"lib/tern_from_ts/defs/" + builtinDefs[def].main,
// TODO: register "extra" defs?
{
experimental: builtinTrusted.indexOf(def) == -1,
url: builtinDefs[def].url
}
);
}
getPlugins(function(err, plugins) {
if (err) return console.error(err);
setPlugins(plugins.concat(defaultPlugins));
});
language.getWorker(function(err, worker) {
if (err) return console.error(err);
var config = settings.getJson("project/language/tern_defs");
var resetConfig = !config;
if (resetConfig)
config = {};
// TODO: add these plugins as options to the preferences
// registerDef("angular", "tern/plugin/angular", { url: "https://angularjs.org/", isPlugin: true });
// registerDef("node", "tern/plugin/angular", { url: "https://angularjs.org/", isPlugin: true });
// registerDef("requirejs", "tern/plugin/angular", { url: "https://angularjs.org/", isPlugin: true });
// var defsToAdd = [];
defaultDefs.forEach(function(def) {
if (resetConfig && def.enabled)
config[def.name] = { enabled: true };
else
def.enabled = config[def.name] && config[def.name].enabled;
def.default = true;
if (defs[def.name]) // skip builtins already added
return;
registerDef(def.name, def.path, def);
});
for (var key in config) {
if (config[key].enabled && defs[key] && !defs[key].default)
setDefEnabled(key, true);
}
settings.setJson("project/language/tern_defs", config);
emit.sticky("ready");
});
}
function registerDef(name, def, options) {
options = options || {};
options.name = name;
defs[name] = def;
preferenceDefs[name] = options;
if (options.enabled)
setDefEnabled(name, true, options);
}
function setDefEnabled(name, enabled, options) {
if (!defs[name] && !defaultPlugins[name])
throw new Error("Definition " + name + " not found");
language.getWorker(function(err, worker) {
if (err) return console.error(err);
worker.emit("tern_set_def_enabled", { data: {
name: name,
def: defs[name],
enabled: enabled !== false,
options: options,
}});
});
}
function setPluginEnabled(plugin, enabled) {
plugin.enabled = plugin;
getPlugins(function(err, plugins) {
if (err) return console.error(err);
setPlugins(plugins.filter(function(p) {
return p.name !== plugin;
}).concat(plugin));
});
}
function setTernServerOptions(ternServerOptions) {
language.getWorker(function(err, worker) {
if (err) return console.error(err);
worker.emit("tern_set_server_options", { data: ternServerOptions });
});
}
function getPlugins(callback) {
language.getWorker(function(err, worker) {
if (err) return console.error(err);
worker.on("tern_read_plugins", function tern_read_plugins(e) {
var backupPluginStatus;
worker.off("tern_read_plugins", tern_read_plugins);
backupPluginStatus = JSON.stringify(e.data);
callback(null, e.data);
// FIXME: remove this strange implicit setter behavior of getPlugins()
if (JSON.stringify(e.data) != backupPluginStatus) {
// state of plugins have changed, update ternWorker
setPlugins(e.data);
}
});
worker.emit("tern_get_plugins", { data: null });
});
}
function setPlugins(plugins) {
language.getWorker(function(err, worker) {
if (err) return console.error(err);
worker.emit("tern_update_plugins", { data: plugins });
});
}
function setTernRequestOptions(ternRequestOptions) {
language.getWorker(function(err, worker) {
if (err) return console.error(err);
worker.emit("tern_set_request_options", { data: ternRequestOptions });
});
}
function getDefs() {
return preferenceDefs;
}
plugin.on("load", load);
plugin.on("unload", function() {
loaded = false;
defs = {};
preferenceDefs = {};
});
/**
* Tern code completion plugin.
*/
plugin.freezePublicAPI({
/**
* Callback function for getting tern definition list from directly tern server
* @typedef {Object} pluginInfo
* @property {String} name - name of the plugin
* @property {boolean} enabled - Setting it false marks plugin for removal
* @property {String} path - Parameter to provide while loading a new plugin
*
* This callback is to retrieve names of definitions
* @callback getTernDefNamesCallback
* @param {Array.String} names Array of names
*/
/**
* Add a tern definition that users can enable.
* @param {String} name
* @param {String|Object} def The definition or a URL pointing to the definiton
* @param {Object} [options]
* @param {Boolean} [options.enabled] Whether to enable this definition by default
* @param {Boolean} [options.hidden] Hide this definition from the preferences UI
*/
registerDef: registerDef,
/**
* Enable or disable a definition.
* @param name
* @param {Boolean} enabled
* @param {Object} [options]
* @param {Boolean} [options.firstClass]
* Treat as if these were built-in types,
* showing nicer icons and hiding the library name.
*/
setDefEnabled: setDefEnabled,
/**
* Sets tern server options
* @param {Object} ternServerOptions
*/
setTernServerOptions: setTernServerOptions,
/**
* Gets list of loaded tern plugins.
*
* @param {Function} callback required function to process status of plugins
* @param {Object} callback.err
* @param {Object[]} callback.results
*/
getPlugins: getPlugins,
/**
* Sets list of loaded tern plugins.
*
* @param {Object[]} plugins
*/
setPlugins: setPlugins,
/**
* Enable or disable a plugin.
* @param name
* @param {Boolean} enabled
*/
setPluginEnabled: setPluginEnabled,
/**
* Sets tern request options
* @param {Object} ternRequestOptions
*/
setTernRequestOptions: setTernRequestOptions,
/**
* Get a list of all definitions.
* @return {String[]}
*/
getDefs: getDefs
});
register(null, {
"language.tern": plugin
});
}
});