Exemple #1
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
	}
}