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 } }