mirror of https://github.com/misterzym/jdocset.git
commit
9e865cbe6c
4 changed files with 701 additions and 0 deletions
@ -0,0 +1,106 @@ |
|||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/go,macos,intellij+iml |
||||||
|
|
||||||
|
### Go ### |
||||||
|
# Binaries for programs and plugins |
||||||
|
*.exe |
||||||
|
*.dll |
||||||
|
*.so |
||||||
|
*.dylib |
||||||
|
|
||||||
|
# Test binary, build with `go test -c` |
||||||
|
*.test |
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE |
||||||
|
*.out |
||||||
|
|
||||||
|
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 |
||||||
|
.glide/ |
||||||
|
|
||||||
|
### Intellij+iml ### |
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm |
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 |
||||||
|
|
||||||
|
# User-specific stuff: |
||||||
|
.idea/**/workspace.xml |
||||||
|
.idea/**/tasks.xml |
||||||
|
.idea/dictionaries |
||||||
|
|
||||||
|
# Sensitive or high-churn files: |
||||||
|
.idea/**/dataSources/ |
||||||
|
.idea/**/dataSources.ids |
||||||
|
.idea/**/dataSources.xml |
||||||
|
.idea/**/dataSources.local.xml |
||||||
|
.idea/**/sqlDataSources.xml |
||||||
|
.idea/**/dynamic.xml |
||||||
|
.idea/**/uiDesigner.xml |
||||||
|
|
||||||
|
# Gradle: |
||||||
|
.idea/**/gradle.xml |
||||||
|
.idea/**/libraries |
||||||
|
|
||||||
|
# CMake |
||||||
|
cmake-build-debug/ |
||||||
|
|
||||||
|
# Mongo Explorer plugin: |
||||||
|
.idea/**/mongoSettings.xml |
||||||
|
|
||||||
|
## File-based project format: |
||||||
|
*.iws |
||||||
|
|
||||||
|
## Plugin-specific files: |
||||||
|
|
||||||
|
# IntelliJ |
||||||
|
/out/ |
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin |
||||||
|
.idea_modules/ |
||||||
|
|
||||||
|
# JIRA plugin |
||||||
|
atlassian-ide-plugin.xml |
||||||
|
|
||||||
|
# Cursive Clojure plugin |
||||||
|
.idea/replstate.xml |
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ) |
||||||
|
com_crashlytics_export_strings.xml |
||||||
|
crashlytics.properties |
||||||
|
crashlytics-build.properties |
||||||
|
fabric.properties |
||||||
|
|
||||||
|
### Intellij+iml Patch ### |
||||||
|
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 |
||||||
|
|
||||||
|
*.iml |
||||||
|
modules.xml |
||||||
|
.idea/misc.xml |
||||||
|
*.ipr |
||||||
|
|
||||||
|
### macOS ### |
||||||
|
*.DS_Store |
||||||
|
.AppleDouble |
||||||
|
.LSOverride |
||||||
|
|
||||||
|
# Icon must end with two \r |
||||||
|
Icon |
||||||
|
|
||||||
|
# Thumbnails |
||||||
|
._* |
||||||
|
|
||||||
|
# Files that might appear in the root of a volume |
||||||
|
.DocumentRevisions-V100 |
||||||
|
.fseventsd |
||||||
|
.Spotlight-V100 |
||||||
|
.TemporaryItems |
||||||
|
.Trashes |
||||||
|
.VolumeIcon.icns |
||||||
|
.com.apple.timemachine.donotpresent |
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share |
||||||
|
.AppleDB |
||||||
|
.AppleDesktop |
||||||
|
Network Trash Folder |
||||||
|
Temporary Items |
||||||
|
.apdisk |
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/go,macos,intellij+iml |
@ -0,0 +1,36 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
type ElementType int |
||||||
|
|
||||||
|
const ( |
||||||
|
NotFound ElementType = iota |
||||||
|
Class |
||||||
|
Method |
||||||
|
Field |
||||||
|
Constructor |
||||||
|
Interface |
||||||
|
Exception |
||||||
|
Error |
||||||
|
Enum |
||||||
|
Trait |
||||||
|
Notation |
||||||
|
Package |
||||||
|
) |
||||||
|
|
||||||
|
var VALUES = map[ElementType]string{ |
||||||
|
Class: "Class", |
||||||
|
Method: "Method", |
||||||
|
Field: "Field", |
||||||
|
Constructor: "Constructor", |
||||||
|
Interface: "Interface", |
||||||
|
Exception: "Exception", |
||||||
|
Error: "Error", |
||||||
|
Enum: "Enum", |
||||||
|
Trait: "Trait", |
||||||
|
Notation: "Notation", |
||||||
|
Package: "Package", |
||||||
|
} |
||||||
|
|
||||||
|
func (e *ElementType) value() string { |
||||||
|
return VALUES[*e] |
||||||
|
} |
@ -0,0 +1,356 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"os" |
||||||
|
"path" |
||||||
|
"github.com/inconshreveable/log15" |
||||||
|
"path/filepath" |
||||||
|
"errors" |
||||||
|
"strings" |
||||||
|
"io" |
||||||
|
"database/sql" |
||||||
|
_ "github.com/mattn/go-sqlite3" |
||||||
|
"fmt" |
||||||
|
) |
||||||
|
|
||||||
|
const OVERVIEW_SUMMARY = "overview-summary.html" |
||||||
|
|
||||||
|
var log = log15.New() |
||||||
|
|
||||||
|
var toIndex []string |
||||||
|
|
||||||
|
func main() { |
||||||
|
|
||||||
|
arguments := os.Args |
||||||
|
argLength := len(arguments) |
||||||
|
if (argLength == 2 && arguments[1] == "--help") { |
||||||
|
printUsage() |
||||||
|
return |
||||||
|
} else if (argLength != 3) { |
||||||
|
log.Error("Invalid argument(s) provided") |
||||||
|
printUsage() |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
docsetName := path.Clean(arguments[1]) |
||||||
|
var javadocPath = path.Clean(arguments[2]) |
||||||
|
|
||||||
|
log.Info("Running with arguments", "docsetName", docsetName, "javadocPath", javadocPath) |
||||||
|
|
||||||
|
docsetDirectoryPath := docsetName + ".docset" |
||||||
|
|
||||||
|
if exists, _ := pathExists(docsetDirectoryPath); exists { |
||||||
|
log.Info("Removing existing docset directory", "Docset directory path", docsetDirectoryPath) |
||||||
|
if err := os.RemoveAll(docsetDirectoryPath); err != nil { |
||||||
|
log.Error( |
||||||
|
"Unable to remove existing docset directory", |
||||||
|
"Docset directory path", docsetDirectoryPath, |
||||||
|
"error", err, |
||||||
|
) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
contentsDirectoryPath := docsetDirectoryPath + "/Contents" |
||||||
|
resourcesDirectoryPath := contentsDirectoryPath + "/Resources" |
||||||
|
documentsDirectoryPath := resourcesDirectoryPath + "/Documents" |
||||||
|
|
||||||
|
log.Info("Creating docset folder structure...") |
||||||
|
if err := os.MkdirAll(documentsDirectoryPath, os.ModePerm); err != nil { |
||||||
|
log.Error("Unable to create docset folder structure", "Docset directory", docsetDirectoryPath) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
var docsetIndexFile string |
||||||
|
overviewSummaryPath := javadocPath + OVERVIEW_SUMMARY |
||||||
|
var summaryFound = false |
||||||
|
|
||||||
|
if exists, _ := pathExists(overviewSummaryPath); !exists { |
||||||
|
|
||||||
|
walkCount := 0 |
||||||
|
filepath.Walk(javadocPath, func(filePath string, info os.FileInfo, err error) error { |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Error("Failed to walk path", "path", filePath, "err", err) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
walkCount++ |
||||||
|
|
||||||
|
if walkCount < 10000 { |
||||||
|
|
||||||
|
if info.Name() == OVERVIEW_SUMMARY { |
||||||
|
javadocPath = path.Dir(filePath) |
||||||
|
summaryFound = true |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} else { |
||||||
|
return errors.New("Hit file enumeration limit") |
||||||
|
} |
||||||
|
}) |
||||||
|
} else { |
||||||
|
summaryFound = true |
||||||
|
} |
||||||
|
|
||||||
|
if summaryFound { |
||||||
|
docsetIndexFile = OVERVIEW_SUMMARY |
||||||
|
} |
||||||
|
|
||||||
|
hasMultipleIndices := false |
||||||
|
indexFilesPath := javadocPath + "index-files" |
||||||
|
if exists, _ := pathExists(indexFilesPath); exists { |
||||||
|
if docsetIndexFile == "" { |
||||||
|
docsetIndexFile = "index-files/index-1.html" |
||||||
|
} |
||||||
|
hasMultipleIndices = true |
||||||
|
} |
||||||
|
log.Info("Done!") |
||||||
|
|
||||||
|
copyFiles(documentsDirectoryPath, javadocPath) |
||||||
|
|
||||||
|
documentsDirectoryIndex := documentsDirectoryPath + "/index-all.html" |
||||||
|
if exists, _ := pathExists(documentsDirectoryIndex); !hasMultipleIndices && exists { |
||||||
|
|
||||||
|
toIndex = append(toIndex, documentsDirectoryIndex) |
||||||
|
|
||||||
|
if docsetIndexFile == "" { |
||||||
|
docsetIndexFile = "index-all.html" |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
indexFilesPath := documentsDirectoryPath + "/index-files" |
||||||
|
filepath.Walk(indexFilesPath, func(filePath string, info os.FileInfo, err error) error { |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Error("Failed to walk path", "filePath", filePath, "err", err) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
filename := info.Name() |
||||||
|
if strings.HasPrefix(filename, "index-") && strings.HasSuffix(filename, ".html") { |
||||||
|
toIndex = append(toIndex, filePath) |
||||||
|
} |
||||||
|
return err |
||||||
|
}) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if len(toIndex) == 0 { |
||||||
|
log.Error("API folder specified does not contain any index files (either an 'index-all.html' file or an 'index-files' folder and is not valid") |
||||||
|
printUsage() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
writeInfoPlist(docsetName, docsetIndexFile, contentsDirectoryPath) |
||||||
|
|
||||||
|
initDB(resourcesDirectoryPath, index(toIndex)) |
||||||
|
} |
||||||
|
|
||||||
|
func printUsage() { |
||||||
|
log.Info("Usage: javadocset <docset name> <javadoc API folder>") |
||||||
|
log.Info("<docset name> - anything you want") |
||||||
|
log.Info("<javadoc API folder> - the path of the javadoc API folder you want to index") |
||||||
|
} |
||||||
|
|
||||||
|
func copyFiles(documentsDirectoryPath, javadocPath string) { |
||||||
|
log.Info("Copying files...", "source", javadocPath, "destination", documentsDirectoryPath) |
||||||
|
|
||||||
|
src := path.Clean(javadocPath) |
||||||
|
dst := path.Clean(documentsDirectoryPath) |
||||||
|
|
||||||
|
srcBase := path.Base(src) |
||||||
|
filepath.Walk(src, func(filePath string, info os.FileInfo, err error) error { |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Error("Error walking path", "filePath", filePath) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
if info.IsDir() { |
||||||
|
|
||||||
|
if path.Base(filePath) != srcBase { |
||||||
|
|
||||||
|
// We only want to copy the directories within the source directory
|
||||||
|
// to the destination directory
|
||||||
|
directoryName := strings.Split(filePath, srcBase)[1] |
||||||
|
|
||||||
|
err := os.MkdirAll(dst + directoryName, os.ModePerm) |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to create directory", "directory", directoryName) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
// Copy file
|
||||||
|
fileName := filepath.Base(filePath) |
||||||
|
directoryName := strings.Split(filepath.Dir(filePath), srcBase)[1] |
||||||
|
|
||||||
|
dstPath := filepath.Clean(dst + directoryName + "/" + fileName) |
||||||
|
|
||||||
|
err = copyFileContents(filePath, dstPath) |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to copy file", "src", filePath, "dst", dstPath) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return err |
||||||
|
}) |
||||||
|
|
||||||
|
log.Info("Done!") |
||||||
|
} |
||||||
|
|
||||||
|
func writeInfoPlist(docsetName, docsetIndexFile, contentsDirectoryPath string) { |
||||||
|
plistContentTemplate := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><plist version=\"1.0\"><dict><key>CFBundleIdentifier</key> <string>%v</string><key>CFBundleName</key> <string>%v</string> <key>DocSetPlatformFamily</key> <string>%v</string> <key>dashIndexFilePath</key><string>%v</string><key>DashDocSetFamily</key><string>java</string><key>isDashDocset</key><true/></dict></plist>" |
||||||
|
|
||||||
|
docsetIdentifier := firstPhraseLowerCased(docsetName) |
||||||
|
|
||||||
|
plistContent := fmt.Sprintf( |
||||||
|
plistContentTemplate, |
||||||
|
docsetIdentifier, |
||||||
|
docsetName, |
||||||
|
docsetIdentifier, |
||||||
|
docsetIndexFile, |
||||||
|
) |
||||||
|
|
||||||
|
infoPlistPath := contentsDirectoryPath + "/Info.plist" |
||||||
|
err := writeStringToFile(plistContent, infoPlistPath) |
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to write to plist file", "plistPath", infoPlistPath) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func initDB(resourcesDirectoryPath string, dbFunc func(*sql.DB)) { |
||||||
|
|
||||||
|
dbPath := filepath.Clean(resourcesDirectoryPath + "/docset.dsidx") |
||||||
|
|
||||||
|
// We don't care, we just want to remove the index
|
||||||
|
os.Remove(dbPath) |
||||||
|
|
||||||
|
db, err := sql.Open("sqlite3", dbPath) |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to create sqlite database", "destination", dbPath, "error", err) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
defer db.Close() |
||||||
|
|
||||||
|
_, err = db.Exec("CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT)") |
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to create table", "error", err) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
if dbFunc != nil { |
||||||
|
dbFunc(db) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func index(indicesToIndex []string) func(db *sql.DB) { |
||||||
|
return func(db *sql.DB) { |
||||||
|
|
||||||
|
tx, err := db.Begin() |
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to begin transactions for database", "error", err) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
stmt, err := tx.Prepare("INSERT INTO searchIndex(name, type, path) VALUES (?, ?, ?)") |
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to create statement to insert into database", "error", err) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
defer stmt.Close() |
||||||
|
|
||||||
|
added := make(map[string]bool) |
||||||
|
|
||||||
|
for _, toIndex := range indicesToIndex { |
||||||
|
parseIndex(toIndex, func(entry IndexEntry) { |
||||||
|
|
||||||
|
name, elementType, path := entry.name, entry.elementType.value(), entry.path |
||||||
|
|
||||||
|
uniqueKey := name + elementType + path |
||||||
|
|
||||||
|
if !added[uniqueKey] { |
||||||
|
_, err := stmt.Exec(name, elementType, path) |
||||||
|
if err != nil { |
||||||
|
log.Error( |
||||||
|
"Unable to insert entry", |
||||||
|
"name", name, |
||||||
|
"elementType", elementType, |
||||||
|
"path", path, |
||||||
|
) |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
added[uniqueKey] = true |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
tx.Commit() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
Utility functions |
||||||
|
*/ |
||||||
|
func pathExists(path string) (bool, error) { |
||||||
|
_, err := os.Stat(path) |
||||||
|
if err == nil { |
||||||
|
return true, nil |
||||||
|
} |
||||||
|
if os.IsNotExist(err) { |
||||||
|
return false, nil |
||||||
|
} |
||||||
|
return true, err |
||||||
|
} |
||||||
|
|
||||||
|
func writeStringToFile(content, dst string) error { |
||||||
|
file, err := os.Create(dst) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
defer file.Close() |
||||||
|
|
||||||
|
_, err = file.Write([]byte(content)) |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
func copyFileContents(src, dst string) (err error) { |
||||||
|
|
||||||
|
in, err := os.Open(src) |
||||||
|
if err != nil { |
||||||
|
return |
||||||
|
} |
||||||
|
defer in.Close() |
||||||
|
out, err := os.Create(dst) |
||||||
|
if err != nil { |
||||||
|
return |
||||||
|
} |
||||||
|
defer func() { |
||||||
|
cerr := out.Close() |
||||||
|
if err == nil { |
||||||
|
err = cerr |
||||||
|
} |
||||||
|
}() |
||||||
|
if _, err = io.Copy(out, in); err != nil { |
||||||
|
log.Error("Error copying", "error", err) |
||||||
|
return |
||||||
|
} |
||||||
|
err = out.Sync() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func firstPhraseLowerCased(s string) string { |
||||||
|
return strings.ToLower(func() string { |
||||||
|
return strings.Split(s, " ")[0] |
||||||
|
}()) |
||||||
|
} |
@ -0,0 +1,203 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"os" |
||||||
|
"github.com/yhat/scrape" |
||||||
|
"strings" |
||||||
|
"golang.org/x/net/html" |
||||||
|
"golang.org/x/net/html/atom" |
||||||
|
) |
||||||
|
|
||||||
|
type Verifier func(string) bool |
||||||
|
type TypeEvaluator func(Verifier, Verifier) bool |
||||||
|
type IndexEntry struct { |
||||||
|
name string |
||||||
|
elementType ElementType |
||||||
|
path string |
||||||
|
} |
||||||
|
|
||||||
|
var ALL_ELEMENT_TYPES = []ElementType{ |
||||||
|
Class, |
||||||
|
Method, |
||||||
|
Field, |
||||||
|
Constructor, |
||||||
|
Interface, |
||||||
|
Exception, |
||||||
|
Error, |
||||||
|
Enum, |
||||||
|
Trait, |
||||||
|
Notation, |
||||||
|
Package, |
||||||
|
} |
||||||
|
|
||||||
|
var ELEMENT_TYPE_TO_TYPE_EVALUATORS = map[ElementType][]TypeEvaluator{ |
||||||
|
Class: NewTypeEvaluators(isClass), |
||||||
|
Method: NewTypeEvaluators(isStaticMethod, isMethod), |
||||||
|
Field: NewTypeEvaluators(isStaticField, isField), |
||||||
|
Constructor: NewTypeEvaluators(isConstructor), |
||||||
|
Interface: NewTypeEvaluators(isInterface), |
||||||
|
Exception: NewTypeEvaluators(isException), |
||||||
|
Error: NewTypeEvaluators(isError), |
||||||
|
Enum: NewTypeEvaluators(isEnum), |
||||||
|
Trait: NewTypeEvaluators(isTrait), |
||||||
|
Notation: NewTypeEvaluators(isNotation), |
||||||
|
Package: NewTypeEvaluators(isPackage), |
||||||
|
} |
||||||
|
|
||||||
|
func parseIndex(indexFilePath string, entryHandler func(IndexEntry)) { |
||||||
|
|
||||||
|
log.Info("Indexing from file", "file", indexFilePath) |
||||||
|
|
||||||
|
indexed := 0 |
||||||
|
file, err := os.OpenFile(indexFilePath, os.O_RDONLY, 0666) |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to open file", "file", indexFilePath, "error", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
root, err := html.Parse(file) |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Error("Unable to parse index", "file", file, "error", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
anchorTags := scrape.FindAll(root, scrape.ByTag(atom.A)) |
||||||
|
|
||||||
|
for _, tag := range anchorTags { |
||||||
|
var parentTag = tag.Parent |
||||||
|
|
||||||
|
if parentTag.FirstChild != tag { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
isParentSpan := parentTag.DataAtom == atom.Span |
||||||
|
isParentCode := parentTag.DataAtom == atom.Code |
||||||
|
isParentItalic := parentTag.DataAtom == atom.I |
||||||
|
isParentBold := parentTag.DataAtom == atom.B |
||||||
|
|
||||||
|
if isParentSpan || isParentCode || isParentItalic || isParentBold { |
||||||
|
parentTag = parentTag.Parent |
||||||
|
if parentTag.FirstChild != tag.Parent { |
||||||
|
continue |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if parentTag.DataAtom != atom.Dt { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
text := scrape.Text(parentTag) |
||||||
|
var tagType ElementType = NotFound |
||||||
|
var dtClassName = scrape.Attr(parentTag, "class") |
||||||
|
|
||||||
|
lowercaseText := strings.ToLower(text) |
||||||
|
|
||||||
|
textContainsInsensitive := func(s string) bool { |
||||||
|
return strings.Contains(lowercaseText, s) |
||||||
|
} |
||||||
|
|
||||||
|
dtClassNameHasSuffix := func(s string) bool { |
||||||
|
return strings.HasSuffix(dtClassName, s) |
||||||
|
} |
||||||
|
|
||||||
|
tagTypeDetermined := false |
||||||
|
|
||||||
|
for _, elementType := range ALL_ELEMENT_TYPES { |
||||||
|
|
||||||
|
typeEvaluators := ELEMENT_TYPE_TO_TYPE_EVALUATORS[elementType] |
||||||
|
|
||||||
|
for _, evaluator := range typeEvaluators { |
||||||
|
|
||||||
|
if evaluator(textContainsInsensitive, dtClassNameHasSuffix) { |
||||||
|
tagType = elementType |
||||||
|
tagTypeDetermined = true |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if tagTypeDetermined { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if tagType == NotFound { |
||||||
|
log.Warn("Warning: could not determine type", "text", text, "dtClassName", dtClassName) |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
name := scrape.Text(tag) |
||||||
|
path := scrape.Attr(tag, "href") |
||||||
|
|
||||||
|
entryHandler(IndexEntry{name: name, elementType: tagType, path: path}) |
||||||
|
|
||||||
|
indexed++ |
||||||
|
} |
||||||
|
|
||||||
|
log.Info("Indexed", "count", indexed) |
||||||
|
} |
||||||
|
|
||||||
|
func NewTypeEvaluators(a TypeEvaluator, others ...TypeEvaluator) []TypeEvaluator { |
||||||
|
|
||||||
|
typeEvaluators := make([]TypeEvaluator, 1 + len(others)) |
||||||
|
|
||||||
|
typeEvaluators[0] = a |
||||||
|
for i, typeEvaluator := range others { |
||||||
|
typeEvaluators[i + 1] = typeEvaluator |
||||||
|
} |
||||||
|
|
||||||
|
return typeEvaluators |
||||||
|
} |
||||||
|
|
||||||
|
func isClass(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("class in") || textContainsInsensitive("- class") || dtClassNameHasSuffix("class") |
||||||
|
} |
||||||
|
|
||||||
|
func isStaticMethod(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("static method in") || dtClassNameHasSuffix("method") |
||||||
|
} |
||||||
|
|
||||||
|
func isStaticField(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("static variable in") || textContainsInsensitive("field in") || dtClassNameHasSuffix("field") |
||||||
|
} |
||||||
|
|
||||||
|
func isConstructor(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("constructor") || dtClassNameHasSuffix("constructor") |
||||||
|
} |
||||||
|
|
||||||
|
func isMethod(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("method in") |
||||||
|
} |
||||||
|
|
||||||
|
func isField(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("variable in") |
||||||
|
} |
||||||
|
|
||||||
|
func isInterface(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("interface in") || textContainsInsensitive("- interface") || dtClassNameHasSuffix("interface") |
||||||
|
} |
||||||
|
|
||||||
|
func isException(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("exception in") || textContainsInsensitive("- exception") || dtClassNameHasSuffix("exception") |
||||||
|
} |
||||||
|
|
||||||
|
func isError(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("error in") || textContainsInsensitive("- error") || dtClassNameHasSuffix("error") |
||||||
|
} |
||||||
|
|
||||||
|
func isEnum(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("enum in") || textContainsInsensitive("- enum") || dtClassNameHasSuffix("enum") |
||||||
|
} |
||||||
|
|
||||||
|
func isTrait(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("trait in") |
||||||
|
} |
||||||
|
|
||||||
|
func isNotation(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("annotation type") || dtClassNameHasSuffix("annotation") |
||||||
|
} |
||||||
|
|
||||||
|
func isPackage(textContainsInsensitive, dtClassNameHasSuffix Verifier) bool { |
||||||
|
return textContainsInsensitive("package") || dtClassNameHasSuffix("package") |
||||||
|
} |
Loading…
Reference in new issue