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
//! **The format strings** — a small language inside a literal, drawn where the client drew one colour.
//!
//! ```cpp
//! std::println("值 = {:.3f},宽度 {:{}}", x, w); `{:…}` a field, `f` its conversion, `{}` an argument
//! printf("%-8.2f|%*d|%%", y, w); `%-8.2` a specifier, `*` an argument, `%%` an escape
//! scanf("%3d %[a-z] %n", &n, name, &used); and the scanset
//! ```
//!
//! # What this layer is, and what it is not
//!
//! Nothing here decides **which** literal is a format string or **what** its parts are: that is
//! [`cpp_code_analysis::format`], a pure walk with no LSP in it, and this file is the three lines that turn
//! its answer into claims. The split is the one the module's other passes already make — [`super::push_names`] gets a
//! list of names and paints them — and it is what lets the same walk serve a check later ("this format string wants
//! three arguments and the call passes two") without a second implementation of either grammar.
//!
//! # The fallbacks, and why a reader sees colour without configuring anything
//!
//! The four types are **custom**: the protocol's vocabulary has no word for "the specification of a format field",
//! and a client that was not told about a type cannot draw it ([`Builder::push_range`] refuses the claim). So each
//! piece has a **standard** type behind it:
//!
//! ```text
//! a field formatSpecifier → regexp the pattern language of a string — which is what it is
//! an argument formatArgument → parameter a reference to something the call passes
//! a conversion formatConversion → keyword one letter that changes what a value means
//! an escape formatEscape → (nothing) the client's own string colour already draws it
//! ```
//!
//! The fallbacks are *not* a worse approximation of the same picture; they are the three standard types whose theme
//! rules are closest to the four custom ones, so an editor whose theme has never heard of `formatSpecifier` still
//! shows the field, the argument and the conversion apart from the text around them. A client that *does* advertise
//! the custom types — or a theme that colours them — gets them instead, because [`Builder::push_range`] is asked for
//! the custom one first.
//!
//! An escape has **no fallback on purpose**: `string` is the colour it already has, and sending a token to repaint a
//! literal as a literal is one token of answer for no difference on screen.
use ;
use crate;
/// **What a piece is drawn as**, custom type first and the standard one it falls back to.
///
/// `None` for the fallback means "there is nothing to fall back to" — the escape, whose colour is the literal's own.
/// **Paint every piece of every format string of a file.**
///
/// The offsets are the file's, because the walk that produced them read the file's own text (see
/// [`cpp_code_analysis::Session::format_literals`]) — there is no mapping to do here, which is the reason that
/// query insists on a written view rather than a rendering.