forked from ternjs/tern
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
208 lines (166 loc) · 7.56 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<!doctype html>
<head>
<meta charset="utf-8">
<script src="node_modules/codemirror/lib/codemirror.js"></script>
<script src="node_modules/codemirror/mode/javascript/javascript.js"></script>
<link rel=stylesheet href="node_modules/codemirror/lib/codemirror.css">
<script src="node_modules/codemirror/addon/hint/show-hint.js"></script>
<link rel="stylesheet" href="node_modules/codemirror/addon/hint/show-hint.css">
<script src="node_modules/codemirror/addon/dialog/dialog.js"></script>
<link rel="stylesheet" href="node_modules/codemirror/addon/dialog/dialog.css">
<script src="node_modules/codemirror/addon/search/searchcursor.js"></script>
<script src="node_modules/codemirror/addon/search/search.js"></script>
<script src="node_modules/codemirror/addon/edit/matchbrackets.js"></script>
<script src="node_modules/acorn/acorn.js"></script>
<script src="node_modules/acorn/acorn_loose.js"></script>
<script src="node_modules/acorn/util/walk.js"></script>
<script src="lib/tern.js"></script>
<script src="lib/def.js"></script>
<script src="lib/jsdoc.js"></script>
<script src="lib/infer.js"></script>
<script src="demo/demo.js"></script>
<script src="plugin/requirejs.js"></script>
<link rel=stylesheet href="doc/docs.css">
<title>Tern</title>
</head>
<div id=head>
<h1>Tern. <span>Intelligent JavaScript editing</span></h1>
<img id=head-image src="doc/header.png">
</div>
<div id=main>
<p>A tern is a small sea bird. It darts over the waves, looking for
fish below the surface. When it spots one, it dives into the water,
vanishes for an instant, and bursts out again with its prey in its
beak.</p>
<p>Tern is a piece of software. It dives into the muddy depths of a
JavaScript system to locate the information that it was asked for.
Combined with an editor plug-in, it can make the life of a JavaScript
programmer a lot more pleasant.</p>
<p>Find the code on <a href="http://github.com/marijnh/tern">Github</a>.</p>
<h2>Demo</h2>
<p>This editor is hooked up to Tern. The drop-down in the top right
corner lists the commands and keyboard shortcuts available. Output and
function argument hints will appear in the bar below the editor.</p>
<div style="position: relative" id="demospace">
<select id="commands">
<option>commands...</option>
<option value=complete>Autocomplete (ctrl-space)</option>
<option value=jumptodef>Jump to definition (alt-.)</option>
<option value=findtype>Find type of (ctrl-i)</option>
<option value=rename>Rename variable (ctrl-q)</option>
<option value=addfile>Add a new file</option>
<option value=delfile>Remove this file</option>
</select>
<form>
<ul class="tabs" id="docs"></ul>
<textarea id=code name=code>
// Use ctrl-space to complete something
co
document.body.a
// Put the cursor in or after an expression, press ctrl-i to
// find its type
var foo = ["array", "of", "strings"];
var bar = foo.slice(0, 2).join("").split("a")[0];
// Works for locally defined types too.
function CTor() { this.size = 10; }
CTor.prototype.hallo = "hallo";
var baz = new CTor;
baz.
// You can press ctrl-q when the cursor is on a variable name to
// rename it. Try it with CTor...
// When the cursor is in an argument list, the arguments are
// shown below the editor.
[1].reduce( );
// And a little more advanced code...
(function(exports) {
exports.randomElt = function(arr) {
return arr[Math.floor(arr.length * Math.random())];
};
exports.strList = "foo".split("");
exports.intList = exports.strList.map(function(s) { return s.charCodeAt(0); });
})(window.myMod = {});
var randomStr = myMod.randomElt(myMod.strList);
var randomInt = myMod.randomElt(myMod.intList);
// A test of the requirejs plug-in. Check the 'test_dep.js' tab,
// notice that the test variable.
requirejs(["test_dep.js"], function(test) {
var word = test.capitalize(test.garble("coconut"));
console.log(word);
});
</textarea></form>
<pre class=output id=out></pre>
</div>
<pre style="display: none" id="requirejs_test_dep">define(function() {
return {
capitalize: function(word) {
return word.charAt(0).toUpperCase() + word.slice(1);
},
garble: function(word) {
return word.replace(/[auiyoe]/g, function() {
return "auiyoe".charAt(Math.floor(Math.random() * 6));
});
}
};
});</pre>
<h2>What is the status of the project?</h2>
<p>Tern is not yet finished. The core works well enough to be useful,
but a lot of work is still to be done: testing, documenting, fixing
bugs, and writing editor plug-ins.</p>
<p>Tern is open source software, under an MIT license. You can find
the code on <a href="https://github.com/marijnh/tern">Github</a>.
Documentation does not exist yet, but is being worked on.</p>
<h2>How does it work?</h2>
<p>Tern parses and analyzes a program on the fly, using a simple form
of type inference along with a lot of heuristics and dirty tricks to
approximate the types of the variables and expressions in the
program.</p>
<p>The type inference algorithm is roughly based on
the <a href="http://rfrn.org/~shu/drafts/ti.pdf">algorithm</a> used in
Mozilla's SpiderMonkey engine. It deviates from their approach in
several ways, because, on the one hand, it does not have access to
run-time information, and, on the other hand, it does not have to be
entirely precise, and can use approximations in some cases.</p>
<p>Once you know the type of a thing, it is easy to provide a
meaningful list of property completions, or display a function type as
a set of parameter hints.</p>
<p>Tern can be run in two ways — as a JavaScript library, for
integration in JavaScript-based systems like the demo above, or as an
HTTP server, for use with desktop editor plug-ins.</p>
<h2>Is this new?</h2>
<p>I am under the impression that the approach I'm taking here has
never before been applied to JavaScript editing assistance.</p>
<p>Microsoft's Visual Studio's JavaScript Intellisense comes the
closest, in terms of power. It uses a completely different approach
(actually running the code, instead of doing type inference), and has
some different strengths and weaknesses.</p>
<p>But that is a proprietary system tied to a single IDE. Tern is an
open system that can (and will) be plugged into a variety of editors
and IDEs.</p>
<h2>Does it scale?</h2>
<p>So is this a clever toy that works in a little text input like the
one above, or something that can be applied when working on real, big,
multi-file, multi-dependency projects?</p>
<p>I've tried to keep big codebases in mind as I built this. These are
the strategies Tern uses to stay responsive in the face of huge bulks
of code:</p>
<ul>
<li>The parser it uses
(<a href="http://marijnhaverbeke.nl/acorn/">Acorn</a>) is heavily
optimized.</li>
<li>The type inference algorithm is designed to be lightweight (its
other use, in the SpiderMonkey compiler, is similarly
performance-critical).</li>
<li>Tern runs as a server (or instance) which reuses as much
information as possible between queries, and tries to time
recomputation work so that it doesn't hold up the interface.</li>
<li>When editing large files, there is a mechanism for re-evaluating
only a small slice of the file, using information from a previous
evaluation run as context.</li>
<li>It is possible to automatically 'condense' a JavaScript library
to a simple JSON document that holds its type information, and then
load only that information when analysing code that uses the
library. (You can hand-edit such documents to fix inference mistakes
or add information.)</li>
</ul>
<p style="margin-top: 4em; text-align: right">- <a href="http://marijnhaverbeke.nl">Marijn Haverbeke</a></p>
</div>