164 lines
3.8 KiB
Go
164 lines
3.8 KiB
Go
/*
|
|
Copyright © 2022 Sameer Rahmani <lxsameer@gnu.org>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package core
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
"sync"
|
|
|
|
git "github.com/go-git/go-git/v5"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type State struct {
|
|
Version int
|
|
ProjectRoot string
|
|
Repo *git.Repository
|
|
// A mapping of file extensions to the language
|
|
// e.g '.h' -> 'C/C++'
|
|
EnabledLangs map[string]*Lang
|
|
BlockTypePattern *regexp.Regexp
|
|
EndBlockTypePattern *regexp.Regexp
|
|
TagPattern *regexp.Regexp
|
|
FirstLineContent *regexp.Regexp
|
|
WaitGroup sync.WaitGroup
|
|
ErrChannel chan error
|
|
NumberOfWorkers int
|
|
}
|
|
|
|
func CreateState(projectRoot string, debug bool) (*State, error) {
|
|
state := State{}
|
|
var err error
|
|
|
|
if debug {
|
|
log.SetLevel(log.TraceLevel)
|
|
} else {
|
|
log.SetLevel(log.InfoLevel)
|
|
}
|
|
|
|
state.ProjectRoot = strings.TrimSpace(projectRoot)
|
|
log.Debugf("Found project at '%s'", state.ProjectRoot)
|
|
|
|
state.Repo, err = git.PlainOpen(state.ProjectRoot)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO: Read the pattern from the global or project wide config file
|
|
// using viper
|
|
state.BlockTypePattern = regexp.MustCompile(`^(?P<type>[A-Z]+):`)
|
|
state.EndBlockTypePattern = regexp.MustCompile(`/(?P<end>[A-Z]+)$`)
|
|
state.TagPattern = regexp.MustCompile(`\[([^]]+)\]`)
|
|
state.FirstLineContent = regexp.MustCompile(`[A-Z]+:\s+(?:\[[^]]+\])*\s?(?P<text>.*)`)
|
|
|
|
state.EnabledLangs = ExtsToLang
|
|
state.ErrChannel = make(chan error, 10)
|
|
state.NumberOfWorkers = 2
|
|
|
|
return &state, nil
|
|
}
|
|
|
|
func (s *State) LogErrors() {
|
|
for err := range s.ErrChannel {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
|
|
func (s *State) CheckErr(e error) {
|
|
if e != nil {
|
|
s.ErrChannel <- e
|
|
}
|
|
}
|
|
|
|
func (s *State) GetLangForExt(ext string) *Lang {
|
|
|
|
// If the extension is the filename itself.
|
|
// like: LICENSE
|
|
key := ext
|
|
|
|
if strings.Contains(key, ".") {
|
|
// dotless extension
|
|
key = ext[1:]
|
|
}
|
|
|
|
lang, exists := s.EnabledLangs[key]
|
|
if exists {
|
|
return lang
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TODO: Maybe move these functions under a different data structure
|
|
func (s *State) getCommentType(comment string) *string {
|
|
|
|
match := s.BlockTypePattern.FindAllStringSubmatch(comment, -1)
|
|
if len(match) > 0 {
|
|
if len(match[0]) == 2 {
|
|
// Return the group of regex which is the tag group
|
|
return &match[0][1]
|
|
} else {
|
|
log.Fatal("bad regex for the block type")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *State) getTags(comment string) []string {
|
|
match := s.TagPattern.FindAllStringSubmatch(comment, -1)
|
|
|
|
var tags []string
|
|
if len(match) > 0 {
|
|
for _, tag := range match {
|
|
tags = append(tags, tag[1])
|
|
}
|
|
return tags
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *State) detectClosingBlock(comment *string) (*string, bool) {
|
|
match := s.EndBlockTypePattern.FindAllStringSubmatch(*comment, -1)
|
|
if len(match) > 0 {
|
|
if len(match[0]) == 2 {
|
|
// Return the group of regex which is the type group
|
|
return &match[0][1], true
|
|
}
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
func (s *State) TrimTypeAndTags(comment *string) *string {
|
|
match := s.FirstLineContent.FindAllStringSubmatch(*comment, -1)
|
|
if len(match) > 0 {
|
|
if len(match[0]) == 2 {
|
|
// Return the group of regex which is the text group
|
|
return &match[0][1]
|
|
} else {
|
|
log.Fatal("bad regex for the first line content")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// /TODO
|