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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | 23x 25x 25x 25x 25x 25x 20x 5x 5x 170x 170x 170x 170x 170x 274x 274x 274x 274x 274x 274x 274x 274x 3x 3x 3x 3x 3x 2x 3x 3x 271x 21x 21x 274x 274x 24x 274x 170x | /**
* StructCollector - Extracts struct type declarations from parse trees.
* Handles fields with types, arrays, and const modifiers.
*/
import * as Parser from "../../../parser/grammar/CNextParser";
import ESourceLanguage from "../../../../../utils/types/ESourceLanguage";
import ESymbolKind from "../../../../../utils/types/ESymbolKind";
import IStructSymbol from "../../types/IStructSymbol";
import IFieldInfo from "../../types/IFieldInfo";
import TypeUtils from "../utils/TypeUtils";
import LiteralUtils from "../../../../../utils/LiteralUtils";
class StructCollector {
/**
* Parse array dimension expressions and append resolved sizes to dimensions array.
*/
private static parseArrayDimensions(
arrayDims: Parser.ArrayDimensionContext[],
dimensions: number[],
constValues?: Map<string, number>,
): void {
for (const dim of arrayDims) {
const sizeExpr = dim.expression();
Eif (sizeExpr) {
const dimText = sizeExpr.getText();
const literalSize = LiteralUtils.parseIntegerLiteral(dimText);
if (literalSize !== undefined) {
dimensions.push(literalSize);
E} else if (constValues?.has(dimText)) {
dimensions.push(constValues.get(dimText)!);
}
}
}
}
/**
* Collect a struct declaration and return an IStructSymbol.
*
* @param ctx The struct declaration context
* @param sourceFile Source file path
* @param scopeName Optional scope name for nested structs
* @param constValues Map of constant names to their numeric values (for resolving array dimensions)
* @returns The struct symbol
*/
static collect(
ctx: Parser.StructDeclarationContext,
sourceFile: string,
scopeName?: string,
constValues?: Map<string, number>,
): IStructSymbol {
const name = ctx.IDENTIFIER().getText();
const fullName = scopeName ? `${scopeName}_${name}` : name;
const line = ctx.start?.line ?? 0;
const fields = new Map<string, IFieldInfo>();
for (const member of ctx.structMember()) {
const fieldName = member.IDENTIFIER().getText();
const typeCtx = member.type();
const fieldType = TypeUtils.getTypeName(typeCtx, scopeName);
// Note: C-Next struct members don't have const modifier in grammar
const isConst = false;
const arrayDims = member.arrayDimension();
const dimensions: number[] = [];
let isArray = false;
// Handle string types specially
if (typeCtx.stringType()) {
const stringCtx = typeCtx.stringType()!;
const intLiteral = stringCtx.INTEGER_LITERAL();
Eif (intLiteral) {
const capacity = Number.parseInt(intLiteral.getText(), 10);
// If there are array dimensions, they come BEFORE string capacity
if (arrayDims.length > 0) {
StructCollector.parseArrayDimensions(
arrayDims,
dimensions,
constValues,
);
}
// String capacity becomes final dimension (+1 for null terminator)
dimensions.push(capacity + 1);
isArray = true;
}
} else if (arrayDims.length > 0) {
// Non-string array
isArray = true;
StructCollector.parseArrayDimensions(
arrayDims,
dimensions,
constValues,
);
}
const fieldInfo: IFieldInfo = {
type: fieldType,
isArray,
isConst,
};
if (dimensions.length > 0) {
fieldInfo.dimensions = dimensions;
}
fields.set(fieldName, fieldInfo);
}
return {
name: fullName,
parent: scopeName,
sourceFile,
sourceLine: line,
sourceLanguage: ESourceLanguage.CNext,
isExported: true,
kind: ESymbolKind.Struct,
fields,
};
}
}
export default StructCollector;
|