{"__v":20,"_id":"552e6fcd5d4baa0d00783691","category":{"__v":9,"_id":"54d5635632d98b0d00384b01","pages":["54d5635732d98b0d00384b10","54d5635732d98b0d00384b11","55104b632dd9010d0019e144","55104c802dd9010d0019e146","551bd2c50d209f21006cad92","552e6fcd5d4baa0d00783691","552e73705d4baa0d00783699","567be431ee052b1700dbda49","567ef29af9ffa20d008782ff","56a8dd2470a9440d00ef5fe4"],"project":"54d53c7b23010a0d001aca0c","version":"54d5635532d98b0d00384afb","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-02-07T00:03:52.618Z","from_sync":false,"order":11,"slug":"language-tooling","title":"Language Tooling"},"parentDoc":null,"project":"54d53c7b23010a0d001aca0c","user":"54d5c32a7e05890d006f150d","version":{"__v":10,"_id":"54d5635532d98b0d00384afb","forked_from":"54d53c7c23010a0d001aca0f","project":"54d53c7b23010a0d001aca0c","createdAt":"2015-02-07T00:59:01.934Z","releaseDate":"2015-02-07T00:59:01.934Z","categories":["54d5635632d98b0d00384afc","54d5635632d98b0d00384afd","54d5635632d98b0d00384afe","54d5635632d98b0d00384aff","54d5635632d98b0d00384b00","54d5635632d98b0d00384b01","54d5635632d98b0d00384b02","54d652097e05890d006f153e","54dd1315ca1e5219007e9daa","54e21e2b22de1c230094b147","54e68e62a43fe13500db3879","54fa1d3fe7a0ba2f00306309","551c453a23a1ee190034d19a","551df586e52a0b23000c62b6","551f39be6886f8230055f02a","55a6720751457325000e4d97"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"0.1.0","version":"0.1"},"updates":["5660137407e3200d006e46eb"],"next":{"pages":[],"description":""},"createdAt":"2015-04-15T14:03:57.018Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":3,"body":"Jsonalyzer handlers are a specialized form of [Language Handlers](doc:language-handlers). They address one issue with language handlers: they are sometimes considered too much like a *blank slate*. They allow for a lot of freedom and are extremely powerful, but they require plugin developers to do all the hard work themselves.\n\nTo make it easier to implement language tooling, Cloud9 provides *the Jsonalyzer*. The Jsonalyzer is a layer on top of the normal language handler interface. It is actually built itself as a language handler, implementing the [base_handler](https://docs.c9.io/api/#!/api/language.base_handler) interface, and using simple JSON datastructures to describe analysis results (hence the name: we smashed together json and analyzer). These JSON structures for example describe all the classes and functions in a file. The Jsonalyzer consumes the structures to implement an outline view, and a basis for more advanced services like code completion and jump to definition.\n\n# Jsonalyzer Handlers\n\nJsonalyzer handlers implement the [jsonalyzer_base_handler interface](https://github.com/c9/c9.ide.language.jsonalyzer/blob/master/worker/jsonalyzer_base_handler.js). They should be registered in a Cloud9 plugin as follows:\n\n```javascript      \ndefine(function(require, exports, module) {\n    main.consumes = [\"jsonalyzer\"];\n    main.provides = [];\n    return main;\n          \n    function main(options, imports, register) {\n        var jsonalyzer = imports.jsonalyzer;\n          \n        jsonalyzer.registerWorkerHandler('plugins/my.plugin/bar_handler');\n          \n        register(null, {});\n    }\n});\n```\n\nThis registers a new jsonalyzer plugin in the web worker. Jsonalyzer plugins can also run on the server, if you register them with `jsonalyzer.registerServerHandler()` instead.\n\nBelow is an example client-side jsonalyzer handler for Python:\n\n```javascript\ndefine(function(require, exports, module) {\n\nvar PluginBase = require(\"plugins/c9.ide.language.jsonalyzer/worker/jsonalyzer_base_handler\");\nvar handler = module.exports = Object.create(PluginBase);\nvar util = require(\"plugins/c9.ide.language.jsonalyzer/worker/ctags/ctags_util\");\n\nhandler.languages = [\"py\"];\nhandler.extensions = [\"py\"];\n\nhandler.analyzeCurrent = function(path, doc, ast, options, callback) {\n    var structure = {};\n    \n    doc.replace(/(?:^|\\n)\\s*def\\s+(?!_)([^ \\(:]+)/g, function(fullMatch, name, offset) {\n        results[\"_\" + name] = [{\n            row: util.getOffsetRow(doc, offset),\n            kind: \"method\",\n            guessFargs: true\n        }];\n    });\n    \n    var errors = [{\n        pos: { sl: 0, sc: 0 },\n        message: \"This is a message for python users from a jsonalyzer handler\",\n        level: \"info\"\n    }]\n\n    return callback(null, { properties: structure }, errors);\n};\n\n});\n```\n\nThe plugin above uses regular expressions to find all python definitions in a file (`/`*something something `def` something something*`/`). It creates a JavaScript object `structure` that describes the structure of the file based on this. This object is a map of the following form:\n\n* `row` the row of the definition\n* `kind` the kind of definition\n* `properties` any nested definitions inside the current definition; another map\n* `guessFargs` a boolean indicating if Jsonalyzer should try to guess the arguments of this function (usually, this should be true for anything that might take arguments)\n\nThe other thing the example above does is return a list of errors. This can be done with a normal language handler just as easily, but the main reason to chose for the jsonalyzer is that jsonalyzer handlers can also easily run on the server — that is, in the workspace of the user. This way you can call any server-side linter or analyzer from your plugin and display any errors it returns in the editor.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/tySHnFSmQcOfgI0kQz9Y_image.png\",\n        \"image.png\",\n        \"1570\",\n        \"451\",\n        \"#1b5bbd\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\nWe can have many handlers and handler functions per language, so this just adds to the standard JavaScript analyzer. Based on the above starting point, you can make your analyzer as sophisticated as you want, or integrate any existing analyzer. The base_handler interface also provides methods for doing code completion, showing an outline view, etc. that works in a similar fashion to what is shown above.\n\n# Client-side and Server-side handlers\n\nJsonalyzer handlers can run either in client or on the server. As seen above, client-side handlers can be registered using:\n\n```\njsonalyzer.registerWorkerHandler(\"plugins/my.plugin/bar_handler\");\n```\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Advanced: Server-Side Handlers\",\n  \"body\": \"Working with server-side Jsonalyzer handlers is generally more tricky and error-prone than with handlers that run in the worker. As an alternative to running a handler fully in the server, Cloud9 also provides a new API for controlling server-side tools from the worker; see [Using Existing Language Tools](doc:existing-tools).\"\n}\n[/block]\nServer-side handlers can be registered using:\n\n```\njsonalyzer.registerServerHandler(\"plugins/my.plugin/bar_handler\");\n```\n\nto register a server-side handler. Examples of server-side handlers can be found in https://github.com/c9/c9.ide.language.jsonalyzer/tree/master/server/handlers. These handlers all call a server-side tool on the workspace of the user. For instance, the php handler uses the built-in linter of php by calling `php -l` on the command-line. It grabs all messages displayed and returns them as JavaScript objects to Cloud9.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Reference Implementation\"\n}\n[/block]\nThe Python example of the [Reference Implementations](doc:complete-examples) section has an example Jsonalyzer handler used to implement a Python outline: https://github.com/c9/c9.ide.language.python/blob/7aeaf4a/worker/python_jsonalyzer.js.","excerpt":"","slug":"jsonalyzer-handlers","type":"basic","title":"Jsonalyzer Handlers"}

Jsonalyzer Handlers


Jsonalyzer handlers are a specialized form of [Language Handlers](doc:language-handlers). They address one issue with language handlers: they are sometimes considered too much like a *blank slate*. They allow for a lot of freedom and are extremely powerful, but they require plugin developers to do all the hard work themselves. To make it easier to implement language tooling, Cloud9 provides *the Jsonalyzer*. The Jsonalyzer is a layer on top of the normal language handler interface. It is actually built itself as a language handler, implementing the [base_handler](https://docs.c9.io/api/#!/api/language.base_handler) interface, and using simple JSON datastructures to describe analysis results (hence the name: we smashed together json and analyzer). These JSON structures for example describe all the classes and functions in a file. The Jsonalyzer consumes the structures to implement an outline view, and a basis for more advanced services like code completion and jump to definition. # Jsonalyzer Handlers Jsonalyzer handlers implement the [jsonalyzer_base_handler interface](https://github.com/c9/c9.ide.language.jsonalyzer/blob/master/worker/jsonalyzer_base_handler.js). They should be registered in a Cloud9 plugin as follows: ```javascript define(function(require, exports, module) { main.consumes = ["jsonalyzer"]; main.provides = []; return main; function main(options, imports, register) { var jsonalyzer = imports.jsonalyzer; jsonalyzer.registerWorkerHandler('plugins/my.plugin/bar_handler'); register(null, {}); } }); ``` This registers a new jsonalyzer plugin in the web worker. Jsonalyzer plugins can also run on the server, if you register them with `jsonalyzer.registerServerHandler()` instead. Below is an example client-side jsonalyzer handler for Python: ```javascript define(function(require, exports, module) { var PluginBase = require("plugins/c9.ide.language.jsonalyzer/worker/jsonalyzer_base_handler"); var handler = module.exports = Object.create(PluginBase); var util = require("plugins/c9.ide.language.jsonalyzer/worker/ctags/ctags_util"); handler.languages = ["py"]; handler.extensions = ["py"]; handler.analyzeCurrent = function(path, doc, ast, options, callback) { var structure = {}; doc.replace(/(?:^|\n)\s*def\s+(?!_)([^ \(:]+)/g, function(fullMatch, name, offset) { results["_" + name] = [{ row: util.getOffsetRow(doc, offset), kind: "method", guessFargs: true }]; }); var errors = [{ pos: { sl: 0, sc: 0 }, message: "This is a message for python users from a jsonalyzer handler", level: "info" }] return callback(null, { properties: structure }, errors); }; }); ``` The plugin above uses regular expressions to find all python definitions in a file (`/`*something something `def` something something*`/`). It creates a JavaScript object `structure` that describes the structure of the file based on this. This object is a map of the following form: * `row` the row of the definition * `kind` the kind of definition * `properties` any nested definitions inside the current definition; another map * `guessFargs` a boolean indicating if Jsonalyzer should try to guess the arguments of this function (usually, this should be true for anything that might take arguments) The other thing the example above does is return a list of errors. This can be done with a normal language handler just as easily, but the main reason to chose for the jsonalyzer is that jsonalyzer handlers can also easily run on the server — that is, in the workspace of the user. This way you can call any server-side linter or analyzer from your plugin and display any errors it returns in the editor. [block:image] { "images": [ { "image": [ "https://files.readme.io/tySHnFSmQcOfgI0kQz9Y_image.png", "image.png", "1570", "451", "#1b5bbd", "" ] } ] } [/block] We can have many handlers and handler functions per language, so this just adds to the standard JavaScript analyzer. Based on the above starting point, you can make your analyzer as sophisticated as you want, or integrate any existing analyzer. The base_handler interface also provides methods for doing code completion, showing an outline view, etc. that works in a similar fashion to what is shown above. # Client-side and Server-side handlers Jsonalyzer handlers can run either in client or on the server. As seen above, client-side handlers can be registered using: ``` jsonalyzer.registerWorkerHandler("plugins/my.plugin/bar_handler"); ``` [block:callout] { "type": "warning", "title": "Advanced: Server-Side Handlers", "body": "Working with server-side Jsonalyzer handlers is generally more tricky and error-prone than with handlers that run in the worker. As an alternative to running a handler fully in the server, Cloud9 also provides a new API for controlling server-side tools from the worker; see [Using Existing Language Tools](doc:existing-tools)." } [/block] Server-side handlers can be registered using: ``` jsonalyzer.registerServerHandler("plugins/my.plugin/bar_handler"); ``` to register a server-side handler. Examples of server-side handlers can be found in https://github.com/c9/c9.ide.language.jsonalyzer/tree/master/server/handlers. These handlers all call a server-side tool on the workspace of the user. For instance, the php handler uses the built-in linter of php by calling `php -l` on the command-line. It grabs all messages displayed and returns them as JavaScript objects to Cloud9. [block:api-header] { "type": "basic", "title": "Reference Implementation" } [/block] The Python example of the [Reference Implementations](doc:complete-examples) section has an example Jsonalyzer handler used to implement a Python outline: https://github.com/c9/c9.ide.language.python/blob/7aeaf4a/worker/python_jsonalyzer.js.