Exemplo n.º 1
0
// specValues returns the list of initialization expressions
// for the given part (spec) of a constant declaration.
// TODO(gri) Make this more efficient by caching results
// (using a map in checker).
func (check *checker) specValues(spec *ast.ValueSpec) []ast.Expr {
	if len(spec.Values) > 0 {
		return spec.Values
	}

	// find the corresponding values
	for _, file := range check.pkg.Files {
		for _, d := range file.Decls {
			if d, ok := d.(*ast.GenDecl); ok && d.Tok == token.CONST {
				var values []ast.Expr
				for _, s := range d.Specs {
					if s, ok := s.(*ast.ValueSpec); ok {
						if len(s.Values) > 0 {
							values = s.Values
						}
						if s == spec {
							return values
						}
					}
				}
			}
		}
	}

	check.invalidAST(spec.Pos(), "no initialization values provided")
	return nil
}
Exemplo n.º 2
0
// arityMatch checks that the lhs and rhs of a const or var decl
// have the appropriate number of names and init exprs. For const
// decls, init is the value spec providing the init exprs; for
// var decls, init is nil (the init exprs are in s in this case).
func (check *checker) arityMatch(s, init *ast.ValueSpec) {
	l := len(s.Names)
	r := len(s.Values)
	if init != nil {
		r = len(init.Values)
	}

	switch {
	case init == nil && r == 0:
		// var decl w/o init expr
		if s.Type == nil {
			check.errorf(s.Pos(), "missing type or init expr")
		}
	case l < r:
		if l < len(s.Values) {
			// init exprs from s
			n := s.Values[l]
			check.errorf(n.Pos(), "extra init expr %s", n)
		} else {
			// init exprs "inherited"
			check.errorf(s.Pos(), "extra init expr at %s", init.Pos())
		}
	case l > r && (init != nil || r != 1):
		n := s.Names[r]
		check.errorf(n.Pos(), "missing init expr for %s", n)
	}
}