github.com/tardisgo/tardisgo@v0.0.0-20161119180838-e0dd9a7e46b5/pogo/errors.go (about) 1 // Copyright 2014 Elliott Stoneham and The TARDIS Go Authors 2 // Use of this source code is governed by an MIT-style 3 // license that can be found in the LICENSE file. 4 5 package pogo 6 7 import ( 8 "fmt" 9 "go/token" 10 "os" 11 "sort" 12 ) 13 14 func (comp *Compilation) initErrors() { 15 comp.hadErrors = false 16 comp.stopOnError = true // TODO make this soft and default true 17 comp.warnings = make([]string, 0) // Warnings are collected up and added to the end of the output code. 18 comp.messagesGiven = make(map[string]bool) // This map de-dups error messages 19 20 // PosHashFileList holds the list of input go files with their posHash information 21 comp.PosHashFileList = make([]PosHashFileStruct, 0) 22 // LatestValidPosHash holds the latest valid PosHash value seen, for use when an invalid one requires a "near" reference. 23 comp.LatestValidPosHash = NoPosHash 24 } 25 26 // Utility message handler for errors 27 func (comp *Compilation) logMessage(level, loc, lang string, err error) { 28 msg := fmt.Sprintf("%s : %s (%s) %v \n", level, loc, lang, err) 29 // don't emit duplicate messages 30 _, hadIt := comp.messagesGiven[msg] 31 if !hadIt { 32 fmt.Fprintf(os.Stderr, "%s", msg) 33 comp.messagesGiven[msg] = true 34 } 35 } 36 37 // LogWarning but a warning does not stop the compiler from claiming success. 38 func (comp *Compilation) LogWarning(loc, lang string, err error) { 39 comp.warnings = append(comp.warnings, fmt.Sprintf("Warning: %s (%s) %v", loc, lang, err)) 40 } 41 42 // LogError and potentially stop the compilation process. 43 func (comp *Compilation) LogError(loc, lang string, err error) { 44 comp.logMessage("Error", loc, lang, err) 45 comp.hadErrors = true 46 } 47 48 // CodePosition is a utility to provide a string version of token.Pos. 49 // this string should be used for documentation & debug only. 50 func (comp *Compilation) CodePosition(pos token.Pos) string { 51 52 p := comp.rootProgram.Fset.Position(pos).String() 53 if p == "-" { 54 return "" 55 } 56 return p 57 } 58 59 // A PosHash is a hash of the code position, set -ve if a nearby PosHash is used. 60 type PosHash int 61 62 // NoPosHash is a code position hash constant to represent none, lines number from 1, so 0 is invalid. 63 const NoPosHash = PosHash(0) 64 65 // PosHashFileStruct stores the code position information for each file in order to generate PosHash values. 66 type PosHashFileStruct struct { 67 FileName string // The name of the file. 68 LineCount int // The number of lines in that file. 69 BasePosHash int // The base posHash value for this file. 70 } 71 72 type posHashFileSorter []PosHashFileStruct 73 74 func (a posHashFileSorter) Len() int { return len(a) } 75 func (a posHashFileSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 76 func (a posHashFileSorter) Less(i, j int) bool { return a[i].FileName < a[j].FileName } 77 78 // Create the PosHashFileList to enable poshash values to be emitted 79 func (comp *Compilation) setupPosHash() { 80 comp.rootProgram.Fset.Iterate(func(fRef *token.File) bool { 81 comp.PosHashFileList = append(comp.PosHashFileList, 82 PosHashFileStruct{FileName: fRef.Name(), LineCount: fRef.LineCount()}) 83 return true 84 }) 85 sort.Sort(posHashFileSorter(comp.PosHashFileList)) 86 for f := range comp.PosHashFileList { 87 if f > 0 { 88 comp.PosHashFileList[f].BasePosHash = 89 comp.PosHashFileList[f-1].BasePosHash + comp.PosHashFileList[f-1].LineCount 90 } 91 } 92 } 93 94 // MakePosHash keeps track of references put into the code for later extraction in a runtime debug function. 95 // It returns the PosHash integer to be used for exception handling that was passed in. 96 func (comp *Compilation) MakePosHash(pos token.Pos) PosHash { 97 if pos.IsValid() { 98 fname := comp.rootProgram.Fset.Position(pos).Filename 99 for f := range comp.PosHashFileList { 100 if comp.PosHashFileList[f].FileName == fname { 101 comp.LatestValidPosHash = PosHash(comp.PosHashFileList[f].BasePosHash + 102 comp.rootProgram.Fset.Position(pos).Line) 103 return comp.LatestValidPosHash 104 } 105 } 106 panic(fmt.Errorf("pogo.MakePosHash() Cant find file: %s", fname)) 107 } else { 108 if comp.LatestValidPosHash == NoPosHash { 109 return NoPosHash 110 } 111 return -comp.LatestValidPosHash // -ve value => nearby reference 112 } 113 }