// Copyright 2015 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.// TODO(gri): This file and the file src/cmd/gofmt/internal.go are// the same (but for this comment and the package name). Do not modify// one without the other. Determine if we can factor out functionality// in a public API. See also #11844 for context.package formatimport ()// parse parses src, which was read from the named file,// as a Go source file, declaration, or statement list.func parse( *token.FileSet, string, []byte, bool) ( *ast.File,func( []byte, int) []byte,int,error,) {// Try as whole source file. , = parser.ParseFile(, , , parserMode)// If there's no error, return. If the error is that the source file didn't begin with a // package line and source fragments are ok, fall through to // try as a source fragment. Stop and return on any other error.if == nil || ! || !strings.Contains(.Error(), "expected 'package'") {return }// If this is a declaration list, make it a source file // by inserting a package clause. // Insert using a ';', not a newline, so that the line numbers // in psrc match the ones in src. := append([]byte("package p;"), ...) , = parser.ParseFile(, , , parserMode)if == nil { = func( []byte, int) []byte {// Remove the package clause. // Gofmt has turned the ';' into a '\n'. = [+len("package p\n"):]returnbytes.TrimSpace() }return }// If the error is that the source file didn't begin with a // declaration, fall through to try as a statement list. // Stop and return on any other error.if !strings.Contains(.Error(), "expected declaration") {return }// If this is a statement list, make it a source file // by inserting a package clause and turning the list // into a function body. This handles expressions too. // Insert using a ';', not a newline, so that the line numbers // in fsrc match the ones in src. Add an extra '\n' before the '}' // to make sure comments are flushed before the '}'. := append(append([]byte("package p; func _() {"), ...), '\n', '\n', '}') , = parser.ParseFile(, , , parserMode)if == nil { = func( []byte, int) []byte {// Cap adjusted indent to zero.if < 0 { = 0 }// Remove the wrapping. // Gofmt has turned the "; " into a "\n\n". // There will be two non-blank lines with indent, hence 2*indent. = [2*+len("package p\n\nfunc _() {"):]// Remove only the "}\n" suffix: remaining whitespaces will be trimmed anyway = [:len()-len("}\n")]returnbytes.TrimSpace() }// Gofmt has also indented the function body one level. // Adjust that with indentAdj. = -1 }// Succeeded, or out of options.return}// format formats the given package file originally obtained from src// and adjusts the result based on the original source via sourceAdj// and indentAdj.func format( *token.FileSet, *ast.File,func( []byte, int) []byte,int, []byte,printer.Config,) ([]byte, error) {if == nil {// Complete source file.varbytes.Buffer := .Fprint(&, , )if != nil {returnnil, }return .Bytes(), nil }// Partial source file. // Determine and prepend leading space. , := 0, 0for < len() && isSpace([]) {if [] == '\n' { = + 1// byte offset of last line in leading space } ++ }var []byte = append(, [:]...)// Determine and prepend indentation of first code line. // Spaces are ignored unless there are no tabs, // in which case spaces count as one tab. := 0 := falsefor , := range [:] {switch {case' ': = truecase'\t': ++ } }if == 0 && { = 1 }for := 0; < ; ++ { = append(, '\t') }// Format the source. // Write it without any leading and trailing space. .Indent = + varbytes.Buffer := .Fprint(&, , )if != nil {returnnil, } := (.Bytes(), .Indent)// If the adjusted output is empty, the source // was empty but (possibly) for white space. // The result is the incoming source.iflen() == 0 {return , nil }// Otherwise, append output to leading space. = append(, ...)// Determine and append trailing space. = len()for > 0 && isSpace([-1]) { -- }returnappend(, [:]...), nil}// isSpace reports whether the byte is a space character.// isSpace defines a space as being among the following bytes: ' ', '\t', '\n' and '\r'.func isSpace( byte) bool {return == ' ' || == '\t' || == '\n' || == '\r'}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.