-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscanner.go
90 lines (82 loc) · 2.81 KB
/
scanner.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright 2014 The presenti Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"go/scanner"
"go/token"
"strconv"
"strings"
"github.com/dupoxy/presenti/notebook"
)
const generatedby = noteBookMarker + " # DO NOT EDIT GENERATED by presenti */"
// makeNoteBook scan source file and return a *notebook.NoteBook or an error.
// it only looks for toplevel comments with a noteBookMarker that are detached
// from next line.
func makeNoteBook(file string, source []byte) (*notebook.NoteBook, error) {
nb := notebook.NewNoteBook()
// add generated comment
currentNote, err := newFilteredNote(generatedby)
if err != nil {
return nil, fmt.Errorf("FilteredNote: %v", err)
}
nb.Save(currentNote) // save it
fset := token.NewFileSet()
// error handler
eh := func(_ token.Position, msg string) {
fmt.Errorf("scanner error handler called (msg = %s)", msg)
}
var s scanner.Scanner
s.Init(fset.AddFile(file, fset.Base(), len(source)), source, eh, scanner.ScanComments)
nbcommentlit := "" // used to store a found nbcommentlit
nbcommentline := 0
expectedline := 0
for {
pos, tok, lit := s.Scan()
if tok == token.EOF {
// take care of end of file nbcommentlit
if nbcommentlit != "" && expectedline != 0 {
nbStart := noteBookMarker + " # from source line " + strconv.Itoa(nbcommentline) + " */"
currentNoteLine, err := newFilteredNote(nbStart)
nb.Save(currentNoteLine)
currentNote, err := newFilteredNote(nbcommentlit)
if err != nil {
return nil, fmt.Errorf("FilteredNote: %v", err)
}
nb.Save(currentNote) // save it
}
break
}
switch { // check that nbcommentlit is detached from the current line
case expectedline != lineNum(fset, pos): // in case it's not
nbcommentlit = "" // empty it
expectedline = 0 // and put expectedline back to 0
case expectedline == lineNum(fset, pos): // in case it is
nbStart := noteBookMarker + " # from source line " + strconv.Itoa(nbcommentline) + " */"
currentNoteLine, err := newFilteredNote(nbStart)
nb.Save(currentNoteLine)
currentNote, err := newFilteredNote(nbcommentlit)
if err != nil {
return nil, fmt.Errorf("FilteredNote: %v", err)
}
nb.Save(currentNote) // save it
expectedline = 0 // and put expectedline back to 0
}
// we are only interested in toplevel comments with a noteBookMarker
switch {
// in case it is
case tok == token.COMMENT && topLevelComment(fset, pos) && strings.Contains(lit, noteBookMarker):
// set nbcommentlit
nbcommentlit = lit
nbcommentline = lineNum(fset, pos)
// split it by lines
commentlines := strings.Split(nbcommentlit, "\n")
// set expectedline
expectedline = lineNum(fset, pos) + len(commentlines) + 1
default:
continue
}
}
return nb, nil
}