Merge pull request #17713 from roidelapluie/roidelapluie/fix_ui_updates

web/ui: Add checks for Mantine UI PromQL docs and update generated files
This commit is contained in:
Julien 2025-12-29 10:50:23 +01:00 committed by GitHub
commit 46e58a68da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 2293 additions and 900 deletions

View File

@ -202,20 +202,22 @@ jobs:
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
run: exit 1
check_generated_parser:
# Checks generated parser and UI functions list. Not renaming as it is a required check.
name: Check generated parser
runs-on: ubuntu-latest
container:
image: quay.io/prometheus/golang-builder:1.25-base
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Install Go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
- uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3
- uses: ./.github/promci/actions/setup_environment
with:
cache: false
go-version: 1.25.x
- name: Run goyacc and check for diff
run: make install-goyacc check-generated-parser
enable_npm: true
- run: make install-goyacc check-generated-parser
- run: make check-generated-promql-functions
golangci:
name: golangci-lint
runs-on: ubuntu-latest

1
.gitignore vendored
View File

@ -26,6 +26,7 @@ npm_licenses.tar.bz2
/vendor
/.build
/go.work.sum
/**/node_modules

View File

@ -79,6 +79,20 @@ ui-lint:
# new Mantine-based UI is fully integrated and the old app can be removed.
cd $(UI_PATH)/react-app && npm run lint
.PHONY: generate-promql-functions
generate-promql-functions: ui-install
@echo ">> generating PromQL function signatures"
@cd $(UI_PATH)/mantine-ui/src/promql/tools && $(GO) run ./gen_functions_list > ../functionSignatures.ts
@echo ">> generating PromQL function documentation"
@cd $(UI_PATH)/mantine-ui/src/promql/tools && $(GO) run ./gen_functions_docs $(CURDIR)/docs/querying/functions.md > ../functionDocs.tsx
@echo ">> formatting generated files"
@cd $(UI_PATH)/mantine-ui && npx prettier --write --print-width 120 src/promql/functionSignatures.ts src/promql/functionDocs.tsx
.PHONY: check-generated-promql-functions
check-generated-promql-functions: generate-promql-functions
@echo ">> checking generated PromQL functions"
@git diff --exit-code -- $(UI_PATH)/mantine-ui/src/promql/functionSignatures.ts $(UI_PATH)/mantine-ui/src/promql/functionDocs.tsx || (echo "Generated PromQL function files are out of date. Please run 'make generate-promql-functions' and commit the changes." && false)
.PHONY: assets
ifndef SKIP_UI_BUILD
assets: check-node-version ui-install ui-build
@ -194,6 +208,8 @@ GO_SUBMODULE_DIRS := documentation/examples/remote_storage internal/tools web/ui
.PHONY: update-all-go-deps
update-all-go-deps: update-go-deps
$(foreach dir,$(GO_SUBMODULE_DIRS),$(MAKE) update-go-deps-in-dir DIR=$(dir);)
@echo ">> syncing Go workspace"
@$(GO) work sync
.PHONY: update-go-deps-in-dir
update-go-deps-in-dir:

8
go.work Normal file
View File

@ -0,0 +1,8 @@
go 1.24.9
use (
.
./documentation/examples/remote_storage
./internal/tools
./web/ui/mantine-ui/src/promql/tools
)

File diff suppressed because it is too large Load Diff

View File

@ -1,140 +1,196 @@
import { valueType, Func } from './ast';
import { valueType, Func } from "./ast";
export const functionSignatures: Record<string, Func> = {
abs: { name: 'abs', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
absent: { name: 'absent', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
absent_over_time: { name: 'absent_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
acos: { name: 'acos', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
acosh: { name: 'acosh', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
asin: { name: 'asin', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
asinh: { name: 'asinh', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
atan: { name: 'atan', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
atanh: { name: 'atanh', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
avg_over_time: { name: 'avg_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
ceil: { name: 'ceil', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
changes: { name: 'changes', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
abs: { name: "abs", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
absent: { name: "absent", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
absent_over_time: {
name: "absent_over_time",
argTypes: [valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
acos: { name: "acos", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
acosh: { name: "acosh", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
asin: { name: "asin", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
asinh: { name: "asinh", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
atan: { name: "atan", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
atanh: { name: "atanh", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
avg_over_time: { name: "avg_over_time", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
ceil: { name: "ceil", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
changes: { name: "changes", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
clamp: {
name: 'clamp',
name: "clamp",
argTypes: [valueType.vector, valueType.scalar, valueType.scalar],
variadic: 0,
returnType: valueType.vector,
},
clamp_max: {
name: 'clamp_max',
name: "clamp_max",
argTypes: [valueType.vector, valueType.scalar],
variadic: 0,
returnType: valueType.vector,
},
clamp_min: {
name: 'clamp_min',
name: "clamp_min",
argTypes: [valueType.vector, valueType.scalar],
variadic: 0,
returnType: valueType.vector,
},
cos: { name: 'cos', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
cosh: { name: 'cosh', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
count_over_time: { name: 'count_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
day_of_month: { name: 'day_of_month', argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
day_of_week: { name: 'day_of_week', argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
day_of_year: { name: 'day_of_year', argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
days_in_month: { name: 'days_in_month', argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
deg: { name: 'deg', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
delta: { name: 'delta', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
deriv: { name: 'deriv', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
exp: { name: 'exp', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
floor: { name: 'floor', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
histogram_avg: { name: 'histogram_avg', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
histogram_count: { name: 'histogram_count', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
cos: { name: "cos", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
cosh: { name: "cosh", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
count_over_time: { name: "count_over_time", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
day_of_month: { name: "day_of_month", argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
day_of_week: { name: "day_of_week", argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
day_of_year: { name: "day_of_year", argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
days_in_month: { name: "days_in_month", argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
deg: { name: "deg", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
delta: { name: "delta", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
deriv: { name: "deriv", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
double_exponential_smoothing: {
name: "double_exponential_smoothing",
argTypes: [valueType.matrix, valueType.scalar, valueType.scalar],
variadic: 0,
returnType: valueType.vector,
},
exp: { name: "exp", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
first_over_time: { name: "first_over_time", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
floor: { name: "floor", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
histogram_avg: { name: "histogram_avg", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
histogram_count: { name: "histogram_count", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
histogram_fraction: {
name: 'histogram_fraction',
name: "histogram_fraction",
argTypes: [valueType.scalar, valueType.scalar, valueType.vector],
variadic: 0,
returnType: valueType.vector,
},
histogram_quantile: {
name: 'histogram_quantile',
name: "histogram_quantile",
argTypes: [valueType.scalar, valueType.vector],
variadic: 0,
returnType: valueType.vector,
},
histogram_stddev: { name: 'histogram_stddev', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
histogram_stdvar: { name: 'histogram_stdvar', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
histogram_sum: { name: 'histogram_sum', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
double_exponential_smoothing: {
name: 'double_exponential_smoothing',
argTypes: [valueType.matrix, valueType.scalar, valueType.scalar],
histogram_stddev: {
name: "histogram_stddev",
argTypes: [valueType.vector],
variadic: 0,
returnType: valueType.vector,
},
hour: { name: 'hour', argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
idelta: { name: 'idelta', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
increase: { name: 'increase', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
irate: { name: 'irate', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
histogram_stdvar: {
name: "histogram_stdvar",
argTypes: [valueType.vector],
variadic: 0,
returnType: valueType.vector,
},
histogram_sum: { name: "histogram_sum", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
hour: { name: "hour", argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
idelta: { name: "idelta", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
increase: { name: "increase", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
info: { name: "info", argTypes: [valueType.vector, valueType.vector], variadic: 1, returnType: valueType.vector },
irate: { name: "irate", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
label_join: {
name: 'label_join',
name: "label_join",
argTypes: [valueType.vector, valueType.string, valueType.string, valueType.string],
variadic: -1,
returnType: valueType.vector,
},
label_replace: {
name: 'label_replace',
name: "label_replace",
argTypes: [valueType.vector, valueType.string, valueType.string, valueType.string, valueType.string],
variadic: 0,
returnType: valueType.vector,
},
last_over_time: { name: 'last_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
ln: { name: 'ln', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
log10: { name: 'log10', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
log2: { name: 'log2', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
mad_over_time: { name: 'mad_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
max_over_time: { name: 'max_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
min_over_time: { name: 'min_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
minute: { name: 'minute', argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
month: { name: 'month', argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
pi: { name: 'pi', argTypes: [], variadic: 0, returnType: valueType.scalar },
last_over_time: { name: "last_over_time", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
ln: { name: "ln", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
log10: { name: "log10", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
log2: { name: "log2", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
mad_over_time: { name: "mad_over_time", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
max_over_time: { name: "max_over_time", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
min_over_time: { name: "min_over_time", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
minute: { name: "minute", argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
month: { name: "month", argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
pi: { name: "pi", argTypes: [], variadic: 0, returnType: valueType.scalar },
predict_linear: {
name: 'predict_linear',
name: "predict_linear",
argTypes: [valueType.matrix, valueType.scalar],
variadic: 0,
returnType: valueType.vector,
},
present_over_time: { name: 'present_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
present_over_time: {
name: "present_over_time",
argTypes: [valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
quantile_over_time: {
name: 'quantile_over_time',
name: "quantile_over_time",
argTypes: [valueType.scalar, valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
rad: { name: 'rad', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
rate: { name: 'rate', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
resets: { name: 'resets', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
round: { name: 'round', argTypes: [valueType.vector, valueType.scalar], variadic: 1, returnType: valueType.vector },
scalar: { name: 'scalar', argTypes: [valueType.vector], variadic: 0, returnType: valueType.scalar },
sgn: { name: 'sgn', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sin: { name: 'sin', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sinh: { name: 'sinh', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sort: { name: 'sort', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
rad: { name: "rad", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
rate: { name: "rate", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
resets: { name: "resets", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
round: { name: "round", argTypes: [valueType.vector, valueType.scalar], variadic: 1, returnType: valueType.vector },
scalar: { name: "scalar", argTypes: [valueType.vector], variadic: 0, returnType: valueType.scalar },
sgn: { name: "sgn", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sin: { name: "sin", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sinh: { name: "sinh", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sort: { name: "sort", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sort_by_label: {
name: 'sort_by_label',
name: "sort_by_label",
argTypes: [valueType.vector, valueType.string],
variadic: -1,
returnType: valueType.vector,
},
sort_by_label_desc: {
name: 'sort_by_label_desc',
name: "sort_by_label_desc",
argTypes: [valueType.vector, valueType.string],
variadic: -1,
returnType: valueType.vector,
},
sort_desc: { name: 'sort_desc', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sqrt: { name: 'sqrt', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
stddev_over_time: { name: 'stddev_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
stdvar_over_time: { name: 'stdvar_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
sum_over_time: { name: 'sum_over_time', argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
tan: { name: 'tan', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
tanh: { name: 'tanh', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
time: { name: 'time', argTypes: [], variadic: 0, returnType: valueType.scalar },
timestamp: { name: 'timestamp', argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
vector: { name: 'vector', argTypes: [valueType.scalar], variadic: 0, returnType: valueType.vector },
year: { name: 'year', argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
sort_desc: { name: "sort_desc", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
sqrt: { name: "sqrt", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
stddev_over_time: {
name: "stddev_over_time",
argTypes: [valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
stdvar_over_time: {
name: "stdvar_over_time",
argTypes: [valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
sum_over_time: { name: "sum_over_time", argTypes: [valueType.matrix], variadic: 0, returnType: valueType.vector },
tan: { name: "tan", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
tanh: { name: "tanh", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
time: { name: "time", argTypes: [], variadic: 0, returnType: valueType.scalar },
timestamp: { name: "timestamp", argTypes: [valueType.vector], variadic: 0, returnType: valueType.vector },
ts_of_first_over_time: {
name: "ts_of_first_over_time",
argTypes: [valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
ts_of_last_over_time: {
name: "ts_of_last_over_time",
argTypes: [valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
ts_of_max_over_time: {
name: "ts_of_max_over_time",
argTypes: [valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
ts_of_min_over_time: {
name: "ts_of_min_over_time",
argTypes: [valueType.matrix],
variadic: 0,
returnType: valueType.vector,
},
vector: { name: "vector", argTypes: [valueType.scalar], variadic: 0, returnType: valueType.vector },
year: { name: "year", argTypes: [valueType.vector], variadic: 1, returnType: valueType.vector },
};

View File

@ -18,7 +18,7 @@ import (
"fmt"
"io"
"log"
"net/http"
"os"
"sort"
"strings"
@ -26,20 +26,23 @@ import (
"github.com/russross/blackfriday/v2"
)
var funcDocsRe = regexp.MustCompile("^## `(.+)\\(\\)`\n$|^## (Trigonometric Functions)\n$")
var funcDocsRe = regexp.MustCompile("^## `([^)]+)\\(\\)` and `([^)]+)\\(\\)`\n$|^## `(.+)\\(\\)`\n$|^## (Trigonometric Functions)\n$")
func main() {
resp, err := http.Get("https://raw.githubusercontent.com/prometheus/prometheus/master/docs/querying/functions.md")
// Read from local file instead of fetching from upstream.
if len(os.Args) < 2 {
log.Fatalln("Usage: gen_functions_docs <path-to-functions.md>")
}
functionsPath := os.Args[1]
file, err := os.Open(functionsPath)
if err != nil {
log.Fatalln("Failed to fetch function docs:", err)
}
if resp.StatusCode != 200 {
log.Fatalln("Bad status code while fetching function docs:", resp.Status)
log.Fatalln("Failed to open function docs:", err)
}
defer file.Close()
funcDocs := map[string]string{}
r := bufio.NewReader(resp.Body)
r := bufio.NewReader(file)
currentFunc := ""
currentDocs := ""
@ -58,6 +61,11 @@ func main() {
"last_over_time",
"present_over_time",
"mad_over_time",
"first_over_time",
"ts_of_first_over_time",
"ts_of_last_over_time",
"ts_of_max_over_time",
"ts_of_min_over_time",
} {
funcDocs[fn] = currentDocs
}
@ -81,6 +89,12 @@ func main() {
} {
funcDocs[fn] = currentDocs
}
case "histogram_count_and_histogram_sum":
funcDocs["histogram_count"] = currentDocs
funcDocs["histogram_sum"] = currentDocs
case "histogram_stddev_and_histogram_stdvar":
funcDocs["histogram_stddev"] = currentDocs
funcDocs["histogram_stdvar"] = currentDocs
default:
funcDocs[currentFunc] = currentDocs
}
@ -103,10 +117,16 @@ func main() {
}
currentDocs = ""
currentFunc = string(matches[1])
if matches[2] != "" {
// This is the case for "## Trigonometric Functions"
currentFunc = matches[2]
if matches[1] != "" && matches[2] != "" {
// Combined functions: "## `function1()` and `function2()`"
// Store as "function1_and_function2" and handle in saveCurrent.
currentFunc = matches[1] + "_and_" + matches[2]
} else if matches[3] != "" {
// Single function: "## `function_name()`"
currentFunc = string(matches[3])
} else if matches[4] != "" {
// Special section: "## Trigonometric Functions"
currentFunc = matches[4]
}
} else {
currentDocs += line

View File

@ -41,10 +41,10 @@ func main() {
sort.Strings(fnNames)
fmt.Println(`import { valueType, Func } from './ast';
export const functionSignatures: Record<string, Func> = {`)
export const functionSignatures: Record<string, Func> = {`)
for _, fnName := range fnNames {
fn := parser.Functions[fnName]
fmt.Printf(" %s: { name: '%s', argTypes: [%s], variadic: %d, returnType: %s },\n", fn.Name, fn.Name, formatValueTypes(fn.ArgTypes), fn.Variadic, formatValueType(fn.ReturnType))
}
fmt.Println("}")
fmt.Println("};")
}