var underscore = ast.NewIdent("_")
+func filterCompositeLit(lit *ast.CompositeLit, filter Filter, export bool) {
+ n := len(lit.Elts)
+ lit.Elts = filterExprList(lit.Elts, filter, export)
+ if len(lit.Elts) < n {
+ lit.Incomplete = true
+ }
+}
+
+func filterExprList(list []ast.Expr, filter Filter, export bool) []ast.Expr {
+ j := 0
+ for _, exp := range list {
+ switch x := exp.(type) {
+ case *ast.CompositeLit:
+ filterCompositeLit(x, filter, export)
+ case *ast.KeyValueExpr:
+ if x, ok := x.Key.(*ast.Ident); ok && !filter(x.Name) {
+ continue
+ }
+ if x, ok := x.Value.(*ast.CompositeLit); ok {
+ filterCompositeLit(x, filter, export)
+ }
+ }
+ list[j] = exp
+ j++
+ }
+ return list[0:j]
+}
+
// updateIdentList replaces all unexported identifiers with underscore
// and reports whether at least one exported name exists.
func updateIdentList(list []*ast.Ident) (hasExported bool) {
// always keep imports so we can collect them
return true
case *ast.ValueSpec:
+ s.Values = filterExprList(s.Values, ast.IsExported, true)
if len(s.Values) > 0 || s.Type == nil && len(s.Values) == 0 {
// If there are values declared on RHS, just replace the unexported
// identifiers on the LHS with underscore, so that it matches
if !indent {
mode = noIndent
}
- p.exprList(token.NoPos, xlist, 1, mode, token.NoPos)
+ p.exprList(token.NoPos, xlist, 1, mode, token.NoPos, false)
}
+const filteredMsg = "contains filtered or unexported fields"
+
// Print a list of expressions. If the list spans multiple
// source lines, the original line breaks are respected between
// expressions.
// TODO(gri) Consider rewriting this to be independent of []ast.Expr
// so that we can use the algorithm for any kind of list
// (e.g., pass list via a channel over which to range).
-func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos) {
+func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos, isIncomplete bool) {
if len(list) == 0 {
+ if isIncomplete {
+ prev := p.posFor(prev0)
+ next := p.posFor(next0)
+ if prev.IsValid() && prev.Line == next.Line {
+ p.print("/* " + filteredMsg + " */")
+ } else {
+ p.print(newline)
+ p.print(indent, "// "+filteredMsg, unindent, newline)
+ }
+ }
return
}
}
p.expr0(x, depth)
}
+ if isIncomplete {
+ p.print(token.COMMA, blank, "/* "+filteredMsg+" */")
+ }
return
}
if mode&commaTerm != 0 && next.IsValid() && p.pos.Line < next.Line {
// Print a terminating comma if the next token is on a new line.
p.print(token.COMMA)
+ if isIncomplete {
+ p.print(newline)
+ p.print("// " + filteredMsg)
+ }
if ws == ignore && mode&noIndent == 0 {
// unindent if we indented
p.print(unindent)
return
}
+ if isIncomplete {
+ p.print(token.COMMA, newline)
+ p.print("// "+filteredMsg, newline)
+ }
+
if ws == ignore && mode&noIndent == 0 {
// unindent if we indented
p.print(unindent)
p.print(formfeed)
}
p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
- p.setLineComment("// contains filtered or unexported fields")
+ p.setLineComment("// " + filteredMsg)
}
} else { // interface
}
p.print(x.Lparen, token.LPAREN)
if x.Ellipsis.IsValid() {
- p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis)
+ p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis, false)
p.print(x.Ellipsis, token.ELLIPSIS)
if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) {
p.print(token.COMMA, formfeed)
}
} else {
- p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen)
+ p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen, false)
}
p.print(x.Rparen, token.RPAREN)
if wasIndented {
}
p.level++
p.print(x.Lbrace, token.LBRACE)
- p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace)
+ p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace, x.Incomplete)
// do not insert extra line break following a /*-style comment
// before the closing '}' as it might break the code if there
// is no trailing ','
if len(s.Lhs) > 1 && len(s.Rhs) > 1 {
depth++
}
- p.exprList(s.Pos(), s.Lhs, depth, 0, s.TokPos)
+ p.exprList(s.Pos(), s.Lhs, depth, 0, s.TokPos, false)
p.print(blank, s.TokPos, s.Tok, blank)
- p.exprList(s.TokPos, s.Rhs, depth, 0, token.NoPos)
+ p.exprList(s.TokPos, s.Rhs, depth, 0, token.NoPos, false)
case *ast.GoStmt:
p.print(token.GO, blank)
// lead to more nicely formatted code in general.
if p.indentList(s.Results) {
p.print(indent)
- p.exprList(s.Pos(), s.Results, 1, noIndent, token.NoPos)
+ p.exprList(s.Pos(), s.Results, 1, noIndent, token.NoPos, false)
p.print(unindent)
} else {
- p.exprList(s.Pos(), s.Results, 1, 0, token.NoPos)
+ p.exprList(s.Pos(), s.Results, 1, 0, token.NoPos, false)
}
}
case *ast.CaseClause:
if s.List != nil {
p.print(token.CASE, blank)
- p.exprList(s.Pos(), s.List, 1, 0, s.Colon)
+ p.exprList(s.Pos(), s.List, 1, 0, s.Colon, false)
} else {
p.print(token.DEFAULT)
}
}
if s.Values != nil {
p.print(vtab, token.ASSIGN, blank)
- p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos)
+ p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)
extraTabs--
}
if s.Comment != nil {
}
if s.Values != nil {
p.print(blank, token.ASSIGN, blank)
- p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos)
+ p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)
}
p.setComment(s.Comment)