func BenchmarkFindtype(b *testing.B) { var ( n Net args content.CompleteAtArgs ) args.Location.File.Name = "./testdata/CompleteSharp.cs" args.Location.File.Load() args.Location.Line = 95 args.Location.Column = 45 cache, _ := n.cache(&args.Args) var up csharp.CSHARP up.SetData(args.Location.File.Contents) if !up.UsingDirectives() { b.Fatal(up.Error()) } using := up.RootNode() for i := 0; i < b.N; i++ { findtype(cache, using, "string") } }
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 } contents := args.Location.File.Contents var up csharp.CSHARP up.SetData(contents) if !up.UsingDirectives() { return up.Error() } using := up.RootNode() var p csharp.CSHARP off := args.Location.Offset() 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 { switch n := node.Name; n { case "CompleteOp": n := len(node.Children) if n < 2 { return fmt.Errorf("Not enough children in Op node: %d < 2: %s", n, node) } switch op := node.Children[1].Data(); op { case ".": if td == nil { tn := ns + node.Children[0].Data() if td = findtype(cache, 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]) loc := content.File{Contents: scopes.Substr(args.Location.File.Contents, scopes.Visibility(args.Location))} if re, err := regexp.Compile(fmt.Sprintf(`[=\(,;}\s](\w+(\s*\[\])*\s+)*%s[;\s=,)\[]`, v)); err != nil { return err } else { 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() { if t := c.variable(p.RootNode()); t != "" { if td = findtype(cache, using, t); td != nil { break } else { // Internal class perhaps? var p csharp.CSHARP if p.Parse(loc.Contents) { for _, t2 := range c.classes("", nil, p.RootNode()) { if !strings.HasSuffix(t2, t) { continue } if td = findtype(cache, 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) default: if n < 3 { return fmt.Errorf("Not enough children in Op node: %d < 3: %s", n, node) } td = nil return complete(node.Children[2]) } default: return fmt.Errorf("Don't know how to complete %s", node) } return nil } if err := complete(r.Children[0]); err == tdnil { return err } else { return err } }