Merge pull request #486 from gradha/pr_idetools_docs
Adds idetools docs
This commit is contained in:
commit
7b946ec025
23 changed files with 683 additions and 46 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -168,12 +168,14 @@ examples/cross_calculator/android/tags
|
||||||
/testresults.html
|
/testresults.html
|
||||||
/testresults.json
|
/testresults.json
|
||||||
/tests/caas/SymbolProcRun.*/
|
/tests/caas/SymbolProcRun.*/
|
||||||
|
/tests/caas/absurd_nesting
|
||||||
|
/tests/caas/forward_declarations
|
||||||
/tests/caas/idetools_api
|
/tests/caas/idetools_api
|
||||||
/tests/caas/imported
|
/tests/caas/imported
|
||||||
/tests/caas/issue_416_template_shift
|
/tests/caas/issue_416_template_shift
|
||||||
/tests/caas/issue_452_export_shift
|
/tests/caas/issue_452_export_shift
|
||||||
/tests/caas/issue_477_dynamic_dispatch
|
/tests/caas/issue_477_dynamic_dispatch
|
||||||
|
/tests/caas/its_full_of_procs
|
||||||
/tests/caas/main
|
/tests/caas/main
|
||||||
/tests/caasdriver
|
/tests/caasdriver
|
||||||
/tools/nimgrep
|
/tools/nimgrep
|
||||||
no changes added to commit (use "git add" and/or "git commit -a")
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ Advanced commands:
|
||||||
--context list possible invokation context
|
--context list possible invokation context
|
||||||
--usages list all usages of the symbol at position
|
--usages list all usages of the symbol at position
|
||||||
--eval evaluates an expression
|
--eval evaluates an expression
|
||||||
|
//serve start the compiler as a service mode (CAAS)
|
||||||
|
--server.type:TYPE either stdin or tcp
|
||||||
|
--server.port:PORT port for tcp mode, by default 6000
|
||||||
|
--server.address:HOST binds to that address, by default ""
|
||||||
|
|
||||||
Advanced options:
|
Advanced options:
|
||||||
-m, --mainmodule:FILE set the project main module
|
-m, --mainmodule:FILE set the project main module
|
||||||
|
|
|
||||||
467
doc/idetools.txt
Normal file
467
doc/idetools.txt
Normal file
|
|
@ -0,0 +1,467 @@
|
||||||
|
================================
|
||||||
|
Nimrod IDE Integration Guide
|
||||||
|
================================
|
||||||
|
|
||||||
|
:Author: Britney Spears
|
||||||
|
:Version: |nimrodversion|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
|
|
||||||
|
Nimrod differs from many other compilers in that it is really fast,
|
||||||
|
and being so fast makes it suited to provide external queries for
|
||||||
|
text editors about the source code being written. Through the
|
||||||
|
``idetools`` command of `the compiler <nimrodc.html>`_, any IDE can
|
||||||
|
query a ``.nim`` source file and obtain useful information like
|
||||||
|
definition of symbols or suggestions for completion.
|
||||||
|
|
||||||
|
This document will guide you through the available options. If you
|
||||||
|
want to look at practical examples of idetools support you can look
|
||||||
|
at the test files found in ``tests/caas/*.txt`` or `various editor
|
||||||
|
integrations <https://github.com/Araq/Nimrod/wiki/Editor-Support>`_
|
||||||
|
already available.
|
||||||
|
|
||||||
|
|
||||||
|
Idetools invokation
|
||||||
|
===================
|
||||||
|
|
||||||
|
Specifying the location of the query
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
All of the available idetools commands require you to specify a
|
||||||
|
query location through the ``--track`` or ``--trackDirty`` switches.
|
||||||
|
The general idetools invokations are::
|
||||||
|
|
||||||
|
nimrod idetools --track:FILE,LINE,COL <switches> proj.nim
|
||||||
|
|
||||||
|
Or::
|
||||||
|
|
||||||
|
nimrod idetools --trackDirty:DIRTY_FILE,FILE,LINE,COL <switches> proj.nim
|
||||||
|
|
||||||
|
``proj.nim``
|
||||||
|
This is the main *project* filename. Most of the time you will
|
||||||
|
pass in the same as **FILE**, but for bigger projects this is
|
||||||
|
the file which is used as main entry point for the program, the
|
||||||
|
one which users compile to generate a final binary.
|
||||||
|
|
||||||
|
``<switches>``
|
||||||
|
This would be any of the other idetools available options, like
|
||||||
|
``--def`` or ``--suggest`` explained in the following sections.
|
||||||
|
|
||||||
|
``COL``
|
||||||
|
An integer with the column you are going to query. For the
|
||||||
|
compiler columns start at zero, so the first column will be
|
||||||
|
**0** and the last in an 80 column terminal will be **79**.
|
||||||
|
|
||||||
|
``LINE``
|
||||||
|
An integer with the line you are going to query. For the compiler
|
||||||
|
lines start at **1**.
|
||||||
|
|
||||||
|
``FILE``
|
||||||
|
The file you want to perform the query on. Usually you will
|
||||||
|
pass in the same value as **proj.nim**.
|
||||||
|
|
||||||
|
``DIRTY_FILE``
|
||||||
|
The **FILE** paramater is enough for static analysis, but IDEs
|
||||||
|
tend to have *unsaved buffers* where the user may still be in
|
||||||
|
the middle of typing a line. In such situations the IDE can
|
||||||
|
save the current contents to a temporary file and then use the
|
||||||
|
``--trackDirty`` switch.
|
||||||
|
|
||||||
|
Dirty files are likely to contain errors and they are usually
|
||||||
|
compiled partially only to the point needed to service the
|
||||||
|
idetool request. The compiler discriminates them to ensure that
|
||||||
|
**a)** they won't be cached and **b)** they won't invalidate
|
||||||
|
the cached contents of the original module.
|
||||||
|
|
||||||
|
The other reason is that the dirty file can appear anywhere on
|
||||||
|
disk (e.g. in tmpfs), but it must be treated as having a path
|
||||||
|
matching the original module when it comes to usage of relative
|
||||||
|
paths, etc. Queries, however, will refer to the dirty module
|
||||||
|
name in their answers instead of the normal filename.
|
||||||
|
|
||||||
|
|
||||||
|
Definitions
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The ``--def`` idetools switch performs a query about the definition
|
||||||
|
of a specific symbol. If available, idetools will answer with the
|
||||||
|
type, source file, line/column information and other accessory data
|
||||||
|
if available like a docstring. With this information an IDE can
|
||||||
|
provide the typical *Jump to definition* where a user puts the
|
||||||
|
cursor on a symbol or uses the mouse to select it and is redirected
|
||||||
|
to the place where the symbol is located.
|
||||||
|
|
||||||
|
Since Nimrod is implemented in Nimrod, one of the nice things of
|
||||||
|
this feature is that any user with an IDE supporting it can quickly
|
||||||
|
jump around the standard library implementation and see exactly
|
||||||
|
what a proc does, learning about the language and seeing real life
|
||||||
|
examples of how to write/implement specific features.
|
||||||
|
|
||||||
|
Idetools will always answer with a single definition or none if it
|
||||||
|
can't find any valid symbol matching the position of the query.
|
||||||
|
|
||||||
|
|
||||||
|
Suggestions
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The ``--suggest`` idetools switch performs a query about possible
|
||||||
|
completion symbols at some point in the file. IDEs can easily provide
|
||||||
|
an autocompletion feature where the IDE scans the current file (and
|
||||||
|
related ones, if it knows about the language being edited and follows
|
||||||
|
includes/imports) and when the user starts typing something a
|
||||||
|
completion box with different options appears.
|
||||||
|
|
||||||
|
However such features are not context sensitive and work simply on
|
||||||
|
string matching, which can be problematic in Nimrod especially due
|
||||||
|
to the case insensitiveness of the language (plus underscores as
|
||||||
|
separators!).
|
||||||
|
|
||||||
|
The typical usage scenario for this option is to call it after the
|
||||||
|
user has typed the dot character for `the object oriented call
|
||||||
|
syntax <tut2.html#method-call-syntax>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Invokation context
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The ``--context`` idetools switch is very similar to the suggestions
|
||||||
|
switch, but instead of being used after the user has typed a dot
|
||||||
|
character, this one is meant to be used after the user has typed
|
||||||
|
an opening brace to start typing parameters.
|
||||||
|
|
||||||
|
|
||||||
|
Symbol usages
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The ``--usages`` idetools switch lists all usages of the symbol at
|
||||||
|
a position. IDEs can use this to find all the places in the file
|
||||||
|
where the symbol is used and offer the user to rename it in all
|
||||||
|
places at the same time. Again, a pure string based search and
|
||||||
|
replace may catch symbols out of the scope of a funcion/loop.
|
||||||
|
|
||||||
|
For this kind of query the IDE will most likely ignore all the
|
||||||
|
type/signature info provided by idetools and concentrate on the
|
||||||
|
filename, line and column position of the multiple returned answers.
|
||||||
|
|
||||||
|
|
||||||
|
Expression evaluation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
This feature is still under development. In the future it will allow
|
||||||
|
an IDE to evaluate an expression in the context of the currently
|
||||||
|
running/debugged user project.
|
||||||
|
|
||||||
|
|
||||||
|
Compiler as a service (CAAS)
|
||||||
|
============================
|
||||||
|
|
||||||
|
The ocasional use of idetools is acceptable for things like
|
||||||
|
definitions, where the user puts the cursor on a symbol or double
|
||||||
|
clicks it and after a second or two the IDE displays where that
|
||||||
|
symbol is defined. Such latencies would be terrible for features
|
||||||
|
like symbol suggestion, plus why wait at all if we can avoid it?
|
||||||
|
|
||||||
|
The idetools command can be run as a compiler service, where you
|
||||||
|
first launch the compiler and it will stay online as a server,
|
||||||
|
accepting queries in a telnet like fashion. The advantage of staying
|
||||||
|
on is that for many queries the compiler can cache the results of
|
||||||
|
the compilation, and subsequent queries should be fast in the
|
||||||
|
millisecond range, thus being responsive enough for IDEs.
|
||||||
|
|
||||||
|
If you want to start the server using stdin/stdout as communication
|
||||||
|
you need to type::
|
||||||
|
|
||||||
|
nimrod serve --server.type:stdin proj.nim
|
||||||
|
|
||||||
|
If you want to start the server using tcp and a port, you need to type::
|
||||||
|
|
||||||
|
nimrod serve --server.type:tcp --server.port:6000 \
|
||||||
|
--server.address:hostname proj.nim
|
||||||
|
|
||||||
|
In both cases the server will start up and await further commands.
|
||||||
|
The syntax of the commands you can now send to the server is
|
||||||
|
practically the same as running the nimrod compiler on the commandline,
|
||||||
|
you only need to remove the name of the compiler since you are
|
||||||
|
already talking to it. The server will answer with as many lines
|
||||||
|
of text it thinks necessary plus an empty line to indicate the end
|
||||||
|
of the answer.
|
||||||
|
|
||||||
|
You can find examples of client/server communication in the idetools
|
||||||
|
tests found in ``tests/caas/*.txt``.
|
||||||
|
|
||||||
|
|
||||||
|
Parsing idetools output
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Idetools outputs is always returned on single lines separated by
|
||||||
|
tab characters (``\t``). The values of each column are:
|
||||||
|
|
||||||
|
1. Three characters indicating the type of returned answer (e.g.
|
||||||
|
def for definition, ``sug`` for suggestion, etc).
|
||||||
|
2. Type of the symbol. This can be ``skProc``, ``skLet``, and just
|
||||||
|
about any of the enums defined in the module ``compiler/ast.nim``.
|
||||||
|
3. Full qualitifed path of the symbol. If you are querying a symbol
|
||||||
|
defined in the ``proj.nim`` file, this would have the form
|
||||||
|
``proj.symbolName``.
|
||||||
|
4. Type/signature. For variables and enums this will contain the
|
||||||
|
type of the symbol, for procs, methods and templates this will
|
||||||
|
contain the full unique signature (e.g. ``proc (TFile)``).
|
||||||
|
5. Full path to the file containing the symbol.
|
||||||
|
6. Line where the symbol is located in the file. Lines start to
|
||||||
|
count at **1**.
|
||||||
|
7. Column where the symbol is located in the file. Columns start
|
||||||
|
to count at **0**.
|
||||||
|
8. Docstring for the symbol if available or the empty string. To
|
||||||
|
differentiate the docstring from end of answer in server mode,
|
||||||
|
the docstring is always provided enclosed in double quotes, and
|
||||||
|
if the docstring spans multiple lines, all following lines of the
|
||||||
|
docstring will start with a blank space to align visually with
|
||||||
|
the starting quote.
|
||||||
|
|
||||||
|
Also, you won't find raw ``\n`` characters breaking the one
|
||||||
|
answer per line format. Instead you will need to parse sequences
|
||||||
|
in the form ``\xHH``, where *HH* is a hexadecimal value (e.g.
|
||||||
|
newlines generate the sequence ``\x0A``).
|
||||||
|
|
||||||
|
The following sections define the expected output for each kind of
|
||||||
|
symbol for which idetools returns valid output.
|
||||||
|
|
||||||
|
|
||||||
|
skConst
|
||||||
|
-------
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + const name.
|
||||||
|
| **Fourth column**: the type of the const value.
|
||||||
|
| **Docstring**: always the empty string.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
const SOME_SEQUENCE = @[1, 2]
|
||||||
|
--> col 2: $MODULE.SOME_SEQUENCE
|
||||||
|
col 3: seq[int]
|
||||||
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
skEnumField
|
||||||
|
-----------
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + enum type + enum field name.
|
||||||
|
| **Fourth column**: enum type grouping other enum fields.
|
||||||
|
| **Docstring**: always the empty string.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
Open(filename, fmWrite)
|
||||||
|
--> col 2: system.TFileMode.fmWrite
|
||||||
|
col 3: TFileMode
|
||||||
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
skForVar
|
||||||
|
--------
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + var name.
|
||||||
|
| **Fourth column**: type of the var.
|
||||||
|
| **Docstring**: always the empty string.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc looper(filename = "tests.nim") =
|
||||||
|
for letter in filename:
|
||||||
|
echo letter
|
||||||
|
--> col 2: $MODULE.looper.letter
|
||||||
|
col 3: char
|
||||||
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
skIterator
|
||||||
|
----------
|
||||||
|
|
||||||
|
The fourth column will be the empty string if the iterator is being
|
||||||
|
defined, since at that point in the file the parser hasn't processed
|
||||||
|
the full line yet. The signature will be returned complete in
|
||||||
|
posterior instances of the iterator.
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + iterator name.
|
||||||
|
| **Fourth column**: signature of the iterator including return type.
|
||||||
|
| **Docstring**: docstring if available.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
let
|
||||||
|
text = "some text"
|
||||||
|
letters = toSeq(runes(text))
|
||||||
|
--> col 2: unicode.runes
|
||||||
|
col 3: iterator (string): TRune
|
||||||
|
col 7: "iterates over any unicode character of the string `s`."
|
||||||
|
|
||||||
|
|
||||||
|
skLet
|
||||||
|
-----
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + let name.
|
||||||
|
| **Fourth column**: the type of the let variable.
|
||||||
|
| **Docstring**: always the empty string.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
let
|
||||||
|
text = "some text"
|
||||||
|
--> col 2: $MODULE.text
|
||||||
|
col 3: TaintedString
|
||||||
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
skMethod
|
||||||
|
--------
|
||||||
|
|
||||||
|
The fourth column will be the empty string if the method is being
|
||||||
|
defined, since at that point in the file the parser hasn't processed
|
||||||
|
the full line yet. The signature will be returned complete in
|
||||||
|
posterior instances of the method.
|
||||||
|
|
||||||
|
Methods imply `dynamic dispatch <tut2.html#dynamic-dispatch>`_ and
|
||||||
|
idetools performs a static analysis on the code. For this reason
|
||||||
|
idetools may not return the definition of the correct method you
|
||||||
|
are querying because it may be impossible to know until the code
|
||||||
|
is executed. It will try to return the method which covers the most
|
||||||
|
possible cases (i.e. for variations of different classes in a
|
||||||
|
hierarchy it will prefer methods using the base class).
|
||||||
|
|
||||||
|
While at the language level a method is differentiated from others
|
||||||
|
by the parameters and return value, the signature of the method
|
||||||
|
returned by idetools returns also the pragmas for the method.
|
||||||
|
|
||||||
|
Note that at the moment the word ``proc`` is returned for the
|
||||||
|
signature of the found method instead of the expected ``method``.
|
||||||
|
This may change in the future.
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + method name.
|
||||||
|
| **Fourth column**: signature of the method including return type.
|
||||||
|
| **Docstring**: docstring if available.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
method eval(e: PExpr): int = quit "to override!"
|
||||||
|
method eval(e: PLiteral): int = e.x
|
||||||
|
method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)
|
||||||
|
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
|
||||||
|
--> col 2: $MODULE.eval
|
||||||
|
col 3: proc (PPlusExpr): int
|
||||||
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
skParam
|
||||||
|
-------
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + param name.
|
||||||
|
| **Fourth column**: the type of the parameter.
|
||||||
|
| **Docstring**: always the empty string.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc reader(filename = "tests.nim") =
|
||||||
|
let text = readFile(filename)
|
||||||
|
--> col 2: $MODULE.reader.filename
|
||||||
|
col 3: string
|
||||||
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
skProc
|
||||||
|
------
|
||||||
|
|
||||||
|
The fourth column will be the empty string if the proc is being
|
||||||
|
defined, since at that point in the file the parser hasn't processed
|
||||||
|
the full line yet. The signature will be returned complete in
|
||||||
|
posterior instances of the proc.
|
||||||
|
|
||||||
|
While at the language level a proc is differentiated from others
|
||||||
|
by the parameters and return value, the signature of the proc
|
||||||
|
returned by idetools returns also the pragmas for the proc.
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + proc name.
|
||||||
|
| **Fourth column**: signature of the proc including return type.
|
||||||
|
| **Docstring**: docstring if available.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
Open(filename, fmWrite)
|
||||||
|
--> col 2: system.Open
|
||||||
|
col 3: proc (var TFile, string, TFileMode, int): bool
|
||||||
|
col 7:
|
||||||
|
"Opens a file named `filename` with given `mode`.
|
||||||
|
|
||||||
|
Default mode is readonly. Returns true iff the file could be opened.
|
||||||
|
This throws no exception if the file could not be opened."
|
||||||
|
|
||||||
|
|
||||||
|
skResult
|
||||||
|
--------
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + result.
|
||||||
|
| **Fourth column**: the type of the result.
|
||||||
|
| **Docstring**: always the empty string.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc getRandomValue() : int =
|
||||||
|
return 4
|
||||||
|
--> col 2: $MODULE.getRandomValue.result
|
||||||
|
col 3: int
|
||||||
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
skTemplate
|
||||||
|
----------
|
||||||
|
|
||||||
|
The fourth column will be the empty string if the template is being
|
||||||
|
defined, since at that point in the file the parser hasn't processed
|
||||||
|
the full line yet. The signature will be returned complete in
|
||||||
|
posterior instances of the template.
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + template name.
|
||||||
|
| **Fourth column**: signature of the template including return type.
|
||||||
|
| **Docstring**: docstring if available.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
let
|
||||||
|
text = "some text"
|
||||||
|
letters = toSeq(runes(text))
|
||||||
|
--> col 2: sequtils.toSeq
|
||||||
|
col 3: proc (expr): expr
|
||||||
|
col 7:
|
||||||
|
"Transforms any iterator into a sequence.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
let
|
||||||
|
numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
|
||||||
|
if x mod 2 == 1:
|
||||||
|
result = true)
|
||||||
|
assert odd_numbers == @[1, 3, 5, 7, 9]"
|
||||||
|
|
||||||
|
|
||||||
|
skType
|
||||||
|
------
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + type name.
|
||||||
|
| **Fourth column**: the type.
|
||||||
|
| **Docstring**: always the empty string.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc writeTempFile() =
|
||||||
|
var output: TFile
|
||||||
|
--> col 2: system.TFile
|
||||||
|
col 3: TFile
|
||||||
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
skVar
|
||||||
|
-----
|
||||||
|
|
||||||
|
| **Third column**: module + [n scope nesting] + var name.
|
||||||
|
| **Fourth column**: the type of the var.
|
||||||
|
| **Docstring**: always the empty string.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc writeTempFile() =
|
||||||
|
var output: TFile
|
||||||
|
output.open("/tmp/somefile", fmWrite)
|
||||||
|
output.write("test")
|
||||||
|
--> col 2: $MODULE.writeTempFile.output
|
||||||
|
col 3: TFile
|
||||||
|
col 7: ""
|
||||||
|
|
@ -458,6 +458,14 @@ in C/C++).
|
||||||
**Note**: This pragma will not exist for the LLVM backend.
|
**Note**: This pragma will not exist for the LLVM backend.
|
||||||
|
|
||||||
|
|
||||||
|
Nimrod idetools integration
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Nimrod provides language integration with external IDEs through the
|
||||||
|
idetools command. See the documentation of `idetools <idetools.html>`_
|
||||||
|
for further information.
|
||||||
|
|
||||||
|
|
||||||
Nimrod interactive mode
|
Nimrod interactive mode
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
|
|
||||||
29
tests/caas/absurd_nesting.nim
Normal file
29
tests/caas/absurd_nesting.nim
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Tries to test the full ownership path generated by idetools.
|
||||||
|
|
||||||
|
proc lev1(t1: string) =
|
||||||
|
var temp = t1
|
||||||
|
for i in 0..len(temp)-1:
|
||||||
|
temp[i] = chr(int(temp[i]) + 1)
|
||||||
|
|
||||||
|
proc lev2(t2: string) =
|
||||||
|
var temp = t2
|
||||||
|
for i in 0..len(temp)-1:
|
||||||
|
temp[i] = chr(int(temp[i]) + 1)
|
||||||
|
|
||||||
|
proc lev3(t3: string) =
|
||||||
|
var temp = t3
|
||||||
|
for i in 0..len(temp)-1:
|
||||||
|
temp[i] = chr(int(temp[i]) + 1)
|
||||||
|
|
||||||
|
proc lev4(t4: string) =
|
||||||
|
var temp = t4
|
||||||
|
for i in 0..len(temp)-1:
|
||||||
|
temp[i] = chr(int(temp[i]) + 1)
|
||||||
|
|
||||||
|
echo temp & "(lev4)"
|
||||||
|
lev4(temp & "(lev3)")
|
||||||
|
lev3(temp & "(lev2)")
|
||||||
|
lev2(temp & "(lev1)")
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
lev1("abcd")
|
||||||
29
tests/caas/absurd_nesting.txt
Normal file
29
tests/caas/absurd_nesting.txt
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
absurd_nesting.nim
|
||||||
|
|
||||||
|
> c --verbosity:0 --hints:on
|
||||||
|
SuccessX
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,6,6 --def $SILENT
|
||||||
|
skVar\tabsurd_nesting.lev1.temp\tstring
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,21,13 --def $SILENT
|
||||||
|
skVar\tabsurd_nesting.lev1.lev2.lev3.lev4.temp\tstring
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,6,27 --def $SILENT
|
||||||
|
skForVar\tabsurd_nesting.lev1.i\tint
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,21,33 --def $SILENT
|
||||||
|
skForVar\tabsurd_nesting.lev1.lev1.lev3.lev4.i\tint
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,24,8 --def $SILENT
|
||||||
|
skProc\tabsurd_nesting.lev1.lev1.lev3.lev4\tproc \(string\)
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,4,13 --def $SILENT
|
||||||
|
skParam\tabsurd_nesting.lev1.t1\tstring
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,4,13 --def $SILENT
|
||||||
|
skParam\tabsurd_nesting.lev1.t1\tstring
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,19,19 --def $SILENT
|
||||||
|
skParam\tabsurd_nesting.lev1.lev2.lev3.lev4.t4\tstring
|
||||||
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
main.nim
|
main.nim
|
||||||
> c
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
> c
|
|
||||||
# The "Processing" string will be found always in proc mode since each
|
# The "Processing" string will be found always in proc mode since each
|
||||||
# compilation command will generate it. We need to test it only in Caas mode to
|
# compilation command will generate it. We need to test it only in Caas mode to
|
||||||
# verify the server is not recompiling again the file.
|
# verify the server is not recompiling again the file.
|
||||||
|
CaasRun > c --verbosity:0 --hints:on
|
||||||
CaasRun ! Processing
|
CaasRun ! Processing
|
||||||
SuccessX
|
CaasRun SuccessX
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
main.nim
|
main.nim
|
||||||
> c
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
> idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest
|
> idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest $SILENT
|
||||||
skField\tx
|
skField\tx
|
||||||
skField\ty
|
skField\ty
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
main.nim
|
main.nim
|
||||||
> c
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
> idetools --track:$TESTNIM,5,18 --def
|
|
||||||
|
> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
|
||||||
strutils.toUpper
|
strutils.toUpper
|
||||||
! SuccessX
|
! SuccessX
|
||||||
> idetools --track:$TESTNIM,5,18 --def
|
|
||||||
|
> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
|
||||||
strutils.toUpper
|
strutils.toUpper
|
||||||
! SuccessX
|
! SuccessX
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
main.nim
|
main.nim
|
||||||
> idetools --track:$TESTNIM,5,18 --def
|
> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
|
||||||
strutils.toUpper
|
strutils.toUpper
|
||||||
! SuccessX
|
! SuccessX
|
||||||
> idetools --track:$TESTNIM,5,18 --def
|
|
||||||
|
> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
|
||||||
strutils.toUpper
|
strutils.toUpper
|
||||||
! SuccessX
|
! SuccessX
|
||||||
> c
|
|
||||||
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
main.nim
|
main.nim
|
||||||
> idetools --track:$TESTNIM,5,18 --def
|
> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
|
||||||
strutils.toUpper
|
strutils.toUpper
|
||||||
! SuccessX
|
! SuccessX
|
||||||
> c
|
|
||||||
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
|
|
||||||
|
|
|
||||||
15
tests/caas/forward_declarations.nim
Normal file
15
tests/caas/forward_declarations.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# This example shows that idetools returns an empty signature for a forward
|
||||||
|
# declared proc in proc/symproc runs, but correctly returns the full signature
|
||||||
|
# in caas mode.
|
||||||
|
|
||||||
|
proc echoHello(text: string)
|
||||||
|
|
||||||
|
proc testForward() =
|
||||||
|
echo "T"
|
||||||
|
echoHello("T")
|
||||||
|
|
||||||
|
proc echoHello(text: string) =
|
||||||
|
echo "Hello Mr." & text
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
testForward()
|
||||||
9
tests/caas/forward_declarations.txt
Normal file
9
tests/caas/forward_declarations.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
forward_declarations.nim
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,9,5 --def $SILENT
|
||||||
|
skProc
|
||||||
|
proc \(string\)
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,5,9 --def $SILENT
|
||||||
|
skProc
|
||||||
|
proc \(string\)
|
||||||
17
tests/caas/forward_usages.txt
Normal file
17
tests/caas/forward_usages.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
forward_declarations.nim
|
||||||
|
|
||||||
|
> c --verbosity:0 --hints:on
|
||||||
|
SuccessX
|
||||||
|
|
||||||
|
# None of the following return three instances of the echoHello proc, the first
|
||||||
|
# being the forward declaration, the second being the usage inside testForward,
|
||||||
|
# and the third being the actual implementation.
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,5,5 --usages $SILENT
|
||||||
|
skProc.*\n.*skProc.*\n.*skProc
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,9,5 --usages $SILENT
|
||||||
|
skProc.*\n.*skProc.*\n.*skProc
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,11,5 --usages $SILENT
|
||||||
|
skProc.*\n.*skProc.*\n.*skProc
|
||||||
|
|
@ -1,44 +1,44 @@
|
||||||
idetools_api.nim
|
idetools_api.nim
|
||||||
> c
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
> idetools --track:$TESTNIM,4,11 --def
|
> idetools --track:$TESTNIM,4,11 --def $SILENT
|
||||||
def\tskType\tsystem.TFile\tTFile
|
def\tskType\tsystem.TFile\tTFile
|
||||||
> idetools --track:$TESTNIM,5,7 --def
|
> idetools --track:$TESTNIM,5,7 --def $SILENT
|
||||||
def\tskProc\tsystem.Open\tproc \(var TFile, string, TFileMode, int\): bool
|
def\tskProc\tsystem.Open\tproc \(var TFile, string, TFileMode, int\): bool
|
||||||
> idetools --track:$TESTNIM,5,21 --def
|
> idetools --track:$TESTNIM,5,21 --def $SILENT
|
||||||
def\tskProc\tsystem.\&\tproc \(string, string\): string\{.noSideEffect.\}
|
def\tskProc\tsystem.\&\tproc \(string, string\): string\{.noSideEffect.\}
|
||||||
> idetools --track:$TESTNIM,5,38 --def
|
> idetools --track:$TESTNIM,5,38 --def $SILENT
|
||||||
def\tskEnumField\tsystem.TFileMode.fmWrite\tTFileMode
|
def\tskEnumField\tsystem.TFileMode.fmWrite\tTFileMode
|
||||||
> idetools --track:$TESTNIM,7,6 --def
|
> idetools --track:$TESTNIM,7,6 --def $SILENT
|
||||||
def\tskProc\tsystem.Close\tproc \(TFile\)
|
def\tskProc\tsystem.Close\tproc \(TFile\)
|
||||||
> idetools --track:$TESTNIM,12,23 --def
|
> idetools --track:$TESTNIM,12,23 --def $SILENT
|
||||||
def\tskIterator\tunicode.runes\titerator \(string\): TRune
|
def\tskIterator\tunicode.runes\titerator \(string\): TRune
|
||||||
> idetools --track:$TESTNIM,12,15 --def
|
> idetools --track:$TESTNIM,12,15 --def $SILENT
|
||||||
def\tskTemplate\tsequtils.toSeq\tproc \(expr\): expr
|
def\tskTemplate\tsequtils.toSeq\tproc \(expr\): expr
|
||||||
> idetools --track:$TESTNIM,15,7 --def
|
> idetools --track:$TESTNIM,15,7 --def $SILENT
|
||||||
|
|
||||||
# ProcRun mode will fail the next line, because the type is returned empty.
|
# ProcRun mode will fail the next line, because the type is returned empty.
|
||||||
def\tskConst\t$MODULE.SOME_SEQUENCE\tseq\[int\]\t
|
def\tskConst\t$MODULE.SOME_SEQUENCE\tseq\[int\]\t
|
||||||
> idetools --track:$TESTNIM,15,23 --def
|
> idetools --track:$TESTNIM,15,23 --def $SILENT
|
||||||
def\tskProc\tsystem.@\tproc \(array\[IDX, T\]\): seq\[T\]\{.noSideEffect.\}
|
def\tskProc\tsystem.@\tproc \(array\[IDX, T\]\): seq\[T\]\{.noSideEffect.\}
|
||||||
> idetools --track:$TESTNIM,17,3 --def
|
> idetools --track:$TESTNIM,17,3 --def $SILENT
|
||||||
|
|
||||||
# ProcRun mode will fail the next line, because the type is returned empty.
|
# ProcRun mode will fail the next line, because the type is returned empty.
|
||||||
def\tskType\t$MODULE.bad_string\tbad_string\t
|
def\tskType\t$MODULE.bad_string\tbad_string\t
|
||||||
> idetools --track:$TESTNIM,11,24 --def
|
> idetools --track:$TESTNIM,11,24 --def $SILENT
|
||||||
def\tskParam\t$MODULE.test_iterators.filename\tstring
|
def\tskParam\t$MODULE.test_iterators.filename\tstring
|
||||||
> idetools --track:$TESTNIM,6,5 --def
|
> idetools --track:$TESTNIM,6,5 --def $SILENT
|
||||||
def\tskVar\t$MODULE.test_enums.o\tTFile
|
def\tskVar\t$MODULE.test_enums.o\tTFile
|
||||||
> idetools --track:$TESTNIM,12,34 --def
|
> idetools --track:$TESTNIM,12,34 --def $SILENT
|
||||||
def\tskLet\t$MODULE.test_iterators.input\tTaintedString
|
def\tskLet\t$MODULE.test_iterators.input\tTaintedString
|
||||||
> idetools --track:$TESTNIM,13,35 --def
|
> idetools --track:$TESTNIM,13,35 --def $SILENT
|
||||||
def\tskForVar\t$MODULE.test_iterators.letter\tTRune
|
def\tskForVar\t$MODULE.test_iterators.letter\tTRune
|
||||||
> idetools --track:$TESTNIM,23,3 --def
|
> idetools --track:$TESTNIM,23,3 --def $SILENT
|
||||||
def\tskResult\t$MODULE.adder.result\tint
|
def\tskResult\t$MODULE.adder.result\tint
|
||||||
> idetools --track:$TESTNIM,19,6 --def
|
> idetools --track:$TESTNIM,19,6 --def $SILENT
|
||||||
|
|
||||||
# ProcRun mode will fail the next line, because the type is returned empty.
|
# ProcRun mode will fail the next line, because the type is returned empty.
|
||||||
def\tskField\t$MODULE.TPerson.name\tbad_string\t
|
def\tskField\t$MODULE.TPerson.name\tbad_string\t
|
||||||
|
|
||||||
> idetools --track:$TESTNIM,43,7 --def
|
> idetools --track:$TESTNIM,43,7 --def $SILENT
|
||||||
def\tskMethod\t$MODULE.eval\tproc \(PPlusExpr\): int\t
|
def\tskMethod\t$MODULE.eval\tproc \(PPlusExpr\): int\t
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
issue_416_template_shift.nim
|
issue_416_template_shift.nim
|
||||||
> c
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
> idetools --track:$TESTNIM,12,28 --def
|
> idetools --track:$TESTNIM,12,28 --def $SILENT
|
||||||
def\tskType\tsystem.string\tstring
|
def\tskType\tsystem.string\tstring
|
||||||
> idetools --track:$TESTNIM,12,35 --def
|
> idetools --track:$TESTNIM,12,35 --def $SILENT
|
||||||
def\tskLet\t$MODULE.failtest.input\tTaintedString
|
def\tskLet\t$MODULE.failtest.input\tTaintedString
|
||||||
|
|
||||||
# The following fail because they seem shifted one colum to the right.
|
# The following fail because they seem shifted one colum to the right.
|
||||||
> idetools --track:$TESTNIM,12,16 --def
|
> idetools --track:$TESTNIM,12,16 --def $SILENT
|
||||||
def\tskTemplate\tsequtils.toSeq\tproc \(expr\): expr
|
def\tskTemplate\tsequtils.toSeq\tproc \(expr\): expr
|
||||||
> idetools --track:$TESTNIM,12,22 --def
|
> idetools --track:$TESTNIM,12,22 --def $SILENT
|
||||||
def\tskIterator\tunicode.runes\titerator \(string\): TRune
|
def\tskIterator\tunicode.runes\titerator \(string\): TRune
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
issue_452_export_shift.nim
|
issue_452_export_shift.nim
|
||||||
> c
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
> idetools --track:$TESTNIM,2,2 --def
|
> idetools --track:$TESTNIM,2,2 --def $SILENT
|
||||||
def\tskConst\t$MODULE.VERSION_STR1\tstring
|
def\tskConst\t$MODULE.VERSION_STR1\tstring
|
||||||
> idetools --track:$TESTNIM,3,2 --def
|
> idetools --track:$TESTNIM,3,2 --def $SILENT
|
||||||
def\tskConst\t$MODULE.VERSION_STR2\tstring
|
def\tskConst\t$MODULE.VERSION_STR2\tstring
|
||||||
> idetools --track:$TESTNIM,7,5 --def
|
> idetools --track:$TESTNIM,7,5 --def $SILENT
|
||||||
def\tskProc\t$MODULE.forward1\tproc \(\): string\t
|
def\tskProc\t$MODULE.forward1\tproc \(\): string\t
|
||||||
> idetools --track:$TESTNIM,8,5 --def
|
> idetools --track:$TESTNIM,8,5 --def $SILENT
|
||||||
def\tskProc\t$MODULE.forward2\tproc \(\): string\t
|
def\tskProc\t$MODULE.forward2\tproc \(\): string\t
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
issue_477_dynamic_dispatch.nim
|
issue_477_dynamic_dispatch.nim
|
||||||
> c --run
|
> c --run
|
||||||
SuccessX
|
SuccessX
|
||||||
> idetools --track:issue_477_dynamic_dispatch.nim,19,5 --def
|
> idetools --track:issue_477_dynamic_dispatch.nim,19,5 --def $SILENT
|
||||||
def\tskMethod\tissue_477_dynamic_dispatch.collide\tproc \(TUnit, TThing\)\{.inline.\}
|
def\tskMethod\tissue_477_dynamic_dispatch.collide\tproc \(TUnit, TThing\)\{.inline.\}
|
||||||
|
|
|
||||||
29
tests/caas/its_full_of_procs.nim
Normal file
29
tests/caas/its_full_of_procs.nim
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import unicode, sequtils
|
||||||
|
|
||||||
|
# This example shows that idetools returns proc as signature for everything
|
||||||
|
# which can be called. While a clever person would use the second column to
|
||||||
|
# differentiate betwen procs, methods and others, why does the output contain
|
||||||
|
# incorrect information?
|
||||||
|
|
||||||
|
type
|
||||||
|
TThing = object of TObject
|
||||||
|
TUnit = object of TThing
|
||||||
|
x: int
|
||||||
|
|
||||||
|
method collide(a, b: TThing) {.inline.} =
|
||||||
|
quit "to override!"
|
||||||
|
|
||||||
|
method collide(a: TThing, b: TUnit) {.inline.} =
|
||||||
|
echo "1"
|
||||||
|
|
||||||
|
method collide(a: TUnit, b: TThing) {.inline.} =
|
||||||
|
echo "2"
|
||||||
|
|
||||||
|
var
|
||||||
|
a, b: TUnit
|
||||||
|
|
||||||
|
let
|
||||||
|
input = readFile("its_full_of_procs.nim")
|
||||||
|
letters = toSeq(runes(string(input)))
|
||||||
|
|
||||||
|
collide(a, b) # output: 2
|
||||||
20
tests/caas/its_full_of_procs.txt
Normal file
20
tests/caas/its_full_of_procs.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
its_full_of_procs.nim
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,26,15 --def $SILENT
|
||||||
|
skProc
|
||||||
|
proc \(
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,27,21 --def $SILENT
|
||||||
|
skIterator
|
||||||
|
iterator \(
|
||||||
|
!proc \(
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,29,0 --def $SILENT
|
||||||
|
skMethod
|
||||||
|
method \(
|
||||||
|
!proc \(
|
||||||
|
|
||||||
|
> idetools --track:$TESTNIM,27,15 --def $SILENT
|
||||||
|
skTemplate
|
||||||
|
template \(
|
||||||
|
!proc \(
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
main.nim
|
main.nim
|
||||||
> idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest
|
> idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest $SILENT
|
||||||
skField\tx
|
skField\tx
|
||||||
skField\ty
|
skField\ty
|
||||||
> c
|
> c --verbosity:0 --hints:on
|
||||||
SuccessX
|
SuccessX
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ const
|
||||||
modes = [CaasRun, ProcRun, SymbolProcRun]
|
modes = [CaasRun, ProcRun, SymbolProcRun]
|
||||||
filenameReplaceVar = "$TESTNIM"
|
filenameReplaceVar = "$TESTNIM"
|
||||||
moduleReplaceVar = "$MODULE"
|
moduleReplaceVar = "$MODULE"
|
||||||
|
silentReplaceVar = "$SILENT"
|
||||||
|
silentReplaceText = "--verbosity:0 --hints:off"
|
||||||
|
|
||||||
var
|
var
|
||||||
TesterDir = getAppDir()
|
TesterDir = getAppDir()
|
||||||
|
|
@ -67,6 +69,7 @@ var
|
||||||
proc replaceVars(session: var TNimrodSession, text: string): string =
|
proc replaceVars(session: var TNimrodSession, text: string): string =
|
||||||
result = text.replace(filenameReplaceVar, session.filename)
|
result = text.replace(filenameReplaceVar, session.filename)
|
||||||
result = result.replace(moduleReplaceVar, session.modname)
|
result = result.replace(moduleReplaceVar, session.modname)
|
||||||
|
result = result.replace(silentReplaceVar, silentReplaceText)
|
||||||
|
|
||||||
proc startNimrodSession(project, script: string, mode: TRunMode):
|
proc startNimrodSession(project, script: string, mode: TRunMode):
|
||||||
TNimrodSession =
|
TNimrodSession =
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ UNIX. We don't believe this to be a coincidence. - Jeremy S. Anderson."""
|
||||||
|
|
||||||
[Documentation]
|
[Documentation]
|
||||||
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview;filters;trmacros"
|
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview;filters;trmacros"
|
||||||
doc: "tools;c2nim;niminst;nimgrep;gc;estp"
|
doc: "tools;c2nim;niminst;nimgrep;gc;estp;idetools"
|
||||||
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst;gc"
|
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst;gc"
|
||||||
srcdoc2: "system.nim;impure/graphics;wrappers/sdl"
|
srcdoc2: "system.nim;impure/graphics;wrappers/sdl"
|
||||||
srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned"
|
srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue