hoshi-lang dev
Yet another programming language
Loading...
Searching...
No Matches
symbolExtractor.cpp
Go to the documentation of this file.
1//
2// Symbol Extractor implementation — walks AST and collects symbols
3//
4
5#include "symbolExtractor.h"
6#include <share/def.hpp>
7
8namespace lsp {
9
11 return tok.strVal;
12}
13
15 symbols.clear();
16 if (!module) return symbols;
17
18 for (auto *stmt : module->stmts) {
19 visitGlobal(stmt);
20 }
21
22 return symbols;
23}
24
25void SymbolExtractor::visitGlobal(yoi::globalStmt *stmt) {
26 if (!stmt) return;
27
28 switch (stmt->kind) {
30 visitFuncDef(static_cast<yoi::funcDefStmt *>(stmt->value.ptr));
31 break;
33 visitStructDef(static_cast<yoi::structDefStmt *>(stmt->value.ptr));
34 break;
36 visitInterfaceDef(static_cast<yoi::interfaceDefStmt *>(stmt->value.ptr));
37 break;
39 visitLetStmt(static_cast<yoi::letStmt *>(stmt->value.ptr));
40 break;
42 visitTypeAlias(static_cast<yoi::typeAliasStmt *>(stmt->value.ptr));
43 break;
45 visitUse(static_cast<yoi::useStmt *>(stmt->value.ptr));
46 break;
48 visitImport(static_cast<yoi::importDecl *>(stmt->value.ptr));
49 break;
51 visitExport(static_cast<yoi::exportDecl *>(stmt->value.ptr));
52 break;
54 visitImpl(static_cast<yoi::implStmt *>(stmt->value.ptr));
55 break;
57 visitDataStruct(static_cast<yoi::dataStructDefStmt *>(stmt->value.ptr));
58 break;
60 visitEnum(static_cast<yoi::enumerationDefinition *>(stmt->value.ptr));
61 break;
63 visitConceptDef(static_cast<yoi::conceptDefinition *>(stmt->value.ptr));
64 break;
65 default:
66 break;
67 }
68}
69
70void SymbolExtractor::visitFuncDef(yoi::funcDefStmt *stmt) {
71 if (!stmt || !stmt->id || !stmt->id->id) return;
72
73 Symbol sym;
74 sym.kind = HoshiSymbolKind::Function;
75 sym.line = stmt->getLine();
76 sym.column = stmt->getColumn();
77 sym.name = stmt->id->id->node.strVal;
78
79 // Build detail: "func name(args): returnType"
80 yoi::wstr detail = L"func ";
81 detail += formatIdentifierWithDefTemplateArg(stmt->id);
82 if (stmt->args) {
83 detail += formatDefinitionArgs(stmt->args);
84 }
85 if (stmt->resultType) {
86 detail += L": ";
87 detail += formatTypeSpec(stmt->resultType);
88 }
89 sym.detail = detail;
90
91 if (stmt->resultType) {
92 sym.typeInfo = formatTypeSpec(stmt->resultType);
93 }
94 if (stmt->block) {
95 sym.endLine = stmt->block->endLine;
96 sym.endColumn = stmt->block->endColumn + 1;
97 }
98
99 symbols.push_back(sym);
100
101 // Extract parameters as local variables
102 if (stmt->args) {
103 for (auto *arg : stmt->args->spec) {
104 if (arg && arg->id) {
105 Symbol param;
106 param.kind = HoshiSymbolKind::Variable;
107 param.line = arg->getLine();
108 param.column = arg->getColumn();
109 param.name = tokenStrVal(arg->id->node);
110 param.parentName = sym.name;
111 param.isLocal = true;
112 param.ownerLine = sym.line;
113 if (arg->spec) param.typeInfo = formatTypeSpec(arg->spec);
114 param.detail = L"param " + param.name;
115 if (!param.typeInfo.empty()) param.detail += L": " + param.typeInfo;
116 symbols.push_back(param);
117 }
118 }
119 }
120
121 // Visit function body for local symbols
122 if (stmt->block) {
123 for (auto *cbStmt : stmt->block->stmts) {
124 visitInCodeBlock(cbStmt, sym.name, sym.line);
125 }
126 }
127}
128
129void SymbolExtractor::visitStructDef(yoi::structDefStmt *stmt) {
130 if (!stmt || !stmt->id || !stmt->id->id) return;
131
132 Symbol sym;
133 sym.kind = HoshiSymbolKind::Struct;
134 sym.line = stmt->getLine();
135 sym.column = stmt->getColumn();
136 sym.name = stmt->id->id->node.strVal;
137 sym.detail = L"struct " + formatIdentifierWithDefTemplateArg(stmt->id);
138
139 // Extract fields and methods as children
140 if (stmt->inner) {
141 for (auto *pair : stmt->inner->inner) {
142 if (!pair) continue;
143
144 Symbol child;
145 child.parentName = sym.name;
146
147 if (pair->kind == 0 && pair->var) {
148 // Field
149 child.kind = HoshiSymbolKind::Field;
150 child.line = pair->getLine();
151 child.column = pair->getColumn();
152 child.name = tokenStrVal(pair->var->id->node);
153 child.typeInfo = formatTypeSpec(pair->var->spec);
154 child.detail = child.name + L": " + child.typeInfo;
155 } else if (pair->kind == 1 && pair->con) {
156 // Constructor
157 child.kind = HoshiSymbolKind::Constructor;
158 child.line = pair->getLine();
159 child.column = pair->getColumn();
160 child.name = L"constructor";
161 child.detail = L"constructor" + formatDefinitionArgs(pair->con->args);
162 } else if (pair->kind == 2 && pair->method) {
163 // Method
164 child.kind = HoshiSymbolKind::Method;
165 child.line = pair->getLine();
166 child.column = pair->getColumn();
167 child.name = tokenStrVal(pair->method->name->id->node);
168 child.detail = L"func " + child.name + formatDefinitionArgs(pair->method->args);
169 if (pair->method->resultType) {
170 child.detail += L": ";
171 child.detail += formatTypeSpec(pair->method->resultType);
172 child.typeInfo = formatTypeSpec(pair->method->resultType);
173 }
174 } else if (pair->kind == 3 && pair->finalizer) {
175 // Finalizer
176 child.kind = HoshiSymbolKind::Finalizer;
177 child.line = pair->getLine();
178 child.column = pair->getColumn();
179 child.name = L"finalizer";
180 child.detail = L"finalizer()";
181 }
182
183 if (!child.name.empty())
184 sym.children.push_back(child);
185 }
186 }
187
188 symbols.push_back(sym);
189}
190
191void SymbolExtractor::visitInterfaceDef(yoi::interfaceDefStmt *stmt) {
192 if (!stmt || !stmt->id || !stmt->id->id) return;
193
194 Symbol sym;
195 sym.kind = HoshiSymbolKind::Interface;
196 sym.line = stmt->getLine();
197 sym.column = stmt->getColumn();
198 sym.name = stmt->id->id->node.strVal;
199 sym.detail = L"interface " + formatIdentifierWithDefTemplateArg(stmt->id);
200
201 // Extract methods
202 if (stmt->inner) {
203 for (auto *pair : stmt->inner->inner) {
204 if (!pair) continue;
205
206 Symbol child;
207 child.parentName = sym.name;
208
209 if (pair->method) {
210 child.kind = HoshiSymbolKind::Method;
211 child.line = pair->getLine();
212 child.column = pair->getColumn();
213 child.name = tokenStrVal(pair->method->name->id->node);
214 child.detail = L"func " + child.name + formatDefinitionArgs(pair->method->args);
215 if (pair->method->resultType) {
216 child.detail += L": ";
217 child.detail += formatTypeSpec(pair->method->resultType);
218 child.typeInfo = formatTypeSpec(pair->method->resultType);
219 }
220 } else if (pair->var) {
221 child.kind = HoshiSymbolKind::Field;
222 child.line = pair->getLine();
223 child.column = pair->getColumn();
224 child.name = tokenStrVal(pair->var->id->node);
225 child.typeInfo = formatTypeSpec(pair->var->spec);
226 child.detail = child.name + L": " + child.typeInfo;
227 }
228
229 if (!child.name.empty())
230 sym.children.push_back(child);
231 }
232 }
233
234 symbols.push_back(sym);
235}
236
237// Try to extract a type name from an initializer expression.
238// For "str.Str(...)" → returns "Str"
239// For other expressions → returns empty
241 if (!expr || !expr->expr) return L"";
242
243 // Walk down the single-term expression chain to reach the primary
244 yoi::logicalOrExpr *lor = expr->expr;
245 if (!lor || lor->terms.empty()) return L"";
246 yoi::logicalAndExpr *land = lor->terms.back();
247 if (!land || land->terms.empty()) return L"";
248 yoi::inclusiveExpr *inc = land->terms.back();
249 if (!inc || inc->terms.empty()) return L"";
250 yoi::exclusiveExpr *exc = inc->terms.back();
251 if (!exc || exc->terms.empty()) return L"";
252 yoi::andExpr *andE = exc->terms.back();
253 if (!andE || andE->terms.empty()) return L"";
254 yoi::equalityExpr *eq = andE->terms.back();
255 if (!eq || eq->terms.empty()) return L"";
256 yoi::relationalExpr *rel = eq->terms.back();
257 if (!rel || rel->terms.empty()) return L"";
258 yoi::shiftExpr *sh = rel->terms.back();
259 if (!sh || sh->terms.empty()) return L"";
260 yoi::addExpr *add = sh->terms.back();
261 if (!add || add->terms.empty()) return L"";
262 yoi::mulExpr *mul = add->terms.back();
263 if (!mul || mul->terms.empty()) return L"";
264 yoi::leftExpr *left = mul->terms.back();
265 if (!left || !left->lhs) return L"";
266 yoi::uniqueExpr *unq = left->lhs;
267 if (!unq || !unq->lhs) return L"";
268 yoi::abstractExpr *abs = unq->lhs;
269 if (!abs || !abs->lhs) return L"";
270 yoi::primary *prim = abs->lhs;
271 if (!prim) return L"";
272
273 // Check for memberExpr (e.g., str.Str(...))
274 if (prim->kind == yoi::primary::primaryKind::memberExpr && prim->member) {
275 auto &terms = prim->member->terms;
276 if (terms.empty()) return L"";
277 auto *lastTerm = terms.back();
278 if (!lastTerm || !lastTerm->id || !lastTerm->id->id) return L"";
279 yoi::wstr name = lastTerm->id->id->node.strVal;
280 // Constructor name starts with uppercase
281 if (!name.empty() && std::iswupper(name[0])) {
282 return name;
283 }
284 }
285
286 return L"";
287}
288
289void SymbolExtractor::visitLetStmt(yoi::letStmt *stmt, const yoi::wstr &inParent,
290 yoi::indexT ownerLine) {
291 if (!stmt) return;
292
293 for (auto *pair : stmt->terms) {
294 if (!pair || !pair->lhs) continue;
295
296 Symbol sym;
297 sym.kind = HoshiSymbolKind::Variable;
298 sym.line = pair->getLine();
299 sym.column = pair->getColumn();
300 sym.parentName = inParent;
301 sym.isLocal = !inParent.empty();
302 sym.ownerLine = ownerLine;
303
304 if (pair->lhs->kind == yoi::letAssignmentPairLHS::vKind::identifier && pair->lhs->id) {
305 sym.name = tokenStrVal(pair->lhs->id->node);
306 } else if (!pair->lhs->list.empty()) {
307 sym.name = pair->lhs->list[0].strVal;
308 }
309
310 if (pair->type) {
311 sym.typeInfo = formatTypeSpec(pair->type);
312 sym.detail = L"let " + sym.name + L": " + sym.typeInfo;
313 } else {
314 // Try to infer type from the initializer expression
315 sym.typeInfo = tryExtractTypeFromExpr(pair->rhs);
316 if (!sym.typeInfo.empty()) {
317 sym.detail = L"let " + sym.name + L": " + sym.typeInfo;
318 } else {
319 sym.detail = L"let " + sym.name;
320 }
321 }
322
323 if (!sym.name.empty())
324 symbols.push_back(sym);
325 }
326}
327
328void SymbolExtractor::visitTypeAlias(yoi::typeAliasStmt *stmt) {
329 if (!stmt || !stmt->lhs || !stmt->lhs->id) return;
330
331 Symbol sym;
332 sym.kind = HoshiSymbolKind::TypeAlias;
333 sym.line = stmt->getLine();
334 sym.column = stmt->getColumn();
335 sym.name = stmt->lhs->id->node.strVal;
336 sym.detail = L"alias " + formatIdentifierWithDefTemplateArg(stmt->lhs);
337 if (stmt->rhs) {
338 sym.typeInfo = formatTypeSpec(stmt->rhs);
339 sym.detail += L" = " + sym.typeInfo;
340 }
341
342 symbols.push_back(sym);
343}
344
345void SymbolExtractor::visitEnum(yoi::enumerationDefinition *stmt) {
346 if (!stmt || !stmt->name) return;
347
348 Symbol sym;
349 sym.kind = HoshiSymbolKind::Enum;
350 sym.line = stmt->getLine();
351 sym.column = stmt->getColumn();
352 sym.name = tokenStrVal(stmt->name->node);
353 sym.detail = L"enum " + sym.name;
354
355 for (auto *ep : stmt->values) {
356 if (!ep || !ep->name) continue;
357 Symbol child;
358 child.kind = HoshiSymbolKind::EnumMember;
359 child.parentName = sym.name;
360 child.line = ep->getLine();
361 child.column = ep->getColumn();
362 child.name = tokenStrVal(ep->name->node);
363 child.detail = sym.name + L"." + child.name;
364 sym.children.push_back(child);
365 }
366
367 symbols.push_back(sym);
368}
369
370void SymbolExtractor::visitImport(yoi::importDecl *stmt) {
371 if (!stmt || !stmt->inner || !stmt->inner->name || !stmt->inner->name->id) return;
372
373 Symbol sym;
374 sym.kind = HoshiSymbolKind::Import;
375 sym.line = stmt->getLine();
376 sym.column = stmt->getColumn();
377 sym.name = tokenStrVal(stmt->inner->name->id->node);
378 sym.detail = L"import " + sym.name + formatDefinitionArgs(stmt->inner->args)
379 + L": " + formatTypeSpec(stmt->inner->resultType)
380 + L" from " + stmt->from_path.strVal;
381 sym.typeInfo = formatTypeSpec(stmt->inner->resultType);
382 sym.importPath = stmt->from_path.strVal; // Store path for cross-module resolution
383
384 symbols.push_back(sym);
385}
386
387void SymbolExtractor::visitUse(yoi::useStmt *stmt) {
388 if (!stmt || !stmt->name) return;
389
390 Symbol sym;
391 sym.kind = HoshiSymbolKind::ModuleAlias;
392 sym.line = stmt->getLine();
393 sym.column = stmt->getColumn();
394 sym.name = tokenStrVal(stmt->name->node);
395 sym.importPath = stmt->path.strVal; // The module path string
396 sym.detail = L"use " + sym.name + L" \"" + sym.importPath + L"\"";
397
398 symbols.push_back(sym);
399}
400
401void SymbolExtractor::visitExport(yoi::exportDecl *stmt) {
402 if (!stmt || !stmt->as) return;
403
404 Symbol sym;
405 sym.kind = HoshiSymbolKind::Export;
406 sym.line = stmt->getLine();
407 sym.column = stmt->getColumn();
408 sym.name = tokenStrVal(stmt->as->node);
409 sym.detail = L"export ";
410 if (stmt->from) {
411 sym.typeInfo = formatTypeSpec(stmt->from);
412 sym.detail += sym.typeInfo;
413 }
414 sym.detail += L" as " + sym.name;
415
416 symbols.push_back(sym);
417}
418
419void SymbolExtractor::visitImpl(yoi::implStmt *stmt) {
420 if (!stmt) return;
421
422 // For impl blocks, extract method implementations
423 if (stmt->inner) {
424 yoi::wstr structName = formatExternModuleAccessExpression(stmt->structName);
425
426 for (auto *pair : stmt->inner->inner) {
427 if (!pair) continue;
428
429 Symbol sym;
430 sym.parentName = structName;
431
432 if (pair->met) {
433 sym.kind = HoshiSymbolKind::Method;
434 sym.line = pair->getLine();
435 sym.column = pair->getColumn();
436 sym.name = tokenStrVal(pair->met->name->id->node);
437 sym.detail = L"func " + sym.name + formatDefinitionArgs(pair->met->args);
438 if (pair->met->resultType) {
439 sym.detail += L": " + formatTypeSpec(pair->met->resultType);
440 sym.typeInfo = formatTypeSpec(pair->met->resultType);
441 }
442 if (pair->met->block) {
443 sym.endLine = pair->met->block->endLine;
444 sym.endColumn = pair->met->block->endColumn + 1;
445 }
446 // Synthetic 'this' variable for member access completion
447 if (!structName.empty()) {
448 Symbol thisSym;
449 thisSym.kind = HoshiSymbolKind::Variable;
450 thisSym.name = L"this";
451 thisSym.parentName = sym.name;
452 thisSym.isLocal = true;
453 thisSym.ownerLine = sym.line;
454 thisSym.typeInfo = structName;
455 thisSym.detail = L"this: " + structName;
456 thisSym.line = sym.line;
457 thisSym.column = sym.column;
458 symbols.push_back(thisSym);
459 }
460 // Extract parameters as local variables
461 if (pair->met->args) {
462 for (auto *arg : pair->met->args->spec) {
463 if (arg && arg->id) {
464 Symbol param;
465 param.kind = HoshiSymbolKind::Variable;
466 param.line = arg->getLine();
467 param.column = arg->getColumn();
468 param.name = tokenStrVal(arg->id->node);
469 param.parentName = sym.name;
470 param.isLocal = true;
471 param.ownerLine = sym.line;
472 if (arg->spec) param.typeInfo = formatTypeSpec(arg->spec);
473 param.detail = L"param " + param.name;
474 if (!param.typeInfo.empty()) param.detail += L": " + param.typeInfo;
475 symbols.push_back(param);
476 }
477 }
478 }
479 // Visit method body for local variables
480 if (pair->met->block) {
481 for (auto *cbStmt : pair->met->block->stmts) {
482 visitInCodeBlock(cbStmt, sym.name, sym.line);
483 }
484 }
485 } else if (pair->con) {
486 sym.kind = HoshiSymbolKind::Constructor;
487 sym.line = pair->getLine();
488 sym.column = pair->getColumn();
489 sym.name = L"constructor";
490 sym.detail = L"constructor" + formatDefinitionArgs(pair->con->args);
491 if (pair->con->block) {
492 sym.endLine = pair->con->block->endLine;
493 sym.endColumn = pair->con->block->endColumn + 1;
494 }
495 // Extract constructor parameters
496 if (pair->con->args) {
497 for (auto *arg : pair->con->args->spec) {
498 if (arg && arg->id) {
499 Symbol param;
500 param.kind = HoshiSymbolKind::Variable;
501 param.line = arg->getLine();
502 param.column = arg->getColumn();
503 param.name = tokenStrVal(arg->id->node);
504 param.parentName = L"constructor";
505 param.isLocal = true;
506 param.ownerLine = sym.line;
507 if (arg->spec) param.typeInfo = formatTypeSpec(arg->spec);
508 param.detail = L"param " + param.name;
509 if (!param.typeInfo.empty()) param.detail += L": " + param.typeInfo;
510 symbols.push_back(param);
511 }
512 }
513 }
514 // Visit constructor body
515 if (pair->con->block) {
516 for (auto *cbStmt : pair->con->block->stmts) {
517 visitInCodeBlock(cbStmt, L"constructor", sym.line);
518 }
519 }
520 } else if (pair->finalizer) {
521 sym.kind = HoshiSymbolKind::Finalizer;
522 sym.line = pair->getLine();
523 sym.column = pair->getColumn();
524 sym.name = L"finalizer";
525 sym.detail = L"finalizer()";
526 if (pair->finalizer->block) {
527 sym.endLine = pair->finalizer->block->endLine;
528 sym.endColumn = pair->finalizer->block->endColumn + 1;
529 for (auto *cbStmt : pair->finalizer->block->stmts) {
530 visitInCodeBlock(cbStmt, sym.name, sym.line);
531 }
532 }
533 }
534
535 if (!sym.name.empty())
536 symbols.push_back(sym);
537 }
538 }
539}
540
541void SymbolExtractor::visitDataStruct(yoi::dataStructDefStmt *stmt) {
542 if (!stmt || !stmt->id) return;
543
544 Symbol sym;
545 sym.kind = HoshiSymbolKind::Struct;
546 sym.line = stmt->getLine();
547 sym.column = stmt->getColumn();
548 sym.name = tokenStrVal(stmt->id->node);
549 sym.detail = L"datastruct " + sym.name;
550
551 if (stmt->inner) {
552 for (auto *pair : stmt->inner->inner) {
553 if (!pair || !pair->var) continue;
554
555 Symbol child;
556 child.kind = HoshiSymbolKind::Field;
557 child.parentName = sym.name;
558 child.line = pair->getLine();
559 child.column = pair->getColumn();
560 child.name = tokenStrVal(pair->var->id->node);
561 child.typeInfo = formatTypeSpec(pair->var->spec);
562 child.detail = child.name + L": " + child.typeInfo;
563 sym.children.push_back(child);
564 }
565 }
566
567 symbols.push_back(sym);
568}
569
570void SymbolExtractor::visitConceptDef(yoi::conceptDefinition *stmt) {
571 if (!stmt) return;
572
573 Symbol sym;
574 sym.kind = HoshiSymbolKind::Concept_;
575 sym.line = stmt->getLine();
576 sym.column = stmt->getColumn();
577 sym.name = stmt->name.strVal;
578 sym.detail = L"concept " + sym.name;
579
580 symbols.push_back(sym);
581}
582
583void SymbolExtractor::visitInCodeBlock(yoi::inCodeBlockStmt *stmt, const yoi::wstr &inParent,
584 yoi::indexT ownerLine) {
585 if (!stmt) return;
586
587 switch (stmt->kind) {
589 visitLetStmt(static_cast<yoi::letStmt *>(stmt->value.ptr), inParent, ownerLine);
590 break;
592 auto *cb = static_cast<yoi::codeBlock *>(stmt->value.ptr);
593 if (cb) {
594 for (auto *s : cb->stmts)
595 visitInCodeBlock(s, inParent, ownerLine);
596 }
597 break;
598 }
600 auto *ifs = static_cast<yoi::ifStmt *>(stmt->value.ptr);
601 if (ifs) {
602 if (ifs->ifB.block)
603 for (auto *s : ifs->ifB.block->stmts)
604 visitInCodeBlock(s, inParent, ownerLine);
605 for (auto &elif : ifs->elifB)
606 if (elif.block)
607 for (auto *s : elif.block->stmts)
608 visitInCodeBlock(s, inParent, ownerLine);
609 if (ifs->elseB)
610 for (auto *s : ifs->elseB->stmts)
611 visitInCodeBlock(s, inParent, ownerLine);
612 }
613 break;
614 }
616 auto *ws = static_cast<yoi::whileStmt *>(stmt->value.ptr);
617 if (ws && ws->block)
618 for (auto *s : ws->block->stmts)
619 visitInCodeBlock(s, inParent, ownerLine);
620 break;
621 }
623 auto *fs = static_cast<yoi::forStmt *>(stmt->value.ptr);
624 if (fs) {
625 if (fs->initStmt) visitInCodeBlock(fs->initStmt, inParent, ownerLine);
626 if (fs->afterStmt) visitInCodeBlock(fs->afterStmt, inParent, ownerLine);
627 if (fs->block)
628 for (auto *s : fs->block->stmts)
629 visitInCodeBlock(s, inParent, ownerLine);
630 }
631 break;
632 }
634 auto *fes = static_cast<yoi::forEachStmt *>(stmt->value.ptr);
635 if (fes && fes->var) {
636 Symbol sym;
637 sym.kind = HoshiSymbolKind::Variable;
638 sym.line = fes->var->getLine();
639 sym.column = fes->var->getColumn();
640 sym.name = tokenStrVal(fes->var->node);
641 sym.detail = L"foreach " + sym.name;
642 sym.parentName = inParent;
643 sym.isLocal = true;
644 sym.ownerLine = ownerLine;
645 symbols.push_back(sym);
646 }
647 if (fes && fes->block)
648 for (auto *s : fes->block->stmts)
649 visitInCodeBlock(s, inParent, ownerLine);
650 break;
651 }
653 auto *tcs = static_cast<yoi::tryCatchStmt *>(stmt->value.ptr);
654 if (tcs) {
655 if (tcs->tryBlock)
656 for (auto *s : tcs->tryBlock->stmts)
657 visitInCodeBlock(s, inParent, ownerLine);
658 for (auto *cp : tcs->catchParams) {
659 if (cp && cp->name) {
660 Symbol sym;
661 sym.kind = HoshiSymbolKind::Variable;
662 sym.line = cp->name->getLine();
663 sym.column = cp->name->getColumn();
664 sym.name = tokenStrVal(cp->name->node);
665 sym.detail = L"catch " + sym.name;
666 sym.parentName = inParent;
667 sym.isLocal = true;
668 sym.ownerLine = ownerLine;
669 symbols.push_back(sym);
670 }
671 if (cp && cp->block)
672 for (auto *s : cp->block->stmts)
673 visitInCodeBlock(s, inParent, ownerLine);
674 }
675 if (tcs->finallyBlock)
676 for (auto *s : tcs->finallyBlock->stmts)
677 visitInCodeBlock(s, inParent, ownerLine);
678 }
679 break;
680 }
681 default:
682 break;
683 }
684}
685
686// ---- Formatting helpers ----
687
688yoi::wstr SymbolExtractor::formatTypeSpec(yoi::typeSpec *spec) {
689 if (!spec) return L"void";
690
691 switch (spec->kind) {
693 return L"null";
695 if (spec->func) {
696 yoi::wstr result = L"func";
697 if (spec->func->args) {
698 result += L"(";
699 for (size_t i = 0; i < spec->func->args->types.size(); i++) {
700 if (i > 0) result += L", ";
701 result += formatTypeSpec(spec->func->args->types[i]);
702 }
703 result += L")";
704 }
705 if (spec->func->resultType)
706 result += L": " + formatTypeSpec(spec->func->resultType);
707 return result;
708 }
709 return L"func";
711 if (spec->elipsis)
712 return L"..." + formatTypeSpec(spec->elipsis);
713 return L"...";
715 return L"decltype(...)";
717 default:
718 if (spec->member)
719 return formatExternModuleAccessExpression(spec->member);
720 return L"unknown";
721 }
722}
723
724yoi::wstr SymbolExtractor::formatDefinitionArgs(yoi::definitionArguments *args) {
725 if (!args || args->spec.empty()) return L"()";
726
727 yoi::wstr result = L"(";
728 for (size_t i = 0; i < args->spec.size(); i++) {
729 if (i > 0) result += L", ";
730 auto *spec = args->spec[i];
731 if (spec && spec->id) {
732 result += spec->id->node.strVal;
733 if (spec->spec)
734 result += L": " + formatTypeSpec(spec->spec);
735 }
736 }
737 result += L")";
738 return result;
739}
740
741yoi::wstr SymbolExtractor::formatIdentifierWithDefTemplateArg(yoi::identifierWithDefTemplateArg *id) {
742 if (!id || !id->id) return L"";
743 return tokenStrVal(id->id->node);
744}
745
746yoi::wstr SymbolExtractor::formatIdentifierWithTemplateArg(yoi::identifierWithTemplateArg *id) {
747 if (!id || !id->id) return L"";
748 return tokenStrVal(id->id->node);
749}
750
751yoi::wstr SymbolExtractor::formatExternModuleAccessExpression(yoi::externModuleAccessExpression *expr) {
752 if (!expr || expr->terms.empty()) return L"";
753
754 yoi::wstr result;
755 for (size_t i = 0; i < expr->terms.size(); i++) {
756 if (i > 0) result += L".";
757 result += formatIdentifierWithTemplateArg(expr->terms[i]);
758 }
759 return result;
760}
761
762} // namespace lsp
yoi::vec< Symbol > symbols
yoi::vec< Symbol > extract(yoi::hoshiModule *module)
yoi::indexT getColumn()
Definition ast.cpp:1042
yoi::indexT getLine()
Definition ast.cpp:1046
primary * lhs
Definition ast.hpp:438
vec< mulExpr * > terms
Definition ast.hpp:490
vec< equalityExpr * > terms
Definition ast.hpp:538
yoi::indexT endLine
Definition ast.hpp:1025
vec< inCodeBlockStmt * > stmts
Definition ast.hpp:1023
yoi::indexT endColumn
Definition ast.hpp:1026
lexer::token name
Definition ast.hpp:1115
structDefInner * inner
Definition ast.hpp:724
identifier * id
Definition ast.hpp:723
vec< identifierWithTypeSpec * > spec
Definition ast.hpp:307
vec< enumerationPair * > values
Definition ast.hpp:1099
vec< relationalExpr * > terms
Definition ast.hpp:526
vec< andExpr * > terms
Definition ast.hpp:550
typeSpec * from
Definition ast.hpp:1050
identifier * as
Definition ast.hpp:1051
vec< identifierWithTemplateArg * > terms
Definition ast.hpp:1040
codeBlock * block
Definition ast.hpp:624
identifierWithDefTemplateArg * id
Definition ast.hpp:621
typeSpec * resultType
Definition ast.hpp:623
definitionArguments * args
Definition ast.hpp:622
typeSpec * resultType
Definition ast.hpp:315
unnamedDefinitionArguments * args
Definition ast.hpp:314
union yoi::globalStmt::vValue value
enum yoi::globalStmt::vKind kind
lexer::token node
Definition ast.hpp:254
vec< implInnerPair * > inner
Definition ast.hpp:755
implInner * inner
Definition ast.hpp:764
externModuleAccessExpression * structName
Definition ast.hpp:763
lexer::token from_path
Definition ast.hpp:1057
innerMethodDecl * inner
Definition ast.hpp:1056
union yoi::inCodeBlockStmt::vValue value
enum yoi::inCodeBlockStmt::vKind kind
vec< exclusiveExpr * > terms
Definition ast.hpp:562
typeSpec * resultType
Definition ast.hpp:965
identifierWithDefTemplateArg * name
Definition ast.hpp:963
definitionArguments * args
Definition ast.hpp:964
vec< interfaceDefInnerPair * > inner
Definition ast.hpp:652
identifierWithDefTemplateArg * id
Definition ast.hpp:659
interfaceDefInner * inner
Definition ast.hpp:660
uniqueExpr * lhs
Definition ast.hpp:464
vec< letAssignmentPair * > terms
Definition ast.hpp:795
vec< inclusiveExpr * > terms
Definition ast.hpp:574
vec< logicalAndExpr * > terms
Definition ast.hpp:586
vec< subscriptExpr * > terms
Definition ast.hpp:391
vec< leftExpr * > terms
Definition ast.hpp:478
enum yoi::primary::primaryKind kind
memberExpr * member
Definition ast.hpp:418
logicalOrExpr * expr
Definition ast.hpp:598
vec< shiftExpr * > terms
Definition ast.hpp:514
vec< addExpr * > terms
Definition ast.hpp:502
vec< structDefInnerPair * > inner
Definition ast.hpp:706
structDefInner * inner
Definition ast.hpp:714
identifierWithDefTemplateArg * id
Definition ast.hpp:713
yoi::identifierWithDefTemplateArg * lhs
Definition ast.hpp:223
yoi::typeSpec * rhs
Definition ast.hpp:224
externModuleAccessExpression * member
Definition ast.hpp:331
funcTypeSpec * func
Definition ast.hpp:332
enum yoi::typeSpec::typeSpecKind kind
typeSpec * elipsis
Definition ast.hpp:333
abstractExpr * lhs
Definition ast.hpp:452
vec< typeSpec * > types
Definition ast.hpp:1093
identifier * name
Definition ast.hpp:605
lexer::token path
Definition ast.hpp:606
detail namespace with internal helper functions
Definition json.hpp:263
static yoi::wstr tokenStrVal(yoi::lexer::token &tok)
static yoi::wstr tryExtractTypeFromExpr(yoi::rExpr *expr)
std::vector< t > vec
Definition def.hpp:56
std::wstring wstr
Definition def.hpp:51
uint64_t indexT
Definition def.hpp:54
yoi::indexT ownerLine
yoi::wstr detail
yoi::wstr importPath
yoi::indexT endLine
yoi::indexT column
yoi::indexT line
std::vector< Symbol > children
yoi::wstr parentName
yoi::wstr name
HoshiSymbolKind kind
yoi::indexT endColumn
yoi::wstr typeInfo