cuelang.org/go@v0.13.0/cue/build/context.go (about)

     1  // Copyright 2018 The CUE Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package build defines data types and utilities for defining CUE configuration
    16  // instances.
    17  //
    18  // This package enforces the rules regarding packages and instances as defined
    19  // in the spec, but it leaves any other details, as well as handling of modules,
    20  // up to the implementation.
    21  //
    22  // A full implementation of instance loading can be found in the loader package.
    23  //
    24  // WARNING: this packages may change. It is fine to use load and cue, who both
    25  // use this package.
    26  package build
    27  
    28  import (
    29  	"cuelang.org/go/cue/ast"
    30  )
    31  
    32  // A Context keeps track of state of building instances and caches work.
    33  type Context struct {
    34  	loader    LoadFunc
    35  	parseFunc func(str string, src interface{}) (*ast.File, error)
    36  
    37  	initialized bool
    38  
    39  	imports map[string]*Instance
    40  }
    41  
    42  // NewInstance creates an instance for this Context. If the [LoadFunc]
    43  // is nil, then the LoadFunc in the [Context] is used.
    44  func (c *Context) NewInstance(dir string, f LoadFunc) *Instance {
    45  	if c == nil {
    46  		c = &Context{}
    47  	}
    48  	if f == nil {
    49  		f = c.loader
    50  	}
    51  	return &Instance{
    52  		ctxt:     c,
    53  		loadFunc: f,
    54  		Dir:      dir,
    55  	}
    56  }
    57  
    58  // Complete finishes the initialization of an instance. All files must have
    59  // been added with AddFile before this call.
    60  func (inst *Instance) Complete() error {
    61  	if inst.done {
    62  		return inst.Err
    63  	}
    64  	inst.done = true
    65  
    66  	err := inst.complete()
    67  	if err != nil {
    68  		inst.ReportError(err)
    69  	}
    70  	if inst.Err != nil {
    71  		inst.Incomplete = true
    72  		return inst.Err
    73  	}
    74  	return nil
    75  }
    76  
    77  func (c *Context) init() {
    78  	if !c.initialized {
    79  		c.initialized = true
    80  		c.imports = map[string]*Instance{}
    81  	}
    82  }
    83  
    84  // Options:
    85  // - certain parse modes
    86  // - parallelism
    87  // - error handler (allows cancelling the context)
    88  // - file set.
    89  
    90  // NewContext creates a new build context.
    91  //
    92  // All instances must be created with a context.
    93  func NewContext(opts ...Option) *Context {
    94  	c := &Context{}
    95  	for _, o := range opts {
    96  		o(c)
    97  	}
    98  	c.init()
    99  	return c
   100  }
   101  
   102  // Option define build options.
   103  type Option func(c *Context)
   104  
   105  // Loader sets parsing options.
   106  func Loader(f LoadFunc) Option {
   107  	return func(c *Context) { c.loader = f }
   108  }
   109  
   110  // ParseFile is called to read and parse each file
   111  // when building syntax tree.
   112  // It must be safe to call ParseFile simultaneously from multiple goroutines.
   113  // If f is nil, the loader will use [cuelang.org/go/cue/parser.ParseFile].
   114  //
   115  // ParseFile should parse the source from src and use filename only for
   116  // recording position information.
   117  //
   118  // An application may supply a custom implementation of ParseFile
   119  // to change the effective file contents or the behavior of the parser,
   120  // or to modify the syntax tree. For example, changing the backwards
   121  // compatibility.
   122  func ParseFile(f func(filename string, src interface{}) (*ast.File, error)) Option {
   123  	return func(c *Context) { c.parseFunc = f }
   124  }