idetools.rst 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. ================================
  2. Nim IDE Integration Guide
  3. ================================
  4. :Author: Britney Spears
  5. :Version: |nimversion|
  6. .. contents::
  7. .. raw:: html
  8. <blockquote><p>
  9. "yes, I'm the creator" -- Araq, 2013-07-26 19:28:32.
  10. </p></blockquote>
  11. Note: this is mostly outdated, see instead `nimsuggest <nimsuggest.html>`_
  12. Nim differs from many other compilers in that it is really fast,
  13. and being so fast makes it suited to provide external queries for
  14. text editors about the source code being written. Through the
  15. ``idetools`` command of `the compiler <nimc.html>`_, any IDE
  16. can query a ``.nim`` source file and obtain useful information like
  17. definition of symbols or suggestions for completion.
  18. This document will guide you through the available options. If you
  19. want to look at practical examples of idetools support you can look
  20. at the test files found in the `Test suite`_ or `various editor
  21. integrations <https://github.com/Araq/Nim/wiki/Editor-Support>`_
  22. already available.
  23. Idetools invocation
  24. ===================
  25. Specifying the location of the query
  26. ------------------------------------
  27. All of the available idetools commands require you to specify a
  28. query location through the ``--track`` or ``--trackDirty`` switches.
  29. The general idetools invocations are::
  30. nim idetools --track:FILE,LINE,COL <switches> proj.nim
  31. Or::
  32. nim idetools --trackDirty:DIRTY_FILE,FILE,LINE,COL <switches> proj.nim
  33. ``proj.nim``
  34. This is the main *project* filename. Most of the time you will
  35. pass in the same as **FILE**, but for bigger projects this is
  36. the file which is used as main entry point for the program, the
  37. one which users compile to generate a final binary.
  38. ``<switches>``
  39. This would be any of the other idetools available options, like
  40. ``--def`` or ``--suggest`` explained in the following sections.
  41. ``COL``
  42. An integer with the column you are going to query. For the
  43. compiler columns start at zero, so the first column will be
  44. **0** and the last in an 80 column terminal will be **79**.
  45. ``LINE``
  46. An integer with the line you are going to query. For the compiler
  47. lines start at **1**.
  48. ``FILE``
  49. The file you want to perform the query on. Usually you will
  50. pass in the same value as **proj.nim**.
  51. ``DIRTY_FILE``
  52. The **FILE** parameter is enough for static analysis, but IDEs
  53. tend to have *unsaved buffers* where the user may still be in
  54. the middle of typing a line. In such situations the IDE can
  55. save the current contents to a temporary file and then use the
  56. ``--trackDirty`` switch.
  57. Dirty files are likely to contain errors and they are usually
  58. compiled partially only to the point needed to service the
  59. idetool request. The compiler discriminates them to ensure that
  60. **a)** they won't be cached and **b)** they won't invalidate
  61. the cached contents of the original module.
  62. The other reason is that the dirty file can appear anywhere on
  63. disk (e.g. in tmpfs), but it must be treated as having a path
  64. matching the original module when it comes to usage of relative
  65. paths, etc. Queries, however, will refer to the dirty module
  66. name in their answers instead of the normal filename.
  67. Definitions
  68. -----------
  69. The ``--def`` idetools switch performs a query about the definition
  70. of a specific symbol. If available, idetools will answer with the
  71. type, source file, line/column information and other accessory data
  72. if available like a docstring. With this information an IDE can
  73. provide the typical *Jump to definition* where a user puts the
  74. cursor on a symbol or uses the mouse to select it and is redirected
  75. to the place where the symbol is located.
  76. Since Nim is implemented in Nim, one of the nice things of
  77. this feature is that any user with an IDE supporting it can quickly
  78. jump around the standard library implementation and see exactly
  79. what a proc does, learning about the language and seeing real life
  80. examples of how to write/implement specific features.
  81. Idetools will always answer with a single definition or none if it
  82. can't find any valid symbol matching the position of the query.
  83. Suggestions
  84. -----------
  85. The ``--suggest`` idetools switch performs a query about possible
  86. completion symbols at some point in the file. IDEs can easily provide
  87. an autocompletion feature where the IDE scans the current file (and
  88. related ones, if it knows about the language being edited and follows
  89. includes/imports) and when the user starts typing something a
  90. completion box with different options appears.
  91. However such features are not context sensitive and work simply on
  92. string matching, which can be problematic in Nim especially due
  93. to the case insensitiveness of the language (plus underscores as
  94. separators!).
  95. The typical usage scenario for this option is to call it after the
  96. user has typed the dot character for `the object oriented call
  97. syntax <tut2.html#object-oriented-programming-method-call-syntax>`_.
  98. Idetools will try to return the suggestions sorted first by scope
  99. (from innermost to outermost) and then by item name.
  100. Invocation context
  101. ------------------
  102. The ``--context`` idetools switch is very similar to the suggestions
  103. switch, but instead of being used after the user has typed a dot
  104. character, this one is meant to be used after the user has typed
  105. an opening brace to start typing parameters.
  106. Symbol usages
  107. -------------
  108. The ``--usages`` idetools switch lists all usages of the symbol at
  109. a position. IDEs can use this to find all the places in the file
  110. where the symbol is used and offer the user to rename it in all
  111. places at the same time. Again, a pure string based search and
  112. replace may catch symbols out of the scope of a function/loop.
  113. For this kind of query the IDE will most likely ignore all the
  114. type/signature info provided by idetools and concentrate on the
  115. filename, line and column position of the multiple returned answers.
  116. Expression evaluation
  117. ---------------------
  118. This feature is still under development. In the future it will allow
  119. an IDE to evaluate an expression in the context of the currently
  120. running/debugged user project.
  121. Compiler as a service (CAAS)
  122. ============================
  123. The occasional use of idetools is acceptable for things like
  124. definitions, where the user puts the cursor on a symbol or double
  125. clicks it and after a second or two the IDE displays where that
  126. symbol is defined. Such latencies would be terrible for features
  127. like symbol suggestion, plus why wait at all if we can avoid it?
  128. The idetools command can be run as a compiler service (CAAS),
  129. where you first launch the compiler and it will stay online as a
  130. server, accepting queries in a telnet like fashion. The advantage
  131. of staying on is that for many queries the compiler can cache the
  132. results of the compilation, and subsequent queries should be fast
  133. in the millisecond range, thus being responsive enough for IDEs.
  134. If you want to start the server using stdin/stdout as communication
  135. you need to type::
  136. nim serve --server.type:stdin proj.nim
  137. If you want to start the server using tcp and a port, you need to type::
  138. nim serve --server.type:tcp --server.port:6000 \
  139. --server.address:hostname proj.nim
  140. In both cases the server will start up and await further commands.
  141. The syntax of the commands you can now send to the server is
  142. practically the same as running the nim compiler on the commandline,
  143. you only need to remove the name of the compiler since you are
  144. already talking to it. The server will answer with as many lines
  145. of text it thinks necessary plus an empty line to indicate the end
  146. of the answer.
  147. You can find examples of client/server communication in the idetools
  148. tests found in the `Test suite`_.
  149. Parsing idetools output
  150. =======================
  151. Idetools outputs is always returned on single lines separated by
  152. tab characters (``\t``). The values of each column are:
  153. 1. Three characters indicating the type of returned answer (e.g.
  154. def for definition, ``sug`` for suggestion, etc).
  155. 2. Type of the symbol. This can be ``skProc``, ``skLet``, and just
  156. about any of the enums defined in the module ``compiler/ast.nim``.
  157. 3. Full qualified path of the symbol. If you are querying a symbol
  158. defined in the ``proj.nim`` file, this would have the form
  159. ``proj.symbolName``.
  160. 4. Type/signature. For variables and enums this will contain the
  161. type of the symbol, for procs, methods and templates this will
  162. contain the full unique signature (e.g. ``proc (File)``).
  163. 5. Full path to the file containing the symbol.
  164. 6. Line where the symbol is located in the file. Lines start to
  165. count at **1**.
  166. 7. Column where the symbol is located in the file. Columns start
  167. to count at **0**.
  168. 8. Docstring for the symbol if available or the empty string. To
  169. differentiate the docstring from end of answer in server mode,
  170. the docstring is always provided enclosed in double quotes, and
  171. if the docstring spans multiple lines, all following lines of the
  172. docstring will start with a blank space to align visually with
  173. the starting quote.
  174. Also, you won't find raw ``\n`` characters breaking the one
  175. answer per line format. Instead you will need to parse sequences
  176. in the form ``\xHH``, where *HH* is a hexadecimal value (e.g.
  177. newlines generate the sequence ``\x0A``).
  178. The following sections define the expected output for each kind of
  179. symbol for which idetools returns valid output.
  180. skConst
  181. -------
  182. | **Third column**: module + [n scope nesting] + const name.
  183. | **Fourth column**: the type of the const value.
  184. | **Docstring**: always the empty string.
  185. .. code-block:: nim
  186. const SOME_SEQUENCE = @[1, 2]
  187. --> col 2: $MODULE.SOME_SEQUENCE
  188. col 3: seq[int]
  189. col 7: ""
  190. skEnumField
  191. -----------
  192. | **Third column**: module + [n scope nesting] + enum type + enum field name.
  193. | **Fourth column**: enum type grouping other enum fields.
  194. | **Docstring**: always the empty string.
  195. .. code-block:: nim
  196. Open(filename, fmWrite)
  197. --> col 2: system.FileMode.fmWrite
  198. col 3: FileMode
  199. col 7: ""
  200. skForVar
  201. --------
  202. | **Third column**: module + [n scope nesting] + var name.
  203. | **Fourth column**: type of the var.
  204. | **Docstring**: always the empty string.
  205. .. code-block:: nim
  206. proc looper(filename = "tests.nim") =
  207. for letter in filename:
  208. echo letter
  209. --> col 2: $MODULE.looper.letter
  210. col 3: char
  211. col 7: ""
  212. skIterator, skClosureIterator
  213. -----------------------------
  214. The fourth column will be the empty string if the iterator is being
  215. defined, since at that point in the file the parser hasn't processed
  216. the full line yet. The signature will be returned complete in
  217. posterior instances of the iterator.
  218. | **Third column**: module + [n scope nesting] + iterator name.
  219. | **Fourth column**: signature of the iterator including return type.
  220. | **Docstring**: docstring if available.
  221. .. code-block:: nim
  222. let
  223. text = "some text"
  224. letters = toSeq(runes(text))
  225. --> col 2: unicode.runes
  226. col 3: iterator (string): Rune
  227. col 7: "iterates over any unicode character of the string `s`."
  228. skLabel
  229. -------
  230. | **Third column**: module + [n scope nesting] + name.
  231. | **Fourth column**: always the empty string.
  232. | **Docstring**: always the empty string.
  233. .. code-block:: nim
  234. proc test(text: string) =
  235. var found = -1
  236. block loops:
  237. --> col 2: $MODULE.test.loops
  238. col 3: ""
  239. col 7: ""
  240. skLet
  241. -----
  242. | **Third column**: module + [n scope nesting] + let name.
  243. | **Fourth column**: the type of the let variable.
  244. | **Docstring**: always the empty string.
  245. .. code-block:: nim
  246. let
  247. text = "some text"
  248. --> col 2: $MODULE.text
  249. col 3: TaintedString
  250. col 7: ""
  251. skMacro
  252. -------
  253. The fourth column will be the empty string if the macro is being
  254. defined, since at that point in the file the parser hasn't processed
  255. the full line yet. The signature will be returned complete in
  256. posterior instances of the macro.
  257. | **Third column**: module + [n scope nesting] + macro name.
  258. | **Fourth column**: signature of the macro including return type.
  259. | **Docstring**: docstring if available.
  260. .. code-block:: nim
  261. proc testMacro() =
  262. expect(EArithmetic):
  263. --> col 2: idetools_api.expect
  264. col 3: proc (varargs[expr], stmt): stmt
  265. col 7: ""
  266. skMethod
  267. --------
  268. The fourth column will be the empty string if the method is being
  269. defined, since at that point in the file the parser hasn't processed
  270. the full line yet. The signature will be returned complete in
  271. posterior instances of the method.
  272. Methods imply `dynamic dispatch
  273. <tut2.html#object-oriented-programming-dynamic-dispatch>`_ and
  274. idetools performs a static analysis on the code. For this reason
  275. idetools may not return the definition of the correct method you
  276. are querying because it may be impossible to know until the code
  277. is executed. It will try to return the method which covers the most
  278. possible cases (i.e. for variations of different classes in a
  279. hierarchy it will prefer methods using the base class).
  280. While at the language level a method is differentiated from others
  281. by the parameters and return value, the signature of the method
  282. returned by idetools returns also the pragmas for the method.
  283. Note that at the moment the word ``proc`` is returned for the
  284. signature of the found method instead of the expected ``method``.
  285. This may change in the future.
  286. | **Third column**: module + [n scope nesting] + method name.
  287. | **Fourth column**: signature of the method including return type.
  288. | **Docstring**: docstring if available.
  289. .. code-block:: nim
  290. method eval(e: PExpr): int = quit "to override!"
  291. method eval(e: PLiteral): int = e.x
  292. method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)
  293. echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
  294. --> col 2: $MODULE.eval
  295. col 3: proc (PPlusExpr): int
  296. col 7: ""
  297. skParam
  298. -------
  299. | **Third column**: module + [n scope nesting] + param name.
  300. | **Fourth column**: the type of the parameter.
  301. | **Docstring**: always the empty string.
  302. .. code-block:: nim
  303. proc reader(filename = "tests.nim") =
  304. let text = readFile(filename)
  305. --> col 2: $MODULE.reader.filename
  306. col 3: string
  307. col 7: ""
  308. skProc
  309. ------
  310. The fourth column will be the empty string if the proc is being
  311. defined, since at that point in the file the parser hasn't processed
  312. the full line yet. The signature will be returned complete in
  313. posterior instances of the proc.
  314. While at the language level a proc is differentiated from others
  315. by the parameters and return value, the signature of the proc
  316. returned by idetools returns also the pragmas for the proc.
  317. | **Third column**: module + [n scope nesting] + proc name.
  318. | **Fourth column**: signature of the proc including return type.
  319. | **Docstring**: docstring if available.
  320. .. code-block:: nim
  321. open(filename, fmWrite)
  322. --> col 2: system.Open
  323. col 3: proc (var File, string, FileMode, int): bool
  324. col 7:
  325. "Opens a file named `filename` with given `mode`.
  326. Default mode is readonly. Returns true iff the file could be opened.
  327. This throws no exception if the file could not be opened."
  328. skResult
  329. --------
  330. | **Third column**: module + [n scope nesting] + result.
  331. | **Fourth column**: the type of the result.
  332. | **Docstring**: always the empty string.
  333. .. code-block:: nim
  334. proc getRandomValue() : int =
  335. return 4
  336. --> col 2: $MODULE.getRandomValue.result
  337. col 3: int
  338. col 7: ""
  339. skTemplate
  340. ----------
  341. The fourth column will be the empty string if the template is being
  342. defined, since at that point in the file the parser hasn't processed
  343. the full line yet. The signature will be returned complete in
  344. posterior instances of the template.
  345. | **Third column**: module + [n scope nesting] + template name.
  346. | **Fourth column**: signature of the template including return type.
  347. | **Docstring**: docstring if available.
  348. .. code-block:: nim
  349. let
  350. text = "some text"
  351. letters = toSeq(runes(text))
  352. --> col 2: sequtils.toSeq
  353. col 3: proc (expr): expr
  354. col 7:
  355. "Transforms any iterator into a sequence.
  356. Example:
  357. .. code-block:: nim
  358. let
  359. numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
  360. odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
  361. if x mod 2 == 1:
  362. result = true)
  363. assert odd_numbers == @[1, 3, 5, 7, 9]"
  364. skType
  365. ------
  366. | **Third column**: module + [n scope nesting] + type name.
  367. | **Fourth column**: the type.
  368. | **Docstring**: always the empty string.
  369. .. code-block:: nim
  370. proc writeTempFile() =
  371. var output: File
  372. --> col 2: system.File
  373. col 3: File
  374. col 7: ""
  375. skVar
  376. -----
  377. | **Third column**: module + [n scope nesting] + var name.
  378. | **Fourth column**: the type of the var.
  379. | **Docstring**: always the empty string.
  380. .. code-block:: nim
  381. proc writeTempFile() =
  382. var output: File
  383. output.open("/tmp/somefile", fmWrite)
  384. output.write("test")
  385. --> col 2: $MODULE.writeTempFile.output
  386. col 3: File
  387. col 7: ""
  388. Test suite
  389. ==========
  390. To verify that idetools is working properly there are files in the
  391. ``tests/caas/`` directory which provide unit testing. If you find
  392. odd idetools behaviour and are able to reproduce it, you are welcome
  393. to report it as a bug and add a test to the suite to avoid future
  394. regressions.
  395. Running the test suite
  396. ----------------------
  397. At the moment idetools support is still in development so the test
  398. suite is not integrated with the main test suite and you have to
  399. run it manually. First you have to compile the tester::
  400. $ cd my/nim/checkout/tests
  401. $ nim c testament/caasdriver.nim
  402. Running the ``caasdriver`` without parameters will attempt to process
  403. all the test cases in all three operation modes. If a test succeeds
  404. nothing will be printed and the process will exit with zero. If any
  405. test fails, the specific line of the test preceding the failure
  406. and the failure itself will be dumped to stdout, along with a final
  407. indicator of the success state and operation mode. You can pass the
  408. parameter ``verbose`` to force all output even on successful tests.
  409. The normal operation mode is called ``ProcRun`` and it involves
  410. starting a process for each command or query, similar to running
  411. manually the Nim compiler from the commandline. The ``CaasRun``
  412. mode starts a server process to answer all queries. The ``SymbolProcRun``
  413. mode is used by compiler developers. This means that running all
  414. tests involves processing all ``*.txt`` files three times, which
  415. can be quite time consuming.
  416. If you don't want to run all the test case files you can pass any
  417. substring as a parameter to ``caasdriver``. Only files matching the
  418. passed substring will be run. The filtering doesn't use any globbing
  419. metacharacters, it's a plain match. For example, to run only
  420. ``*-compile*.txt`` tests in verbose mode::
  421. ./caasdriver verbose -compile
  422. Test case file format
  423. ---------------------
  424. All the ``tests/caas/*.txt`` files encode a session with the compiler:
  425. * The first line indicates the main project file.
  426. * Lines starting with ``>`` indicate a command to be sent to the
  427. compiler and the lines following a command include checks for
  428. expected or forbidden output (``!`` for forbidden).
  429. * If a line starts with ``#`` it will be ignored completely, so you
  430. can use that for comments.
  431. * Since some cases are specific to either ``ProcRun`` or ``CaasRun``
  432. modes, you can prefix a line with the mode and the line will be
  433. processed only in that mode.
  434. * The rest of the line is treated as a `regular expression <re.html>`_,
  435. so be careful escaping metacharacters like parenthesis.
  436. Before the line is processed as a regular expression, some basic
  437. variables are searched for and replaced in the tests. The variables
  438. which will be replaced are:
  439. * **$TESTNIM**: filename specified in the first line of the script.
  440. * **$MODULE**: like $TESTNIM but without extension, useful for
  441. expected output.
  442. When adding a test case to the suite it is a good idea to write a
  443. few comments about what the test is meant to verify.