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  }