Repository: lyraproj/hiera
Pull request #6 (2019-03-20 10:43:00)

Fix warnings from lint and GoLand inspections


Patch:
diff --git a/.gitignore b/.gitignore
index 4a98eb4..185031b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,57 @@
 # Created by .ignore support plugin (hsz.mobi)
+### JetBrains template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# CMake
+cmake-build-debug/
+cmake-build-release/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
 ### Go template
 # Binaries for programs and plugins
 *.exe
@@ -13,4 +66,3 @@
 # Output of the go coverage tool, specifically when used with LiteIDE
 *.out
 
-/.idea/
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <state>
+    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
+  </state>
+</component>
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..15a15b2
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding" addBOMForNewFiles="with NO BOM" />
+</project>
\ No newline at end of file
diff --git a/.idea/hiera.iml b/.idea/hiera.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/hiera.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..332f95d
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,18 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="GoUnusedExportedFunction" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GoUnusedGlobalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PuppetUnresolved" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SpellCheckingInspection" enabled="true" level="TYPO" enabled_by_default="false">
+      <scope name="SpellCheck" level="TYPO" enabled="true">
+        <option name="processCode" value="true" />
+        <option name="processLiterals" value="true" />
+        <option name="processComments" value="true" />
+      </scope>
+      <option name="processCode" value="true" />
+      <option name="processLiterals" value="true" />
+      <option name="processComments" value="true" />
+    </inspection_tool>
+  </profile>
+</component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..64fef64
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+  <component name="NodePackageJsonFileManager">
+    <packageJsonPaths />
+  </component>
+  <component name="ProjectInspectionProfilesVisibleTreeState">
+    <entry key="Project Default">
+      <profile-state />
+    </entry>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..d7f7d97
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/hiera.iml" filepath="$PROJECT_DIR$/.idea/hiera.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/scopes/SpellCheck.xml b/.idea/scopes/SpellCheck.xml
new file mode 100644
index 0000000..3ce8737
--- /dev/null
+++ b/.idea/scopes/SpellCheck.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+  <scope name="SpellCheck" pattern="!file:go.mod&amp;&amp;!file:go.sum" />
+</component>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml
new file mode 100644
index 0000000..90b60c1
--- /dev/null
+++ b/.idea/watcherTasks.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectTasksOptions">
+    <TaskOptions isEnabled="true">
+      <option name="arguments" value="-w $FilePath$" />
+      <option name="checkSyntaxErrors" value="true" />
+      <option name="description" />
+      <option name="exitCodeBehavior" value="ERROR" />
+      <option name="fileExtension" value="go" />
+      <option name="immediateSync" value="false" />
+      <option name="name" value="goimports" />
+      <option name="output" value="$FilePath$" />
+      <option name="outputFilters">
+        <array />
+      </option>
+      <option name="outputFromStdout" value="false" />
+      <option name="program" value="goimports" />
+      <option name="runOnExternalChanges" value="false" />
+      <option name="scopeName" value="Project Files" />
+      <option name="trackOnlyRoot" value="true" />
+      <option name="workingDir" value="$ProjectFileDir$" />
+      <envs>
+        <env name="GOROOT" value="$GOROOT$" />
+        <env name="GOPATH" value="$GOPATH$" />
+        <env name="PATH" value="$GoBinDirs$" />
+      </envs>
+    </TaskOptions>
+    <TaskOptions isEnabled="true">
+      <option name="arguments" value="fmt $FilePath$" />
+      <option name="checkSyntaxErrors" value="true" />
+      <option name="description" />
+      <option name="exitCodeBehavior" value="ERROR" />
+      <option name="fileExtension" value="go" />
+      <option name="immediateSync" value="false" />
+      <option name="name" value="go fmt" />
+      <option name="output" value="$FilePath$" />
+      <option name="outputFilters">
+        <array />
+      </option>
+      <option name="outputFromStdout" value="false" />
+      <option name="program" value="$GoExecPath$" />
+      <option name="runOnExternalChanges" value="false" />
+      <option name="scopeName" value="Project Files" />
+      <option name="trackOnlyRoot" value="true" />
+      <option name="workingDir" value="$ProjectFileDir$" />
+      <envs>
+        <env name="GOROOT" value="$GOROOT$" />
+        <env name="GOPATH" value="$GOPATH$" />
+        <env name="PATH" value="$GoBinDirs$" />
+      </envs>
+    </TaskOptions>
+  </component>
+</project>
\ No newline at end of file
diff --git a/README.md b/README.md
index f30f2d9..733f316 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ cannot handle legacy Hiera 3 backends.
 * [x] interpolation using alias function
 * [x] interpolation using literal function
 * [ ] configuration
-* [ ] layerered hierarchy
+* [ ] layered hierarchy
 * [ ] merge strategies
 * [ ] YAML configuration
 * [x] YAML data
diff --git a/config/hiera.go b/config/hiera.go
index 30e7ffa..33f3f33 100644
--- a/config/hiera.go
+++ b/config/hiera.go
@@ -7,15 +7,15 @@ import (
 
 type LookupKind string
 
-const DATA_DIG = LookupKind(`data_dig`)
-const DATA_HASH = LookupKind(`data_hash`)
-const LOOKUP_KEY = LookupKind(`lookup_key`)
+const DataDig = LookupKind(`data_dig`)
+const DataHash = LookupKind(`data_hash`)
+const LookupKey = LookupKind(`lookup_key`)
 
-var FUNCTION_KEYS = []string{string(DATA_DIG), string(DATA_HASH), string(LOOKUP_KEY)}
+var FunctionKeys = []string{string(DataDig), string(DataHash), string(LookupKey)}
 
-var LOCATION_KEYS = []string{string(lookup.LC_PATH), `paths`, string(lookup.LC_GLOB), `globs`, string(lookup.LC_URI), `uris`, string(lookup.LC_MAPPED_PATHS)}
+var LocationKeys = []string{string(lookup.LcPath), `paths`, string(lookup.LcGlob), `globs`, string(lookup.LcUri), `uris`, string(lookup.LcMappedPaths)}
 
-var RESERVED_OPTION_KEYS = []string{string(lookup.LC_PATH), string(lookup.LC_URI)}
+var ReservedOptionKeys = []string{string(lookup.LcPath), string(lookup.LcUri)}
 
 type Function interface {
 	Kind() LookupKind
diff --git a/go.mod b/go.mod
index 6c16cc2..a38fde7 100644
--- a/go.mod
+++ b/go.mod
@@ -2,8 +2,7 @@ module github.com/lyraproj/hiera
 
 require (
 	github.com/bmatcuk/doublestar v1.1.1
-	github.com/gobwas/glob v0.2.3
-	github.com/lyraproj/issue v0.0.0-20190213110846-64f0e861a560
-	github.com/lyraproj/pcore v0.0.0-20190313112821-30e7bb7af627
+	github.com/lyraproj/issue v0.0.0-20190319145359-029b4266d45b
+	github.com/lyraproj/pcore v0.0.0-20190319163905-c435c6e1b96e
 	gopkg.in/yaml.v2 v2.2.2
 )
diff --git a/go.sum b/go.sum
index c2389ff..15db0f0 100644
--- a/go.sum
+++ b/go.sum
@@ -11,6 +11,9 @@ github.com/lyraproj/issue v0.0.0-20190122215520-5efbea1d1edb h1:R3ukQUNWJTypfOAZ
 github.com/lyraproj/issue v0.0.0-20190122215520-5efbea1d1edb/go.mod h1:F3Zu9SjR6zROUIVdxgxuX0/Mi4npwgDRalQCNzCyzU0=
 github.com/lyraproj/issue v0.0.0-20190213110846-64f0e861a560 h1:VVFwiMUrZe1a64kpEGzrPdeB6QzGEZTAVeo1OTOEWEk=
 github.com/lyraproj/issue v0.0.0-20190213110846-64f0e861a560/go.mod h1:F3Zu9SjR6zROUIVdxgxuX0/Mi4npwgDRalQCNzCyzU0=
+github.com/lyraproj/issue v0.0.0-20190319142512-87bdca048c6e h1:sUMHEmbU4Hwj1BXtYyU/VzFxgD3wv8KLMKfljGOP6RY=
+github.com/lyraproj/issue v0.0.0-20190319145359-029b4266d45b h1:niKVq5VjkwpgwUqXmr7jL+WuoWXbqN2UvkM/grgj4gk=
+github.com/lyraproj/issue v0.0.0-20190319145359-029b4266d45b/go.mod h1:F3Zu9SjR6zROUIVdxgxuX0/Mi4npwgDRalQCNzCyzU0=
 github.com/lyraproj/pcore v0.0.0-20190121224504-9cbd778da25e h1:DZJzTl39sOcjV0F8cmjBXsDm1SpMgqr7VfunUm5yy9I=
 github.com/lyraproj/pcore v0.0.0-20190121224504-9cbd778da25e/go.mod h1:zzujLCRGe29CXjx2PYphNjYQAnasgzsz+np2ww6d3Mo=
 github.com/lyraproj/pcore v0.0.0-20190123101558-8fe6588e638e h1:CbcxIHAR4yFUUjcbpb5dJPXM1W+iWYKoD8/Qg4asasQ=
@@ -21,6 +24,9 @@ github.com/lyraproj/pcore v0.0.0-20190312090417-c3ed62d0aa05 h1:JNIo0lVg4D0H9A4F
 github.com/lyraproj/pcore v0.0.0-20190312090417-c3ed62d0aa05/go.mod h1:hKQkpsnpeamSKHIhhrKdhNAAViuZNfKYC3x0Drmra2w=
 github.com/lyraproj/pcore v0.0.0-20190313112821-30e7bb7af627 h1:BcQpv7SBmbdFgQUhESoRE+fTv5ZQ9MHaWSBIbdxuqXU=
 github.com/lyraproj/pcore v0.0.0-20190313112821-30e7bb7af627/go.mod h1:hKQkpsnpeamSKHIhhrKdhNAAViuZNfKYC3x0Drmra2w=
+github.com/lyraproj/pcore v0.0.0-20190319142435-27ce0d28a7c5 h1:XTHjvfLXrF73FG9nTiJC4ej/W0wk6ZCDpS8WMSXejdo=
+github.com/lyraproj/pcore v0.0.0-20190319163905-c435c6e1b96e h1:W2omAJqkyi++wiadcWBNKTyBnlLJ8p2WXYFTMu5AsMo=
+github.com/lyraproj/pcore v0.0.0-20190319163905-c435c6e1b96e/go.mod h1:zaYm7Mn2rIKNNpcMGy+QkWUqoTpGAQiAmVwJpJ4wYDc=
 github.com/lyraproj/puppet-parser v0.0.0-20181212205830-31c3104fe78d h1:iDn6XlJAiA+BuwG6L8xsCapPpc7jz24SGj9z7NQA1sg=
 github.com/lyraproj/puppet-parser v0.0.0-20181212205830-31c3104fe78d/go.mod h1:8va5g/XEw+jP9jnwEXPmanUy/hD9+6iggnaioihPLP0=
 github.com/lyraproj/semver v0.0.0-20181213164306-02ecea2cd6a2 h1:vb4PbiMtIXdhsOUinkkcqZiASDIZzXRhSG4yvNfE0tg=
diff --git a/impl/concurrentmap.go b/impl/concurrentmap.go
index af5981f..3b4d6a2 100644
--- a/impl/concurrentmap.go
+++ b/impl/concurrentmap.go
@@ -20,8 +20,8 @@ func NewConcurrentMap(capacity int) *ConcurrentMap {
 // map. If it does, the thread will deadlock.
 func (c *ConcurrentMap) AtomicReplace(key string, replacer func(oldValue interface{}) interface{}) interface{} {
 	c.lock.Lock()
-	oldValue, _ := c.valueMutexWait(key)
 	defer c.lock.Unlock()
+	oldValue, _ := c.valueMutexWait(key)
 
 	newValue := replacer(oldValue)
 	c.values[key] = newValue
@@ -45,8 +45,8 @@ func (c *ConcurrentMap) valueMutexWait(key string) (interface{}, bool) {
 				// The value is currently a lock. Wait until it's released
 				c.lock.Unlock()
 				l.RLock()
-				l.RUnlock()
 				c.lock.Lock()
+				l.RUnlock()
 				continue
 			}
 		}
@@ -97,11 +97,13 @@ func (c *ConcurrentMap) Get(key string) (value interface{}, ok bool) {
 	c.lock.RLock()
 	value, ok = c.values[key]
 	c.lock.RUnlock()
-	if l, ok := value.(*sync.RWMutex); ok {
-		// The value is currently a lock. Wait for the real value
-		l.RLock()
-		l.RUnlock()
-		return c.Get(key)
+	if ok {
+		if l, isMutex := value.(*sync.RWMutex); isMutex {
+			// The value is currently a lock. Wait for the real value
+			l.RLock()
+			value, ok = c.values[key]
+			l.RUnlock()
+		}
 	}
 	return
 }
@@ -114,8 +116,8 @@ func (c *ConcurrentMap) Set(key string, value interface{}) {
 			// The value is currently a lock. Wait until it's released
 			c.lock.Unlock()
 			l.RLock()
-			l.RUnlock()
 			c.lock.Lock()
+			l.RUnlock()
 		}
 	}
 	c.values[key] = value
diff --git a/impl/config.go b/impl/config.go
index 683432a..63b90de 100644
--- a/impl/config.go
+++ b/impl/config.go
@@ -2,6 +2,8 @@ package impl
 
 import (
 	"fmt"
+	"path/filepath"
+
 	"github.com/lyraproj/hiera/config"
 	"github.com/lyraproj/hiera/lookup"
 	"github.com/lyraproj/issue/issue"
@@ -10,7 +12,6 @@ import (
 	"github.com/lyraproj/pcore/types"
 	"github.com/lyraproj/pcore/utils"
 	"github.com/lyraproj/pcore/yaml"
-	"path/filepath"
 
 	// Ensure that pcore is initialized
 	_ "github.com/lyraproj/pcore/pcore"
@@ -66,9 +67,9 @@ func (e *hierEntry) Name() string {
 
 func (e *hierEntry) CreateProvider(ic lookup.Invocation) lookup.DataProvider {
 	switch e.function.Kind() {
-	case config.DATA_HASH:
+	case config.DataHash:
 		return newDataHashProvider(ic, e)
-	case config.DATA_DIG:
+	case config.DataDig:
 		return newDataDigProvider(ic, e)
 	default:
 		return newLookupKeyProvider(ic, e)
@@ -86,7 +87,7 @@ func (e *hierEntry) Resolve(ic lookup.Invocation, defaults config.Entry) config.
 	}
 
 	if e.function == nil {
-		panic(px.Error(HIERA_MISSING_DATA_PROVIDER_FUNCTION, issue.H{`keys`: config.FUNCTION_KEYS, `name`: e.name}))
+		panic(px.Error(HieraMissingDataProviderFunction, issue.H{`keys`: config.FunctionKeys, `name`: e.name}))
 	}
 
 	if e.dataDir == `` {
@@ -107,10 +108,10 @@ func (e *hierEntry) Resolve(ic lookup.Invocation, defaults config.Entry) config.
 
 	if e.locations != nil {
 		ne := make([]lookup.Location, 0, len(e.locations))
-		ce.locations = ne
 		for _, l := range e.locations {
 			ne = append(ne, l.Resolve(ic, ce.dataDir)...)
 		}
+		ce.locations = ne
 	}
 
 	return &ce
@@ -118,7 +119,7 @@ func (e *hierEntry) Resolve(ic lookup.Invocation, defaults config.Entry) config.
 
 var hieraTypeSet px.Type
 
-var DEFAULT_CONFIG config.Config
+var DefaultConfig config.Config
 
 func init() {
 	hieraTypeSet = px.NewNamedType(`Hiera`, `TypeSet{
@@ -157,11 +158,11 @@ func init() {
 		}
   }`)
 
-	DEFAULT_CONFIG = &hieraCfg{
+	DefaultConfig = &hieraCfg{
 		root:             ``,
 		path:             ``,
 		loadedHash:       nil,
-		defaults:         &entry{dataDir: `data`, function: &function{kind: config.DATA_HASH, name: `yaml_data`}},
+		defaults:         &entry{dataDir: `data`, function: &function{kind: config.DataHash, name: `yaml_data`}},
 		hierarchy:        []config.HierarchyEntry{&hierEntry{name: `Common`, locations: []lookup.Location{&path{original: `common.yaml`}}}},
 		defaultHierarchy: []config.HierarchyEntry{},
 	}
@@ -192,7 +193,7 @@ func NewConfig(ic lookup.Invocation, configPath string) config.Config {
 			return fmt.Sprintf(`The Lookup Configuration at '%s'`, configPath)
 		}, cfgType, yv).(*types.Hash))
 	}
-	return DEFAULT_CONFIG
+	return DefaultConfig
 }
 
 func (hc *hieraCfg) Resolve(ic lookup.Invocation) config.ResolvedConfig {
@@ -239,13 +240,13 @@ func createConfig(ic lookup.Invocation, path string, hash *types.Hash) config.Co
 	if dv, ok := hash.Get4(`defaults`); ok {
 		cfg.defaults = createDefaultsEntry(ic, dv.(*types.Hash))
 	} else {
-		cfg.defaults = DEFAULT_CONFIG.Defaults()
+		cfg.defaults = DefaultConfig.Defaults()
 	}
 
 	if hv, ok := hash.Get4(`hierarchy`); ok {
 		cfg.hierarchy = createHierarchy(ic, hv.(*types.Array))
 	} else {
-		cfg.hierarchy = DEFAULT_CONFIG.Hierarchy()
+		cfg.hierarchy = DefaultConfig.Hierarchy()
 	}
 
 	if hv, ok := hash.Get4(`default_hierarchy`); ok {
@@ -262,7 +263,7 @@ func createHierarchy(ic lookup.Invocation, hier *types.Array) []config.Hierarchy
 		hh := hv.(*types.Hash)
 		name := hh.Get5(`name`, px.EmptyString).String()
 		if uniqueNames[name] {
-			panic(px.Error(HIERA_HIERARCHY_NAME_MULTIPLY_DEFINED, issue.H{`name`: name}))
+			panic(px.Error(HieraHierarchyNameMultiplyDefined, issue.H{`name`: name}))
 		}
 		uniqueNames[name] = true
 		entries = append(entries, createHierarchyEntry(ic, name, hh))
@@ -270,21 +271,21 @@ func createHierarchy(ic lookup.Invocation, hier *types.Array) []config.Hierarchy
 	return entries
 }
 
-func (entry *entry) initialize(ic lookup.Invocation, name string, entryHash *types.Hash) {
+func (e *entry) initialize(ic lookup.Invocation, name string, entryHash *types.Hash) {
 	entryHash.EachPair(func(k, v px.Value) {
 		ks := k.String()
 		if ks == `options` {
-			entry.options = v.(*types.Hash)
-			entry.options.EachKey(func(optKey px.Value) {
-				if utils.ContainsString(config.RESERVED_OPTION_KEYS, optKey.String()) {
-					panic(px.Error(HIERA_OPTION_RESERVED_BY_PUPPET, issue.H{`key`: optKey.String(), `name`: name}))
+			e.options = v.(*types.Hash)
+			e.options.EachKey(func(optKey px.Value) {
+				if utils.ContainsString(config.ReservedOptionKeys, optKey.String()) {
+					panic(px.Error(HieraOptionReservedByPuppet, issue.H{`key`: optKey.String(), `name`: name}))
 				}
 			})
-		} else if utils.ContainsString(config.FUNCTION_KEYS, ks) {
-			if entry.function != nil {
-				panic(px.Error(HIERA_MULTIPLE_DATA_PROVIDER_FUNCTIONS, issue.H{`keys`: config.FUNCTION_KEYS, `name`: name}))
+		} else if utils.ContainsString(config.FunctionKeys, ks) {
+			if e.function != nil {
+				panic(px.Error(HieraMultipleDataProviderFunctions, issue.H{`keys`: config.FunctionKeys, `name`: name}))
 			}
-			entry.function = &function{config.LookupKind(ks), v.String()}
+			e.function = &function{config.LookupKind(ks), v.String()}
 		}
 	})
 }
@@ -300,9 +301,9 @@ func createHierarchyEntry(ic lookup.Invocation, name string, entryHash *types.Ha
 	entry.initialize(ic, name, entryHash)
 	entryHash.EachPair(func(k, v px.Value) {
 		ks := k.String()
-		if utils.ContainsString(config.LOCATION_KEYS, ks) {
+		if utils.ContainsString(config.LocationKeys, ks) {
 			if entry.locations != nil {
-				panic(px.Error(HIERA_MULTIPLE_LOCATION_SPECS, issue.H{`keys`: config.LOCATION_KEYS, `name`: name}))
+				panic(px.Error(HieraMultipleLocationSpecs, issue.H{`keys`: config.LocationKeys, `name`: name}))
 			}
 			switch ks {
 			case `path`:
diff --git a/impl/context.go b/impl/context.go
index 5a30996..45cecd6 100644
--- a/impl/context.go
+++ b/impl/context.go
@@ -2,6 +2,7 @@ package impl
 
 import (
 	"context"
+
 	"github.com/lyraproj/hiera/lookup"
 	"github.com/lyraproj/issue/issue"
 	"github.com/lyraproj/pcore/pcore"
@@ -68,9 +69,9 @@ func init() {
 		if defaultValue == nil {
 			// nil (as opposed to UNDEF) means that no default was provided.
 			if len(names) == 1 {
-				panic(px.Error(HIERA_NAME_NOT_FOUND, issue.H{`name`: names[0]}))
+				panic(px.Error(HieraNameNotFound, issue.H{`name`: names[0]}))
 			}
-			panic(px.Error(HIERA_NOT_ANY_NAME_FOUND, issue.H{`name_list`: names}))
+			panic(px.Error(HieraNotAnyNameFound, issue.H{`name_list`: names}))
 		}
 		return defaultValue
 	}
diff --git a/impl/dataprovider.go b/impl/dataprovider.go
index 4573769..3259f4c 100644
--- a/impl/dataprovider.go
+++ b/impl/dataprovider.go
@@ -2,6 +2,7 @@ package impl
 
 import (
 	"fmt"
+
 	"github.com/lyraproj/hiera/config"
 	"github.com/lyraproj/hiera/lookup"
 
@@ -13,7 +14,7 @@ func CheckedLookup(dp lookup.DataProvider, key lookup.Key, invocation lookup.Inv
 	return invocation.Check(key, func() (px.Value, bool) { return dp.UncheckedLookup(key, invocation, merge) })
 }
 
-type basicProvider struct {
+type BasicProvider struct {
 	function config.Function
 
 	// Set if the designated function has a return type that is equal to or more
@@ -21,12 +22,16 @@ type basicProvider struct {
 	valueIsValidated bool
 }
 
-type dataHashProvider struct {
-	basicProvider
+func (p *BasicProvider) Function() config.Function {
+	return p.function
+}
+
+type DataHashProvider struct {
+	BasicProvider
 	locations []lookup.Location
 }
 
-func (dh *dataHashProvider) UncheckedLookup(key lookup.Key, invocation lookup.Invocation, merge lookup.MergeStrategy) (px.Value, bool) {
+func (dh *DataHashProvider) UncheckedLookup(key lookup.Key, invocation lookup.Invocation, merge lookup.MergeStrategy) (px.Value, bool) {
 	return invocation.WithDataProvider(dh, func() (px.Value, bool) {
 		return merge.Lookup(dh.locations, invocation, func(location lookup.Location) (px.Value, bool) {
 			return dh.invokeWithLocation(invocation, location, key.Root())
@@ -34,7 +39,7 @@ func (dh *dataHashProvider) UncheckedLookup(key lookup.Key, invocation lookup.In
 	})
 }
 
-func (dh *dataHashProvider) invokeWithLocation(invocation lookup.Invocation, location lookup.Location, root string) (px.Value, bool) {
+func (dh *DataHashProvider) invokeWithLocation(invocation lookup.Invocation, location lookup.Location, root string) (px.Value, bool) {
 	if location == nil {
 		return dh.lookupKey(invocation, nil, root)
 	}
@@ -47,7 +52,7 @@ func (dh *dataHashProvider) invokeWithLocation(invocation lookup.Invocation, loc
 	})
 }
 
-func (dh *dataHashProvider) lookupKey(invocation lookup.Invocation, location lookup.Location, root string) (px.Value, bool) {
+func (dh *DataHashProvider) lookupKey(invocation lookup.Invocation, location lookup.Location, root string) (px.Value, bool) {
 	if value, ok := dh.dataValue(invocation, location, root); ok {
 		invocation.ReportFound(root, value)
 		return value, true
@@ -55,7 +60,7 @@ func (dh *dataHashProvider) lookupKey(invocation lookup.Invocation, location loo
 	return nil, false
 }
 
-func (dh *dataHashProvider) dataValue(invocation lookup.Invocation, location lookup.Location, root string) (px.Value, bool) {
+func (dh *DataHashProvider) dataValue(invocation lookup.Invocation, location lookup.Location, root string) (px.Value, bool) {
 	hash := dh.dataHash(invocation, location)
 	value, found := hash.Get4(root)
 	if !found {
@@ -71,23 +76,25 @@ func (dh *dataHashProvider) dataValue(invocation lookup.Invocation, location loo
 	return Interpolate(invocation, value, true), true
 }
 
-func (dh *dataHashProvider) dataHash(invocation lookup.Invocation, location lookup.Location) px.OrderedMap {
+func (dh *DataHashProvider) dataHash(invocation lookup.Invocation, location lookup.Location) px.OrderedMap {
 	// TODO
 	return nil
 }
 
-func (dh *basicProvider) validateDataHash(c px.Context, value px.Value, pfx func() string) px.OrderedMap {
+/*
+func (dh *BasicProvider) validateDataHash(c px.Context, value px.Value, pfx func() string) px.OrderedMap {
 	return px.AssertInstance(pfx, types.DefaultHashType(), value).(px.OrderedMap)
 }
+*/
 
-func (dh *basicProvider) validateDataValue(c px.Context, value px.Value, pfx func() string) px.Value {
+func (dh *BasicProvider) validateDataValue(c px.Context, value px.Value, pfx func() string) px.Value {
 	if !dh.valueIsValidated {
 		px.AssertInstance(pfx, types.DefaultRichDataType(), value)
 	}
 	return value
 }
 
-func (dh *dataHashProvider) FullName() string {
+func (dh *DataHashProvider) FullName() string {
 	return fmt.Sprintf(`data_hash function '%s'`, dh.function.Name())
 }
 
diff --git a/impl/interpolate.go b/impl/interpolate.go
index e0b81fc..a628b11 100644
--- a/impl/interpolate.go
+++ b/impl/interpolate.go
@@ -1,12 +1,13 @@
 package impl
 
 import (
+	"regexp"
+	"strings"
+
 	"github.com/lyraproj/hiera/lookup"
 	"github.com/lyraproj/issue/issue"
 	"github.com/lyraproj/pcore/px"
 	"github.com/lyraproj/pcore/types"
-	"regexp"
-	"strings"
 )
 
 var iplPattern = regexp.MustCompile(`%{[^}]*}`)
@@ -73,7 +74,7 @@ var methodMatch = regexp.MustCompile(`^(\w+)\((?:["]([^"]+)["]|[']([^']+)['])\)$
 func getMethodAndData(expr string, allowMethods bool) (int, string) {
 	if groups := methodMatch.FindStringSubmatch(expr); groups != nil {
 		if !allowMethods {
-			panic(px.Error(HIERA_INTERPOLATION_METHOD_SYNTAX_NOT_ALLOWED, issue.NO_ARGS))
+			panic(px.Error(HieraInterpolationMethodSyntaxNotAllowed, issue.NoArgs))
 		}
 		data := groups[2]
 		if data == `` {
@@ -89,7 +90,7 @@ func getMethodAndData(expr string, allowMethods bool) (int, string) {
 		case `scope`:
 			return scopeMethod, data
 		default:
-			panic(px.Error(HIERA_INTERPOLATION_UNKNOWN_INTERPOLATION_METHOD, issue.H{`name`: groups[1]}))
+			panic(px.Error(HieraInterpolationUnknownInterpolationMethod, issue.H{`name`: groups[1]}))
 		}
 	}
 	return scopeMethod, expr
@@ -97,7 +98,7 @@ func getMethodAndData(expr string, allowMethods bool) (int, string) {
 
 func interpolateString(ic lookup.Invocation, str string, allowMethods bool) (result px.Value, changed bool) {
 	changed = false
-	if strings.Index(str, `%{`) < 0 {
+	if !strings.Contains(str, `%{`) {
 		result = types.WrapString(str)
 		return
 	}
@@ -109,7 +110,7 @@ func interpolateString(ic lookup.Invocation, str string, allowMethods bool) (res
 		var methodKey int
 		methodKey, expr = getMethodAndData(expr, allowMethods)
 		if methodKey == aliasMethod && match != str {
-			panic(px.Error(HIERA_INTERPOLATION_ALIAS_NOT_ENTIRE_STRING, issue.NO_ARGS))
+			panic(px.Error(HieraInterpolationAliasNotEntireString, issue.NoArgs))
 		}
 
 		switch methodKey {
diff --git a/impl/invocation.go b/impl/invocation.go
index 310a8fc..19ca46a 100644
--- a/impl/invocation.go
+++ b/impl/invocation.go
@@ -17,7 +17,7 @@ const HieraConfigsKey = `Hiera::Config::`
 type invocation struct {
 	px.Context
 	nameStack []string
-	scope px.Keyed
+	scope     px.Keyed
 }
 
 // InitContext initializes the given context with the Hiera cache. The context initialized
@@ -40,7 +40,7 @@ func (ic *invocation) topProvider() lookup.LookupKey {
 			return tp
 		}
 	}
-	panic(px.Error(HIERA_NOT_INITIALIZED, issue.NO_ARGS))
+	panic(px.Error(HieraNotInitialized, issue.NoArgs))
 }
 
 func (ic *invocation) topProviderCache() map[string]px.Value {
@@ -50,7 +50,7 @@ func (ic *invocation) topProviderCache() map[string]px.Value {
 			return tc
 		}
 	}
-	panic(px.Error(HIERA_NOT_INITIALIZED, issue.NO_ARGS))
+	panic(px.Error(HieraNotInitialized, issue.NoArgs))
 }
 
 func (ic *invocation) globalOptions() map[string]px.Value {
@@ -60,7 +60,7 @@ func (ic *invocation) globalOptions() map[string]px.Value {
 			return g
 		}
 	}
-	panic(px.Error(HIERA_NOT_INITIALIZED, issue.NO_ARGS))
+	panic(px.Error(HieraNotInitialized, issue.NoArgs))
 }
 
 func (ic *invocation) sharedCache() *ConcurrentMap {
@@ -70,7 +70,7 @@ func (ic *invocation) sharedCache() *ConcurrentMap {
 			return sh
 		}
 	}
-	panic(px.Error(HIERA_NOT_INITIALIZED, issue.NO_ARGS))
+	panic(px.Error(HieraNotInitialized, issue.NoArgs))
 }
 
 func (ic *invocation) Config(configPath string) config.ResolvedConfig {
@@ -110,7 +110,7 @@ func (ic *invocation) lookupViaCache(key lookup.Key, options map[string]px.Value
 
 func (ic *invocation) Check(key lookup.Key, actor lookup.Producer) (px.Value, bool) {
 	if utils.ContainsString(ic.nameStack, key.String()) {
-		panic(px.Error(HIERA_ENDLESS_RECURSION, issue.H{`name_stack`: ic.nameStack}))
+		panic(px.Error(HieraEndlessRecursion, issue.H{`name_stack`: ic.nameStack}))
 	}
 	ic.nameStack = append(ic.nameStack, key.String())
 	defer func() {
diff --git a/impl/issues.go b/impl/issues.go
index bb094f4..201dcc7 100644
--- a/impl/issues.go
+++ b/impl/issues.go
@@ -2,29 +2,30 @@ package impl
 
 import (
 	"fmt"
-	"github.com/lyraproj/issue/issue"
 	"strings"
+
+	"github.com/lyraproj/issue/issue"
 )
 
 const (
-	HIERA_DIG_MISMATCH                               = `HIERA_DIG_MISMATCH`
-	HIERA_EMPTY_KEY_SEGMENT                          = `HIERA_EMPTY_KEY_SEGMENT`
-	HIERA_ENDLESS_RECURSION                          = `HIERA_ENDLESS_RECURSION`
-	HIERA_FIRST_KEY_SEGMENT_INT                      = `HIERA_FIRST_KEY_SEGMENT_INT`
-	HIERA_HIERARCHY_NAME_MULTIPLY_DEFINED            = `HIERA_HIERARCHY_NAME_MULTIPLY_DEFINED`
-	HIERA_INTERPOLATION_ALIAS_NOT_ENTIRE_STRING      = `HIERA_INTERPOLATION_ALIAS_NOT_ENTIRE_STRING`
-	HIERA_INTERPOLATION_METHOD_SYNTAX_NOT_ALLOWED    = `HIERA_INTERPOLATION_METHOD_SYNTAX_NOT_ALLOWED`
-	HIERA_INTERPOLATION_UNKNOWN_INTERPOLATION_METHOD = `HIERA_INTERPOLATION_UNKNOWN_INTERPOLATION_METHOD`
-	HIERA_MISSING_DATA_PROVIDER_FUNCTION             = `HIERA_MISSING_DATA_PROVIDER_FUNCTION`
-	HIERA_MISSING_REQUIRED_OPTION                    = `HIERA_MISSING_REQUIRED_OPTION`
-	HIERA_MULTIPLE_DATA_PROVIDER_FUNCTIONS           = `HIERA_MULTIPLE_DATA_PROVIDER_FUNCTIONS`
-	HIERA_MULTIPLE_LOCATION_SPECS                    = `HIERA_MULTIPLE_LOCATION_SPECS`
-	HIERA_NAME_NOT_FOUND                             = `HIERA_NAME_NOT_FOUND`
-	HIERA_NOT_ANY_NAME_FOUND                         = `HIERA_NOT_ANY_NAME_FOUND`
-	HIERA_NOT_INITIALIZED                            = `HIERA_NOT_INITIALIZED`
-	HIERA_OPTION_RESERVED_BY_PUPPET                  = `HIERA_OPTION_RESERVED_BY_PUPPET`
-	HIERA_UNTERMINATED_QUOTE                         = `HIERA_UNTERMINATED_QUOTE`
-	HIERA_YAML_NOT_HASH                              = `HIERA_YAML_NOT_HASH`
+	HieraDigMismatch                             = `HIERA_DIG_MISMATCH`
+	HieraEmptyKeySegment                         = `HIERA_EMPTY_KEY_SEGMENT`
+	HieraEndlessRecursion                        = `HIERA_ENDLESS_RECURSION`
+	HieraFirstKeySegmentInt                      = `HIERA_FIRST_KEY_SEGMENT_INT`
+	HieraHierarchyNameMultiplyDefined            = `HIERA_HIERARCHY_NAME_MULTIPLY_DEFINED`
+	HieraInterpolationAliasNotEntireString       = `HIERA_INTERPOLATION_ALIAS_NOT_ENTIRE_STRING`
+	HieraInterpolationMethodSyntaxNotAllowed     = `HIERA_INTERPOLATION_METHOD_SYNTAX_NOT_ALLOWED`
+	HieraInterpolationUnknownInterpolationMethod = `HIERA_INTERPOLATION_UNKNOWN_INTERPOLATION_METHOD`
+	HieraMissingDataProviderFunction             = `HIERA_MISSING_DATA_PROVIDER_FUNCTION`
+	HieraMissingRequiredOption                   = `HIERA_MISSING_REQUIRED_OPTION`
+	HieraMultipleDataProviderFunctions           = `HIERA_MULTIPLE_DATA_PROVIDER_FUNCTIONS`
+	HieraMultipleLocationSpecs                   = `HIERA_MULTIPLE_LOCATION_SPECS`
+	HieraNameNotFound                            = `HIERA_NAME_NOT_FOUND`
+	HieraNotAnyNameFound                         = `HIERA_NOT_ANY_NAME_FOUND`
+	HieraNotInitialized                          = `HIERA_NOT_INITIALIZED`
+	HieraOptionReservedByPuppet                  = `HIERA_OPTION_RESERVED_BY_PUPPET`
+	HieraUnterminatedQuote                       = `HIERA_UNTERMINATED_QUOTE`
+	HieraYamlNotHash                             = `HIERA_YAML_NOT_HASH`
 )
 
 func joinNames(v interface{}) string {
@@ -35,44 +36,44 @@ func joinNames(v interface{}) string {
 }
 
 func init() {
-	issue.Hard(HIERA_DIG_MISMATCH,
+	issue.Hard(HieraDigMismatch,
 		`lookup() Got %{type} when a hash-like object was expected to access value using '%{segment}' from key '%{key}'`)
 
-	issue.Hard(HIERA_EMPTY_KEY_SEGMENT, `lookup() key '%{key}' contains an empty segment`)
+	issue.Hard(HieraEmptyKeySegment, `lookup() key '%{key}' contains an empty segment`)
 
-	issue.Hard2(HIERA_ENDLESS_RECURSION, `Recursive lookup detected in [%{name_stack}]`, issue.HF{`name_stack`: joinNames})
+	issue.Hard2(HieraEndlessRecursion, `Recursive lookup detected in [%{name_stack}]`, issue.HF{`name_stack`: joinNames})
 
-	issue.Hard(HIERA_FIRST_KEY_SEGMENT_INT, `lookup() key '%{key}' first segment cannot be an index`)
+	issue.Hard(HieraFirstKeySegmentInt, `lookup() key '%{key}' first segment cannot be an index`)
 
-	issue.Hard(HIERA_HIERARCHY_NAME_MULTIPLY_DEFINED, `Hierarchy name '%{name}' defined more than once`)
+	issue.Hard(HieraHierarchyNameMultiplyDefined, `Hierarchy name '%{name}' defined more than once`)
 
-	issue.Hard(HIERA_INTERPOLATION_ALIAS_NOT_ENTIRE_STRING, `'alias' interpolation is only permitted if the expression is equal to the entire string`)
+	issue.Hard(HieraInterpolationAliasNotEntireString, `'alias' interpolation is only permitted if the expression is equal to the entire string`)
 
-	issue.Hard(HIERA_INTERPOLATION_METHOD_SYNTAX_NOT_ALLOWED, `Interpolation using method syntax is not allowed in this context`)
+	issue.Hard(HieraInterpolationMethodSyntaxNotAllowed, `Interpolation using method syntax is not allowed in this context`)
 
-	issue.Hard(HIERA_INTERPOLATION_UNKNOWN_INTERPOLATION_METHOD, `Unknown interpolation method '%{name}'`)
+	issue.Hard(HieraInterpolationUnknownInterpolationMethod, `Unknown interpolation method '%{name}'`)
 
-	issue.Hard2(HIERA_MISSING_DATA_PROVIDER_FUNCTION, `One of %{keys} must be defined in hierarchy '%{name}'`,
+	issue.Hard2(HieraMissingDataProviderFunction, `One of %{keys} must be defined in hierarchy '%{name}'`,
 		issue.HF{`keys`: joinNames})
 
-	issue.Hard(HIERA_MISSING_REQUIRED_OPTION, `Missing required provider option '%{option}'`)
+	issue.Hard(HieraMissingRequiredOption, `Missing required provider option '%{option}'`)
 
-	issue.Hard2(HIERA_MULTIPLE_DATA_PROVIDER_FUNCTIONS, `Only one of %{keys} can be defined in hierarchy '%{name}'`,
+	issue.Hard2(HieraMultipleDataProviderFunctions, `Only one of %{keys} can be defined in hierarchy '%{name}'`,
 		issue.HF{`keys`: joinNames})
 
-	issue.Hard2(HIERA_MULTIPLE_LOCATION_SPECS, `Only one of %{keys} can be defined in hierarchy '%{name}'`,
+	issue.Hard2(HieraMultipleLocationSpecs, `Only one of %{keys} can be defined in hierarchy '%{name}'`,
 		issue.HF{`keys`: joinNames})
 
-	issue.Hard(HIERA_NAME_NOT_FOUND, `lookup() did not find a value for the name '%{name}'`)
+	issue.Hard(HieraNameNotFound, `lookup() did not find a value for the name '%{name}'`)
 
-	issue.Hard2(HIERA_NOT_ANY_NAME_FOUND, `lookup() did not find a value for any of the names [%{name_list}]`,
+	issue.Hard2(HieraNotAnyNameFound, `lookup() did not find a value for any of the names [%{name_list}]`,
 		issue.HF{`name_list`: joinNames})
 
-	issue.Hard(HIERA_NOT_INITIALIZED, `Given px.Context is not initialized with Hiera`)
+	issue.Hard(HieraNotInitialized, `Given px.Context is not initialized with Hiera`)
 
-	issue.Hard(HIERA_OPTION_RESERVED_BY_PUPPET, `Option key '%{key}' used in hierarchy '%{name}' is reserved by Puppet`)
+	issue.Hard(HieraOptionReservedByPuppet, `Option key '%{key}' used in hierarchy '%{name}' is reserved by Puppet`)
 
-	issue.Hard(HIERA_UNTERMINATED_QUOTE, `Unterminated quote in key '%{key}'`)
+	issue.Hard(HieraUnterminatedQuote, `Unterminated quote in key '%{key}'`)
 
-	issue.Hard(HIERA_YAML_NOT_HASH, `File '%{path}' does not contain a YAML hash`)
+	issue.Hard(HieraYamlNotHash, `File '%{path}' does not contain a YAML hash`)
 }
diff --git a/impl/key.go b/impl/key.go
index bd2995b..427e0ea 100644
--- a/impl/key.go
+++ b/impl/key.go
@@ -2,11 +2,12 @@ package impl
 
 import (
 	"bytes"
+	"strconv"
+
 	"github.com/lyraproj/hiera/lookup"
 	"github.com/lyraproj/issue/issue"
 	"github.com/lyraproj/pcore/px"
 	"github.com/lyraproj/pcore/types"
-	"strconv"
 )
 
 type key struct {
@@ -39,7 +40,7 @@ func (k *key) Dig(v px.Value) (px.Value, bool) {
 				return nil, false
 			}
 		}
-		panic(px.Error(HIERA_DIG_MISMATCH, issue.H{`type`: px.GenericValueType(v), `segment`: p, `key`: k.orig}))
+		panic(px.Error(HieraDigMismatch, issue.H{`type`: px.GenericValueType(v), `segment`: p, `key`: k.orig}))
 	}
 	return v, true
 }
@@ -60,12 +61,12 @@ func parseUnquoted(b *bytes.Buffer, key, part string, parts []interface{}) []int
 	mungePart := func(ix int, part string) interface{} {
 		if i, err := strconv.ParseInt(part, 10, 32); err == nil {
 			if ix == 0 {
-				panic(px.Error(HIERA_FIRST_KEY_SEGMENT_INT, issue.H{`key`: key}))
+				panic(px.Error(HieraFirstKeySegmentInt, issue.H{`key`: key}))
 			}
 			return int(i)
 		}
 		if part == `` {
-			panic(px.Error(HIERA_EMPTY_KEY_SEGMENT, issue.H{`key`: key}))
+			panic(px.Error(HieraEmptyKeySegment, issue.H{`key`: key}))
 		}
 		return part
 	}
@@ -94,5 +95,5 @@ func parseQuoted(b *bytes.Buffer, q rune, key, part string, parts []interface{})
 		}
 		b.WriteRune(c)
 	}
-	panic(px.Error(HIERA_UNTERMINATED_QUOTE, issue.H{`key`: key}))
+	panic(px.Error(HieraUnterminatedQuote, issue.H{`key`: key}))
 }
diff --git a/impl/location.go b/impl/location.go
index 8ad489f..3aee8cb 100644
--- a/impl/location.go
+++ b/impl/location.go
@@ -2,12 +2,13 @@ package impl
 
 import (
 	"fmt"
+	"os"
+	"path/filepath"
+
 	"github.com/bmatcuk/doublestar"
 	"github.com/lyraproj/hiera/lookup"
 	"github.com/lyraproj/pcore/px"
 	"github.com/lyraproj/pcore/types"
-	"os"
-	"path/filepath"
 )
 
 type path struct {
@@ -21,7 +22,7 @@ func (p *path) Exist() bool {
 }
 
 func (p *path) Kind() lookup.LocationKind {
-	return lookup.LC_PATH
+	return lookup.LcPath
 }
 
 func (p *path) String() string {
@@ -44,7 +45,7 @@ func (g *glob) Exist() bool {
 }
 
 func (g *glob) Kind() lookup.LocationKind {
-	return lookup.LC_GLOB
+	return lookup.LcGlob
 }
 
 func (g *glob) String() string {
@@ -54,10 +55,7 @@ func (g *glob) String() string {
 func (g *glob) Resolve(ic lookup.Invocation, dataDir string) []lookup.Location {
 	r, _ := interpolateString(ic, g.pattern, false)
 	rp := filepath.Join(dataDir, r.String())
-	matches, err := doublestar.Glob(rp)
-	if err != nil {
-
-	}
+	matches, _ := doublestar.Glob(rp)
 	locs := make([]lookup.Location, len(matches))
 	for i, m := range matches {
 		locs[i] = &path{g.pattern, m, true}
@@ -75,7 +73,7 @@ func (u *uri) Exist() bool {
 }
 
 func (u *uri) Kind() lookup.LocationKind {
-	return lookup.LC_URI
+	return lookup.LcUri
 }
 
 func (u *uri) String() string {
@@ -103,7 +101,7 @@ func (m *mappedPaths) Exist() bool {
 }
 
 func (m *mappedPaths) Kind() lookup.LocationKind {
-	return lookup.LC_MAPPED_PATHS
+	return lookup.LcMappedPaths
 }
 
 func (m *mappedPaths) String() string {
@@ -128,19 +126,19 @@ func (m *mappedPaths) Resolve(ic lookup.Invocation, dataDir string) []lookup.Loc
 	// Use a parented scope so that the tracking scope held by the context is shielded from the
 	// interpolations of the key introduced by this mapped path.
 	/*
-	ic.DoWithScope(impl.NewParentedScope(ic.Scope(), true), func() {
-		mappedVars.EachWithIndex(func(mv px.Value, i int) {
-			scope := ic.Scope()
-			scope.WithLocalScope(func() px.Value {
-				scope.Set(m.key, mv)
-				r, _ := interpolateString(ic, m.template, false)
-				rp := filepath.Join(dataDir, r.String())
-				_, err := os.Stat(rp)
-				paths[i] = &path{m.template, rp, err == nil}
-				return nil
+		ic.DoWithScope(impl.NewParentedScope(ic.Scope(), true), func() {
+			mappedVars.EachWithIndex(func(mv px.Value, i int) {
+				scope := ic.Scope()
+				scope.WithLocalScope(func() px.Value {
+					scope.Set(m.key, mv)
+					r, _ := interpolateString(ic, m.template, false)
+					rp := filepath.Join(dataDir, r.String())
+					_, err := os.Stat(rp)
+					paths[i] = &path{m.template, rp, err == nil}
+					return nil
+				})
 			})
 		})
-	})
-	 */
+	*/
 	return paths
 }
diff --git a/loader/instantiate.go b/loader/instantiate.go
index cee79f3..8220a18 100644
--- a/loader/instantiate.go
+++ b/loader/instantiate.go
@@ -2,8 +2,8 @@ package loader
 
 import (
 	"github.com/lyraproj/issue/issue"
-	"github.com/lyraproj/pcore/px"
 	"github.com/lyraproj/pcore/loader"
+	"github.com/lyraproj/pcore/px"
 	"github.com/lyraproj/pcore/types"
 	"gopkg.in/yaml.v2"
 )
diff --git a/lookup/location.go b/lookup/location.go
index 64d88eb..812bf75 100644
--- a/lookup/location.go
+++ b/lookup/location.go
@@ -4,10 +4,10 @@ import "fmt"
 
 type LocationKind string
 
-const LC_PATH = LocationKind(`path`)
-const LC_URI = LocationKind(`uri`)
-const LC_GLOB = LocationKind(`glob`)
-const LC_MAPPED_PATHS = LocationKind(`mapped_paths`)
+const LcPath = LocationKind(`path`)
+const LcUri = LocationKind(`uri`)
+const LcGlob = LocationKind(`glob`)
+const LcMappedPaths = LocationKind(`mapped_paths`)
 
 type Location interface {
 	fmt.Stringer
diff --git a/impl/testdata/sample_data.yaml b/lookup/testdata/sample_data.yaml
similarity index 100%
rename from impl/testdata/sample_data.yaml
rename to lookup/testdata/sample_data.yaml
diff --git a/provider/yamlprovider.go b/provider/yamlprovider.go
index c2b1eab..07acf68 100644
--- a/provider/yamlprovider.go
+++ b/provider/yamlprovider.go
@@ -23,7 +23,7 @@ func Yaml(c lookup.ProviderContext, key string, options map[string]px.Value) (px
 			if bin, ok := types.BinaryFromFile2(path); ok {
 				data = yaml.Unmarshal(c.Invocation(), bin.Bytes())
 				if _, ok := data.(px.OrderedMap); !ok {
-					panic(px.Error(impl.HIERA_YAML_NOT_HASH, issue.H{`path`: path}))
+					panic(px.Error(impl.HieraYamlNotHash, issue.H{`path`: path}))
 				}
 			} else {
 				// File not found. This is OK but yields an empty map
@@ -31,7 +31,7 @@ func Yaml(c lookup.ProviderContext, key string, options map[string]px.Value) (px
 			}
 			c.Cache(YamlDataKey, data)
 		} else {
-			panic(px.Error(impl.HIERA_MISSING_REQUIRED_OPTION, issue.H{`option`: `path`}))
+			panic(px.Error(impl.HieraMissingRequiredOption, issue.H{`option`: `path`}))
 		}
 	}
 	hash, _ := data.(px.OrderedMap)
diff --git a/util/glob.go b/util/glob.go
deleted file mode 100644
index 025f1a1..0000000
--- a/util/glob.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package util
-
-import (
-	"github.com/gobwas/glob"
-	"os"
-	"path/filepath"
-)
-
-func Glob(root string, pattern string) (matches []string, e error) {
-	return getDirectoryTree(root, glob.MustCompile(filepath.FromSlash(pattern), filepath.Separator))
-}
-
-func getDirectoryTree(root string, g glob.Glob) ([]string, error) {
-	matches := make([]string, 0, 64)
-	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
-		if err == nil && info.Name() != `.` && g.Match(path) {
-			matches = append(matches, path)
-		}
-		return err
-	})
-	if err != nil {
-		matches = nil
-	}
-	return matches, err
-}


Test patch:
diff --git a/impl/key_test.go b/impl/key_test.go
index 1a50fd9..a7aa2a7 100644
--- a/impl/key_test.go
+++ b/impl/key_test.go
@@ -6,6 +6,7 @@ import (
 	"github.com/lyraproj/hiera/impl"
 	"github.com/lyraproj/pcore/pcore"
 	"github.com/lyraproj/pcore/px"
+	"strings"
 )
 
 func ExampleNewKey_simple() {
@@ -62,8 +63,16 @@ func ExampleNewKey_doubleQuotedQuote() {
 	// Output: a.b."c'd'e", 3, c'd'e
 }
 
+func printErr(e error) {
+	s := e.Error()
+	if ix := strings.Index(s, ` (file: `); ix > 0 {
+		s = s[0:ix]
+	}
+	fmt.Println(s)
+}
+
 func ExampleNewKey_unterminatedQuoted() {
-	fmt.Println(pcore.TryWithParent(context.Background(), func(c px.Context) error {
+	printErr(pcore.TryWithParent(context.Background(), func(c px.Context) error {
 		impl.NewKey(`a.b."c`)
 		return nil
 	}))
@@ -71,7 +80,7 @@ func ExampleNewKey_unterminatedQuoted() {
 }
 
 func ExampleNewKey_empty() {
-	fmt.Println(pcore.TryWithParent(context.Background(), func(c px.Context) error {
+	printErr(pcore.TryWithParent(context.Background(), func(c px.Context) error {
 		impl.NewKey(``)
 		return nil
 	}))
@@ -79,7 +88,7 @@ func ExampleNewKey_empty() {
 }
 
 func ExampleNewKey_emptySegment() {
-	fmt.Println(pcore.TryWithParent(context.Background(), func(c px.Context) error {
+	printErr(pcore.TryWithParent(context.Background(), func(c px.Context) error {
 		impl.NewKey(`a..b`)
 		return nil
 	}))
@@ -87,7 +96,7 @@ func ExampleNewKey_emptySegment() {
 }
 
 func ExampleNewKey_emptySegmentStart() {
-	fmt.Println(pcore.TryWithParent(context.Background(), func(c px.Context) error {
+	printErr(pcore.TryWithParent(context.Background(), func(c px.Context) error {
 		impl.NewKey(`.b`)
 		return nil
 	}))
@@ -95,7 +104,7 @@ func ExampleNewKey_emptySegmentStart() {
 }
 
 func ExampleNewKey_emptySegmentEnd() {
-	fmt.Println(pcore.TryWithParent(context.Background(), func(c px.Context) error {
+	printErr(pcore.TryWithParent(context.Background(), func(c px.Context) error {
 		impl.NewKey(`a.`)
 		return nil
 	}))
@@ -103,7 +112,7 @@ func ExampleNewKey_emptySegmentEnd() {
 }
 
 func ExampleNewKey_firstSegmentIndex() {
-	fmt.Println(pcore.TryWithParent(context.Background(), func(c px.Context) error {
+	printErr(pcore.TryWithParent(context.Background(), func(c px.Context) error {
 		impl.NewKey(`1.a`)
 		return nil
 	}))
diff --git a/impl/context_test.go b/lookup/api_test.go
similarity index 90%
rename from impl/context_test.go
rename to lookup/api_test.go
index 3e5094c..9263e89 100644
--- a/impl/context_test.go
+++ b/lookup/api_test.go
@@ -1,4 +1,4 @@
-package impl_test
+package lookup_test
 
 import (
 	"context"
@@ -10,6 +10,7 @@ import (
 	"github.com/lyraproj/pcore/pcore"
 	"github.com/lyraproj/pcore/px"
 	"github.com/lyraproj/pcore/types"
+	"strings"
 
 	// Ensure initialization
 	_ "github.com/lyraproj/hiera/functions"
@@ -83,6 +84,14 @@ func ExampleLookup_interpolateEmpty() {
 	// startend
 }
 
+func printErr(e error) {
+	s := e.Error()
+	if ix := strings.Index(s, ` (file: `); ix > 0 {
+		s = s[0:ix]
+	}
+	fmt.Println(s)
+}
+
 func ExampleLookup_interpolateLiteral() {
 	lookup.DoWithParent(context.Background(), provider.Yaml, options, func(c px.Context) {
 		fmt.Println(lookup.Lookup(impl.NewInvocation(c, px.EmptyMap), `ipLiteral`, nil, options))
@@ -99,7 +108,7 @@ func ExampleLookup_interpolateAlias() {
 }
 
 func ExampleLookup_interpolateBadAlias() {
-	fmt.Println(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
+	printErr(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
 		lookup.Lookup(impl.NewInvocation(c, px.EmptyMap), `ipBadAlias`, nil, options)
 		return nil
 	}))
@@ -107,7 +116,7 @@ func ExampleLookup_interpolateBadAlias() {
 }
 
 func ExampleLookup_interpolateBadFunction() {
-	fmt.Println(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
+	printErr(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
 		lookup.Lookup(impl.NewInvocation(c, px.EmptyMap), `ipBad`, nil, options)
 		return nil
 	}))
@@ -115,7 +124,7 @@ func ExampleLookup_interpolateBadFunction() {
 }
 
 func ExampleLookup_notFoundWithoutDefault() {
-	fmt.Println(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
+	printErr(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
 		lookup.Lookup(impl.NewInvocation(c, px.EmptyMap), `nonexistent`, nil, options)
 		return nil
 	}))
@@ -144,7 +153,7 @@ func ExampleLookup_notFoundDottedMix() {
 }
 
 func ExampleLookup_badStringDig() {
-	fmt.Println(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
+	printErr(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
 		lookup.Lookup(impl.NewInvocation(c, px.EmptyMap), `hash.int.v`, nil, options)
 		return nil
 	}))
@@ -152,7 +161,7 @@ func ExampleLookup_badStringDig() {
 }
 
 func ExampleLookup_badIntDig() {
-	fmt.Println(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
+	printErr(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
 		lookup.Lookup(impl.NewInvocation(c, px.EmptyMap), `hash.3`, nil, options)
 		return nil
 	}))
@@ -174,7 +183,7 @@ func ExampleLookup2_findSecond() {
 }
 
 func ExampleLookup2_notFoundWithoutDflt() {
-	fmt.Println(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
+	printErr(lookup.TryWithParent(context.Background(), provider.Yaml, options, func(c px.Context) error {
 		lookup.Lookup2(impl.NewInvocation(c, px.EmptyMap), []string{`nonexisting`, `notthere`}, types.DefaultAnyType(), nil, nil, nil, options, nil)
 		return nil
 	}))
@@ -188,7 +197,7 @@ func ExampleLookup2_notFoundDflt() {
 	// Output: default value
 }
 
-func ExampleContextCachedValue() {
+func ExampleProviderContext_CachedValue() {
 
 	cachingProvider := func(ic lookup.ProviderContext, key string, options map[string]px.Value) (px.Value, bool) {
 		if v, ok := ic.CachedValue(key); ok {
diff --git a/util/glob_test.go b/util/glob_test.go
deleted file mode 100644
index 5954b0b..0000000
--- a/util/glob_test.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package util
-
-import (
-	"fmt"
-	"github.com/bmatcuk/doublestar"
-)
-
-func ExampleSplit() {
-	matches, err := doublestar.Glob(`**/*_test.go`)
-	if err != nil {
-		fmt.Println(err)
-	} else {
-		for _, m := range matches {
-			fmt.Println(m)
-		}
-	}
-	// Output: glob_test.go
-}