mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 17:50:22 +00:00
130 lines
2.4 KiB
Go
130 lines
2.4 KiB
Go
package compiler
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
|
|
grammar "github.com/github/linguist/tools/grammars/proto"
|
|
)
|
|
|
|
type LoadedFile struct {
|
|
Path string
|
|
Rule *grammar.Rule
|
|
}
|
|
|
|
func (f *LoadedFile) String() string {
|
|
return fmt.Sprintf("`%s` (in `%s`)", f.Rule.ScopeName, f.Path)
|
|
}
|
|
|
|
type Repository struct {
|
|
Source string
|
|
Upstream string
|
|
Files map[string]*LoadedFile
|
|
Errors []error
|
|
}
|
|
|
|
func newRepository(src string) *Repository {
|
|
return &Repository{
|
|
Source: src,
|
|
Files: make(map[string]*LoadedFile),
|
|
}
|
|
}
|
|
|
|
func (repo *Repository) String() string {
|
|
str := fmt.Sprintf("repository `%s`", repo.Source)
|
|
if repo.Upstream != "" {
|
|
str = str + fmt.Sprintf(" (from %s)", repo.Upstream)
|
|
}
|
|
return str
|
|
}
|
|
|
|
func (repo *Repository) Fail(err error) {
|
|
repo.Errors = append(repo.Errors, err)
|
|
}
|
|
|
|
func (repo *Repository) AddFile(path string, rule *grammar.Rule, uk []string) {
|
|
file := &LoadedFile{
|
|
Path: path,
|
|
Rule: rule,
|
|
}
|
|
|
|
repo.Files[rule.ScopeName] = file
|
|
if len(uk) > 0 {
|
|
repo.Fail(&UnknownKeysError{file, uk})
|
|
}
|
|
}
|
|
|
|
func toMap(slice []string) map[string]bool {
|
|
m := make(map[string]bool)
|
|
for _, s := range slice {
|
|
m[s] = true
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (repo *Repository) CompareScopes(scopes []string) {
|
|
expected := toMap(scopes)
|
|
|
|
for scope, file := range repo.Files {
|
|
if !expected[scope] {
|
|
repo.Fail(&UnexpectedScopeError{file, scope})
|
|
}
|
|
}
|
|
|
|
for scope := range expected {
|
|
if _, ok := repo.Files[scope]; !ok {
|
|
repo.Fail(&MissingScopeError{scope})
|
|
}
|
|
}
|
|
}
|
|
|
|
func (repo *Repository) FixRules(knownScopes map[string]bool) {
|
|
for _, file := range repo.Files {
|
|
w := walker{
|
|
File: file,
|
|
Known: knownScopes,
|
|
Missing: make(map[string]bool),
|
|
}
|
|
|
|
w.walk(file.Rule)
|
|
repo.Errors = append(repo.Errors, w.Errors...)
|
|
|
|
}
|
|
}
|
|
|
|
func (repo *Repository) Scopes() (scopes []string) {
|
|
for s := range repo.Files {
|
|
scopes = append(scopes, s)
|
|
}
|
|
sort.Strings(scopes)
|
|
return
|
|
}
|
|
|
|
func isValidGrammar(path string, info os.FileInfo) bool {
|
|
if info.IsDir() {
|
|
return false
|
|
}
|
|
|
|
// Tree-Sitter grammars are not supported
|
|
if strings.HasPrefix(filepath.Base(path), "tree-sitter-") {
|
|
return false
|
|
}
|
|
|
|
dir := filepath.Dir(path)
|
|
ext := filepath.Ext(path)
|
|
|
|
switch strings.ToLower(ext) {
|
|
case ".plist":
|
|
return strings.HasSuffix(dir, "/Syntaxes")
|
|
case ".tmlanguage", ".yaml-tmlanguage":
|
|
return true
|
|
case ".cson", ".json":
|
|
return strings.HasSuffix(dir, "/grammars") || strings.HasSuffix(dir, "/syntaxes")
|
|
default:
|
|
return false
|
|
}
|
|
}
|