func (t *TranslationUnitCache) reparse(w workunit) { if tu := t.parse(w); tu != nil { tu.Lock() defer tu.Unlock() log4go.Debug("Reparsing %s", w.filename) tu.Reparse(nil, 0) log4go.Debug("Reparsing %s done", w.filename) } }
func RunClang(stdin string, args ...string) ([]byte, []byte, error) { cmd := exec.Command("clang", args...) log4go.Debug("Running clang command: %v", cmd) if in, err := cmd.StdinPipe(); err != nil { return nil, nil, err } else if e, err := cmd.StderrPipe(); err != nil { return nil, nil, err } else if s, err := cmd.StdoutPipe(); err != nil { return nil, nil, err } else if err := cmd.Start(); err != nil { return nil, nil, err } else { in.Write([]byte(stdin)) in.Close() so, serr := ioutil.ReadAll(s) eo, eerr := ioutil.ReadAll(e) // We ignore the output error here as a non-zero exit // code doesn't necessarily mean that the output isn't // useful cmd.Wait() log4go.Fine("stdout: %s\n", string(so)) log4go.Fine("stderr: %s\n", string(eo)) if serr != nil { return so, eo, serr } else if eerr != nil { return so, eo, eerr } return so, eo, nil } }
func (t *TranslationUnitCache) parse(w workunit) (ret *LockedTranslationUnit) { // TODO(q): SublimeClang marked the file as "busy". Is that needed? defer func() { t.Lock() defer t.Unlock() t.parsing[w.filename] = false // TODO(q): Is on_done really needed? if w.on_done != nil { w.on_done() } }() log4go.Debug("Parsing %s", w.filename) ret = t.GetTranslationUnit(w.filename, w.options, w.options_script, nil) log4go.Debug("Parsing %s done", w.filename) return ret }
func (c *Net) Complete(args *content.CompleteArgs, cmp *content.CompletionResult) error { cache, err := c.cache(&args.Args) if err != nil { return err } log4go.Debug("Trying to complete: %s", args.Location) return c.complete(cache, &content.Type{Name: args.Location}, cmp) }
func (c *Net) cache(args *content.Args) (*Cache, error) { var cache *Cache session := args.SessionOrCreate(".internal.net.default") if a, ok := session.Get("net_cache").(*Cache); ok { cache = a } if cache == nil { log4go.Debug("cache is nil..") paths := DefaultPaths() c := Cache{paths: paths} std := []string{"mscorlib.dll", "System.dll"} for _, lib := range std { asm, err := c.Load(lib) if err != nil { return nil, err } log4go.Debug("Found %s (%s)", lib, asm.Name()) } cache = &c session.Set("net_cache", cache) } s := args.Settings() if v, ok := s.Get("net_paths").([]string); ok { for _, p := range v { cache.AddPath(p) } } if v, ok := s.Get("net_assemblies").([]string); ok { for _, lib := range v { asm, err := cache.Load(lib) if err != nil { return nil, err } log4go.Debug("Found %s (%s)", lib, asm.Name()) } } return cache, nil }
func (t *TranslationUnitCache) GetTranslationUnit(filename string, options []string, options_script string, unsaved_files map[string]string) *LockedTranslationUnit { t.Lock() tu, ok := t.lut[filename] if !ok { t.Unlock() // TODO(q): SublimeClang executed opts_script here args := make([]string, len(options)) for i := range options { args[i] = expand_path.ExpandPath(options[i]) } log4go.Debug("Will compile file %s with the following options:\n%v", filename, options) if tu2 := t.index.Parse(filename, options, unsaved_files, index_parse_options); true || tu2.IsValid() { tu = &LockedTranslationUnit{} tu.TranslationUnit = tu2 tu.opts = options tu.opts_script = options_script t.Lock() defer t.Unlock() t.lut[filename] = tu } else { log4go.Warn("Failed to compile %s, %v", filename, tu2) } return tu } recompile := !reflect.DeepEqual(tu.opts, options) || tu.opts_script != options_script if recompile { // TODO: need to dispose the tu.. Who's responsible for its disposal? delete(t.lut, filename) } t.Unlock() if recompile { log4go.Debug("Options change detected. Will recompile %s", filename) t.addEx(workunit{filename, options, options_script, nil}) } return tu }
func (d *Daemon) handleConn(conn net.Conn) { s := time.Now() conn.SetDeadline(time.Time{}) codec := jsonrpc.NewServerCodec(conn) defer func() { codec.Close() if r := recover(); r != nil { log4go.Error("Recovered from panic: %v, stack: %s", r, string(debug.Stack())) } log4go.Debug("Serviced in %f milliseconds", time.Since(s).Seconds()*1000) }() for { if err := d.server.ServeRequest(codec); err != nil { log4go.Error("Error handling request: %v", err) break } } }
func NewDWARFHelper(id string, r io.ReaderAt) (*DWARFHelper, error) { // TODO: detect file format.. f, err := macho.NewFile(r) if err != nil { return nil, err } defer f.Close() df, err := f.DWARF() if err != nil { for i := range f.Sections { log4go.Debug(f.Sections[i]) } return nil, err } var ret DWARFHelper ret.df = df ret.id = id return &ret, nil }
func (a *Assembly) Types() (types []content.Type, err error) { var ( idx = ConcreteTableIndex{&a.MetadataUtil, 0, id_TypeDef} ) for i := uint32(0); i < a.Tables[id_TypeDef].Rows; i++ { idx.index = 1 + i rawtype, err := idx.Data() if err != nil { return nil, err } var ( tr = rawtype.(*TypeDefRow) ) tc := ToContentType(tr) if err := check(&tc, tc.Name); err != nil { log4go.Debug("Skipping type %v, %s", tc, err) continue } types = append(types, tc) } return }
func (d *Daemon) serverloop() error { errorcount := 0 sigchan := make(chan os.Signal) conchan := make(chan net.Conn) errchan := make(chan error) signal.Notify(sigchan, os.Interrupt, os.Kill) go func() { for { if conn, err := d.l.Accept(); err != nil { if d.quit { return } errchan <- log4go.Error("Error accepting connection: %s", err) } else { conchan <- conn } } }() outer: for { select { case s := <-sigchan: log4go.Debug("Exiting due to signal: %s", s) d.quit = true break outer case conn := <-conchan: go d.handleConn(conn) case <-errchan: errorcount++ if errorcount > 10 { return log4go.Error("Too many errors, shutting server down") } } } return nil }
func (c *Net) CompleteAt(args *content.CompleteAtArgs, cmp *content.CompletionResult) error { cache, err := c.cache(&args.Args) if err != nil { return err } if err := args.Location.File.Load(); err != nil { return err } off := args.Location.Offset() off_ := int(off) contents := args.Location.File.Contents var up csharp.CSHARP up.SetData(contents) if !up.UsingDirectives() { return up.Error() } using := up.RootNode() var code csharp.CSHARP code.SetData(contents) code.Code() code.Namespace() namespace := "" for _, ns := range code.RootNode().Children { if ns.Name == "Namespace" && ns.Range.A <= off_ && off_ < ns.Range.B { namespace = ns.Children[0].Data() break } } if len(namespace) == 0 { log4go.Debug("Couldn't find namespace") } var p csharp.CSHARP line := args.Location.File.Line(off) line = line[:args.Location.Column-1] p.SetData(line) if !p.Complete() { return fmt.Errorf("%s, %s, %s", line, p.Error(), p.RootNode()) } r := p.RootNode() r.Simplify() var td *TypeDef var complete func(node *parser.Node) error var ns string complete = func(node *parser.Node) error { if node.Name != "CompleteOp" { return fmt.Errorf("Don't know how to complete %s", node) } n := len(node.Children) if n < 2 { return fmt.Errorf("Not enough children in Op node: %d < 2: %s", n, node) } if op := node.Children[1].Data(); op != "." { if n < 3 { return fmt.Errorf("Not enough children in Op node: %d < 3: %s", n, node) } td = nil return complete(node.Children[2]) } if td == nil { tn := ns + node.Children[0].Data() if td = findtype(cache, namespace, using, tn); td == nil { ns = tn + "." } } else if t2, err := typeresolve(td, node.Children[0]); err != nil { return err } else if td, err = cache.FindType(t2.Name); err != nil { return err } else if td == nil { return fmt.Errorf("Couldn't find type: %s", node.Children[0]) } if td == nil { // Probably a variable completion then? v := c.variable(node.Children[0]) data := scopes.Substr(args.Location.File.Contents, scopes.Visibility(args.Location)) loc := content.File{Contents: data} re, err := regexp.Compile(fmt.Sprintf(`[=\(,;}\s](\w+(\s*\[\])*\s+)*%s[;\s=,)\[]`, v)) if err != nil { return err } idx := re.FindAllStringIndex(loc.Contents, -1) for _, i := range idx { // TODO: It's better at getting the right variable, but still not 100% correct line := loc.Contents[i[0]+1 : i[1]-1] var p csharp.CSHARP p.SetData(line) if !p.CompleteVariable() { continue } t := c.variable(p.RootNode()) if t == "" { continue } if td = findtype(cache, namespace, using, t); td != nil { break } // Internal class perhaps? var p2 csharp.CSHARP if !p2.Parse(loc.Contents) { continue } for _, t2 := range c.classes("", nil, p2.RootNode()) { if !strings.HasSuffix(t2, t) { continue } if td = findtype(cache, namespace, using, t2); td != nil { break } } if td != nil { break } } } if n > 2 { return complete(node.Children[2]) } else if td == nil { return tdnil } return c.complete(cache, &content.Type{Name: td.Name()}, cmp) } if err := complete(r.Children[0]); err == tdnil { return err } else { return err } }