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 | 987x 987x 987x 987x 987x 987x 987x 987x 987x 987x 987x 253x 253x 253x 253x 253x 253x 253x 253x 23x 25x 25x 25x 25x 253x 253x 23x 253x | /**
* FunctionCollector - Extracts function declarations from parse trees.
* Handles return types, parameters, visibility, and signature generation.
*/
import * as Parser from "../../../parser/grammar/CNextParser";
import ESourceLanguage from "../../../../../utils/types/ESourceLanguage";
import ESymbolKind from "../../../../../utils/types/ESymbolKind";
import IFunctionSymbol from "../../types/IFunctionSymbol";
import IParameterInfo from "../../types/IParameterInfo";
import TypeUtils from "../utils/TypeUtils";
class FunctionCollector {
/**
* Collect a function declaration and return an IFunctionSymbol.
*
* @param ctx The function declaration context
* @param sourceFile Source file path
* @param scopeName Optional scope name for nested functions
* @param visibility Visibility for scope functions (default "private")
* @returns The function symbol
*/
static collect(
ctx: Parser.FunctionDeclarationContext,
sourceFile: string,
scopeName?: string,
visibility: "public" | "private" = "private",
): IFunctionSymbol {
const name = ctx.IDENTIFIER().getText();
const fullName = scopeName ? `${scopeName}_${name}` : name;
const line = ctx.start?.line ?? 0;
// Get return type
const returnTypeCtx = ctx.type();
const returnType = TypeUtils.getTypeName(returnTypeCtx, scopeName);
// Collect parameters
const params = ctx.parameterList()?.parameter() ?? [];
const parameters = FunctionCollector.collectParameters(params, scopeName);
// Generate signature for overload detection
const paramTypes = parameters.map((p) => p.type);
const signature = `${returnType} ${fullName}(${paramTypes.join(", ")})`;
return {
name: fullName,
parent: scopeName,
sourceFile,
sourceLine: line,
sourceLanguage: ESourceLanguage.CNext,
isExported: visibility === "public",
kind: ESymbolKind.Function,
returnType,
parameters,
visibility,
signature,
};
}
/**
* Extract parameter information from parameter contexts.
*/
private static collectParameters(
params: Parser.ParameterContext[],
scopeName?: string,
): IParameterInfo[] {
return params.map((p) => {
const name = p.IDENTIFIER().getText();
const typeCtx = p.type();
const type = TypeUtils.getTypeName(typeCtx, scopeName);
const isConst = p.constModifier() !== null;
const arrayDims = p.arrayDimension();
const isArray = arrayDims.length > 0;
// Extract array dimensions as strings (can contain expressions like SIZE)
const arrayDimensions: string[] = [];
if (isArray) {
for (const dim of arrayDims) {
const text = dim.getText();
const regex = /\[([^\]]*)\]/;
const match = regex.exec(text);
arrayDimensions.push(match ? match[1] : ""); // "" means unbounded
}
}
const paramInfo: IParameterInfo = {
name,
type,
isConst,
isArray,
};
if (arrayDimensions.length > 0) {
paramInfo.arrayDimensions = arrayDimensions;
}
return paramInfo;
});
}
}
export default FunctionCollector;
|