001package gudusoft.gsqlparser.ir.bound; 002 003import gudusoft.gsqlparser.ir.common.SourceAnchor; 004 005import java.util.Collections; 006import java.util.List; 007 008/** 009 * A procedure/function symbol declaration. 010 */ 011public class BoundRoutineSymbol extends BoundSymbol { 012 013 /** Owning package name (optional, null for standalone routines). */ 014 private final String packageName; 015 016 /** Procedure/function name. */ 017 private final String routineName; 018 019 /** Parameter signatures. */ 020 private final List<BoundParameterSymbol> parameters; 021 022 /** Return type (for functions). */ 023 private final BoundTypeRef returnType; 024 025 /** Routine type. */ 026 private final ERoutineKind routineKind; 027 028 public BoundRoutineSymbol(String routineName, String packageName, 029 BoundScope declaringScope, SourceAnchor declarationAnchor, 030 List<BoundParameterSymbol> parameters, 031 BoundTypeRef returnType, ERoutineKind routineKind) { 032 super(routineName, declaringScope, declarationAnchor); 033 this.routineName = routineName; 034 this.packageName = packageName; 035 this.parameters = parameters != null 036 ? Collections.unmodifiableList(parameters) 037 : Collections.<BoundParameterSymbol>emptyList(); 038 this.returnType = returnType; 039 this.routineKind = routineKind; 040 } 041 042 public String getPackageName() { return packageName; } 043 public String getRoutineName() { return routineName; } 044 public List<BoundParameterSymbol> getParameters() { return parameters; } 045 public BoundTypeRef getReturnType() { return returnType; } 046 public ERoutineKind getRoutineKind() { return routineKind; } 047 048 /** 049 * Returns a unique identifier for this routine. 050 * Format: {@code [pkg.]name/KIND(paramCount)} where KIND is one of: 051 * P (procedure), F (function), T (trigger), A (anonymous block), 052 * NP (nested procedure), NF (nested function), TM (type method). 053 * <p> 054 * Examples: 055 * <pre> 056 * MY_PKG.CALC/F(2) — function CALC in MY_PKG, 2 params 057 * MY_PKG.CALC/P(2) — procedure CALC in MY_PKG, 2 params 058 * STANDALONE/P(0) — standalone procedure, no params 059 * <anonymous>/A(0) — anonymous block 060 * </pre> 061 */ 062 public String getRoutineId() { 063 StringBuilder sb = new StringBuilder(); 064 if (packageName != null && !packageName.isEmpty()) { 065 sb.append(packageName).append('.'); 066 } 067 sb.append(routineName); 068 sb.append('/').append(kindCode()); 069 sb.append('(').append(parameters.size()).append(')'); 070 return sb.toString(); 071 } 072 073 private String kindCode() { 074 switch (routineKind) { 075 case PROCEDURE: return "P"; 076 case FUNCTION: return "F"; 077 case TRIGGER: return "T"; 078 case ANONYMOUS_BLOCK: return "A"; 079 case NESTED_PROCEDURE: return "NP"; 080 case NESTED_FUNCTION: return "NF"; 081 case TYPE_METHOD: return "TM"; 082 default: return "P"; 083 } 084 } 085 086 @Override 087 public ESymbolKind getSymbolKind() { 088 return ESymbolKind.ROUTINE; 089 } 090 091 @Override 092 public String toString() { 093 return "BoundRoutineSymbol{" + getRoutineId() + ", " + routineKind + "}"; 094 } 095}