本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
2.8KB

  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package scanner
  5. import (
  6. "fmt"
  7. "io"
  8. "sort"
  9. )
  10. import (
  11. "github.com/src-d/gcfg/token"
  12. )
  13. // In an ErrorList, an error is represented by an *Error.
  14. // The position Pos, if valid, points to the beginning of
  15. // the offending token, and the error condition is described
  16. // by Msg.
  17. //
  18. type Error struct {
  19. Pos token.Position
  20. Msg string
  21. }
  22. // Error implements the error interface.
  23. func (e Error) Error() string {
  24. if e.Pos.Filename != "" || e.Pos.IsValid() {
  25. // don't print "<unknown position>"
  26. // TODO(gri) reconsider the semantics of Position.IsValid
  27. return e.Pos.String() + ": " + e.Msg
  28. }
  29. return e.Msg
  30. }
  31. // ErrorList is a list of *Errors.
  32. // The zero value for an ErrorList is an empty ErrorList ready to use.
  33. //
  34. type ErrorList []*Error
  35. // Add adds an Error with given position and error message to an ErrorList.
  36. func (p *ErrorList) Add(pos token.Position, msg string) {
  37. *p = append(*p, &Error{pos, msg})
  38. }
  39. // Reset resets an ErrorList to no errors.
  40. func (p *ErrorList) Reset() { *p = (*p)[0:0] }
  41. // ErrorList implements the sort Interface.
  42. func (p ErrorList) Len() int { return len(p) }
  43. func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
  44. func (p ErrorList) Less(i, j int) bool {
  45. e := &p[i].Pos
  46. f := &p[j].Pos
  47. if e.Filename < f.Filename {
  48. return true
  49. }
  50. if e.Filename == f.Filename {
  51. return e.Offset < f.Offset
  52. }
  53. return false
  54. }
  55. // Sort sorts an ErrorList. *Error entries are sorted by position,
  56. // other errors are sorted by error message, and before any *Error
  57. // entry.
  58. //
  59. func (p ErrorList) Sort() {
  60. sort.Sort(p)
  61. }
  62. // RemoveMultiples sorts an ErrorList and removes all but the first error per line.
  63. func (p *ErrorList) RemoveMultiples() {
  64. sort.Sort(p)
  65. var last token.Position // initial last.Line is != any legal error line
  66. i := 0
  67. for _, e := range *p {
  68. if e.Pos.Filename != last.Filename || e.Pos.Line != last.Line {
  69. last = e.Pos
  70. (*p)[i] = e
  71. i++
  72. }
  73. }
  74. (*p) = (*p)[0:i]
  75. }
  76. // An ErrorList implements the error interface.
  77. func (p ErrorList) Error() string {
  78. switch len(p) {
  79. case 0:
  80. return "no errors"
  81. case 1:
  82. return p[0].Error()
  83. }
  84. return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1)
  85. }
  86. // Err returns an error equivalent to this error list.
  87. // If the list is empty, Err returns nil.
  88. func (p ErrorList) Err() error {
  89. if len(p) == 0 {
  90. return nil
  91. }
  92. return p
  93. }
  94. // PrintError is a utility function that prints a list of errors to w,
  95. // one error per line, if the err parameter is an ErrorList. Otherwise
  96. // it prints the err string.
  97. //
  98. func PrintError(w io.Writer, err error) {
  99. if list, ok := err.(ErrorList); ok {
  100. for _, e := range list {
  101. fmt.Fprintf(w, "%s\n", e)
  102. }
  103. } else if err != nil {
  104. fmt.Fprintf(w, "%s\n", err)
  105. }
  106. }
上海开阖软件有限公司 沪ICP备12045867号-1