Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 81 82 83 84 85 86 87 | 616x 616x 1058x 616x 616x 1058x 331x 331x 727x 476x 476x 258x 476x 251x 118x 246x 118x 133x 17x | /**
* 2.2 Plan -- every type name a file's public header will name.
*
* ## Why this is one function and not two predicates
*
* "Which types does this header name?" was derived twice, and both derivations
* stopped in the same place: at functions and variables (#1520).
*
* `Transpiler._headerNeedsUserCHeaders` branched on `symbol.kind`, handled
* `variable` and `function`, and answered `false` for a struct -- so a struct
* never asked for the header defining its FIELD's type.
*
* `HeaderGeneratorUtils.collectExternalTypes` walked function returns,
* function parameters and variables, and had no struct-field loop.
*
* Four `tests/issue-502` headers declared `SeaDash::Parse::ParseResult result;`
* and included nothing that defines it. Patching one derivation would have left
* the other wrong, which is why the enumeration moved here instead: a type the
* header names is a fact about the symbols, and it has one answer.
*
* ## It enumerates; it does not judge
*
* Whether a name is a builtin, local, forward-declarable or needs an include
* are all different questions with different answers, asked by different
* callers. Deciding any of them here would put a second question in a function
* that answers one -- and it is exactly how the `::` skip came to serve two
* masters, right for "can this be forward-declared" and wrong for "does this
* need an include".
*/
import type TSymbol from "../../types/symbols/TSymbol";
import TypeResolver from "../../utils/TypeResolver";
class HeaderTypeNames {
/**
* Every type name the header's declarations will name, bare.
*
* @param symbols the file's public interface, as `PublicInterface.forFile`
* settled it
*/
static collect(symbols: readonly TSymbol[]): Set<string> {
const named = new Set<string>();
for (const symbol of symbols) {
HeaderTypeNames.addNamesOf(symbol, named);
}
named.delete("");
return named;
}
/** The type names one symbol contributes, by kind. */
private static addNamesOf(symbol: TSymbol, into: Set<string>): void {
if (symbol.kind === "variable") {
into.add(TypeResolver.getTypeName(symbol.type));
return;
}
if (symbol.kind === "function") {
into.add(TypeResolver.getTypeName(symbol.returnType));
for (const parameter of symbol.parameters) {
into.add(TypeResolver.getTypeName(parameter.type));
}
return;
}
// A struct's own name is not what it NAMES -- its fields are. The struct is
// declared by this header, so it needs nothing included for itself; the
// types of its fields may need a great deal (#1520).
if (symbol.kind === "struct") {
for (const field of symbol.fields.values()) {
into.add(TypeResolver.getTypeName(field.type));
}
return;
}
// A bitmap emits `typedef uint8_t Flags;`, and that `uint8_t` is the one
// type it names. It is not on a field and not on the symbol's own `type` --
// it is `backingType`, which is why the first version of this missed it and
// twelve bitmap headers lost `<stdint.h>`. `headers:standalone:check`
// caught it, for the second time on the same construct.
if (symbol.kind === "bitmap") {
into.add(symbol.backingType);
}
}
}
export default HeaderTypeNames;
|