Copyright 2019 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.

package frontend

import (
	
)
A Section represents a collection of lines with a common prefix. The collection is itself divided into sections by prefix, forming a tree.
type Section struct {
	Prefix   string     // prefix for this section, or if Subs==nil, a single line
	Subs     []*Section // subsections
	NumLines int        // total number of lines in subsections
}

func ( string) *Section {
	return &Section{Prefix: , NumLines: 0}
}

func ( *Section) ( *Section) {
	.Subs = append(.Subs, )
	if .Subs == nil {
		.NumLines++
	} else {
		.NumLines += .NumLines
	}
}
A prefixFunc returns the next prefix of s, given the current prefix. It should return the empty string if there are no more prefixes.
type prefixFunc func(s, prefix string) string
Sections transforms a list of lines, which must be sorted, into a list of Sections. Each Section in the result contains all the contiguous lines with the same prefix. The nextPrefix function is responsible for extracting prefixes from lines.
func ( []string,  prefixFunc) []*Section {
	,  := section("", , )
	return .Subs
}
section collects all lines with the same prefix into a section. It assumes that lines is sorted. It returns the section along with the remaining lines.
func ( string,  []string,  prefixFunc) (*Section, []string) {
	 := newSection()
	for len() > 0 {
		 := [0]
		if !strings.HasPrefix(, ) {
			break
		}

		 := (, )
		var  *Section
		if  == "" {
			 = newSection()
			 = [1:]
		} else {
			,  = (, , )
		}
		.add()
Collapse a section with a single subsection, except at top level.
	if len(.Subs) == 1 &&  != "" {
		 = .Subs[0]
	}
	return , 
}
nextPrefixAccount is a prefixFunc (see above). Its first argument is an import path, and its second is the previous prefix that it returned for that path, or "" if this is the first prefix. nextPrefixAccount tries to return an initial prefix for path that consists of the "account": the entity controlling the remainder of the path. In the most common case, paths beginning with "github.com", the account is the second path element, the GitHub user or org. So for example, the first prefix of "github.com/google/go-cmp/cmp" is "github.com/google/". nextPrefixAccount returns a second prefix that is one path element past the account. For github.com paths, this is the repo. Continuing the above example, the second prefix is "github.com/google/go-cmp/". nextPrefixAccount does not return any prefixes beyond those two.
If the last prefix consisted of the entire path, then there is no next prefix.
	if  ==  {
		return ""
	}
	 := strings.Split(, "/")
	,  := accountPrefix()
	if  == "" {
		return 
	}
Second prefix: one element past the first. The +1 is safe because we know that pre is shorter than path from the first test of the function.
		 := strings.Join([:len()+1], "/")
		if  !=  {
			 += "/"
		}
		return 
No more prefixes after the first two.
	return ""
}
accountPrefix guesses the prefix of the path (split into parts at "/") that corresponds to the account.
TODO(jba): handle repo import paths like "example.org/foo/bar.hg".
The first two cases below handle the special cases that the go command does. See "go help importpath".
	switch [0] {
	case "github.com", "bitbucket.org", "launchpad.net", "golang.org":
		 = 1
	case "hub.jazz.net":
		 = 2
For custom import paths, use the host as the first prefix.
		 = 0
	}
	if  >= len()-1 {
		return strings.Join(, "/"), 
	}
	return strings.Join([:+1], "/") + "/", [:+1]