|
2 | 2 |
|
3 | 3 | ### License |
4 | 4 |
|
5 | | -<PROJECT NAME> is licensed under the terms in [LICENSE]<link to license file in repo>. By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. |
| 5 | +DML Language Server is dual-licensed under the terms in [APACHE 2.0](./LICENSE-APACHE) and [MIT](./LICENSE-MIT). By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. |
6 | 6 |
|
7 | 7 | ### Sign your work |
8 | 8 |
|
@@ -55,3 +55,172 @@ Use your real name (sorry, no pseudonyms or anonymous contributions.) |
55 | 55 |
|
56 | 56 | If you set your `user.name` and `user.email` git configs, you can sign your |
57 | 57 | commit automatically with `git commit -s`. |
| 58 | + |
| 59 | +## How-To |
| 60 | + |
| 61 | +This section provides information for developers who want to contribute to the |
| 62 | +DLS or run it in a heavily customised configuration. |
| 63 | + |
| 64 | +Testing, reporting issues, writing documentation, writing tests, |
| 65 | +writing code, and implementing clients are all extremely valuable. |
| 66 | + |
| 67 | +To get help with this, either leave an issue on the repo or contact the primary |
| 68 | +developer directly. |
| 69 | + |
| 70 | +If you want to implement DLS support in an editor, see [clients.md](clients.md). |
| 71 | + |
| 72 | +## Building |
| 73 | + |
| 74 | +``` |
| 75 | +git clone https://github.com/intel/dml-language-server.git |
| 76 | +cd dml-language-server |
| 77 | +cargo build --release |
| 78 | +``` |
| 79 | + |
| 80 | +## Running and testing |
| 81 | + |
| 82 | +There are three main ways to run the DLS, you can run it directly with: |
| 83 | + |
| 84 | +``` |
| 85 | +cargo run --bin dls |
| 86 | +``` |
| 87 | +Which starts up the DLS in a server-mode, so its of narrow applicability unless |
| 88 | +you are planning on directly sending LSP communication into it. By passing the |
| 89 | +'--cli' option you start up the server in command-line mode, see [CLI](#cli). |
| 90 | + |
| 91 | +You can run the Direct-File-Analysis (DFA) binary with: |
| 92 | +``` |
| 93 | +cargo run --bin dfa [options ...] <dls-binary> [files ...] |
| 94 | +``` |
| 95 | +This will analyze the specified 'files' using the 'dls-binary' server binary |
| 96 | +as-if they had been opened in a language client, this is usefull to quickly |
| 97 | +test and debug initial file analysis and error reporting without advanced |
| 98 | +client-interaction. |
| 99 | + |
| 100 | +Most commonly, you'll use an IDE plugin to invoke the DLS binary for you |
| 101 | +(see [README.md](README.md) for details). |
| 102 | + |
| 103 | +Test the crate using `cargo test`. |
| 104 | + |
| 105 | +Testing is unfortunately minimal. There is support for some regression tests, |
| 106 | +but not many actual tests exists yet. There is significant work to do |
| 107 | +before we have a comprehensive testing story. |
| 108 | + |
| 109 | +### <a id="cli"></a>CLI |
| 110 | + |
| 111 | +You can run DLS in the command line mode which is useful for debugging and |
| 112 | +testing, especially to narrow down a bug to either the DLS or a client. |
| 113 | + |
| 114 | +You need to run it with the |
| 115 | +`--cli` flag, e.g., `cargo run --bin dls -- --cli`. This should initialize the |
| 116 | +DLS and then give you a `>` prompt. |
| 117 | +Look for the final message that will signal the end of the |
| 118 | +initialization phase which will look something like: |
| 119 | +``` |
| 120 | +{"jsonrpc":"2.0","method":"window/showMessage","params":{"message": "DML Language Server Started", "type": 3}} |
| 121 | +``` |
| 122 | + |
| 123 | +Type `help` (or just `h`) to see the [commands available][CLI_COMMANDS]. Note |
| 124 | +that the [positions][LSP_POSITION] in the requests and the responses are |
| 125 | +_zero-based_ (contrary to what you'll normally see in the IDE line numbers). |
| 126 | + |
| 127 | +[LSP_POSITION]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/specification.md#position |
| 128 | + |
| 129 | +[CLI_COMMANDS]: dls/src/cmd.rs#L508-L542 |
| 130 | + |
| 131 | +## Implementation overview |
| 132 | + |
| 133 | +The idea behind the DLS is to grant fast and mostly-accurate feedback for DML |
| 134 | +development, of either specific devices or DML common-code. Due to complexities |
| 135 | +in the DML language, and the high level of customization available when running |
| 136 | +DMLC, this information will not be perfectly accurate or holistic at all times. |
| 137 | +However the goal is to give a best-effort analysis that minimizes noisy |
| 138 | +incorrect feedback and maximizes the amount of valuable info a developer can |
| 139 | +extract, as well as providing basic standard-issue IDE functionality. |
| 140 | + |
| 141 | +### Analysis |
| 142 | + |
| 143 | +The DLS tracks changes to files, and keeps the changed file in memory (i.e., the |
| 144 | +DLS does not need the IDE to save a file before providing data). These changed |
| 145 | +files are tracked by the 'Virtual File System'. |
| 146 | + |
| 147 | +Analysis is divided into two phases. |
| 148 | +- The 'isolated' analysis analyses each |
| 149 | +DML file individually, and does parsing and some post-parse processing. This |
| 150 | +analysis perform syntactic analysis and is enough to report basic syntax errors, |
| 151 | +- The 'device' analysis analyses from the perspective of a particular DML file with |
| 152 | +a device declaration, pulling in information from the various isolated |
| 153 | +analysises. This analysis performs semantic analysis, and is what |
| 154 | +powers reference-matching, object resolution, etc. |
| 155 | + |
| 156 | +Isolated analysis is started as soon as the user opens or changes a file |
| 157 | +(although this can be configured in the settings to be only on save). |
| 158 | +In addition the DLS will use information about import paths and workspaces to |
| 159 | +try to resolve file imports, and recursively analyse any file imported from |
| 160 | +an opened one. See the section on [include paths](#include-paths) for more |
| 161 | +information on them. Device analysis is started as soon as it is determined that |
| 162 | +it could be, or needs to be re-done. Commonly this is when an isolated analysis |
| 163 | +involved in the import tree of a device-file is updated, if all files that the |
| 164 | +device depends on have had an isolated analysis done. There are corner-case |
| 165 | +exceptions to this (allowing for a partially correct device analysis when an |
| 166 | +imported file is missing) but for simplicity that is not described here. |
| 167 | + |
| 168 | +### Communicating with IDEs |
| 169 | + |
| 170 | +The DLS communicates with IDEs via |
| 171 | +the [Language Server protocol](https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md). |
| 172 | + |
| 173 | +The LS protocol uses JSON sent over stdin/stdout. The JSON is rather dynamic - |
| 174 | +we can't make structs to easily map to many of the protocol objects. The client |
| 175 | +sends commands and notifications to the DLS. Commands must get a reply, |
| 176 | +notifications do not. Usually the structure of the reply is dictated by the |
| 177 | +protocol spec. The DLS can also send notifications to the client. So for a long |
| 178 | +running task (such as a build), the DLS will reply quickly to acknowledge the |
| 179 | +request, then send a message later with the result of the task. |
| 180 | + |
| 181 | +Associating requests with replies is done using an id which must be handled by |
| 182 | +the DLS. |
| 183 | + |
| 184 | +### Extensions to the Language Server Protocol |
| 185 | + |
| 186 | +The DLS uses some custom extensions to the Language Server Protocol. |
| 187 | +These are all sent from the DLS to an LSP client and are only used to |
| 188 | +improve the user experience by showing progress indicators. |
| 189 | + |
| 190 | +* `window/progress`: notification, `title: "Analysing", value: WorkDoneProgressBegin`. Sent when the first analysis starts |
| 191 | +* ... standard LSP `publishDiagnostics` |
| 192 | +* `window/progress`: notification, `title: "Analysing", value: WorkDoneProgressEnd`. Sent when the last analysis finishes |
| 193 | + |
| 194 | +### <a id="include-paths"></a>Include Paths |
| 195 | +In order to support fairly generic and complicating import configurations, the |
| 196 | +DLS uses a context-aware methodology in order to resolve import paths. |
| 197 | + |
| 198 | +Sidenote: be aware that due to past DMLC 1.2/1.4 interoperability functionality, |
| 199 | +the DLS will correctly search the "./" and "./1.4/" of every path it searches. |
| 200 | + |
| 201 | +When importing a file "A.dml" from some file "B", the DLS will search, in no |
| 202 | +particular order: |
| 203 | +- The folder of B |
| 204 | +- The root folder of the workspace |
| 205 | +- All other workspace roots |
| 206 | +- Every include path specified by the [DML Compile commands](#dml-compile-commands) under the related module |
| 207 | + |
| 208 | +#### <a id="dml-compile-commands"></a> DML Compile Commands |
| 209 | +The DML compile commands file is used by the DLS in order to obtain per-module |
| 210 | +information used to resolve imports and specify options for specific devices. |
| 211 | + |
| 212 | +Commonly this will be auto-generated by the CMake indexing in your Simics |
| 213 | +project, but it is possible to construct such a file by hand if absolutely |
| 214 | +neccessary. It is a json file with the following format: |
| 215 | +``` |
| 216 | +{ |
| 217 | + <full path to device file>: { |
| 218 | + "includes": [<include folders as full paths>], |
| 219 | + "dmlc_flags: [<flags passed to dmlc invocation>] |
| 220 | + }, |
| 221 | + ... <more device paths> |
| 222 | +} |
| 223 | +``` |
| 224 | + |
| 225 | +This will add the include folders specified when analysing files included, |
| 226 | +directly or indirectly, from the specified device file. |
0 commit comments