Copyright 2011 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
This file implements export filtering of an AST.

package doc

import (
	
	
)
filterIdentList removes unexported names from list in place and returns the resulting list.
func ( []*ast.Ident) []*ast.Ident {
	 := 0
	for ,  := range  {
		if token.IsExported(.Name) {
			[] = 
			++
		}
	}
	return [0:]
}

var underscore = ast.NewIdent("_")

func ( *ast.CompositeLit,  Filter,  bool) {
	 := len(.Elts)
	.Elts = filterExprList(.Elts, , )
	if len(.Elts) <  {
		.Incomplete = true
	}
}

func ( []ast.Expr,  Filter,  bool) []ast.Expr {
	 := 0
	for ,  := range  {
		switch x := .(type) {
		case *ast.CompositeLit:
			filterCompositeLit(, , )
		case *ast.KeyValueExpr:
			if ,  := .Key.(*ast.Ident);  && !(.Name) {
				continue
			}
			if ,  := .Value.(*ast.CompositeLit);  {
				filterCompositeLit(, , )
			}
		}
		[] = 
		++
	}
	return [0:]
}
updateIdentList replaces all unexported identifiers with underscore and reports whether at least one exported name exists.
func ( []*ast.Ident) ( bool) {
	for ,  := range  {
		if token.IsExported(.Name) {
			 = true
		} else {
			[] = underscore
		}
	}
	return 
}
hasExportedName reports whether list contains any exported names.
func ( []*ast.Ident) bool {
	for ,  := range  {
		if .IsExported() {
			return true
		}
	}
	return false
}
removeErrorField removes anonymous fields named "error" from an interface. This is called when "error" has been determined to be a local name, not the predeclared type.
func ( *ast.InterfaceType) {
	 := .Methods.List // we know that ityp.Methods != nil
	 := 0
	for ,  := range  {
		 := true
anonymous field
			if ,  := baseTypeName(.Type);  == "error" {
				 = false
			}
		}
		if  {
			[] = 
			++
		}
	}
	if  < len() {
		.Incomplete = true
	}
	.Methods.List = [0:]
}
filterFieldList removes unexported fields (field names) from the field list in place and reports whether fields were removed. Anonymous fields are recorded with the parent type. filterType is called with the types of all remaining fields.
func ( *reader) ( *namedType,  *ast.FieldList,  *ast.InterfaceType) ( bool) {
	if  == nil {
		return
	}
	 := .List
	 := 0
	for ,  := range  {
		 := false
anonymous field
			 := .recordAnonymousField(, .Type)
			if token.IsExported() {
				 = true
possibly the predeclared error interface; keep it for now but remember this interface so that it can be fixed if error is also defined locally
				 = true
				.remember()
			}
		} else {
			.Names = filterIdentList(.Names)
			if len(.Names) <  {
				 = true
			}
			if len(.Names) > 0 {
				 = true
			}
		}
		if  {
			.filterType(nil, .Type)
			[] = 
			++
		}
	}
	if  < len() {
		 = true
	}
	.List = [0:]
	return
}
filterParamList applies filterType to each parameter type in fields.
func ( *reader) ( *ast.FieldList) {
	if  != nil {
		for ,  := range .List {
			.filterType(nil, .Type)
		}
	}
}
filterType strips any unexported struct fields or method types from typ in place. If fields (or methods) have been removed, the corresponding struct or interface type has the Incomplete field set to true.
func ( *reader) ( *namedType,  ast.Expr) {
	switch t := .(type) {
nothing to do
	case *ast.ParenExpr:
		.(nil, .X)
	case *ast.ArrayType:
		.(nil, .Elt)
	case *ast.StructType:
		if .filterFieldList(, .Fields, nil) {
			.Incomplete = true
		}
	case *ast.FuncType:
		.filterParamList(.Params)
		.filterParamList(.Results)
	case *ast.InterfaceType:
		if .filterFieldList(, .Methods, ) {
			.Incomplete = true
		}
	case *ast.MapType:
		.(nil, .Key)
		.(nil, .Value)
	case *ast.ChanType:
		.(nil, .Value)
	}
}

func ( *reader) ( ast.Spec) bool {
	switch s := .(type) {
always keep imports so we can collect them
If there are values declared on RHS, just replace the unexported identifiers on the LHS with underscore, so that it matches the sequence of expression on the RHS. Similarly, if there are no type and values, then this expression must be following an iota expression, where order matters.
			if updateIdentList(.Names) {
				.filterType(nil, .Type)
				return true
			}
		} else {
			.Names = filterIdentList(.Names)
			if len(.Names) > 0 {
				.filterType(nil, .Type)
				return true
			}
		}
	case *ast.TypeSpec:
		if  := .Name.Name; token.IsExported() {
			.filterType(.lookupType(.Name.Name), .Type)
			return true
special case: remember that error is declared locally
			.errorDecl = true
		}
	}
	return false
}
copyConstType returns a copy of typ with position pos. typ must be a valid constant type. In practice, only (possibly qualified) identifiers are possible.
func ( ast.Expr,  token.Pos) ast.Expr {
	switch typ := .(type) {
	case *ast.Ident:
		return &ast.Ident{Name: .Name, NamePos: }
	case *ast.SelectorExpr:
presumably a qualified identifier
			return &ast.SelectorExpr{
				Sel: ast.NewIdent(.Sel.Name),
				X:   &ast.Ident{Name: .Name, NamePos: },
			}
		}
	}
	return nil // shouldn't happen, but be conservative and don't panic
}

func ( *reader) ( []ast.Spec,  token.Token) []ast.Spec {
Propagate any type information that would get lost otherwise when unexported constants are filtered.
		var  ast.Expr
		for ,  := range  {
			 := .(*ast.ValueSpec)
provide current spec with an explicit type
				.Type = copyConstType(, .Pos())
			}
exported names are preserved so there's no need to propagate the type
				 = nil
			} else {
				 = .Type
			}
		}
	}

	 := 0
	for ,  := range  {
		if .filterSpec() {
			[] = 
			++
		}
	}
	return [0:]
}

func ( *reader) ( ast.Decl) bool {
	switch d := .(type) {
	case *ast.GenDecl:
		.Specs = .filterSpecList(.Specs, .Tok)
		return len(.Specs) > 0
ok to filter these methods early because any conflicting method will be filtered here, too - thus, removing these methods early will not lead to the false removal of possible conflicts
		return token.IsExported(.Name.Name)
	}
	return false
}
fileExports removes unexported declarations from src in place.
func ( *reader) ( *ast.File) {
	 := 0
	for ,  := range .Decls {
		if .filterDecl() {
			.Decls[] = 
			++
		}
	}
	.Decls = .Decls[0:]