276 lines
6.9 KiB
Go
276 lines
6.9 KiB
Go
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package repo
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"code.gitea.io/gitea/modules/markup"
|
|
"code.gitea.io/gitea/modules/markup/markdown"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
"code.gitea.io/gitea/services/context"
|
|
sourcegraph_service "code.gitea.io/gitea/services/sourcegraph"
|
|
)
|
|
|
|
// sourcegraphRepoName returns the full repository name for Sourcegraph,
|
|
// which includes the server domain prefix (e.g., "git.example.com/owner/repo")
|
|
func sourcegraphRepoName(ctx *context.APIContext) string {
|
|
return setting.Domain + "/" + ctx.Repo.Repository.FullName()
|
|
}
|
|
|
|
// SourcegraphHover returns hover information at a position
|
|
func SourcegraphHover(ctx *context.APIContext) {
|
|
// swagger:operation GET /repos/{owner}/{repo}/sourcegraph/hover repository repoSourcegraphHover
|
|
// ---
|
|
// summary: Get code intelligence hover info
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: path
|
|
// in: query
|
|
// description: file path
|
|
// type: string
|
|
// required: true
|
|
// - name: line
|
|
// in: query
|
|
// description: line number (0-indexed)
|
|
// type: integer
|
|
// required: true
|
|
// - name: character
|
|
// in: query
|
|
// description: character position (0-indexed)
|
|
// type: integer
|
|
// required: true
|
|
// - name: ref
|
|
// in: query
|
|
// description: git ref (commit SHA, branch, tag)
|
|
// type: string
|
|
// required: true
|
|
// responses:
|
|
// "200":
|
|
// description: hover information
|
|
// "400":
|
|
// "$ref": "#/responses/error"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
// "503":
|
|
// description: Sourcegraph integration not available
|
|
|
|
if !setting.Sourcegraph.Enabled {
|
|
ctx.APIError(http.StatusServiceUnavailable, "Sourcegraph integration is not enabled")
|
|
return
|
|
}
|
|
|
|
path := ctx.FormString("path")
|
|
line := ctx.FormInt("line")
|
|
char := ctx.FormInt("character")
|
|
ref := ctx.FormString("ref")
|
|
|
|
if path == "" || ref == "" {
|
|
ctx.APIError(http.StatusBadRequest, "path and ref are required")
|
|
return
|
|
}
|
|
|
|
client := sourcegraph_service.GetClient()
|
|
if client == nil {
|
|
ctx.APIError(http.StatusServiceUnavailable, "Sourcegraph client not initialized")
|
|
return
|
|
}
|
|
|
|
result, err := client.Hover(ctx, sourcegraphRepoName(ctx), ref, path, line, char)
|
|
if err != nil {
|
|
ctx.APIError(http.StatusBadGateway, err)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
ctx.JSON(http.StatusOK, map[string]any{})
|
|
return
|
|
}
|
|
|
|
// Render markdown content to HTML
|
|
if result.Contents != "" {
|
|
rendered, err := markdown.RenderString(markup.NewRenderContext(ctx).WithMetas(markup.ComposeSimpleDocumentMetas()), result.Contents)
|
|
if err == nil {
|
|
result.Contents = string(rendered)
|
|
}
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// SourcegraphDefinition returns definition locations for a symbol
|
|
func SourcegraphDefinition(ctx *context.APIContext) {
|
|
// swagger:operation GET /repos/{owner}/{repo}/sourcegraph/definition repository repoSourcegraphDefinition
|
|
// ---
|
|
// summary: Get code intelligence definition locations
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: path
|
|
// in: query
|
|
// description: file path
|
|
// type: string
|
|
// required: true
|
|
// - name: line
|
|
// in: query
|
|
// description: line number (0-indexed)
|
|
// type: integer
|
|
// required: true
|
|
// - name: character
|
|
// in: query
|
|
// description: character position (0-indexed)
|
|
// type: integer
|
|
// required: true
|
|
// - name: ref
|
|
// in: query
|
|
// description: git ref (commit SHA, branch, tag)
|
|
// type: string
|
|
// required: true
|
|
// responses:
|
|
// "200":
|
|
// description: definition locations
|
|
// "400":
|
|
// "$ref": "#/responses/error"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
// "503":
|
|
// description: Sourcegraph integration not available
|
|
|
|
if !setting.Sourcegraph.Enabled {
|
|
ctx.APIError(http.StatusServiceUnavailable, "Sourcegraph integration is not enabled")
|
|
return
|
|
}
|
|
|
|
path := ctx.FormString("path")
|
|
line := ctx.FormInt("line")
|
|
char := ctx.FormInt("character")
|
|
ref := ctx.FormString("ref")
|
|
|
|
if path == "" || ref == "" {
|
|
ctx.APIError(http.StatusBadRequest, "path and ref are required")
|
|
return
|
|
}
|
|
|
|
client := sourcegraph_service.GetClient()
|
|
if client == nil {
|
|
ctx.APIError(http.StatusServiceUnavailable, "Sourcegraph client not initialized")
|
|
return
|
|
}
|
|
|
|
result, err := client.Definition(ctx, sourcegraphRepoName(ctx), ref, path, line, char)
|
|
if err != nil {
|
|
ctx.APIError(http.StatusBadGateway, err)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
result = []sourcegraph_service.Location{}
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// SourcegraphReferences returns reference locations for a symbol
|
|
func SourcegraphReferences(ctx *context.APIContext) {
|
|
// swagger:operation GET /repos/{owner}/{repo}/sourcegraph/references repository repoSourcegraphReferences
|
|
// ---
|
|
// summary: Get code intelligence reference locations
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: path
|
|
// in: query
|
|
// description: file path
|
|
// type: string
|
|
// required: true
|
|
// - name: line
|
|
// in: query
|
|
// description: line number (0-indexed)
|
|
// type: integer
|
|
// required: true
|
|
// - name: character
|
|
// in: query
|
|
// description: character position (0-indexed)
|
|
// type: integer
|
|
// required: true
|
|
// - name: ref
|
|
// in: query
|
|
// description: git ref (commit SHA, branch, tag)
|
|
// type: string
|
|
// required: true
|
|
// responses:
|
|
// "200":
|
|
// description: reference locations
|
|
// "400":
|
|
// "$ref": "#/responses/error"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
// "503":
|
|
// description: Sourcegraph integration not available
|
|
|
|
if !setting.Sourcegraph.Enabled {
|
|
ctx.APIError(http.StatusServiceUnavailable, "Sourcegraph integration is not enabled")
|
|
return
|
|
}
|
|
|
|
path := ctx.FormString("path")
|
|
line := ctx.FormInt("line")
|
|
char := ctx.FormInt("character")
|
|
ref := ctx.FormString("ref")
|
|
|
|
if path == "" || ref == "" {
|
|
ctx.APIError(http.StatusBadRequest, "path and ref are required")
|
|
return
|
|
}
|
|
|
|
client := sourcegraph_service.GetClient()
|
|
if client == nil {
|
|
ctx.APIError(http.StatusServiceUnavailable, "Sourcegraph client not initialized")
|
|
return
|
|
}
|
|
|
|
result, err := client.References(ctx, sourcegraphRepoName(ctx), ref, path, line, char)
|
|
if err != nil {
|
|
ctx.APIError(http.StatusBadGateway, err)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
result = []sourcegraph_service.Location{}
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, result)
|
|
}
|