OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE.md file. | |
4 | |
5 library fletchc.messages; | |
6 | |
7 import 'diagnostic.dart' show | |
8 Diagnostic, // For documentation only. | |
9 DiagnosticParameter; | |
10 | |
11 enum DiagnosticKind { | |
12 agentVersionMismatch, | |
13 busySession, | |
14 cantPerformVerbIn, | |
15 cantPerformVerbTo, | |
16 cantPerformVerbWith, | |
17 compilerVersionMismatch, | |
18 duplicatedIn, | |
19 duplicatedTo, | |
20 duplicatedWith, | |
21 expectedAPortNumber, | |
22 expectedTargetButGot, | |
23 extraArguments, | |
24 handShakeFailed, | |
25 illegalDefine, | |
26 internalError, | |
27 missingRequiredArgument, | |
28 missingSessionName, | |
29 missingToFile, | |
30 noAgentFound, | |
31 noFileTarget, | |
32 noSuchSession, | |
33 noTcpSocketTarget, | |
34 quitTakesNoArguments, | |
35 sessionAlreadyExists, | |
36 sessionInvalidState, | |
37 settingsCompileTimeConstantAsOption, | |
38 settingsConstantsNotAMap, | |
39 settingsDeviceAddressNotAString, | |
40 settingsDeviceTypeNotAString, | |
41 settingsDeviceTypeUnrecognized, | |
42 settingsIncrementalModeNotAString, | |
43 settingsIncrementalModeUnrecognized, | |
44 settingsNotAMap, | |
45 settingsNotJson, | |
46 settingsOptionNotAString, | |
47 settingsOptionsNotAList, | |
48 settingsPackagesNotAString, | |
49 settingsUnrecognizedConstantValue, | |
50 settingsUnrecognizedKey, | |
51 socketAgentConnectError, | |
52 socketAgentReplyError, | |
53 socketVmConnectError, | |
54 socketVmReplyError, | |
55 terminatedSession, | |
56 unexpectedArgument, | |
57 unknownAction, | |
58 unknownOption, | |
59 unsupportedPlatform, | |
60 upgradeInvalidPackageName, | |
61 verbDoesNotSupportTarget, | |
62 verbDoesntSupportTarget, | |
63 verbRequiresFileTarget, | |
64 verbRequiresNoSession, | |
65 verbRequiresNoToFile, | |
66 verbRequiresNoWithFile, | |
67 verbRequiresSessionTarget, | |
68 verbRequiresSocketTarget, | |
69 verbRequiresSpecificTarget, | |
70 verbRequiresSpecificTargetButGot, | |
71 verbRequiresTarget, | |
72 versionMismatch, | |
73 | |
74 // TODO(ahe): Remove when debug attach implicitly. | |
75 attachToVmBeforeRun, | |
76 | |
77 // TODO(ahe): Remove when debug compile implicitly. | |
78 compileBeforeRun, | |
79 } | |
80 | |
81 /// Returns the diagnostic message template for [kind]. A diagnostic message | |
82 /// should contain three pieces of information: | |
83 /// | |
84 /// 1. What is wrong? | |
85 /// 2. Why is it wrong? | |
86 /// 3. How do you fix it? | |
87 /// | |
88 /// Where appropriate, we follow the [Google design guidelines](https://www.goog
le.com/design/spec/style/writing.html) | |
89 /// for writing messages to the user. With respect to punctuation, we interpret | |
90 /// error messages as parallel labels, meaning they should use full sentences, | |
91 /// that is, starting with a capital letter and terminated with punctuation | |
92 /// (see [Capitalization & punctuation](https://www.google.com/design/spec/style
/writing.html#writing-capitalization-punctuation)). | |
93 /// | |
94 /// In addition, make sure to get a review from a UX expert before adding new | |
95 /// diagnostics, or when updating existing diagnostics. | |
96 /// | |
97 /// A diagnostic message template is a string which includes special markers | |
98 /// (`"#{parameterName}"`). To produce a human-readable error message, one can | |
99 /// use [Diagnostic.formatMessage]. | |
100 String getMessage(DiagnosticKind kind) { | |
101 // Implementation note: Instead of directly writing `"#{parameterName}"` in | |
102 // templates, use DiagnosticParameter to help reduce the chance of typos, and | |
103 // to ensure all diagnostics can be processed by a third-party. | |
104 | |
105 const DiagnosticParameter message = DiagnosticParameter.message; | |
106 const DiagnosticParameter verb = DiagnosticParameter.verb; | |
107 const DiagnosticParameter sessionName = DiagnosticParameter.sessionName; | |
108 const DiagnosticParameter target = DiagnosticParameter.target; | |
109 const DiagnosticParameter requiredTarget = DiagnosticParameter.requiredTarget; | |
110 const DiagnosticParameter userInput = DiagnosticParameter.userInput; | |
111 const DiagnosticParameter additionalUserInput = | |
112 DiagnosticParameter.additionalUserInput; | |
113 const DiagnosticParameter address = DiagnosticParameter.address; | |
114 const DiagnosticParameter preposition = DiagnosticParameter.preposition; | |
115 const DiagnosticParameter uri = DiagnosticParameter.uri; | |
116 const DiagnosticParameter fixit = DiagnosticParameter.fixit; | |
117 | |
118 switch (kind) { | |
119 case DiagnosticKind.internalError: | |
120 return "Internal error: $message"; | |
121 | |
122 case DiagnosticKind.verbRequiresNoSession: | |
123 return "Can't perform '$verb' in a session. " | |
124 "Try removing 'in session $sessionName'."; | |
125 | |
126 case DiagnosticKind.cantPerformVerbIn: | |
127 return "Can't perform '$verb' in '$target'."; | |
128 | |
129 case DiagnosticKind.cantPerformVerbTo: | |
130 return "Can't perform '$verb' to '$target'."; | |
131 | |
132 case DiagnosticKind.cantPerformVerbWith: | |
133 return "Can't perform '$verb' with '$target'."; | |
134 | |
135 case DiagnosticKind.verbRequiresSessionTarget: | |
136 return "Can't perform '$verb' without a session " | |
137 "target. Try adding 'session <SESSION_NAME>' to the commmand line."; | |
138 | |
139 case DiagnosticKind.verbRequiresFileTarget: | |
140 // TODO(ahe): Be more explicit about what is wrong with the target. | |
141 return "Can't perform '$verb' without a file, but got '$target', which " | |
142 "is not a file target. Try adding 'file' in front."; | |
143 | |
144 case DiagnosticKind.verbRequiresSocketTarget: | |
145 // TODO(ahe): Be more explicit about what is wrong with the target. | |
146 return "Can't perform '$verb' without a socket, but got '$target', " | |
147 "which is not a socket. Try adding 'tcp_socket' in front."; | |
148 | |
149 case DiagnosticKind.verbDoesNotSupportTarget: | |
150 return "'$verb' can't be performed on '$target'."; | |
151 | |
152 case DiagnosticKind.noSuchSession: | |
153 return "Couldn't find a session called '$sessionName'. " | |
154 "Try running 'fletch create session $sessionName'."; | |
155 | |
156 case DiagnosticKind.sessionAlreadyExists: | |
157 return "Couldn't create session named '$sessionName'; " | |
158 "A session called $sessionName already exists."; | |
159 | |
160 case DiagnosticKind.sessionInvalidState: | |
161 return "Session '$sessionName' not in a valid state; " | |
162 "Please stop attached vm, run 'fletch quit' and retry."; | |
163 | |
164 case DiagnosticKind.noFileTarget: | |
165 return "No file provided. Try adding <FILE_NAME> to the command line."; | |
166 | |
167 case DiagnosticKind.noTcpSocketTarget: | |
168 return "No TCP socket provided. " | |
169 "Try adding 'tcp_socket HOST:PORT' to the command line."; | |
170 | |
171 case DiagnosticKind.expectedAPortNumber: | |
172 return "Expected a port number, but got '$userInput'."; | |
173 | |
174 case DiagnosticKind.noAgentFound: | |
175 return "No agent found in this session."; | |
176 | |
177 case DiagnosticKind.upgradeInvalidPackageName: | |
178 return "A dartino-agent package must have a name of the form\n" | |
179 " dartino-agent_<version>_<platform>.deb.\n" | |
180 "Try renaming the file to match this pattern."; | |
181 | |
182 case DiagnosticKind.socketAgentConnectError: | |
183 return "Unable to establish connection to Dartino Agent on " | |
184 "$address: $message."; | |
185 | |
186 case DiagnosticKind.socketVmConnectError: | |
187 return | |
188 "Unable to establish connection to Fletch VM on $address: $message."; | |
189 | |
190 case DiagnosticKind.socketAgentReplyError: | |
191 return "Received invalid reply from Dartino Agent on $address: $message."; | |
192 | |
193 case DiagnosticKind.socketVmReplyError: | |
194 return "Received invalid reply from Fletch VM on $address: $message."; | |
195 | |
196 case DiagnosticKind.attachToVmBeforeRun: | |
197 return "Unable to run program without being attached to a VM. " | |
198 "Try running 'fletch attach'."; | |
199 | |
200 case DiagnosticKind.compileBeforeRun: | |
201 return "No program to run. Try running 'fletch compile'"; | |
202 | |
203 case DiagnosticKind.missingToFile: | |
204 return "No destination file provided. " | |
205 "Try adding 'to <FILE_NAME>' to the command line"; | |
206 | |
207 case DiagnosticKind.unknownOption: | |
208 // TODO(lukechurch): Review UX. | |
209 return "Unknown option: '$userInput'."; | |
210 | |
211 case DiagnosticKind.unsupportedPlatform: | |
212 // TODO(lukechurch): Review UX. | |
213 return "Unsupported platform: $message."; | |
214 | |
215 case DiagnosticKind.missingRequiredArgument: | |
216 // TODO(lukechurch): Consider a correction message. | |
217 return "Option '${DiagnosticParameter.userInput}' needs an argument."; | |
218 | |
219 case DiagnosticKind.missingSessionName: | |
220 // TODO(karlklose,ahe): provide support to list choices here. | |
221 return "Session name missing. Try adding a name after 'session'."; | |
222 | |
223 case DiagnosticKind.unexpectedArgument: | |
224 // TODO(lukechurch): Review UX | |
225 return "Option '${DiagnosticParameter.userInput}' doesn't take an " | |
226 "argument. Try removing '=' from the command line."; | |
227 | |
228 case DiagnosticKind.settingsNotAMap: | |
229 return "$uri: isn't a map."; | |
230 | |
231 case DiagnosticKind.settingsNotJson: | |
232 return "$uri: unable to decode as JSON: $message."; | |
233 | |
234 case DiagnosticKind.settingsPackagesNotAString: | |
235 return "$uri: 'packages' value '$userInput' isn't a String."; | |
236 | |
237 case DiagnosticKind.settingsOptionsNotAList: | |
238 return "$uri: 'options' value '$userInput' isn't a List."; | |
239 | |
240 case DiagnosticKind.settingsDeviceTypeNotAString: | |
241 return "$uri: 'device_type' value '$userInput' isn't a String."; | |
242 | |
243 case DiagnosticKind.settingsIncrementalModeNotAString: | |
244 return "$uri: 'incremental_mode' value '$userInput' isn't a String."; | |
245 | |
246 case DiagnosticKind.settingsOptionNotAString: | |
247 return "$uri: found 'options' entry '$userInput' which isn't a String."; | |
248 | |
249 case DiagnosticKind.settingsDeviceTypeNotAString: | |
250 return | |
251 "$uri: found 'device_type' entry '$userInput' which isn't a String."; | |
252 | |
253 case DiagnosticKind.settingsDeviceTypeUnrecognized: | |
254 return "$uri: found 'device_type' entry '$userInput' which is not one of " | |
255 "the recognized device types 'embedded', 'mobile'."; | |
256 | |
257 case DiagnosticKind.settingsIncrementalModeUnrecognized: | |
258 return "$uri: found 'incremental_mode' entry '$userInput' which is not " | |
259 "one of the recognized modes 'none', 'production', or " | |
260 "'experimental'."; | |
261 | |
262 case DiagnosticKind.settingsCompileTimeConstantAsOption: | |
263 return "$uri: compile-time constants should be in " | |
264 "the 'constants' map, not in 'options': '$userInput'."; | |
265 | |
266 case DiagnosticKind.settingsConstantsNotAMap: | |
267 return "$uri: 'constants' value isn't a Map"; | |
268 | |
269 case DiagnosticKind.settingsUnrecognizedConstantValue: | |
270 return "$uri: found 'constant[$userInput]' value '$additionalUserInput' " | |
271 "isn't a bool, int, or String."; | |
272 | |
273 case DiagnosticKind.settingsUnrecognizedKey: | |
274 return "$uri: unexpected key '$userInput'."; | |
275 | |
276 case DiagnosticKind.settingsDeviceAddressNotAString: | |
277 return "$uri: 'device_address' value '$userInput' isn't a String."; | |
278 | |
279 case DiagnosticKind.unknownAction: | |
280 return "'$userInput' isn't a supported action. " | |
281 "Try running 'fletch help'."; | |
282 | |
283 case DiagnosticKind.extraArguments: | |
284 return "Unrecognized arguments: $userInput."; | |
285 | |
286 case DiagnosticKind.duplicatedIn: | |
287 return "More than one 'in' clause: $preposition."; | |
288 | |
289 case DiagnosticKind.duplicatedTo: | |
290 // TODO(ahe): This is getting a bit tedious by now. We really need to | |
291 // figure out if we need to require exact prepostions. | |
292 return "More than one 'to' clause: $preposition."; | |
293 | |
294 case DiagnosticKind.duplicatedWith: | |
295 return "More than one 'with' clause: $preposition."; | |
296 | |
297 case DiagnosticKind.verbDoesntSupportTarget: | |
298 return "Can't perform '$verb' with '$target'."; | |
299 | |
300 case DiagnosticKind.verbRequiresNoToFile: | |
301 return "Can't perform '$verb' to '$userInput'."; | |
302 | |
303 case DiagnosticKind.verbRequiresNoWithFile: | |
304 return "Can't perform '$verb' with '$userInput'."; | |
305 | |
306 case DiagnosticKind.verbRequiresSpecificTarget: | |
307 return "Can't perform '$verb' without a '$requiredTarget'."; | |
308 | |
309 case DiagnosticKind.verbRequiresTarget: | |
310 return "Can't perform '$verb' without a target."; | |
311 | |
312 case DiagnosticKind.verbRequiresSpecificTargetButGot: | |
313 return "Can't perform '$verb' without a '$requiredTarget', " | |
314 "but got: '$target'."; | |
315 | |
316 case DiagnosticKind.expectedTargetButGot: | |
317 return "Expected 'session(s)', 'class(s)', 'method(s)', 'file(s)', " | |
318 "or 'all', but got: '$userInput'. Did you mean 'file $userInput'?"; | |
319 | |
320 case DiagnosticKind.quitTakesNoArguments: | |
321 return "Unexpected arguments. Try running 'fletch quit'."; | |
322 | |
323 case DiagnosticKind.busySession: | |
324 return "Session '$sessionName' is in use, please try again shortly."; | |
325 | |
326 case DiagnosticKind.terminatedSession: | |
327 return "Session '$sessionName' was terminated."; | |
328 | |
329 case DiagnosticKind.handShakeFailed: | |
330 // TODO(ager): lukechurch: Should this ever happen during normal usage? | |
331 // Should they report this to us as a bug? | |
332 return "Connection rejected because of invalid handshake reply from " | |
333 "VM on $address."; | |
334 | |
335 case DiagnosticKind.versionMismatch: | |
336 // TODO(ager): lukechurch: Is there advice we can give here? | |
337 // E.g. Consider upgrading your compiler? Do we have an easy place they | |
338 // can go to do that? Are we considering adding a tool to auto-upgrade? | |
339 return "Connection rejected because compiler and VM on $address " | |
340 "have different versions. Compiler version: '$userInput' " | |
341 "VM version: '$additionalUserInput'."; | |
342 | |
343 case DiagnosticKind.agentVersionMismatch: | |
344 // TODO(wibling): lukechurch: Is there advice we can give here? | |
345 // E.g. Consider upgrading your compiler? Do we have an easy place they | |
346 // can go to do that? Are we considering adding a tool to auto-upgrade? | |
347 return """ | |
348 Could not start vm on device because the compiler and the | |
349 session's remote device have different versions. | |
350 Compiler version: '$userInput' | |
351 Device version: '$additionalUserInput'. | |
352 $fixit"""; | |
353 | |
354 case DiagnosticKind.compilerVersionMismatch: | |
355 return "Command failed because the running compiler and the " | |
356 "Fletch Command Line Interface (CLI) have " | |
357 "different versions.\nCompiler version: '$userInput'\n" | |
358 "CLI version: '$additionalUserInput'.\n" | |
359 "This can happen if you have recently updated you Fletch SDK. " | |
360 "Try running 'fletch quit' and retry the command."; | |
361 | |
362 case DiagnosticKind.illegalDefine: | |
363 return "The define $userInput has an illegal value part: " | |
364 "$additionalUserInput."; | |
365 } | |
366 } | |
OLD | NEW |