= Tern Reference Manual = Tern consists of several components. Depending on what you are trying to do with it, you will be interested in a different layer. At the very top are the <>. These talk to a <>, which is implemented on top of the <>, which uses the <> to do the actual type inference. [[contents]] == Contents == * <> ** <> ** <> ** <> ** <> *** <> *** <> *** <> *** <> *** <> *** <> *** <> *** <> *** <> *** <> ** <> ** <> * <> ** <> ** <> ** <> ** <> ** <> ** <> ** <> * <> ** <> ** <> ** <> ** <> ** <> * <> [[server]] == The Tern server == The `bin/tern` 'binary' (http://nodejs.org[node.js] script, really), is used to start a Tern server. You will usually want to let an <> start it for you, but it can be started manually, which can be useful for debugging. (Note that the basic structure of the server is also available through a <>, and that some project, especially those running client-side in a browser, will want to use that instead of the HTTP server described here.) [[project_file]] When started, the server will look for a `.tern-project` file in the current directory or one of the directories above that, and use it for its <>. If no project file is found, it'll fall back to a default configuration. You can change this default configuration by putting a `.tern-config` file, with the same format as `.tern-project`, in your home directory. A server write the port it is listening on (which is random) to standard output on startup. It will serve a <> via HTTP on that port. Clients can upload code and ask questions about the code through this protocol. The following command-line flags are supported: `--port `:: Specify a port to listen on, instead of the default behavior of letting the OS pick a random unused port. `--host `:: Specify a host to listen on. Defaults to 127.0.0.1. Pass `null` or `any` to listen on all available hosts. `--persistent`:: By default, the server will shut itself down after five minutes of inactivity. Pass it a this option to disable auto-shutdown. `--verbose`:: Will cause the server to spit out information about the requests and responses that it handles, and any errors that are raised. Useful for debugging. `--no-port-file`:: The server won't write a `.tern-port` file. Can be used if the port files are a problem for you. Will prevent other clients from finding the server (and may thus result in multiple servers for the same project). [[protocol]] === JSON protocol === Sending queries to a Tern server is done by making `POST` requests to the server's port (using `/` as the requests's path) with a http://json.org[JSON] document in the body of the request. This document should be an object, with three optional fields, `query`, `files`, and `timeout`. The first (`query`) describes the kind of information you are requesting. It may be omitted if the request is only used to push new code to the server (in which case you'll get an empty object, `{}` as response). The `files` property, if given, contains an array of file specifications, as described below. It may be omitted when the query should operate on the code that the server already has, without adding anything new. When the `timeout` field is set, it should contain a number, which is interpreted as the maximum amount of milliseconds to work (CPU work, ignoring I/O) on this request before returning with a timeout error. A query is an object with at least a `type` property, which determines what kind of query it is. Depending on the type, other properties must or may be present in order to provide further details. These are the queries that a Tern server understands by default. (Plug-ins may add custom query types.) [[req_completions]]`completions`:: Asks the server for a set of completions at the given point. + Accepted fields are: `file`, `end` (required);; Specify the location to complete at. <>. `types` (optional, default `false`);; Whether to include the types of the completions in the result data. `depths` (optional, default `false`);; Whether to include the distance (in scopes for variables, in prototypes for properties) between the completions and the origin position in the result data. `docs`, `urls`, `origins` (optional, default `false`);; Whether to include documentation strings, urls, and origin files (if found) in the result data. `filter` (optional, default `true`);; When on, only completions that match the current word at the given point will be returned. Turn this off to get all results, so that you can filter on the client side. `caseInsensitive` (optional, default `false`);; Whether to use a case-insensitive compare between the current word and potential completions. `guess` (optional, default `true`);; When completing a property and no completions are found, Tern will use some heuristics to try and return some properties anyway. Set this to `false` to turn that off. `sort` (optional, default `true`);; Determines whether the result set will be sorted. `expandWordForward` (optional, default `true`);; When disabled, only the text _before_ the given position is considered part of the word. When enabled (the default), the whole variable name that the cursor is on will be included. `omitObjectPrototype` (optional, default `true`);; Whether to ignore the properties of `Object.prototype` unless they have been spelled out by at least to characters. `includeKeywords` (optional, default `false`);; Whether to include JavaScript keywords when completing something that is not a property. + The result returned will be an object with `start` and `end` properties, which give the start and end <> of the word that was completed, an `isProperty` property that holds a boolean indicating whether the completion is for a property or a variable, and a `completions` property holding an array of completions. When one of the `types`, `depths`, `docs`, `urls`, or `origins` options was passed, the array will hold objects with a `name` property (the completion text), and, depending on the options, `type`, `depth`, `doc`, `url`, and `origin` properties. When none of these options are enabled, the result array will hold plain strings. [[req_type]]`type`:: Query the type of something. `file`, `end` (required), `start` (optional);; Specify the expression we want the type of. <>. `preferFunction` (optional, default `false`);; Set to `true` when you are interested in a function type. This will cause function types to win when something has multiple types. `depth` (optional, default `0`);; Determines how deep the type string must be expanded. Nested objects will only display property types up to this depth, and be represented by their type name or a representation showing only property names below it. + The returned object will have the following properties: `type` (string);; A description of the type of the value. May be `"?"` when no type was found. `guess` (bool);; Whether the given type was guessed, or should be considered reliable. `name` (string, optional);; The name associated with the type. `exprName` (string, optional);; When the inspected expression was an identifier or a property access, this will hold the name of the variable or property. `doc`, `url`, `origin` (strings, optional);; If the type had documentation and origin information associated with it, these will also be returned. [[req_definition]]`definition`:: Asks for the definition of something. This will try, for a variable or property, to return the point at which it was defined. If that fails, or the chosen expression is not an identifier or property reference, it will try to return the definition site of the type the expression has. If no type is found, or the type is not an object or function (other types don't store their definition site), it will fail to return useful information. + Only takes `file`, `end` (required), and `start` (optional) fields to specify the expression you want the definition of. <>. + The returned object will have the following properties: `start`, `end` (<>, optional);; The start and end positions of the definition. `file` (string, optional);; The file in which the definition was defined. `context` (string, optional), `contextOffset` (number, optional);; A slice of the code in front of the definition, and the offset from the start of the context to the actual definition. Can be used to find a definition's location in a modified file. `doc`, `url`, `origin` (strings, optional);; If the definition had documentation or an origin associated with it, it will be returned. [[req_documentation]]`documentation`:: Get the documentation string and URL for a given expression, if any. + Takes `file`, `end` (required), and `start` (optional) fields to specify the expression we are interested in. <>. + Returns an object with the following properties: `doc`, `url`, `origin` (strings, optional);; The documentation string, url, and the origin of the definition or value, if any. [[req_refs]]`refs`:: Used to find all references to a given variable or property. + Takes `file`, `end` (required), and `start` (optional) fields to specify the expression we are interested in. <>. + Returns an object with a `name` property holding the name of the variable or property, a `refs` property holding an array of `{file, start, end}` objects, and, for variables, a `type` property holding either `"global"` or `"local"`. [[req_rename]]`rename`:: Rename a variable in a scope-aware way. + Takes `file`, `end` (required), and `start` (optional) fields to specify the variable we want to rename (<>), and a `newName` property that gives the new name of the variable. + Returns an object whose `changes` property holds an array of `{file, start, end, text}` objects, which give the changes that must be performed to apply the rename. The client is responsible for doing the actual modification. [[req_properties]]`properties`:: Get a list of all known object property names (for _any_ object). `prefix` (string, optional);; Causes the server to only return properties that start with the given string. `sort` (optional, default `true`);; Whether the result should be sorted. + The returned object will have a `completions` property holding an array of strings, which are the property names. [[req_files]]`files`:: Get the files that the server currently holds in its set of analyzed files. + Does not take any parameters. Returns an object with a `files` property holding an array of strings (the file names). [[loc_spec]] When specifying a location, which is needed for most of the query types, the required `file` field may hold either a filename, or a string in the form `"#N"`, where `N` should be an integer referring to one of the files included in the request (more on that <>). The required `end` field is an offset into this file, either a number or a `{line, ch}` object. It should point at the end of the expression the request is interested in, or somewhere inside of it if that doesn't end up pointing inside a sub-expression (in which case the inner expression would be used). An optional `start` field can be used to disambiguate between expressions—if given, the innermost expression that spans the range between start and end will be used. [[offsets]] Offsets into a file can be either (zero-based) integers, or `{line, ch}` objects, where both `line` and `ch` are zero-based integers. Offsets returned by the server will be integers, unless the `lineCharPositions` field in the request was set to `true`, in which case they will be `{line, ch}` objects. The format of the `doc` field in responses will, by default, only contain the first few sentences of the documentation string, and have newlines stripped. To get the full string, with newlines intact, you can add a `docFormat` field to your query with the value `"full"`. [[variable]] Requests that take an input expression also accept a `variable` field which, when given, will cause the server to not look for an expression in the code, but to make up a variable expression with the given name. This does not remove the need to pass in an `end`, since that will be used to determine the scope in which the variable is interpreted. [[protocol_files]] The `files` property of a request must, if present, hold an array of file descriptions. These can be complete files, which have a `type` property holding `"full"` and `name` and `text` properties holding strings. Complete files will be stored by the server and can be reused in later requests. Alternatively, you can pass in partial files. This is useful when needing to perform a query on a large file without re-uploading and re-analyzing the whole file. A partial file has a `type` property holding the string `"part"`, a `text` property holding some slice of the file (starting at a line boundary), a `name` property referring to an existing file, and an `offset` property, either an integer or a `{line, ch}` object, indicating the approximate position of the fragment in the file. To remove a file from the server's model of the project, you can include an object with a `name` property that identifies the file and a `type` property of `"delete"`. [[server_api]] === Programming interface === [[tern.Server]] The base server (without HTTP or configuration-file reading) is implemented in `lib/tern.js`. That package exposes a `Server` constructor that can be used to create a server. It takes an object holding configuration options as argument. These are recognized (all have a default): [[option_defs]] `defs` (array of strings):: The <> objects to load into the server's environment. [[option_plugins]] `plugins` (object):: Specifies the set of <> that the server should load. The property names of the object name the plugins, and their values hold options that will be passed to them. [[option_ecmaVersion]] `ecmaVersion` (number):: The ECMAScript version to parse. Should be either 5 or 6. Default is 6. [[option_getFile]] `getFile` (function):: Provides a way for the server to try and fetch the content of files. Depending on the `async` option, this is either a function that takes a filename and returns a string (when not `async`), or a function that takes a filename and a callback, and calls the callback with an optional error as the first argument, and the content string (if no error) as the second. [[option_async]] `async` (bool):: Indicates whether `getFile` is asynchronous. Default is `false`. [[option_fetchTimeout]] `fetchTimeout` (number):: Indicates the maximum amount of milliseconds to wait for an asynchronous `getFile` before giving up on it. Defaults to `1000`. A server object has the following methods: [[tern.Server.addFile]] `addFile(name: string, text?: string, parent?: string)`:: Register a file with the server. Note that files can also be <> in requests. When using this to automatically load a dependency, specify the name of the file (as Tern knows it) as the third argument. That way, the file is counted towards the <> of the root of its dependency graph. [[tern.Server.delFile]] `delFile(name: string)`:: Unregister a file. [[tern.Server.request]] `request(doc: object, callback: fn(error, response))`:: Perform a request. `doc` is a (parsed) JSON document as described in the <>. The `callback` function will be called when the request completes. If an error occurred, it will be passed as a first argument. Otherwise, the resonse (parsed) JSON object will be passed as second argument. + When the server hasn't been configured to be <>, the callback will be called before `request` returns. [[tern.Server.flush]] `flush(callback: fn())`:: Forces all files to be fetched an analyzed, and then calls the callback function. [[tern.Server.on]] `on(eventType: string, handler: fn())`:: Register an event handler for the named type of event. [[tern.Server.off]] `off(eventType: string, handler: fn())`:: Unregister an event handler. [[tern.Server.addDefs]] `addDefs(defs: object, atFront?: bool)`:: Add a set of <> to the server. If `atFront` is true, they will be added before all other existing definitions. Otherwise, they are added at the back. [[tern.Server.deleteDefs]] `deleteDefs(name: string)`:: Delete a set of <> from the server, by providing the name, taken from `defs[!name]` property from the definitions. If that property is not available in the current type definitions, it can't be removed. [[tern.Server.loadPlugin]] `loadPlugin(name: string, options?: object)`:: Load a <> (or don't do anything, if the plugin is already loaded). [[events]] The server fires the following type of events (mostly useful for plugins): [[event_reset]] `"reset" ()`:: When the server throws away its current analysis data and starts a fresh run. [[event_beforeLoad]] `"beforeLoad" (file)`:: Before analyzing a file. `file` is an object holding `{name, text, scope}` properties. [[event_afterLoad]] `"afterLoad" (file)`:: After analyzing a file. [[event_preParse]] `"preParse" (text, options)`:: Will be run right before a file is parsed, and passed the given text and options. If a handler returns a new text value, the origin text will be overriden. This is useful for instance when a plugin is able to extract JavaScript content from an HTML file. [[event_postParse]] `"postParse" (ast, text)`:: Run right after a file is parsed, and passed the parse tree and the parsed file as arguments. [[event_preInfer]] `"preInfer" (ast, scope)`:: Run right before the type inference pass, passing the syntax tree and a <> object. [[event_postInfer]] `"postInfer" (ast, scope)`:: Run after the type inference pass. [[event_typeAt]] `"typeAt" (file, end, expr, type)`:: Run after Tern attempts to find the type at the position `end` in the given file. A handler may return either the given type (already calculated by Tern and earlier `"typeAt"` passes) or an alternate type to be used instead. This is useful when a plugin can provide a more helpful type than Tern (e.g. within comments). [[event_completion]] `"completion" (file, query)`:: Run at the start of a completion query. May return a <> to replace the default completion algorithm. [[typedef]] === JSON type definitions === To be able to specify the types of things without actually analyzing source code, either because there is no JavaScript source code (as for the built-in types) or because the source code is too big, or because Tern is unable to construct the correct types from the source code, Tern defines a JSON data format for specifying types. A few examples of files in this format can be found in the `defs/` directory in the distribution. A type definition data structure is basically a tree of objects, where the top-level object specifies variables in the global scope, and the nested objects specify properties of object types. Properties prefixed with an exclamation point (`!`) hold special directives, all other properties refer to variable or property names. Here is an example: [source,application/x-json] ---- { "!name": "mylibrary", "!define": { "point": { "x": "number", "y": "number" } }, "MyConstructor": { "!type": "fn(arg: string)", "staticFunction": "fn() -> bool", "prototype": { "property": "[number]", "clone": "fn() -> +MyConstructor", "getPoint": "fn(i: number) -> point" } }, "someOtherGlobal": "string" } ---- This defines a library that sets two globals, `MyConstructor` holding a constructor function, and `someOtherGlobal` holding a string. The origin of the types, variables, and properties defined by this document will be `"mylibrary"`, as set by the `!name` property. The value of a variable or property can be either a string or an object. Strings can be one of the built-in types (`"number"`, `"string"`, `"bool"`), a function type (`"fn(arg1: type1, arg2: type2) -> rettype"`, where `-> rettype` is optional), or an array type (`"[type]"`). Strings can also name types, either by describing the path to the type in the global scope (`"Date.prototype"`) or by referring to one of the local definitions in the `!define` property of the document. Finally, a type can be prefixed with a `+` to indicate an instance of a constructor (`+Date`). Objects describe types by enumerating their properties. By default, their type will simply be an instance of `Object`, but a `!type` property can be used to make the type a function or array type, as the example does for `MyConstructor`. Alternatively, a `!proto` property can be used to give the object a custom prototype, for example `"!proto": Element.prototype`. Documentation can be attached to a type using `!doc`, which should hold a (short) documentation string and `!url`, which should hold a URL that has the full documentation of the type or function being defined. Finally, a function can be annotated with effects that it has. These aren't currently documented, but you can search for `!effects` in `defs/ecma5.json` to see some examples. Similarly, a function type string's return type may contain the variables `!0` (the first argument's type, `!N` for the N-1th), `!this` (the self type of the call), and a special property `!ret` (the return type of a function). [[plugins]] === Server plugins === Plugins are JavaScript programs that add extra functionality to a server. The distribution currently comes plugins for parsing <>, and plugins for <> and <>, which teach the Tern server about the dependency management mechanisms defined by those systems (as well as, for node.js, including types for the built-in libraries). A plugin can use several hooks to add custom behavior. [[infer.registerFunction]]`infer.registerFunction(name: string, f: fn(self, args, argnodes))`:: This is a function in the <> that allows custom ways to compute function return types or effects. When a function is specified to return `!custom:myname` or has an effect `"custom myname"`, a call to the function will cause the function registered under `"myname"` to be called with the argument types and argument AST nodes given to the call. This is used, for example, to make calls to `require` trigger the necessary machinations to fetch a dependency and return its type. [[tern.registerPlugin]]`tern.registerPlugin(name: string, fn(Server, options))`:: This can be used to register an initialization function for the plugin with the given name. A Tern server, when <> to load this plugin, will call this initialization function, passing in the server instance and the options specified for the plugin (if any). This is the place where you register <> on the server, <> type definitions, <> other plugins as dependencies, and/or initialize the plugin's state. + See the server's <> for ways to wire up plugin behavior. [[tern.defineQueryType]]`tern.defineQueryType(name: string, desc: object)`:: Defines a new type of query with the server. The `desc` object is a property describing the request. It should at least have a `run` property, which holds a function `fn(Server, query)` that will be called to handle queries with a `type` property that matches the given name. It may also have a `takesFile` property which, if true, will cause the server to try and resolve the file on which the query operates (from its `file` property) and pass that (a `{name, text, scope, ast}` object) as a third argument to the `run` function. You will probably need to use the <> to do someting useful in this function. [[plugin_doc_comment]] ==== Doc comments plugin ==== This plugin, which is enabled by default in the `bin/tern` server, parses comments before function declarations, variable declarations, and object properties. It will look for http://usejsdoc.org/[JSDoc]-style type declarations, and try to parse them and add them to the inferred types, and it will treat the first sentence of comment text as the docstring for the defined variable or property. To turn this plugin off, set `doc_comment: null` in your <>. The plugin understands the following configuration parameters: `strong`:: When enabled, types specified in comments take precedence over inferred types. [[plugin_complete_strings]] ==== String completion plugin ==== When enabled, this plugin will gather (short) strings in your code, and completing when inside a string will try to complete to previously seen strings. Takes a single option, `maxLength`, which controls the maximum length of string values to gather, and defaults to 15. [[plugin_commonjs]] ==== CommonJS module plugin ==== This plugin implements CommonJS-style (`require("foo")`) modules. It will wrap files in a file-local scope, and bind `require`, `module`, and `exports` in this scope. Does not implement a module resolution strategy (see for example <>). Depends on the <> plugin. [[plugin_node]] ==== Node.js plugin ==== The http://nodejs.org[node.js] plugin, called `"node"`, provides variables that are part of the node environment, such as `process` and `__dirname`, and loads the <> and <> plugins to allow node-style module loading. It defines types for the built-in modules that node.js provides (`"fs"`, `"http"`, etc). [[plugin_node_resolve]] ==== Node.js resolve plugin === This plugin defines the node.js module resolution strategy—things like defaulting to `index.js` when requiring a directory and searching `node_modules` directories. It depends on the <>. Note that this plugin only does something meaningful when the Tern server is running on node.js itself. [[plugin_modules]] ==== Modules plugin ==== This is a supporting plugin to act as a dependency for other module-loading and module-resolving plugins. It understands the following configuration parameters: `dontLoad`:: Can be set to `true` to disable dynamic loading of required modules entirely, or to a regular expression to disable loading of files that match the expression. `load`:: If `dontLoad` isn't given, this setting is checked. If it is a regular expression, the plugin will only load files that match the expression. `modules`:: Can be used to assign <> to certain modules, so that those are loaded instead of the source code itself. If given, should be an object mapping module names to either JSON objects defining the types in the module, or a string referring to a file name (relative to the project directory) that contains the JSON data. [[plugin_es_modules]] ==== ES modules plugin ==== Builds on top of the <> to support ECMAScript 6's `import` and `export` based module inclusion. [[plugin_requirejs]] ==== RequireJS plugin ==== This plugin (`"requirejs"`) teaches the server to understand http://requirejs.org[RequireJS]-style dependency management. It defines the global functions `define` and `requirejs`, and will do its best to resolve dependencies and give them their proper types. These options are understood: `baseURL`:: The base path to prefix to dependency filenames. `paths`:: An object mapping filename prefixes to specific paths. For example `{"acorn": "lib/acorn/"}`. `override`:: An object that can be used to override some dependency names to refer to predetermined types. The value associated with a name can be a string starting with the character `=`, in which case the part after the `=` will be interpreted as a global variable (or dot-separated path) that contains the proper type. If it is a string not starting with `=`, it is interpreted as the path to the file that contains the code for the module. If it is an object, it is interpreted as <>. [[plugin_angular]] ==== Angular.js plugin ==== Adds the `angular` object to the top-level environment, and tries to wire up some of the bizarre dependency management scheme from this library, so that dependency injections get the right types. Enabled with the name `"angular"`. [[plugin_third_party]] ==== Third-party plugins ==== It is possible to write third-party plugins or JSON type definitions and distribute them independently, either as packages using https://www.npmjs.org[npm] or as raw JavaScript files. When a _name_ attribute is specified in the `libs` section of the project configuration, Tern first searches for a file '`name`'`.json` in its distribution `defs` directory, then for a file '`name`'`.json` in the user's project directory, and finally for an installed package named `"tern-`'`name`'`"` to load as a JSON Type Definition. A JSON Type Definition distributed as an npm package must have a package name matching the pattern `"tern-`'`name`'`"`. When a 'name' attribute is specified in the `plugins` section of the project configuration, Tern first searches for a file '`name`'`.js` in its distribution `plugin` directory, then for a file '`name`'`.js` in the user's project directory, and finally for an installed package named `"tern-`'`name`'`"` to load as a plugin. A plugin distributed as an npm package must have a package name matching the pattern `"tern-`'`name`'`"`. The main module for a third-party plugin that will be installed outside of the Tern distribution should export a single method `initialize(ternDir: string)` which takes the location of the Tern distribution loading the plugin as an argument. Tern will call this method immediately after loading the plugin to tell the plugin where to find Tern modules. A plugin with this method will work regardless of its install location relative to the Tern distribution, but plugins without it may fail to find Tern modules or even silently load the wrong Tern modules depending on install location. Plugin packages can specify the Tern version required as a http://blog.nodejs.org/2013/02/07/peer-dependencies[peer dependency]. [[configuration]] === Project configuration === A `.tern-project` file is a http://json.org[JSON] file in a format like this: [source,application/x-json] ---- { "libs": [ "browser", "jquery" ], "loadEagerly": [ "importantfile.js" ], "plugins": { "requirejs": { "baseURL": "./", "paths": {} } } } ---- The `libs` property refers to the <> that should be loaded into the environment for this project. See the `defs/` directory for examples. The strings given here will be suffixed with `.json`, and searched for first in the project's own dir, and then in the `defs/` directory of the Tern distribution. By default, local files are loaded into the Tern server when queries are run on them the editor. `loadEagerly` allows you to force some files to always be loaded, it may be an array of filenames or glob patterns (i.e. `foo/bar/*.js`). The `dontLoad` option can be used to prevent Tern from loading certain files. It also takes an array of file names or glob patterns. The `plugins` field may hold object used to load and configure Tern plugins. The names of the properties refer to files that implement plugins, either in the project dir or under `plugin/` in the Tern directory. Their values are configuration objects that will be passed to the plugins. You can leave them at `{}` when you don't need to pass any options. You can specify an `ecmaVersion` field to configure the version of ECMAScript that Tern parses. The default is 6, and leaving it at that should be safe even for ECMAScript 5 code, but you can set it to 5 as well. [[dependency_budget]] To configure the amount of work Tern is prepared to do to load a single dependency, the `dependencyBudget` option can be added to a project file. It indicates the maximum size of the files loaded in response to a single dependency (through plugins that load dependencies, such as the <> and <> plugins), counted in expressions. The default value is 20 000. Files loaded as dependencies of dependencies count towards the budget of the original dependency. [[utils]] === Utilities === `bin/test`:: Runs Tern's own testsuite. Tests are defined in the `test/` directory, as code interspersed with comments that indicate the types and conditions to check for. [[condense]]`bin/condense`:: Utility for condensing source code down to a <> file. Takes a list of files to condense, optionally interleaved with filenames prefixed with a `+`, which will be loaded (to provide type information) but not included in the output. + Pass `--plugin name` or `--plugin name={jsonconfig}` to load plugins. Use `--def file` to load <>. `bin/from_ts`:: Given a typescript `.def.ts` file, will attempt to convert it to a Tern-style <> file. [[infer]] == Inference engine == The inference engine module (`lib/infer.js`) implements a system that, given a context and an abstract syntax tree (parsed representation of the code), tries to infer the types of the variables and properties in the code. The parser is implemented in a separate module, http://marijnhaverbeke.nl/acorn[Acorn], which provides a regular JavaScript parser, an error-tolerant parser, and a number of utilities for iterating through and searching in abstract syntax trees. The syntax tree format used by Acorn and Tern is described in the https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API[Mozilla parser API] document (though support for features that are not in ECMAScript 5, such as `let`, is omitted). A high-level description of the way Tern's type inference algorithm works can be found in a http://marijnhaverbeke.nl/blog/tern.html[blog post] I wrote on the subject. This module also exposes some utility functions that are useful to implement the <> the server exposes. [[infer_context]] === Context === A context is an object that holds a global JavaScript scope, as well as some meta-information and state used by the type inference process. Almost all operations in the inference module require a context. To prevent having to pass the context around through every function, a form of dynamic binding is used—the `withContext` function executes a function body with a given object used as the current context. [[infer.Context]]`infer.Context(defs: [object])`:: A constructor function for contexts. `defs` should be an array of <>, which will be used to initialize the global scope. [[infer.withContext]]`infer.withContext(context: Context, f: fn())`:: Calls `f` with the current context bound to `context`. Basically, all code that does something with the inference engine should be wrapped in such a call. [[infer.cx]]`infer.cx() → Context`:: Returns the current context object. [[infer.Context.topScope]]`context.topScope`:: The top-level <> of the context. [[infer_analysis]] === Analysis === To push code into a context, you first parse it, yielding a syntax tree, and then tell Tern to analyze that. [[infer.parse]]`infer.parse(text: string, options?: {}) → AST`:: Parse a piece of code for use by Tern. Will automatically fall back to the error-tolerant parser if the regular parser can't parse the code. [[infer.analyze]]`infer.analyze(ast: AST, name: string, scope?: Scope)`:: Analyze a syntax tree. `name` will be used to set the origin of types, properties, and variables produced by this code. The optional `scope` argument can be used to specify a <> in which the code should be analyzed. It will default to the top-level scope. The same code, or slightly modified variants of the same code, can be analyzed in a context multiple times. The variables and properties that the context knows, as well as the types it assigns to them, will become the union of the variables and types created by the various forms of the code. When incrementally re-analyzing code as it is being edited, this leads to a degradation in the preciseness of the results. To prevent that, it is possible to _purge_ all elements that come from a specific origin from a context. [[infer.purgeTypes]]`infer.purgeTypes(origins: [string], start?: number, end?: number)`:: Purges the types that have one of the origins given from the context. `start` and `end` can be given to only purge types that occurred in the source code between those offsets. This is not entirely precise—the state of the context won't be back where it was before the file was analyzed—but it prevents most of the noticeable inaccuracies that re-analysis tends to produce. [[infer.markVariablesDefinedBy]]`infer.markVariablesDefinedBy(scope: Scope, origins: [string], start?: number, end?: number)`:: Cleaning up variables is slightly trickier than cleaning up types. This does a first pass over the given scope, and marks variables defined by the given origins. This is indended to be followed by a call to <> and then a call to <>. [[infer.purgeMarkedVariables]]`infer.purgeMarkedVariables`:: Purges variables that were marked by a call to <> and not re-defined in the meantime. [[infer_types]] === Types === Tern has a more or less complete implementation of the JavaScript type system. [[infer.Obj]]`infer.Obj(proto, name?: string)`:: Constructor for the type that represents JavaScript objects. `proto` may be another object, or `true` as a short-hand for `Object.prototype`, or `null` for prototype-less objects. [[infer.Fn]]`infer.Fn(name: string?, self: AVal, args: [AVal], argNames: [string], retval: AVal)`:: Constructor for the type that implements functions. Inherits from <>. The <> types are used to track the input and output types of the function. [[infer.Arr]]`infer.Arr(contentType: AVal)`:: Constructor that creates an array type with the given content type. [[infer.Context.num]]`context.num`:: The primitive number type. [[infer.Context.str]]`context.str`:: The primitive string type. [[infer.Context.bool]]`context.bool`:: The primitive boolean type. Types expose the following interface (plus some `AVal`-compatibility methods, see <>). [[infer.Type.name]]`type.name: string`:: The name of the type, if any. [[infer.Type.origin]]`type.origin: string`:: The origin file of the type. [[infer.Type.originNode]]`type.originNode: AST`:: The syntax node that defined the type. Only present for object and function types, and even for those it may be missing (if the type was created by a type definition file, or synthesized in some other way). [[infer.Type.toString]]`type.toString(maxDepth: number) → string`:: Return a string that describes the type. `maxDepth` indicates the depth to which inner types should be shown. [[infer.Type.getProp]]`type.getProp(prop: string) → AVal`:: Get an <> that represents the named property of this type. [[infer.Type.forAllProps]]`type.forAllProps(f: fn(prop: string, val: AVal, local: bool))`:: Call the given function for all properties of the object, including properties that are added in the future. Object types have a few extra methods and properties. [[infer.Obj.proto]]`obj.proto`:: The prototype of the object, or `null`. [[infer.Obj.props]]`obj.props`:: An object mapping the object's known properties to AVals. Don't manipulate this directly (ever), only use it if you have to iterate over the properties. [[infer.Obj.hasProp]]`obj.hasProp(prop: string) → AVal?`:: Looks up the AVal associated with the given property, or returns `null` if it doesn't exist. [[infer.Obj.defProp]]`obj.defProp(prop: string, originNode?: AST) → AVal`:: Looks up the given property, or defines it if it did not yet exist (in which case it will be associated with the given AST node). [[infer_aval]] === Abstract values === Abstract values are objects used to represent sets of types. Each variable and property has an abstract value associated with it, but they are also used for other purposes, such as tracking the return type of a function, or building up the type for some kinds of expressions. In a cleanly typed program where each thing has only a single type, abstract values will all have one type associated with them. When, for example, a variable can hold two different types of values, the associated abstract value will hold both these types. In some cases, no type can be assigned to something at all, in which case the abstract value remains empty. Abstract values expose the following interface: [[infer.AVal]]`infer.AVal()`:: Constructor. Creates an empty AVal. [[infer.AVal.addType]]`aval.addType(type: Type, weight?: number)`:: Add a type to this abstract value. If the type is already in there, this is a no-op. `weight` can be given to give this type a non-default weight, which is mostly useful when adding a provisionary type that should be overridden later if a real type is found. The default weight is `100`, and passing a weight lower than that will make the type assignment ``weak''. [[infer.AVal.propagate]]`aval.propagate(target: Constraint)`:: Sets this AVal to propagate all types it receives to the given <>. This is the mechanism by which types are propagated through the type graph. [[infer.AVal.hasType]]`aval.hasType(type: Type) → bool`:: Queries whether the AVal _currently_ holds the given type. [[infer.AVal.isEmpty]]`aval.isEmpty() → bool`:: Queries whether the AVal is empty. [[infer.AVal.getType]]`aval.getType(guess?: bool) → Type?`:: Asks the abstract value for its current type. May return `null` when there is no type, or conflicting types are present. When `guess` is `true` or not given, an empty AVal will try to use heuristics based on its propagation edges to guess a type. [[infer.AVal.getFunctionType]]`aval.getFunctionType() → Type?`:: Asks the AVal if it contains a function type. Useful when you aren't interested in other kinds of types. Abstract values that are used to represent variables or properties will have, when possible, an `originNode` property pointing to an AST node. [[type_is_aval]] As a memory-consuming hack, <> also expose the interface of abstact values, so that in cases where an AVal is expected, but the precise type is known, the type object can simply be used. [[infer.ANull]]The `infer.ANull` value is a special AVal-like object that never holds any types, and discards types added to it. It can be used as a placeholder in situations where we either aren't interested in the types, or there simply are no types. [[infer_constraint]] === Constraints === Constraints are things that can receive values. They use the same `addType` method to receive them, which causes all AVals to also be useable as constraints. The inference engine defines a number of additional constraints to propagate values in more indirect ways. See the http://marijnhaverbeke.nl/blog/tern.html[blog post] on the inference algorithm for some examples. [[infer.constraint]]`infer.constraint(methods: object) → constructor`:: This is a constructor-constructor for constraints. It'll create a constructor with all the given methods copied into its prototype, which will run its `construct` method on its arguments when instantiated. Beyond <>, there are a few optional methods that constraints can expose to tell the system something about itself. [[infer.Constraint.typeHint]]`constraint.typeHint() → Type?`:: May return a type that <> can use to ``guess'' its type based on the fact that it propagates to this constraint. [[infer.Constraint.propHint]]`constraint.propHint() → string?`:: May return a string when this constraint is indicative of the presence of a specific property in the source AVal. [[infer_scopes]] === Scopes === Scopes are derived from the <> type, and variables are represented the same way as properties. [[infer.Scope]]`infer.Scope(parent?: Scope)`:: Constructor for scope objects. The top scope won't have a parent. [[infer.Scope.defVar]]`scope.defVar(name: string, originNode: AST) → AVal`:: Ensures that this scope or some scope above it has a property by the given name (defining it in the top scope if it is missing), and, if the property doesn't already have an <>, assigns the given node to it. [[infer_util]] === Utilities === These are miscellaneous utilities that come in helpful when doing code analysis. [[infer.findExpressionAt]]`infer.findExpressionAt(ast: AST, start: number?, end: number, scope?: Scope) → {node, state}`:: Searches the given syntax tree for an expression that ends at the given end offset and, if `start` is given, starts at the given start offset. `scope` can be given to override the outer scope, which defaults to the context's top scope. Will return a `{node, state}` object if successful, where `node` is AST node, and `state` is the scope at that point. Returns `null` if unsuccessful. [[infer.findExpressionAround]]`infer.findExpressionAround(ast: AST, start: number?, end: number, scope?: Scope) → {node, state}`:: Similar to <>, except that it will return the innermost expression node that spans the given range, rather than only exact matches. [[infer.expressionType]]`infer.expressionType(expr: {node, state}) → AVal`:: Determine an expression for the given node and scope (as returned by the functions above). Will return an <> or plain <>. [[infer.scopeAt]]`infer.scopeAt(ast: AST, pos: number, scope?: Scope) → Scope`:: Find the scope at a given position in the syntax tree. The `scope` parameter can be used to override the scope used for code that isn't wrapped in any function. [[infer.findRefs]]`infer.findRefs(ast: AST, scope: Scope, name: string, refScope: Scope, f: fn(AST, Scope))`:: Will traverse the given syntax tree, using `scope` as the starting scope, looking for references to variable `name` that resolve to scope `refScope`, and call `f` with the node of the reference and its local scope for each of them. [[infer.findPropRefs]]`infer.findPropRefs(ast: AST, scope: Scope, objType: Obj, propName: string, f: fn(AST))`:: Analogous to <>, but used to look for references to a specific property instead. Whereas `findRefs` is precise, this is dependent on type inference, and thus can not be relied on to be precise. Whenever the code in `lib/infer.js` guesses a type through fuzzy heuristics (through <> or <>), it sets a flag. The following two function allow access to this flag: [[infer.didGuess]]`infer.didGuess() → bool`:: Test whether the guessing flag is set. [[infer.resetGuessing]]`infer.resetGuessing(val?: bool)`:: Reset the guessing flag. [[editor]] == Editor plugins == If your editor of choice is not yet supported, you are encouraged to try and port one of the existing plugins to it. When figuring out how things work, the code powering the demo, in `doc/demo/demo.js`, might also come in useful. All these plugins use the http://nodejs.org[node.js]-based server, and thus require that (as well as http://npmjs.org[npm]) to be installed. [[emacs]] === Emacs === The Emacs mode is part of the main tern https://github.com/ternjs/tern[repository]. It can be installed as follows: . Make sure you are using Emacs 24 or later. The Tern mode requires lexical scoping. . Clone this repository somewhere. Do `npm install` to get the dependencies. . Make Emacs aware of `emacs/tern.el`. For example by adding this to your `.emacs` file: + [source,commonlisp] ---- (add-to-list 'load-path "/path/to/tern/emacs/") (autoload 'tern-mode "tern.el" nil t) ---- . Optionally set `tern-mode` to be automatically enabled for your JavaScript mode of choice. Here's the snippet for `js-mode`: + [source,commonlisp] ---- (add-hook 'js-mode-hook (lambda () (tern-mode t))) ---- The Emacs mode uses the `bin/tern` server, and project configuration is done with a <> file. Buffers in `tern-mode` add a `completion-at-point` function that activates Tern's completion. So, unless you rebound the key, `M-tab` (or `C-M-i`) will trigger completion. When the point is in an argument list, Tern will show argument names and types at the bottom of the screen. The following additional keys are bound: `M-.`:: Jump to the definition of the thing under the cursor. `M-,`:: Brings you back to last place you were when you pressed `M-.`. `C-c C-r`:: Rename the variable under the cursor. `C-c C-c`:: Find the type of the thing under the cursor. `C-c C-d`:: Find docs of the thing under the cursor. Press again to open the associated URL (if any). ==== Auto-Complete ==== If you want to use `auto-complete.el` for completion, append following codes: [source,commonlisp] ---- (eval-after-load 'tern '(progn (require 'tern-auto-complete) (tern-ac-setup))) ---- If `tern-ac-on-dot` is non-nil (default), typing `.`(dot) invokes auto-complete to select completions. Calling the command `tern-ac-complete`, one can invoke auto-complete manually. [[vim]] === Vim === The Vim plugin is maintained in a https://github.com/ternjs/tern_for_vim[separate repository]. Please see its README for details. [[sublime_text]] === Sublime Text === There are two implementations of Sublime Text modules for Tern. One written by me, at . This one uses the node.js-based server. The other is written by Sergey Chikuyonok, and can be found at . It uses a Python V8 bridge to run the server. See the readme files in those repositories for details. [[tern_java]] === Eclipse / Java === https://github.com/angelozerr/tern.java[tern.java] is a Tern client written in Java. It includes Eclipse integration. [[tern_for_gedit]] === gedit === https://github.com/Swatinem/tern_for_gedit[tern_for_gedit] integrates Tern with the https://github.com/Swatinem/tern_for_gedit[gedit] editor. [[software]] == Related Software == This is a place to gather links to software that is built on Tern. Drop me an mailto:marijnh@gmail.com[email] if you want to suggest a link. === jsctags === https://github.com/ramitos/jsctags[jsctags] is a tool that generates ctags files from JavaScript code by using Tern's inference engine. === CodeMirror Tern addon === The http://codemirror.net[CodeMirror] browser-based editor has an http://codemirror.net/demo/tern.html[addon] for integrating with Tern. === tern.ace === https://github.com/angelozerr/tern.ace[tern.ace] integrates Tern in the http://ace.c9.io/[ACE] editor. === tern.orion === https://github.com/angelozerr/tern.orion[tern.orion] integrates Tern in the http://www.eclipse.org/orion/[Orion] editor.