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 | 1612x 1612x 613x 613x 9380x 9380x 8778x 11x 793x 793x 1394x 1394x 723x 122x | /**
* Scope Frame Resolver
*
* Answers "what type does this name have HERE?" for the essential-type
* analyzers, over the frames built by DeclarationScopeCollector.
*
* Composed by each analyzer's listener rather than inherited, so the decision
* -- which frame encloses a node, and which declaration a name resolves to --
* lives in one place. MISRA Rule 10.1 (BooleanOperandAnalyzer) and Rule 10.4
* (MixedTypeCategoryAnalyzer) then differ only in how they classify the type
* text they get back, which is the part that genuinely differs between them.
*
* Extracted in Issue #1183: the two listeners had otherwise begun to carry
* identical frame-walking copies.
*/
import { ParserRuleContext } from "antlr4ng";
import IScopeFrame from "./types/IScopeFrame";
import DeclarationScopeCollector from "./DeclarationScopeCollector";
import CodeGenState from "../../state/CodeGenState";
class ScopeFrameResolver {
private readonly globalFrame: IScopeFrame;
// eslint-disable-next-line @typescript-eslint/lines-between-class-members
private readonly frameOf: Map<ParserRuleContext, IScopeFrame>;
constructor(collector: DeclarationScopeCollector) {
this.globalFrame = collector.getGlobalFrame();
this.frameOf = collector.getFrameOf();
}
/**
* Innermost scope frame enclosing a node, found by walking up its parent
* chain. Falls back to the global frame for a node outside any function or
* named scope.
*/
public frameFor(ctx: ParserRuleContext): IScopeFrame {
let node: ParserRuleContext | null = ctx;
while (node) {
const frame = this.frameOf.get(node);
if (frame) return frame;
node = node.parent;
}
return this.globalFrame;
}
/**
* Declared type text of a name as seen from a frame, searching outward so an
* inner declaration shadows an outer one, then falling back to the symbol
* table for a declaration that arrived through an #include. Null when the
* name is declared nowhere reachable -- a struct field or a call result.
*
* Issue #1220: the fallback is the whole cross-file story for the
* essential-type analyzers. Frames are built by walking THIS file's parse
* tree, so before it every imported declaration resolved to null, every
* check that depended on the operand's type quietly concluded "nothing to
* report", and E0804/E0805/E0807/E0810 all stopped firing the moment their
* operand crossed a file boundary.
*
* Lexical frames are searched FIRST and still win: a local declaration
* shadows an imported one of the same name, exactly as it did before.
*/
public typeOfName(name: string, frame: IScopeFrame): string | null {
let current: IScopeFrame | null = frame;
while (current) {
const typeName = current.vars.get(name);
if (typeName) return typeName;
current = current.parent;
}
return CodeGenState.getCNextVariableTypeName(name);
}
}
export default ScopeFrameResolver;
|