Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swag init fails to resolve external types or internal types after using --parseDependencyLevel in non-standard project layout #1959

Open
39george opened this issue Jan 8, 2025 · 4 comments

Comments

@39george
Copy link

39george commented Jan 8, 2025

I'm encountering an issue with swag (v1.16.4) in a Gin project with a non-standard layout (no Go files at the project root). While go run compiles and executes the project without problems, swag init exhibits inconsistent behavior when handling type resolution.

Steps to reproduce:

My project has a structure where the main package is located in cmd/sitetrace/main.go, and there are no Go files at the root level.

Running swag init -g cmd/sitetrace/main.go -o cmd/docs works as expected unless Swagger comments reference external types (e.g., useragent.UserAgent from the github.com/mileuskin/go-useragent/v2 package). In this case, I receive the following error:

2025/01/08 17:03:53 ParseComment error in file .../internal/routes/protected/starter.go :protected.topDevices.TopDevicesResponse: [user_agent]: cannot find type definition: useragent.UserAgent

If I then attempt to use the --parseDependencyLevel flag (or --parseDependency flag) to resolve the external type issue, by running commands like swag init -g cmd/sitetrace/main.go -o cmd/docs --parseDependencyLevel 3, swag now fails to find internal types that were previously resolved correctly. For example:

2025/01/08 17:14:22 ParseComment error in file .../internal/routes/protected/starter.go :cannot find type definition: protected.dashboardInfo.Params

Root Cause (Suspected):

I suspect the root cause is related to the project's non-standard layout. I initially received the following warning:

2025/01/08 17:22:26 warning: failed to get package name in dir: ./, error: execute go list command, exit status 1, stdout:, stderr:no Go files in /home/george/dev/go/projects/sitetrace/services/sitetrace_main

This suggests that swag's dependency resolution relies on the go list command, which fails when there are no Go files at the root level. By adding a dummy .go file at the root, the issue is resolved.

Expected behavior:

swag should correctly resolve both external and internal types regardless of the project's layout (i.e., whether or not there are Go files at the root level). It should not require a dummy file at the root to function correctly.

Environment:

swag version: v1.16.4
Go version: go1.23.2 linux/amd64

Thank you for your time and consideration.

@sdghchj
Copy link
Member

sdghchj commented Jan 14, 2025

Please show me how/where you define/import protected.topDevices.TopDevicesResponse and useragent.UserAgent.

@39george
Copy link
Author

I define TopDevicesResponse within a handler function, and UserAgent is imported at the top of the {project_root}/internal/routes/protected/starter.go file:

import (
        // other imports...
	"github.com/mileusna/useragent"
)

// @Top	devices for host
// @Schemes
// @Description	Get top devices for host with optional interval parameter.
// @Description	By default, interval is 1 day ago, limit is 100.
// @Tags			starter
// @Param			Host		path		requests.HostParam							true	"Host"
// @Param			interval	query		[]string									false	"Interval in RFC3339  format (do not forget to escape string)"	minlength(2)	length(2)
// @Param			limit		query		int32										false	"Limit top elements count"
// @Success		200			{object}	[]protected.topDevices.TopDevicesResponse{}	"Top"
// @Failure		400			"Badly formed request"
// @Failure		401
// @Failure		403
// @Failure		500	"Postgres error"
// @Router			/starter/dashboard/{host}/top/devices [get]
func topDevices(c *gin.Context) {
	type TopDevicesResponse struct {
		Ua      *useragent.UserAgent `json:"user_agent"`
		Count   int64                `json:"count"`
		Percent float64              `json:"percent"`
	}

@sdghchj
Copy link
Member

sdghchj commented Jan 15, 2025

How about protected.dashboardInfo.Params?

@39george
Copy link
Author

It is in the same file:

// @Summary	Dashboard info
// @Schemes
// @Description	Get dashboard info with params
// @Tags			starter
// @Param			Params	path		protected.dashboardInfo.Params																						true	"User signup data"
// @Success		200		{object}	protected.dashboardInfo.Resp{current_period=[]protected.dashboardInfo.Obj,last_period=protected.dashboardInfo.Obj}	"Dashboard info, `field_value` can be `hour`, `day` or `week`"
// @Failure		400		"Badly formed request"
// @Failure		401
// @Failure		403
// @Failure		500	"Postgres error"
// @Failure		501
// @Router			/starter/dashboard/{host}/info/{period}/{kind} [get]
func dashboardInfo(c *gin.Context) {
	type Params struct {
		Period string `uri:"period" binding:"required,oneof=day week month year"`
		Kind   string `uri:"kind" binding:"required,oneof=session request resptime"`
		Host   string `uri:"host" binidng:"required,max=100,hostname"`
	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants