github.com/lheiskan/zebrapack@v4.1.1-0.20181107023619-e955d028f9bf+incompatible/parse/noload.go (about)

     1  package parse
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/parser"
     7  	"go/token"
     8  
     9  	"github.com/glycerine/zebrapack/cfg"
    10  	"github.com/glycerine/zebrapack/gen"
    11  )
    12  
    13  // FileNoLoad parses a file at the relative path
    14  // provided and produces a new *FileSet.
    15  // If you pass in a path to a directory, the entire
    16  // directory will be parsed.
    17  // If unexport is false, only exported identifiers are included in the FileSet.
    18  // If the resulting FileSet would be empty, an error is returned.
    19  //
    20  // FileNoLoad(), in noload.go, is
    21  // the original msgp version of File()
    22  // that doesn't require full
    23  // compilability/avialability
    24  // of all dependencies. Although this
    25  // doesn't support resolution of
    26  // named constants like the loader
    27  // version does, this can be
    28  // useful when reading a partial
    29  // completed source file or otherwise
    30  // in a situation where it is
    31  // inconvient to have to meet
    32  // the compiler's demands just yet.
    33  //
    34  func FileNoLoad(c *cfg.ZebraConfig) (*FileSet, error) {
    35  	ok, isDir := fileOrDir(c.GoFile)
    36  	if !ok {
    37  		return nil, fmt.Errorf("error: path '%s' does not exist", c.GoFile)
    38  	}
    39  
    40  	name := c.GoFile
    41  	pushstate(name)
    42  	defer popstate()
    43  	fs := &FileSet{
    44  		Specs:      make(map[string]ast.Expr),
    45  		Identities: make(map[string]gen.Elem),
    46  		Cfg:        c,
    47  	}
    48  
    49  	fset := token.NewFileSet()
    50  	if isDir {
    51  		pkgs, err := parser.ParseDir(fset, name, nil, parser.ParseComments)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		if len(pkgs) != 1 {
    56  			return nil, fmt.Errorf("multiple packages in directory: %s", name)
    57  		}
    58  		var one *ast.Package
    59  		for _, nm := range pkgs {
    60  			one = nm
    61  			break
    62  		}
    63  		fs.Package = one.Name
    64  		for _, fl := range one.Files {
    65  			pushstate(fl.Name.Name)
    66  			fs.Directives = append(fs.Directives, yieldComments(fl.Comments)...)
    67  			fs.getZebraSchemaId(fl)
    68  			if !c.Unexported {
    69  				ast.FileExports(fl)
    70  			}
    71  			fs.getTypeSpecs(fl)
    72  			popstate()
    73  		}
    74  	} else {
    75  		f, err := parser.ParseFile(fset, name, nil, parser.ParseComments)
    76  		if err != nil {
    77  			return nil, err
    78  		}
    79  		fs.Package = f.Name.Name
    80  		fs.Directives = yieldComments(f.Comments)
    81  		fs.getZebraSchemaId(f)
    82  		if !c.Unexported {
    83  			ast.FileExports(f)
    84  		}
    85  		fs.getTypeSpecs(f)
    86  	}
    87  
    88  	if len(fs.Specs) == 0 {
    89  		return nil, fmt.Errorf("no definitions in %s", name)
    90  	}
    91  
    92  	err := fs.process()
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	fs.applyDirectives()
    97  	fs.propInline()
    98  
    99  	return fs, nil
   100  }