tiny.smg.scan.clike
Defined in scan.
API (3)
Actions
Public operations.
Source
Source: tools/smg/src/scan/clike.zig
zig
const std = @import("std");const smg = @import("../root.zig");const core = @import("core/root.zig");const scan_metrics = @import("metrics.zig");const graph_mod = smg.graph;const lines_mod = smg.lines;const model = smg.model;const spans = smg.span;const tree = smg.tree;const SourceLines = lines_mod.SourceLines;const Context = struct { allocator: std.mem.Allocator, scratch: std.mem.Allocator, metric_inputs: std.mem.Allocator, graph: *graph_mod.Graph, path: []const u8, source: []const u8, is_cpp: bool,};pub fn enhanceMetadata(allocator: std.mem.Allocator, scratch: std.mem.Allocator, metric_inputs: std.mem.Allocator, graph: *graph_mod.Graph, path: []const u8, source: []const u8, source_lines: SourceLines, lang: []const u8, limits: smg.ParserLimits) !void { const is_cpp = usesCppParser(source, lang); if (!treeParseCandidate(source)) return try enhanceMetadataFromText(allocator, metric_inputs, graph, path, source_lines, is_cpp); const parsed = if (is_cpp) try tree.parseCpp(scratch, source, limits) else try tree.parseC(scratch, source, limits); const parsed_value = parsed orelse return try enhanceMetadataFromText(allocator, metric_inputs, graph, path, source_lines, is_cpp); defer tree.deinit(parsed_value); const context: Context = .{ .allocator = allocator, .scratch = scratch, .metric_inputs = metric_inputs, .graph = graph, .path = path, .source = source, .is_cpp = is_cpp }; try enhanceNode(context, tree.root(parsed_value));}pub fn usesCppParser(source: []const u8, lang: []const u8) bool { if (std.mem.eql(u8, lang, "cpp") or std.mem.eql(u8, lang, "cpp_header")) return true; if (std.mem.eql(u8, lang, "c_header")) return cHeaderLooksLikeCpp(source); return false;}pub fn treeParseCandidate(source: []const u8) bool { return core.compactParseCandidateAny(source, &.{"int "});}fn enhanceMetadataFromText(allocator: std.mem.Allocator, metric_inputs: std.mem.Allocator, graph: *graph_mod.Graph, path: []const u8, source_lines: SourceLines, is_cpp: bool) !void { for (graph.nodes.items) |*node| { const file = node.file orelse continue; if (!std.mem.eql(u8, file, path)) continue; const line = node.line orelse continue; const end_line = node.end_line orelse line; if (std.mem.eql(u8, node.type, model.NodeType.function) or std.mem.eql(u8, node.type, model.NodeType.method)) { if (spans.startsWith(source_lines, line, end_line, "#define ")) { node.metadata = try model.mergePairs(allocator, node.metadata, try scan_metrics.textMacroMetadata(allocator, source_lines, line, end_line)); } else { node.metadata = try model.mergePairs(allocator, node.metadata, try scan_metrics.textFunctionMetadata(allocator, metric_inputs, source_lines, line, end_line, .c)); } } else if (std.mem.eql(u8, node.type, model.NodeType.class) or std.mem.eql(u8, node.type, model.NodeType.type)) { const c_kind = if (is_cpp) null else model.pairValue(node.metadata, "c_kind"); node.metadata = try model.mergePairs(allocator, node.metadata, try scan_metrics.textSpanMetadata(allocator, source_lines, line, end_line, c_kind)); } }}fn cHeaderLooksLikeCpp(source: []const u8) bool { const markers = [_][]const u8{ "class ", "namespace ", "template ", "public:", "private:", "protected:", "virtual ", "override", "::" }; for (markers) |marker| if (std.mem.indexOf(u8, source, marker) != null) return true; return false;}fn enhanceNode(context: Context, node: tree.Node) anyerror!void { if (try enhanceNodeMetadata(context, node)) return; const children = tree.childCount(node); for (0..children) |raw_index| try enhanceNode(context, tree.child(node, @intCast(raw_index)));}fn enhanceNodeMetadata(context: Context, node: tree.Node) !bool { const node_kind = tree.kind(node); if (std.mem.eql(u8, node_kind, "type_definition")) { try enhanceTypeDefinition(context, node); return true; } if (try enhanceFunctionNode(context, node_kind, node)) return false; if (try enhanceRecordNode(context, node_kind, node)) return false; try enhanceMethodDeclarationNode(context, node_kind, node); return false;}fn enhanceFunctionNode(context: Context, node_kind: []const u8, node: tree.Node) !bool { if (std.mem.eql(u8, node_kind, "function_definition")) { try enhanceFunctionDefinition(context, node); return true; } if (std.mem.eql(u8, node_kind, "preproc_function_def")) { try enhanceMacroDefinition(context, node); return true; } return false;}fn enhanceFunctionDefinition(context: Context, node: tree.Node) !void { const types = [_][]const u8{ model.NodeType.function, model.NodeType.method }; try replaceNodeMetadata(context, node, &types, try scan_metrics.cFunctionMetadata(context.allocator, context.scratch, context.metric_inputs, context.source, node));}fn enhanceMacroDefinition(context: Context, node: tree.Node) !void { const types = [_][]const u8{model.NodeType.function}; try replaceNodeMetadata(context, node, &types, try scan_metrics.cMacroMetadata(context.allocator, context.scratch, context.source, node));}fn enhanceRecordNode(context: Context, node_kind: []const u8, node: tree.Node) !bool { if (std.mem.eql(u8, node_kind, "class_specifier")) { try enhanceClassSpecifier(context, node); return true; } if (std.mem.eql(u8, node_kind, "struct_specifier")) { try enhanceAggregateSpecifier(context, node, model.NodeType.class, "struct"); return true; } if (std.mem.eql(u8, node_kind, "union_specifier")) { try enhanceAggregateSpecifier(context, node, model.NodeType.class, "union"); return true; } if (std.mem.eql(u8, node_kind, "enum_specifier")) { try enhanceAggregateSpecifier(context, node, model.NodeType.type, "enum"); return true; } return false;}fn enhanceClassSpecifier(context: Context, node: tree.Node) !void { const types = [_][]const u8{model.NodeType.class}; try replaceNodeMetadata(context, node, &types, try scan_metrics.cDeclarationMetadata(context.allocator, context.scratch, context.source, node));}fn enhanceAggregateSpecifier(context: Context, node: tree.Node, node_type: []const u8, c_kind: []const u8) !void { const types = [_][]const u8{node_type}; const metadata = if (context.is_cpp and !std.mem.eql(u8, c_kind, "enum")) try scan_metrics.cDeclarationMetadata(context.allocator, context.scratch, context.source, node) else try scan_metrics.cRecordMetadata(context.allocator, context.scratch, context.source, node, c_kind); try replaceNodeMetadata(context, node, &types, metadata);}fn enhanceMethodDeclarationNode(context: Context, node_kind: []const u8, node: tree.Node) !void { if (!std.mem.eql(u8, node_kind, "declaration") and !std.mem.eql(u8, node_kind, "field_declaration")) return; if (!core.hasDescendant(node, "function_declarator")) return; const types = [_][]const u8{model.NodeType.method}; try replaceNodeMetadata(context, node, &types, try scan_metrics.cDeclarationMetadata(context.allocator, context.scratch, context.source, node));}fn enhanceTypeDefinition(context: Context, node: tree.Node) !void { const type_node = core.findChild(node, "struct_specifier") orelse core.findChild(node, "union_specifier") orelse core.findChild(node, "enum_specifier") orelse return; const type_kind = tree.kind(type_node); const node_type = if (std.mem.eql(u8, type_kind, "enum_specifier")) model.NodeType.type else model.NodeType.class; const c_kind = if (std.mem.eql(u8, type_kind, "struct_specifier")) "struct" else if (std.mem.eql(u8, type_kind, "union_specifier")) "union" else "enum"; const types = [_][]const u8{node_type}; try replaceNodeMetadata(context, node, &types, try scan_metrics.cRecordMetadata(context.allocator, context.scratch, context.source, node, c_kind));}fn replaceNodeMetadata(context: Context, node: tree.Node, node_types: []const []const u8, metadata: []const model.Pair) !void { replaceUniqueNodeMetadata(context.graph, context.path, tree.startLine(node), tree.endLine(node), node_types, metadata);}fn replaceUniqueNodeMetadata(graph: *graph_mod.Graph, path: []const u8, line: i64, end_line: i64, node_types: []const []const u8, metadata: []const model.Pair) void { var found: ?usize = null; var matches: usize = 0; for (graph.nodes.items, 0..) |node, index| { if (!nodeMatchesRange(node, path, line, end_line, node_types)) continue; found = index; matches += 1; } if (matches != 1) return; graph.nodes.items[found.?].metadata = metadata;}fn nodeMatchesRange(node: model.Node, path: []const u8, line: i64, end_line: i64, node_types: []const []const u8) bool { const file = node.file orelse return false; if (!std.mem.eql(u8, file, path)) return false; if (node.line == null or node.line.? != line) return false; if (node.end_line == null or node.end_line.? != end_line) return false; for (node_types) |node_type| if (std.mem.eql(u8, node.type, node_type)) return true; return false;}Source: tools/smg/src/scan/root.zig:8
zig
pub const clike = @import("clike.zig");Audit
| Definitions | 4 |
|---|---|
| Public names | 4 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |