github.com/nevalang/neva@v0.23.1-0.20240507185603-7696a9bb8dda/cmd/lsp/server/get_file_view.go (about) 1 package server 2 3 import ( 4 "errors" 5 "strings" 6 7 src "github.com/nevalang/neva/internal/compiler/sourcecode" 8 "github.com/tliron/glsp" 9 ) 10 11 type GetFileViewRequest struct { 12 WorkspaceURI URI `json:"workspaceUri"` 13 Document struct { 14 URI URI `json:"uri"` 15 FileName string `json:"fileName"` 16 } `json:"document"` 17 } 18 19 type URI struct { 20 Path string `json:"path"` 21 FSPath string `json:"fsPath"` 22 } 23 24 type GetFileViewResponce struct { 25 File src.File `json:"file"` 26 Extra Extra `json:"extra"` // info that is not presented in the file but needed for rendering 27 } 28 29 type Extra struct { 30 NodesPorts map[string]map[string]src.Interface `json:"nodesPorts"` // components -> nodes -> interface 31 } 32 33 func (s *Server) GetFileView(glspCtx *glsp.Context, req GetFileViewRequest) (GetFileViewResponce, error) { 34 if s.index == nil { 35 return GetFileViewResponce{}, nil 36 } 37 38 relFilePath := strings.TrimPrefix(req.Document.FileName, req.WorkspaceURI.Path) 39 relFilePath = strings.TrimPrefix(relFilePath, "/") 40 41 relPathParts := strings.Split(relFilePath, "/") // relative path to file in slice 42 relPathLastPart := relPathParts[len(relPathParts)-1] // file name with extension 43 relPartsWithoutFile := relPathParts[:len(relPathParts)-1] // relative path to package 44 45 pkgName := strings.Join(relPartsWithoutFile, "/") 46 fileName := strings.TrimSuffix(relPathLastPart, ".neva") 47 48 scope := src.Scope{ 49 Location: src.Location{ 50 ModRef: s.index.EntryModRef, 51 PkgName: pkgName, 52 FileName: fileName, 53 }, 54 Build: *s.index, 55 } 56 57 pkg, ok := s.index.Modules[s.index.EntryModRef].Packages[pkgName] 58 if !ok { 59 return GetFileViewResponce{}, errors.New("no such package: " + pkgName) 60 } 61 62 file, ok := pkg[fileName] 63 if !ok { 64 return GetFileViewResponce{}, errors.New("no such file: " + fileName + "." + pkgName) 65 } 66 67 extra, err := getExtraForFile(file, scope) 68 if err != nil { 69 return GetFileViewResponce{}, err 70 } 71 72 return GetFileViewResponce{ 73 File: file, 74 Extra: Extra{ 75 NodesPorts: extra, 76 }, 77 }, nil 78 } 79 80 func getExtraForFile(file src.File, scope src.Scope) (map[string]map[string]src.Interface, error) { 81 extra := map[string]map[string]src.Interface{} 82 for entityName, entity := range file.Entities { 83 if entity.Kind != src.ComponentEntity { 84 continue 85 } 86 87 nodesIfaces := map[string]src.Interface{} 88 for nodeName, node := range entity.Component.Nodes { 89 nodeEntity, _, err := scope.Entity(node.EntityRef) 90 if err != nil { 91 return nil, err 92 } 93 94 var iface src.Interface 95 if nodeEntity.Kind == src.ComponentEntity { 96 iface = nodeEntity.Component.Interface 97 } else if nodeEntity.Kind == src.InterfaceEntity { 98 iface = nodeEntity.Interface 99 } 100 101 nodesIfaces[nodeName] = iface 102 } 103 104 extra[entityName] = nodesIfaces 105 } 106 107 return extra, nil 108 }