[gnome-code-assistance] [backends/go] Fix for new architecture
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-code-assistance] [backends/go] Fix for new architecture
- Date: Mon, 11 Nov 2013 16:07:50 +0000 (UTC)
commit 9cda0d97c416a8c9e0547b6c36bf04673596d900
Author: Jesse van den Kieboom <jessevdk gmail com>
Date: Mon Nov 11 14:56:17 2013 +0100
[backends/go] Fix for new architecture
backends/go/app.go | 56 ---------
backends/go/dbus.go | 108 ++++++++++++++++
backends/go/diagnostic.go | 57 ---------
backends/go/diagnostic_dbus.go | 35 -----
backends/go/document.go | 36 ------
backends/go/document_dbus.go | 45 -------
backends/go/server_dbus.go | 268 ++++++++++++++++++++++++++++++++++++++++
backends/go/service.go | 103 ++++++++++++++--
backends/go/service_dbus.go | 237 -----------------------------------
backends/go/transport_dbus.go | 23 +++-
10 files changed, 487 insertions(+), 481 deletions(-)
---
diff --git a/backends/go/dbus.go b/backends/go/dbus.go
new file mode 100644
index 0000000..c5d429d
--- /dev/null
+++ b/backends/go/dbus.go
@@ -0,0 +1,108 @@
+package main
+
+import (
+ "github.com/guelfey/go.dbus"
+ "github.com/guelfey/go.dbus/introspect"
+)
+
+type ServiceDbus struct {
+ Server *ServerDbus
+}
+
+type DocumentDbus struct {
+ Document *Document
+}
+
+type OpenDocument struct {
+ Path string
+ DataPath string
+}
+
+type RemoteDocument struct {
+ Path string
+ ObjectPath dbus.ObjectPath
+}
+
+func (s *ServiceDbus) Introspect() *introspect.Node {
+ n := &introspect.Node{
+ Interfaces: []introspect.Interface{
+ {
+ Name: "org.gnome.CodeAssist.Service",
+ Methods: []introspect.Method{
+ {
+ Name: "Parse",
+ Args: []introspect.Arg{
+ {"path", "s", "in"},
+ {"cursor", "x", "in"},
+ {"data_path", "s", "in"},
+ {"options", "a{sv}", "in"},
+ {"result", "o", "out"},
+ },
+ },
+ {
+ Name: "Dispose",
+ Args: []introspect.Arg{
+ {"path", "s", "in"},
+ },
+ },
+ },
+ },
+
+ introspect.Interface{
+ Name: "org.gnome.CodeAssist.Project",
+ Methods: []introspect.Method{
+ {
+ Name: "ParseAll",
+ Args: []introspect.Arg{
+ {"path", "s", "in"},
+ {"cursor", "x", "in"},
+ {"documents", "a(ss)", "in"},
+ {"options", "a{sv}", "in"},
+ {"result", "a(so)", "out"},
+ },
+ },
+ },
+ },
+ },
+ }
+
+ return n
+}
+
+func (d *DocumentDbus) Introspect() *introspect.Node {
+ return &introspect.Node{
+ Interfaces: []introspect.Interface{
+ introspect.Interface{
+ Name: "org.gnome.CodeAssist.Document",
+ },
+
+ introspect.Interface{
+ Name: "org.gnome.CodeAssist.Diagnostics",
+ Methods: []introspect.Method{
+ {
+ Name: "Diagnostics",
+ Args: []introspect.Arg{
+ {"result", "a(ua((x(xx)(xx))s)a(x(xx)(xx))s)", "out"},
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func (s *ServiceDbus) Parse(path string, cursor int64, dataPath string, options map[string]dbus.Variant,
sender dbus.Sender) (dbus.ObjectPath, *dbus.Error) {
+ return s.Server.Parse(string(sender), path, cursor, dataPath, options)
+}
+
+func (s *ServiceDbus) Dispose(path string, sender dbus.Sender) *dbus.Error {
+ return s.Server.Dispose(string(sender), path)
+}
+
+func (s *ServiceDbus) ParseAll(path string, cursor int64, documents []OpenDocument, options
map[string]dbus.Variant, sender dbus.Sender) ([]RemoteDocument, *dbus.Error) {
+ return s.Server.ParseAll(string(sender), path, cursor, documents, options)
+}
+
+func (d *DocumentDbus) Diagnostics() ([]Diagnostic, *dbus.Error) {
+ return d.Document.Diagnostics, nil
+}
diff --git a/backends/go/server_dbus.go b/backends/go/server_dbus.go
new file mode 100644
index 0000000..00624d0
--- /dev/null
+++ b/backends/go/server_dbus.go
@@ -0,0 +1,268 @@
+package main
+
+import (
+ "fmt"
+ "github.com/guelfey/go.dbus"
+ "os"
+ "path/filepath"
+ "sync"
+)
+
+type App struct {
+ id uint64
+ name string
+
+ docs map[string]*DocumentDbus
+
+ service *Service
+
+ nextid uint64
+ mutex sync.Mutex
+}
+
+type ServerDbus struct {
+ transport *TransportDbus
+ service *ServiceDbus
+ apps map[string]*App
+ nextid uint64
+ mutex sync.Mutex
+}
+
+func NewServerDbus(transport *TransportDbus) (*ServerDbus, error) {
+ ret := &ServerDbus{
+ transport: transport,
+ apps: make(map[string]*App),
+ }
+
+ ret.service = &ServiceDbus{
+ Server: ret,
+ }
+
+ transport.export(ret.service, ret.dbusPath())
+ transport.export(new(DocumentDbus), dbus.ObjectPath(fmt.Sprintf("%s/document", ret.dbusPath())))
+
+ go func() {
+ c := make(chan *dbus.Signal, 30)
+ transport.conn.Signal(c)
+
+ for v := range c {
+ if len(v.Body) != 3 {
+ continue
+ }
+
+ oldname := v.Body[1].(string)
+ newname := v.Body[2].(string)
+
+ if len(newname) != 0 {
+ continue
+ }
+
+ ret.mutex.Lock()
+ defer ret.mutex.Unlock()
+
+ if app := ret.apps[oldname]; app != nil {
+ app.mutex.Lock()
+ defer app.mutex.Unlock()
+
+ ret.disposeApp(app)
+ }
+ }
+ }()
+
+ transport.conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
+
"type='signal',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',sender='org.freedesktop.DBus',member='NameOwnerChanged'")
+
+ return ret, nil
+}
+
+func (s *ServerDbus) dbusPath() dbus.ObjectPath {
+ return "/org/gnome/CodeAssist/go"
+}
+
+func (s *ServerDbus) documentDbusPath(app *App, doc *DocumentDbus) dbus.ObjectPath {
+ return dbus.ObjectPath(fmt.Sprintf("%s/%v/documents/%v", s.dbusPath(), app.id, doc.Document.Id))
+}
+
+func (s *ServerDbus) makeApp(name string) *App {
+ app := &App{
+ id: s.nextid,
+ name: name,
+ docs: make(map[string]*DocumentDbus),
+ service: NewService(),
+ }
+
+ s.nextid++
+ s.apps[name] = app
+
+ return app
+}
+
+func (s *ServerDbus) ensureApp(name string) *App {
+ if app := s.apps[name]; app != nil {
+ return app
+ }
+
+ return s.makeApp(name)
+}
+
+func (s *ServerDbus) makeDocument(app *App, path string, clientPath string) *DocumentDbus {
+ doc := &Document{
+ Id: app.nextid,
+ Path: path,
+ ClientPath: clientPath,
+ }
+
+ ddoc := &DocumentDbus{
+ Document: doc,
+ }
+
+ s.transport.export(ddoc, s.documentDbusPath(app, ddoc))
+
+ app.nextid++
+ app.docs[path] = ddoc
+
+ return ddoc
+}
+
+func (s *ServerDbus) ensureDocument(app *App, path string, dataPath string, cursor int64) *DocumentDbus {
+ npath := filepath.Clean(path)
+
+ doc := app.docs[npath]
+
+ if doc == nil {
+ doc = s.makeDocument(app, npath, path)
+ }
+
+ doc.Document.DataPath = dataPath
+ doc.Document.Cursor = cursor
+
+ return doc
+}
+
+func (s *ServerDbus) parseOptions(options map[string]dbus.Variant) (Options, error) {
+ opts := make(map[string]interface{})
+
+ for k, v := range options {
+ opts[k] = v.Value()
+ }
+
+ var o Options
+ err := o.Parse(opts)
+
+ return o, err
+}
+
+func (s *ServerDbus) parse(appid string, path string, cursor int64, documents []OpenDocument, options
map[string]dbus.Variant) ([]RemoteDocument, *dbus.Error) {
+ s.mutex.Lock()
+ app := s.ensureApp(appid)
+ s.mutex.Unlock()
+
+ o, err := s.parseOptions(options)
+
+ if err != nil {
+ return nil, NewDbusError("InvalidOptions", "%v", err)
+ }
+
+ app.mutex.Lock()
+ doc := s.ensureDocument(app, path, "", cursor)
+
+ unsaved := make([]UnsavedDocument, 0, len(documents))
+
+ for _, d := range documents {
+ cpath := filepath.Clean(d.Path)
+
+ if len(d.DataPath) != 0 && d.DataPath != d.Path {
+ f, err := os.Open(d.DataPath)
+
+ if err != nil {
+ return nil, NewDbusError("ParseError", "%v", err)
+ }
+
+ defer f.Close()
+
+ unsaved = append(unsaved, UnsavedDocument{
+ Path: d.Path,
+ Data: f,
+ })
+ }
+
+ if doc := app.docs[cpath]; doc != nil {
+ doc.Document.DataPath = d.DataPath
+ }
+ }
+
+ app.mutex.Unlock()
+
+ if err := app.service.Parse(doc.Document, unsaved, o); err != nil {
+ return nil, NewDbusError("ParseError", "%v", err)
+ }
+
+ return []RemoteDocument{
+ {path, s.documentDbusPath(app, doc)},
+ }, nil
+}
+
+func (s *ServerDbus) Parse(appid string, path string, cursor int64, dataPath string, options
map[string]dbus.Variant) (dbus.ObjectPath, *dbus.Error) {
+ documents := []OpenDocument{
+ {path, dataPath},
+ }
+
+ ret, err := s.parse(appid, path, cursor, documents, options)
+
+ if err != nil {
+ return "", err
+ }
+
+ for _, v := range ret {
+ if v.Path == path {
+ return v.ObjectPath, nil
+ }
+ }
+
+ return "", nil
+}
+
+func (s *ServerDbus) ParseAll(appid string, path string, cursor int64, documents []OpenDocument, options
map[string]dbus.Variant) ([]RemoteDocument, *dbus.Error) {
+ return s.parse(appid, path, cursor, documents, options)
+}
+
+func (s *ServerDbus) disposeApp(app *App) {
+ for _, doc := range app.docs {
+ s.disposeDocument(app, doc)
+ }
+
+ app.docs = nil
+ delete(s.apps, app.name)
+
+ if len(s.apps) == 0 {
+ os.Exit(0)
+ }
+}
+
+func (s *ServerDbus) disposeDocument(app *App, doc *DocumentDbus) {
+ p := s.documentDbusPath(app, doc)
+ s.transport.unexport(doc, p)
+}
+
+func (s *ServerDbus) Dispose(appid string, path string) *dbus.Error {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ if app := s.apps[appid]; app != nil {
+ app.mutex.Lock()
+ defer app.mutex.Unlock()
+
+ cpath := filepath.Clean(path)
+
+ if doc := app.docs[cpath]; doc != nil {
+ s.disposeDocument(app, doc)
+ delete(app.docs, cpath)
+
+ if len(app.docs) == 0 {
+ s.disposeApp(app)
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/backends/go/service.go b/backends/go/service.go
index 24ed9a8..785ad15 100644
--- a/backends/go/service.go
+++ b/backends/go/service.go
@@ -1,5 +1,62 @@
package main
+import (
+ "io"
+ "sync"
+)
+
+type Severity uint32
+
+const (
+ SeverityNone Severity = iota
+ SeverityInfo
+ SeverityWarning
+ SeverityDeprecated
+ SeverityError
+ SeverityFatal
+)
+
+type SourceLocation struct {
+ Line int64
+ Column int64
+}
+
+type SourceRange struct {
+ File int64
+ Start SourceLocation
+ End SourceLocation
+}
+
+type UnsavedDocument struct {
+ Path string
+ Data io.ReadCloser
+}
+
+type Fixit struct {
+ Location SourceRange
+ Replacement string
+}
+
+type Diagnostic struct {
+ Severity Severity
+ Fixits []Fixit
+ Locations []SourceRange
+ Message string
+}
+
+type Document struct {
+ Id uint64
+ Path string
+ DataPath string
+ ClientPath string
+ Cursor int64
+
+ Diagnostics []Diagnostic
+
+ parsed *Parsed
+ mutex sync.Mutex
+}
+
type Service struct {
}
@@ -7,19 +64,49 @@ func NewService() *Service {
return &Service{}
}
-func (s *Service) Parse(path string, cursor int64, unsaved []UnsavedDocument, options Options, doc
*Document) (*Document, error) {
- parsed, err := TheParser.Parse(path, cursor, unsaved, options)
+func (d *Document) process(parsed *Parsed) error {
+ var diagnostics []Diagnostic
- if err != nil {
- return doc, err
+ if parsed != nil {
+ diagnostics = make([]Diagnostic, len(parsed.Errors))
+
+ for i, err := range parsed.Errors {
+ diagnostics[i] = Diagnostic{
+ Severity: SeverityError,
+ Locations: []SourceRange{
+ SourceRange{
+ Start: SourceLocation{
+ Line: int64(err.Pos.Line),
+ Column: int64(err.Pos.Column),
+ },
+ End: SourceLocation{
+ Line: int64(err.Pos.Line),
+ Column: int64(err.Pos.Column),
+ },
+ },
+ },
+ Message: err.Msg,
+ Fixits: []Fixit{},
+ }
+ }
}
- if doc == nil {
- doc = NewDocument(path)
+ d.mutex.Lock()
+ d.parsed = parsed
+ d.Diagnostics = diagnostics
+ d.mutex.Unlock()
+
+ return nil
+}
+
+func (s *Service) Parse(doc *Document, unsaved []UnsavedDocument, options Options) error {
+ parsed, err := TheParser.Parse(doc.Path, doc.Cursor, unsaved, options)
+
+ if err != nil {
+ return err
}
- doc.parsed = parsed
- return doc, nil
+ return doc.process(parsed)
}
func (s *Service) Dispose(doc *Document) error {
diff --git a/backends/go/transport_dbus.go b/backends/go/transport_dbus.go
index be7e339..938d1f2 100644
--- a/backends/go/transport_dbus.go
+++ b/backends/go/transport_dbus.go
@@ -8,13 +8,12 @@ import (
)
type TransportDbus struct {
- conn *dbus.Conn
- service *ServiceDbus
+ conn *dbus.Conn
+ server *ServerDbus
}
type ObjectDbus interface {
Introspect() *introspect.Node
- Path() dbus.ObjectPath
}
func NewDbusError(name string, format string, args ...interface{}) *dbus.Error {
@@ -26,9 +25,18 @@ func NewDbusError(name string, format string, args ...interface{}) *dbus.Error {
}
}
-func (t *TransportDbus) export(obj ObjectDbus) error {
+func (t *TransportDbus) unexport(obj ObjectDbus, p dbus.ObjectPath) {
+ n := obj.Introspect()
+
+ for _, i := range n.Interfaces {
+ t.conn.Unexport(p, i.Name)
+ }
+
+ t.conn.Unexport(p, "org.freedesktop.DBus.Introspectable")
+}
+
+func (t *TransportDbus) export(obj ObjectDbus, p dbus.ObjectPath) error {
n := obj.Introspect()
- p := obj.Path()
for _, i := range n.Interfaces {
if err := t.conn.Export(obj, p, i.Name); err != nil {
@@ -64,12 +72,13 @@ func NewTransportDbus() (Transport, error) {
conn: conn,
}
- t.service = NewServiceDbus(t)
+ server, err := NewServerDbus(t)
- if err := t.export(t.service); err != nil {
+ if err != nil {
return nil, err
}
+ t.server = server
return t, nil
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]