mirror of
https://github.com/kevin-DL/revel-cmd.git
synced 2026-01-23 15:31:26 +00:00
Upatede Error type to SourceError
Added processor object to code Verified compile errors appearing Signed-off-by: notzippy@gmail.com
This commit is contained in:
@@ -388,7 +388,7 @@ func containsValue(m map[string]string, val string) bool {
|
|||||||
|
|
||||||
// Parse the output of the "go build" command.
|
// Parse the output of the "go build" command.
|
||||||
// Return a detailed Error.
|
// Return a detailed Error.
|
||||||
func newCompileError(paths *model.RevelContainer, output []byte) *utils.Error {
|
func newCompileError(paths *model.RevelContainer, output []byte) *utils.SourceError {
|
||||||
errorMatch := regexp.MustCompile(`(?m)^([^:#]+):(\d+):(\d+:)? (.*)$`).
|
errorMatch := regexp.MustCompile(`(?m)^([^:#]+):(\d+):(\d+:)? (.*)$`).
|
||||||
FindSubmatch(output)
|
FindSubmatch(output)
|
||||||
if errorMatch == nil {
|
if errorMatch == nil {
|
||||||
@@ -396,7 +396,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.Error {
|
|||||||
|
|
||||||
if errorMatch == nil {
|
if errorMatch == nil {
|
||||||
utils.Logger.Error("Failed to parse build errors", "error", string(output))
|
utils.Logger.Error("Failed to parse build errors", "error", string(output))
|
||||||
return &utils.Error{
|
return &utils.SourceError{
|
||||||
SourceType: "Go code",
|
SourceType: "Go code",
|
||||||
Title: "Go Compilation Error",
|
Title: "Go Compilation Error",
|
||||||
Description: "See console for build error.",
|
Description: "See console for build error.",
|
||||||
@@ -429,7 +429,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.Error {
|
|||||||
absFilename = findInPaths(relFilename)
|
absFilename = findInPaths(relFilename)
|
||||||
line, _ = strconv.Atoi(string(errorMatch[2]))
|
line, _ = strconv.Atoi(string(errorMatch[2]))
|
||||||
description = string(errorMatch[4])
|
description = string(errorMatch[4])
|
||||||
compileError = &utils.Error{
|
compileError = &utils.SourceError{
|
||||||
SourceType: "Go code",
|
SourceType: "Go code",
|
||||||
Title: "Go Compilation Error",
|
Title: "Go Compilation Error",
|
||||||
Path: relFilename,
|
Path: relFilename,
|
||||||
|
|||||||
@@ -89,12 +89,12 @@ func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err erro
|
|||||||
fmt.Fprintf(iw, "An error ocurred %s", err.Error())
|
fmt.Fprintf(iw, "An error ocurred %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var revelError *utils.Error
|
var revelError *utils.SourceError
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case *utils.Error:
|
case *utils.SourceError:
|
||||||
revelError = e
|
revelError = e
|
||||||
case error:
|
case error:
|
||||||
revelError = &utils.Error{
|
revelError = &utils.SourceError{
|
||||||
Title: "Server Error",
|
Title: "Server Error",
|
||||||
Description: e.Error(),
|
Description: e.Error(),
|
||||||
}
|
}
|
||||||
@@ -199,7 +199,7 @@ func NewHarness(c *model.CommandConfig, paths *model.RevelContainer, runMode str
|
|||||||
|
|
||||||
// Refresh method rebuilds the Revel application and run it on the given port.
|
// Refresh method rebuilds the Revel application and run it on the given port.
|
||||||
// called by the watcher
|
// called by the watcher
|
||||||
func (h *Harness) Refresh() (err *utils.Error) {
|
func (h *Harness) Refresh() (err *utils.SourceError) {
|
||||||
// Allow only one thread to rebuild the process
|
// Allow only one thread to rebuild the process
|
||||||
// If multiple requests to rebuild are queued only the last one is executed on
|
// If multiple requests to rebuild are queued only the last one is executed on
|
||||||
// So before a build is started we wait for a second to determine if
|
// So before a build is started we wait for a second to determine if
|
||||||
@@ -217,10 +217,10 @@ func (h *Harness) Refresh() (err *utils.Error) {
|
|||||||
h.app, newErr = Build(h.config, h.paths)
|
h.app, newErr = Build(h.config, h.paths)
|
||||||
if newErr != nil {
|
if newErr != nil {
|
||||||
utils.Logger.Error("Build detected an error", "error", newErr)
|
utils.Logger.Error("Build detected an error", "error", newErr)
|
||||||
if castErr, ok := newErr.(*utils.Error); ok {
|
if castErr, ok := newErr.(*utils.SourceError); ok {
|
||||||
return castErr
|
return castErr
|
||||||
}
|
}
|
||||||
err = &utils.Error{
|
err = &utils.SourceError{
|
||||||
Title: "App failed to start up",
|
Title: "App failed to start up",
|
||||||
Description: err.Error(),
|
Description: err.Error(),
|
||||||
}
|
}
|
||||||
@@ -231,10 +231,10 @@ func (h *Harness) Refresh() (err *utils.Error) {
|
|||||||
h.app.Port = h.port
|
h.app.Port = h.port
|
||||||
if err2 := h.app.Cmd(h.runMode).Start(h.config); err2 != nil {
|
if err2 := h.app.Cmd(h.runMode).Start(h.config); err2 != nil {
|
||||||
utils.Logger.Error("Could not start application", "error", err2)
|
utils.Logger.Error("Could not start application", "error", err2)
|
||||||
if err,k :=err2.(*utils.Error);k {
|
if err,k :=err2.(*utils.SourceError);k {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return &utils.Error{
|
return &utils.SourceError{
|
||||||
Title: "App failed to start up",
|
Title: "App failed to start up",
|
||||||
Description: err2.Error(),
|
Description: err2.Error(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func (pc *processContainer) processPath(path string, info os.FileInfo, err error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if errList, ok := err.(scanner.ErrorList); ok {
|
if errList, ok := err.(scanner.ErrorList); ok {
|
||||||
var pos = errList[0].Pos
|
var pos = errList[0].Pos
|
||||||
newError := &utils.Error{
|
newError := &utils.SourceError{
|
||||||
SourceType: ".go source",
|
SourceType: ".go source",
|
||||||
Title: "Go Compilation Error",
|
Title: "Go Compilation Error",
|
||||||
Path: pos.Filename,
|
Path: pos.Filename,
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
//"golang.org/x/tools/go/packages"
|
|
||||||
//"github.com/revel/cmd/utils"
|
|
||||||
)
|
|
||||||
//import "golang.org/x/tools/go/packages"
|
|
||||||
//
|
|
||||||
//func GetPackage(appPath, importPath string) {
|
|
||||||
// config := &packages.Config{
|
|
||||||
// Mode: packages.NeedName | packages.NeedFiles,
|
|
||||||
// Dir:appPath,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pkgs, err := packages.Load(config, []string{importPath})
|
|
||||||
// utils.Logger.Info("Loaded packegs ", "len results", len(pkgs), "error",err)
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
246
parser2/read.go
246
parser2/read.go
@@ -1,76 +1,218 @@
|
|||||||
package parser2
|
package parser2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//"go/ast"
|
"go/ast"
|
||||||
//"go/token"
|
"go/token"
|
||||||
|
|
||||||
"github.com/revel/cmd/model"
|
"github.com/revel/cmd/model"
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
"github.com/revel/cmd/utils"
|
"github.com/revel/cmd/utils"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"github.com/revel/cmd/logger"
|
||||||
|
|
||||||
|
)
|
||||||
|
type (
|
||||||
|
SourceProcessor struct {
|
||||||
|
revelContainer *model.RevelContainer
|
||||||
|
log logger.MultiLogger
|
||||||
|
packageList []*packages.Package
|
||||||
|
importMap map[string]string
|
||||||
|
}
|
||||||
)
|
)
|
||||||
func ProcessSource(revelContainer *model.RevelContainer) (sourceInfo *model.SourceInfo, compileError error) {
|
func ProcessSource(revelContainer *model.RevelContainer) (sourceInfo *model.SourceInfo, compileError error) {
|
||||||
utils.Logger.Info("ProcessSource")
|
utils.Logger.Info("ProcessSource")
|
||||||
// Combine packages for modules and app and revel
|
processor := NewSourceProcessor(revelContainer)
|
||||||
allPackages := []string{revelContainer.ImportPath+"/app/controllers/...",model.RevelImportPath}
|
sourceInfo, compileError = processor.parse()
|
||||||
for _,module := range revelContainer.ModulePathMap {
|
fmt.Printf("From parsers \n%v\n%v\n",sourceInfo,compileError)
|
||||||
allPackages = append(allPackages,module.ImportPath+"/app/controllers/...")
|
//// Combine packages for modules and app and revel
|
||||||
}
|
//allPackages := []string{revelContainer.ImportPath+"/app/controllers/...",model.RevelImportPath}
|
||||||
|
//for _,module := range revelContainer.ModulePathMap {
|
||||||
config := &packages.Config{
|
// allPackages = append(allPackages,module.ImportPath+"/app/controllers/...")
|
||||||
Mode: packages.NeedName | packages.NeedFiles | packages.LoadTypes | packages.NeedTypes | packages.NeedSyntax , //| packages.NeedImports |
|
|
||||||
// packages.NeedTypes, // packages.LoadTypes | packages.NeedSyntax | packages.NeedTypesInfo,
|
|
||||||
//packages.LoadSyntax | packages.NeedDeps,
|
|
||||||
Dir:revelContainer.AppPath,
|
|
||||||
}
|
|
||||||
utils.Logger.Info("Before ","apppath", config.Dir,"paths",allPackages)
|
|
||||||
pkgs, err := packages.Load(config, allPackages...)
|
|
||||||
utils.Logger.Info("***Loaded packegs ", "len results", len(pkgs), "error",err)
|
|
||||||
// Lets see if we can output all the path names
|
|
||||||
//packages.Visit(pkgs,func(p *packages.Package) bool{
|
|
||||||
// println("Got pre",p.ID)
|
|
||||||
// return true
|
|
||||||
//}, func(p *packages.Package) {
|
|
||||||
//})
|
|
||||||
counter := 0
|
|
||||||
for _, p := range pkgs {
|
|
||||||
utils.Logger.Info("Errores","error",p.Errors, "id",p.ID)
|
|
||||||
//for _,g := range p.GoFiles {
|
|
||||||
// println("File", g)
|
|
||||||
//}
|
//}
|
||||||
//for _, t:= range p.Syntax {
|
//allPackages = []string{revelContainer.ImportPath+"/app/controllers/..."}
|
||||||
// utils.Logger.Info("File","name",t.Name)
|
|
||||||
//}
|
|
||||||
println("package typoe fouhnd ",p.Types.Name())
|
|
||||||
//imports := map[string]string{}
|
|
||||||
|
|
||||||
for _,s := range p.Syntax {
|
|
||||||
println("File ",s.Name.Name )
|
|
||||||
//for _, decl := range s.Decls {
|
|
||||||
// if decl.Tok == token.IMPORT {
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//p.Fset.Iterate(func(file *token.File) bool{
|
|
||||||
//
|
//
|
||||||
// // utils.Logger.Info("Output","Found file", p.ID," AND NAME ", f.Name())
|
//config := &packages.Config{
|
||||||
// // For each declaration in the source file...
|
// // ode: packages.NeedSyntax | packages.NeedCompiledGoFiles,
|
||||||
// //for _, decl := range file.Decls {
|
// Mode: packages.NeedTypes | packages.NeedSyntax ,
|
||||||
// // addImports(imports, decl, pkgPath)
|
// //Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles |
|
||||||
// //}
|
// // packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile |
|
||||||
// counter ++
|
// // packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo |
|
||||||
// return true
|
// // packages.NeedTypesSizes,
|
||||||
//})
|
//
|
||||||
|
// //Mode: packages.NeedName | packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedFiles |
|
||||||
|
// // packages.NeedCompiledGoFiles | packages.NeedTypesSizes |
|
||||||
|
// // packages.NeedSyntax | packages.NeedCompiledGoFiles ,
|
||||||
|
// //Mode: packages.NeedSyntax | packages.NeedCompiledGoFiles | packages.NeedName | packages.NeedFiles |
|
||||||
|
// // packages.LoadTypes | packages.NeedTypes | packages.NeedDeps, //, // |
|
||||||
|
// // packages.NeedTypes, // packages.LoadTypes | packages.NeedSyntax | packages.NeedTypesInfo,
|
||||||
|
// //packages.LoadSyntax | packages.NeedDeps,
|
||||||
|
// Dir:revelContainer.AppPath,
|
||||||
//}
|
//}
|
||||||
|
//utils.Logger.Info("Before ","apppath", config.Dir,"paths",allPackages)
|
||||||
|
//pkgs, err := packages.Load(config, allPackages...)
|
||||||
|
//utils.Logger.Info("***Loaded packegs ", "len results", len(pkgs), "error",err)
|
||||||
|
//// Lets see if we can output all the path names
|
||||||
|
////packages.Visit(pkgs,func(p *packages.Package) bool{
|
||||||
|
//// println("Got pre",p.ID)
|
||||||
|
//// return true
|
||||||
|
////}, func(p *packages.Package) {
|
||||||
|
////})
|
||||||
|
//counter := 0
|
||||||
|
//for _, p := range pkgs {
|
||||||
|
// utils.Logger.Info("Errores","error",p.Errors, "id",p.ID)
|
||||||
|
// //for _,g := range p.GoFiles {
|
||||||
|
// // println("File", g)
|
||||||
|
// //}
|
||||||
|
// //for _, t:= range p.Syntax {
|
||||||
|
// // utils.Logger.Info("File","name",t.Name)
|
||||||
|
// //}
|
||||||
|
// //println("package typoe fouhnd ",p.Types.Name())
|
||||||
|
// //imports := map[string]string{}
|
||||||
|
//
|
||||||
|
// for _,s := range p.Syntax {
|
||||||
|
// println("File ",s.Name.Name )
|
||||||
|
// for _, decl := range s.Decls {
|
||||||
|
// genDecl, ok := decl.(*ast.GenDecl)
|
||||||
|
// if !ok {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if genDecl.Tok == token.IMPORT {
|
||||||
|
// for _, spec := range genDecl.Specs {
|
||||||
|
// importSpec := spec.(*ast.ImportSpec)
|
||||||
|
// fmt.Printf("*** import specification %#v\n", importSpec)
|
||||||
|
// var pkgAlias string
|
||||||
|
// if importSpec.Name != nil {
|
||||||
|
// pkgAlias = importSpec.Name.Name
|
||||||
|
// if pkgAlias == "_" {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
|
||||||
|
// fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes
|
||||||
|
// if pkgAlias == "" {
|
||||||
|
// pkgAlias = fullPath
|
||||||
|
// if index:=strings.LastIndex(pkgAlias,"/");index>0 {
|
||||||
|
// pkgAlias = pkgAlias[index+1:]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //imports[pkgAlias] = fullPath
|
||||||
|
// println("Package ", pkgAlias, "fullpath", fullPath)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //p.Fset.Iterate(func(file *token.File) bool{
|
||||||
|
// //
|
||||||
|
// // // utils.Logger.Info("Output","Found file", p.ID," AND NAME ", f.Name())
|
||||||
|
// // // For each declaration in the source file...
|
||||||
|
// // //for _, decl := range file.Decls {
|
||||||
|
// // // addImports(imports, decl, pkgPath)
|
||||||
|
// // //}
|
||||||
|
// // counter ++
|
||||||
|
// // return true
|
||||||
|
// //})
|
||||||
|
////}
|
||||||
|
if false {
|
||||||
compileError = errors.New("Incompleted")
|
compileError = errors.New("Incompleted")
|
||||||
println("*******************", counter)
|
|
||||||
utils.Logger.Panic("Not implemented")
|
utils.Logger.Panic("Not implemented")
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewSourceProcessor(revelContainer *model.RevelContainer) *SourceProcessor {
|
||||||
|
return &SourceProcessor{revelContainer:revelContainer, log:utils.Logger.New("parser","SourceProcessor")}
|
||||||
|
}
|
||||||
|
func (s *SourceProcessor) parse() (sourceInfo *model.SourceInfo, compileError error) {
|
||||||
|
if compileError=s.addPackages();compileError!=nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if compileError = s.addImportMap();compileError!=nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (s *SourceProcessor) addPackages() (err error) {
|
||||||
|
allPackages := []string{s.revelContainer.ImportPath+"/app/controllers/...",model.RevelImportPath}
|
||||||
|
for _,module := range s.revelContainer.ModulePathMap {
|
||||||
|
allPackages = append(allPackages,module.ImportPath+"/app/controllers/...")
|
||||||
|
}
|
||||||
|
allPackages = []string{s.revelContainer.ImportPath+"/app/controllers/..."}
|
||||||
|
|
||||||
|
config := &packages.Config{
|
||||||
|
// ode: packages.NeedSyntax | packages.NeedCompiledGoFiles,
|
||||||
|
Mode: packages.NeedTypes | packages.NeedSyntax ,
|
||||||
|
//Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles |
|
||||||
|
// packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile |
|
||||||
|
// packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo |
|
||||||
|
// packages.NeedTypesSizes,
|
||||||
|
|
||||||
|
//Mode: packages.NeedName | packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedFiles |
|
||||||
|
// packages.NeedCompiledGoFiles | packages.NeedTypesSizes |
|
||||||
|
// packages.NeedSyntax | packages.NeedCompiledGoFiles ,
|
||||||
|
//Mode: packages.NeedSyntax | packages.NeedCompiledGoFiles | packages.NeedName | packages.NeedFiles |
|
||||||
|
// packages.LoadTypes | packages.NeedTypes | packages.NeedDeps, //, // |
|
||||||
|
// packages.NeedTypes, // packages.LoadTypes | packages.NeedSyntax | packages.NeedTypesInfo,
|
||||||
|
//packages.LoadSyntax | packages.NeedDeps,
|
||||||
|
Dir:s.revelContainer.AppPath,
|
||||||
|
}
|
||||||
|
s.packageList, err = packages.Load(config, allPackages...)
|
||||||
|
s.log.Info("***Loaded packegs ", "len results", len(s.packageList), "error",err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (s *SourceProcessor) addImportMap() (err error) {
|
||||||
|
s.importMap = map[string]string{}
|
||||||
|
for _, p := range s.packageList {
|
||||||
|
if len(p.Errors)>0 {
|
||||||
|
// Generate a compile error
|
||||||
|
for _,e:=range p.Errors {
|
||||||
|
err = utils.NewCompileError("","",e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
utils.Logger.Info("Errores","error",p.Errors, "id",p.ID)
|
||||||
|
|
||||||
|
for _,tree := range p.Syntax {
|
||||||
|
println("File ",tree.Name.Name )
|
||||||
|
for _, decl := range tree.Decls {
|
||||||
|
genDecl, ok := decl.(*ast.GenDecl)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if genDecl.Tok == token.IMPORT {
|
||||||
|
for _, spec := range genDecl.Specs {
|
||||||
|
importSpec := spec.(*ast.ImportSpec)
|
||||||
|
fmt.Printf("*** import specification %#v\n", importSpec)
|
||||||
|
var pkgAlias string
|
||||||
|
if importSpec.Name != nil {
|
||||||
|
pkgAlias = importSpec.Name.Name
|
||||||
|
if pkgAlias == "_" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
|
||||||
|
fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes
|
||||||
|
if pkgAlias == "" {
|
||||||
|
pkgAlias = fullPath
|
||||||
|
if index:=strings.LastIndex(pkgAlias,"/");index>0 {
|
||||||
|
pkgAlias = pkgAlias[index+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.importMap[pkgAlias] = fullPath
|
||||||
|
println("Package ", pkgAlias, "fullpath", fullPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Add imports to the map from the source dir
|
// Add imports to the map from the source dir
|
||||||
//func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
|
//func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ func describeSuite(testSuite interface{}) TestSuiteDesc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// errorSummary gets an error and returns its summary in human readable format.
|
// errorSummary gets an error and returns its summary in human readable format.
|
||||||
func errorSummary(err *utils.Error) (message string) {
|
func errorSummary(err *utils.SourceError) (message string) {
|
||||||
expectedPrefix := "(expected)"
|
expectedPrefix := "(expected)"
|
||||||
actualPrefix := "(actual)"
|
actualPrefix := "(actual)"
|
||||||
errDesc := err.Description
|
errDesc := err.Description
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/revel/cmd/logger"
|
"github.com/revel/cmd/logger"
|
||||||
|
"strconv"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -43,3 +45,60 @@ func NewBuildIfError(err error, message string, args ...interface{}) (b error) {
|
|||||||
func (b *BuildError) Error() string {
|
func (b *BuildError) Error() string {
|
||||||
return fmt.Sprint(b.Message, b.Args)
|
return fmt.Sprint(b.Message, b.Args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse the output of the "go build" command.
|
||||||
|
// Return a detailed Error.
|
||||||
|
func NewCompileError(importPath, errorLink string, error error) *SourceError {
|
||||||
|
// Get the stack from the error
|
||||||
|
|
||||||
|
errorMatch := regexp.MustCompile(`(?m)^([^:#]+):(\d+):(\d+:)? (.*)$`).
|
||||||
|
FindSubmatch([]byte(error.Error()))
|
||||||
|
if errorMatch == nil {
|
||||||
|
errorMatch = regexp.MustCompile(`(?m)^(.*?):(\d+):\s(.*?)$`).FindSubmatch([]byte(error.Error()))
|
||||||
|
|
||||||
|
if errorMatch == nil {
|
||||||
|
Logger.Error("Failed to parse build errors", "error", error)
|
||||||
|
return &SourceError{
|
||||||
|
SourceType: "Go code",
|
||||||
|
Title: "Go Compilation Error",
|
||||||
|
Description: "See console for build error.",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorMatch = append(errorMatch, errorMatch[3])
|
||||||
|
|
||||||
|
Logger.Error("Build errors", "errors", error)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the source for the offending file.
|
||||||
|
var (
|
||||||
|
relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go"
|
||||||
|
absFilename = relFilename
|
||||||
|
line, _ = strconv.Atoi(string(errorMatch[2]))
|
||||||
|
description = string(errorMatch[4])
|
||||||
|
compileError = &SourceError{
|
||||||
|
SourceType: "Go code",
|
||||||
|
Title: "Go Compilation Error",
|
||||||
|
Path: relFilename,
|
||||||
|
Description: description,
|
||||||
|
Line: line,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// errorLink := paths.Config.StringDefault("error.link", "")
|
||||||
|
|
||||||
|
if errorLink != "" {
|
||||||
|
compileError.SetLink(errorLink)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileStr, err := ReadLines(absFilename)
|
||||||
|
if err != nil {
|
||||||
|
compileError.MetaError = absFilename + ": " + err.Error()
|
||||||
|
Logger.Info("Unable to readlines "+compileError.MetaError, "error", err)
|
||||||
|
return compileError
|
||||||
|
}
|
||||||
|
|
||||||
|
compileError.SourceLines = fileStr
|
||||||
|
return compileError
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
// The error is a wrapper for the
|
// The error is a wrapper for the
|
||||||
type (
|
type (
|
||||||
Error struct {
|
SourceError struct {
|
||||||
SourceType string // The type of source that failed to build.
|
SourceType string // The type of source that failed to build.
|
||||||
Title, Path, Description string // Description of the error, as presented to the user.
|
Title, Path, Description string // Description of the error, as presented to the user.
|
||||||
Line, Column int // Where the error was encountered.
|
Line, Column int // Where the error was encountered.
|
||||||
@@ -24,8 +24,8 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
// Return a new error object
|
// Return a new error object
|
||||||
func NewError(source, title,path,description string) *Error {
|
func NewError(source, title,path,description string) *SourceError {
|
||||||
return &Error {
|
return &SourceError{
|
||||||
SourceType:source,
|
SourceType:source,
|
||||||
Title:title,
|
Title:title,
|
||||||
Path:path,
|
Path:path,
|
||||||
@@ -34,7 +34,7 @@ func NewError(source, title,path,description string) *Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates a link based on the configuration setting "errors.link"
|
// Creates a link based on the configuration setting "errors.link"
|
||||||
func (e *Error) SetLink(errorLink string) {
|
func (e *SourceError) SetLink(errorLink string) {
|
||||||
errorLink = strings.Replace(errorLink, "{{Path}}", e.Path, -1)
|
errorLink = strings.Replace(errorLink, "{{Path}}", e.Path, -1)
|
||||||
errorLink = strings.Replace(errorLink, "{{Line}}", strconv.Itoa(e.Line), -1)
|
errorLink = strings.Replace(errorLink, "{{Line}}", strconv.Itoa(e.Line), -1)
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ func (e *Error) SetLink(errorLink string) {
|
|||||||
// Error method constructs a plaintext version of the error, taking
|
// Error method constructs a plaintext version of the error, taking
|
||||||
// account that fields are optionally set. Returns e.g. Compilation Error
|
// account that fields are optionally set. Returns e.g. Compilation Error
|
||||||
// (in views/header.html:51): expected right delim in end; got "}"
|
// (in views/header.html:51): expected right delim in end; got "}"
|
||||||
func (e *Error) Error() string {
|
func (e *SourceError) Error() string {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
panic("opps")
|
panic("opps")
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ func (e *Error) Error() string {
|
|||||||
|
|
||||||
// ContextSource method returns a snippet of the source around
|
// ContextSource method returns a snippet of the source around
|
||||||
// where the error occurred.
|
// where the error occurred.
|
||||||
func (e *Error) ContextSource() []SourceLine {
|
func (e *SourceError) ContextSource() []SourceLine {
|
||||||
if e.SourceLines == nil {
|
if e.SourceLines == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ func MustChmod(filename string, mode os.FileMode) {
|
|||||||
|
|
||||||
// Called if panic
|
// Called if panic
|
||||||
func PanicOnError(err error, msg string) {
|
func PanicOnError(err error, msg string) {
|
||||||
if revErr, ok := err.(*Error); (ok && revErr != nil) || (!ok && err != nil) {
|
if revErr, ok := err.(*SourceError); (ok && revErr != nil) || (!ok && err != nil) {
|
||||||
Logger.Panicf("Abort: %s: %s %s", msg, revErr, err)
|
Logger.Panicf("Abort: %s: %s %s", msg, revErr, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
type Listener interface {
|
type Listener interface {
|
||||||
// Refresh is invoked by the watcher on relevant filesystem events.
|
// Refresh is invoked by the watcher on relevant filesystem events.
|
||||||
// If the listener returns an error, it is served to the user on the current request.
|
// If the listener returns an error, it is served to the user on the current request.
|
||||||
Refresh() *utils.Error
|
Refresh() *utils.SourceError
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscerningListener allows the receiver to selectively watch files.
|
// DiscerningListener allows the receiver to selectively watch files.
|
||||||
@@ -44,7 +44,7 @@ type Watcher struct {
|
|||||||
paths *model.RevelContainer
|
paths *model.RevelContainer
|
||||||
refreshTimer *time.Timer // The timer to countdown the next refresh
|
refreshTimer *time.Timer // The timer to countdown the next refresh
|
||||||
timerMutex *sync.Mutex // A mutex to prevent concurrent updates
|
timerMutex *sync.Mutex // A mutex to prevent concurrent updates
|
||||||
refreshChannel chan *utils.Error
|
refreshChannel chan *utils.SourceError
|
||||||
refreshChannelCount int
|
refreshChannelCount int
|
||||||
refreshTimerMS time.Duration // The number of milliseconds between refreshing builds
|
refreshTimerMS time.Duration // The number of milliseconds between refreshing builds
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ func NewWatcher(paths *model.RevelContainer, eagerRefresh bool) *Watcher {
|
|||||||
paths.Config.BoolDefault("watch", true) &&
|
paths.Config.BoolDefault("watch", true) &&
|
||||||
paths.Config.StringDefault("watch.mode", "normal") == "eager",
|
paths.Config.StringDefault("watch.mode", "normal") == "eager",
|
||||||
timerMutex: &sync.Mutex{},
|
timerMutex: &sync.Mutex{},
|
||||||
refreshChannel: make(chan *utils.Error, 10),
|
refreshChannel: make(chan *utils.SourceError, 10),
|
||||||
refreshChannelCount: 0,
|
refreshChannelCount: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ func (w *Watcher) NotifyWhenUpdated(listener Listener, watcher *fsnotify.Watcher
|
|||||||
|
|
||||||
// Notify causes the watcher to forward any change events to listeners.
|
// Notify causes the watcher to forward any change events to listeners.
|
||||||
// It returns the first (if any) error returned.
|
// It returns the first (if any) error returned.
|
||||||
func (w *Watcher) Notify() *utils.Error {
|
func (w *Watcher) Notify() *utils.SourceError {
|
||||||
if w.serial {
|
if w.serial {
|
||||||
// Serialize Notify() calls.
|
// Serialize Notify() calls.
|
||||||
w.notifyMutex.Lock()
|
w.notifyMutex.Lock()
|
||||||
@@ -207,7 +207,7 @@ func (w *Watcher) Notify() *utils.Error {
|
|||||||
|
|
||||||
utils.Logger.Info("Watcher:Notify refresh state", "Current Index", i, " last error index", w.lastError)
|
utils.Logger.Info("Watcher:Notify refresh state", "Current Index", i, " last error index", w.lastError)
|
||||||
if w.forceRefresh || refresh || w.lastError == i {
|
if w.forceRefresh || refresh || w.lastError == i {
|
||||||
var err *utils.Error
|
var err *utils.SourceError
|
||||||
if w.serial {
|
if w.serial {
|
||||||
err = listener.Refresh()
|
err = listener.Refresh()
|
||||||
} else {
|
} else {
|
||||||
@@ -229,7 +229,7 @@ func (w *Watcher) Notify() *utils.Error {
|
|||||||
|
|
||||||
// Build a queue for refresh notifications
|
// Build a queue for refresh notifications
|
||||||
// this will not return until one of the queue completes
|
// this will not return until one of the queue completes
|
||||||
func (w *Watcher) notifyInProcess(listener Listener) (err *utils.Error) {
|
func (w *Watcher) notifyInProcess(listener Listener) (err *utils.SourceError) {
|
||||||
shouldReturn := false
|
shouldReturn := false
|
||||||
// This code block ensures that either a timer is created
|
// This code block ensures that either a timer is created
|
||||||
// or that a process would be added the the h.refreshChannel
|
// or that a process would be added the the h.refreshChannel
|
||||||
|
|||||||
Reference in New Issue
Block a user