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 127 128 129 130 131 | 34x 34x 34x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 24x 24x 24x | /**
* FunctionCollector - Collects function symbols from C parse trees.
*/
import type {
DeclaratorContext,
FunctionDefinitionContext,
} from "../../../parser/c/grammar/CParser";
import type ICFunctionSymbol from "../../../../types/symbols/c/ICFunctionSymbol";
import type ICParameterInfo from "../../../../types/symbols/c/ICParameterInfo";
import ESourceLanguage from "../../../../../utils/types/ESourceLanguage";
import DeclaratorUtils from "../utils/DeclaratorUtils";
import type IExtractedParameter from "../../shared/IExtractedParameter";
class FunctionCollector {
/**
* Map extracted parameters to ICParameterInfo array.
*/
private static _mapParameters(
extracted: IExtractedParameter[],
): ICParameterInfo[] {
return extracted.map((p) => ({
name: p.name,
type: p.type,
isConst: p.isConst,
isArray: p.isArray,
}));
}
/**
* Resolve return type, appending '*' if declarator has a pointer.
* Issue #895 Bug B / Issue #945: C grammar puts pointer before directDeclarator
* (e.g., `widget_t *func()` has declarator.pointer() !== null)
*/
private static _resolveReturnType(
baseType: string,
declarator: DeclaratorContext,
): string {
const hasPointer = declarator.pointer() !== null;
return hasPointer ? `${baseType}*` : baseType;
}
/**
* Collect a function symbol from a function definition.
*
* @param funcDef The function definition context
* @param sourceFile Source file path
*/
static collectFromDefinition(
funcDef: FunctionDefinitionContext,
sourceFile: string,
): ICFunctionSymbol | null {
const declarator = funcDef.declarator();
Iif (!declarator) return null;
const name = DeclaratorUtils.extractDeclaratorName(declarator);
Iif (!name) return null;
const line = funcDef.start?.line ?? 0;
// Get return type from declaration specifiers
const declSpecs = funcDef.declarationSpecifiers();
const baseType = declSpecs
? DeclaratorUtils.extractTypeFromDeclSpecs(declSpecs)
: "int";
const returnType = FunctionCollector._resolveReturnType(
baseType,
declarator,
);
const parameters = FunctionCollector._mapParameters(
DeclaratorUtils.extractFunctionParameters(declarator),
);
return {
kind: "function",
name,
sourceFile,
sourceLine: line,
sourceLanguage: ESourceLanguage.C,
isExported: true,
type: returnType,
parameters: parameters.length > 0 ? parameters : undefined,
isDeclaration: false,
};
}
/**
* Collect a function symbol from a declaration (prototype).
*
* @param name Function name
* @param baseType Return type
* @param declarator The declarator context
* @param sourceFile Source file path
* @param line Source line number
* @param isExtern Whether the function is extern
*/
static collectFromDeclaration(
name: string,
baseType: string,
declarator: DeclaratorContext,
sourceFile: string,
line: number,
isExtern: boolean,
): ICFunctionSymbol {
const parameters = FunctionCollector._mapParameters(
DeclaratorUtils.extractFunctionParameters(declarator),
);
const returnType = FunctionCollector._resolveReturnType(
baseType,
declarator,
);
return {
kind: "function",
name,
sourceFile,
sourceLine: line,
sourceLanguage: ESourceLanguage.C,
isExported: !isExtern,
type: returnType,
parameters: parameters.length > 0 ? parameters : undefined,
isDeclaration: true,
};
}
}
export default FunctionCollector;
|