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)
	}
}
Beispiel #2
0
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
}
Beispiel #4
0
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)
}
Beispiel #5
0
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
}
Beispiel #7
0
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
		}
	}
}
Beispiel #8
0
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
}
Beispiel #9
0
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
}
Beispiel #10
0
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
}
Beispiel #11
0
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
	}
}