← back to jeduden__mdsmith

Function bodies 497 total

All specs Real LLM only Function bodies
metrics.Document.LineCount method · go · L49-L58 (10 LOC)
internal/metrics/document.go
func (d *Document) LineCount() int {
	if len(d.Source) == 0 {
		return 0
	}
	lines := bytes.Count(d.Source, []byte("\n"))
	if d.Source[len(d.Source)-1] != '\n' {
		lines++
	}
	return lines
}
metrics.Document.File method · go · L61-L76 (16 LOC)
internal/metrics/document.go
func (d *Document) File() (*lint.File, error) {
	if d.fileReady {
		return d.file, d.fileErr
	}

	f, err := lint.NewFile(d.Path, d.Source)
	if err != nil {
		d.fileErr = fmt.Errorf("parsing markdown: %w", err)
		d.fileReady = true
		return nil, d.fileErr
	}

	d.file = f
	d.fileReady = true
	return d.file, nil
}
metrics.Document.PlainText method · go · L79-L94 (16 LOC)
internal/metrics/document.go
func (d *Document) PlainText() (string, error) {
	if d.plainTextReady {
		return d.plainText, d.plainTextErr
	}

	f, err := d.File()
	if err != nil {
		d.plainTextErr = err
		d.plainTextReady = true
		return "", err
	}

	d.plainText = mdtext.ExtractPlainText(f.AST, f.Source)
	d.plainTextReady = true
	return d.plainText, nil
}
metrics.Document.WordCount method · go · L97-L112 (16 LOC)
internal/metrics/document.go
func (d *Document) WordCount() (int, error) {
	if d.wordCountReady {
		return d.wordCount, d.wordCountErr
	}

	text, err := d.PlainText()
	if err != nil {
		d.wordCountErr = err
		d.wordCountReady = true
		return 0, err
	}

	d.wordCount = mdtext.CountWords(text)
	d.wordCountReady = true
	return d.wordCount, nil
}
metrics.Document.HeadingCount method · go · L115-L140 (26 LOC)
internal/metrics/document.go
func (d *Document) HeadingCount() (int, error) {
	if d.headingCountReady {
		return d.headingCount, d.headingCountErr
	}

	f, err := d.File()
	if err != nil {
		d.headingCountErr = err
		d.headingCountReady = true
		return 0, err
	}

	count := 0
	_ = ast.Walk(f.AST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if entering {
			if _, ok := n.(*ast.Heading); ok {
				count++
			}
		}
		return ast.WalkContinue, nil
	})

	d.headingCount = count
	d.headingCountReady = true
	return d.headingCount, nil
}
metrics.Collect function · go · L18-L42 (25 LOC)
internal/metrics/rank.go
func Collect(paths []string, defs []Definition) ([]Row, error) {
	rows := make([]Row, 0, len(paths))
	for _, path := range paths {
		source, err := os.ReadFile(path)
		if err != nil {
			return nil, fmt.Errorf("reading %q: %w", path, err)
		}

		doc := NewDocument(path, source)
		values := make(map[string]Value, len(defs))
		for _, def := range defs {
			v, err := def.Compute(doc)
			if err != nil {
				return nil, fmt.Errorf("computing %q for %q: %w", def.Name, path, err)
			}
			values[def.Name] = v
		}

		rows = append(rows, Row{
			Path:    path,
			Metrics: values,
		})
	}
	return rows, nil
}
metrics.SortRows function · go · L45-L68 (24 LOC)
internal/metrics/rank.go
func SortRows(rows []Row, by Definition, order Order) {
	sort.Slice(rows, func(i, j int) bool {
		a := rows[i].Metrics[by.Name]
		b := rows[j].Metrics[by.Name]

		// Available values sort before unavailable values.
		if a.Available != b.Available {
			return a.Available
		}

		if a.Available && b.Available {
			diff := a.Number - b.Number
			if math.Abs(diff) > 1e-9 {
				if order == OrderAsc {
					return diff < 0
				}
				return diff > 0
			}
		}

		// Stable deterministic tie-break.
		return rows[i].Path < rows[j].Path
	})
}
Repobility · open methodology · https://repobility.com/research/
metrics.LimitRows function · go · L71-L76 (6 LOC)
internal/metrics/rank.go
func LimitRows(rows []Row, top int) []Row {
	if top <= 0 || top >= len(rows) {
		return rows
	}
	return rows[:top]
}
metrics.FormatValue function · go · L79-L93 (15 LOC)
internal/metrics/rank.go
func FormatValue(def Definition, value Value) string {
	v := JSONValue(def, value)
	if v == nil {
		return "-"
	}

	switch n := v.(type) {
	case int64:
		return strconv.FormatInt(n, 10)
	case float64:
		return fmt.Sprintf("%.*f", def.Precision, n)
	default:
		return "-"
	}
}
metrics.JSONValue function · go · L97-L114 (18 LOC)
internal/metrics/rank.go
func JSONValue(def Definition, value Value) any {
	if !value.Available {
		return nil
	}

	switch def.Kind {
	case KindInteger:
		return int64(math.Round(value.Number))
	case KindFloat:
		if def.Precision < 0 {
			return value.Number
		}
		scale := math.Pow10(def.Precision)
		return math.Round(value.Number*scale) / scale
	default:
		return value.Number
	}
}
metrics.All function · go · L109-L115 (7 LOC)
internal/metrics/registry.go
func All() []Definition {
	defs := append([]Definition(nil), registry...)
	sort.Slice(defs, func(i, j int) bool {
		return defs[i].ID < defs[j].ID
	})
	return defs
}
metrics.ForScope function · go · L118-L127 (10 LOC)
internal/metrics/registry.go
func ForScope(scope Scope) []Definition {
	all := All()
	defs := make([]Definition, 0, len(all))
	for _, def := range all {
		if def.Scope == scope {
			defs = append(defs, def)
		}
	}
	return defs
}
metrics.Defaults function · go · L130-L139 (10 LOC)
internal/metrics/registry.go
func Defaults(scope Scope) []Definition {
	defs := ForScope(scope)
	out := make([]Definition, 0, len(defs))
	for _, def := range defs {
		if def.Default {
			out = append(out, def)
		}
	}
	return out
}
metrics.Lookup function · go · L142-L149 (8 LOC)
internal/metrics/registry.go
func Lookup(query string) (Definition, bool) {
	for _, def := range All() {
		if matches(def, query) {
			return def, true
		}
	}
	return Definition{}, false
}
metrics.LookupScope function · go · L152-L159 (8 LOC)
internal/metrics/registry.go
func LookupScope(scope Scope, query string) (Definition, bool) {
	for _, def := range ForScope(scope) {
		if matches(def, query) {
			return def, true
		}
	}
	return Definition{}, false
}
Repobility analyzer · published findings · https://repobility.com
metrics.Resolve function · go · L163-L192 (30 LOC)
internal/metrics/registry.go
func Resolve(scope Scope, names []string) ([]Definition, error) {
	if len(names) == 0 {
		return Defaults(scope), nil
	}

	seen := make(map[string]struct{}, len(names))
	defs := make([]Definition, 0, len(names))
	for _, raw := range names {
		name := strings.TrimSpace(raw)
		if name == "" {
			continue
		}

		def, ok := LookupScope(scope, name)
		if !ok {
			return nil, unknownMetricErr(scope, name)
		}

		if _, exists := seen[def.ID]; exists {
			continue
		}
		seen[def.ID] = struct{}{}
		defs = append(defs, def)
	}

	if len(defs) == 0 {
		return nil, fmt.Errorf("no metrics selected")
	}
	return defs, nil
}
metrics.SplitList function · go · L195-L208 (14 LOC)
internal/metrics/registry.go
func SplitList(raw string) []string {
	if strings.TrimSpace(raw) == "" {
		return nil
	}
	parts := strings.Split(raw, ",")
	out := make([]string, 0, len(parts))
	for _, p := range parts {
		p = strings.TrimSpace(p)
		if p != "" {
			out = append(out, p)
		}
	}
	return out
}
metrics.matches function · go · L210-L216 (7 LOC)
internal/metrics/registry.go
func matches(def Definition, query string) bool {
	q := strings.TrimSpace(query)
	if q == "" {
		return false
	}
	return strings.EqualFold(def.ID, q) || def.Name == strings.ToLower(q)
}
metrics.unknownMetricErr function · go · L218-L224 (7 LOC)
internal/metrics/registry.go
func unknownMetricErr(scope Scope, name string) error {
	return fmt.Errorf(
		"unknown metric %q (available: %s)",
		name,
		strings.Join(availableNames(scope), ", "),
	)
}
metrics.availableNames function · go · L226-L234 (9 LOC)
internal/metrics/registry.go
func availableNames(scope Scope) []string {
	defs := ForScope(scope)
	names := make([]string, 0, len(defs))
	for _, def := range defs {
		names = append(names, def.Name)
	}
	sort.Strings(names)
	return names
}
metrics.ParseScope function · go · L17-L24 (8 LOC)
internal/metrics/types.go
func ParseScope(raw string) (Scope, error) {
	switch strings.ToLower(strings.TrimSpace(raw)) {
	case "", string(ScopeFile):
		return ScopeFile, nil
	default:
		return "", fmt.Errorf("unknown scope %q (supported: file)", raw)
	}
}
metrics.ParseOrder function · go · L37-L46 (10 LOC)
internal/metrics/types.go
func ParseOrder(raw string) (Order, error) {
	switch strings.ToLower(strings.TrimSpace(raw)) {
	case "", string(OrderDesc):
		return OrderDesc, nil
	case string(OrderAsc):
		return OrderAsc, nil
	default:
		return "", fmt.Errorf("unknown order %q (supported: asc, desc)", raw)
	}
}
metrics.AvailableValue function · go · L65-L70 (6 LOC)
internal/metrics/types.go
func AvailableValue(n float64) Value {
	return Value{
		Number:    n,
		Available: true,
	}
}
Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
output.JSONFormatter.Format method · go · L25-L41 (17 LOC)
internal/output/json.go
func (f *JSONFormatter) Format(w io.Writer, diagnostics []lint.Diagnostic) error {
	items := make([]jsonDiagnostic, 0, len(diagnostics))
	for _, d := range diagnostics {
		items = append(items, jsonDiagnostic{
			File:     d.File,
			Line:     d.Line,
			Column:   d.Column,
			Rule:     d.RuleID,
			Name:     d.RuleName,
			Severity: string(d.Severity),
			Message:  d.Message,
		})
	}
	enc := json.NewEncoder(w)
	enc.SetIndent("", "  ")
	return enc.Encode(items)
}
output.TextFormatter.Format method · go · L18-L34 (17 LOC)
internal/output/text.go
func (f *TextFormatter) Format(w io.Writer, diagnostics []lint.Diagnostic) error {
	for _, d := range diagnostics {
		var err error
		if f.Color {
			// file in cyan, rule in yellow
			_, err = fmt.Fprintf(w, "\033[36m%s:%d:%d\033[0m \033[33m%s\033[0m %s\n",
				d.File, d.Line, d.Column, d.RuleID, d.Message)
		} else {
			_, err = fmt.Fprintf(w, "%s:%d:%d %s %s\n",
				d.File, d.Line, d.Column, d.RuleID, d.Message)
		}
		if err != nil {
			return err
		}
	}
	return nil
}
rule.CloneRule function · go · L9-L33 (25 LOC)
internal/rule/clone.go
func CloneRule(r Rule) Rule {
	if c, ok := r.(Configurable); ok {
		// Create a new zero-value instance of the same concrete type.
		rv := reflect.ValueOf(r)
		if rv.Kind() == reflect.Ptr {
			newPtr := reflect.New(rv.Elem().Type())
			clone := newPtr.Interface().(Rule)
			if cc, ok := clone.(Configurable); ok {
				_ = cc.ApplySettings(c.DefaultSettings())
			}
			return clone
		}
	}

	// Fallback: reflect-based copy for non-Configurable rules.
	rv := reflect.ValueOf(r)
	if rv.Kind() == reflect.Ptr {
		newPtr := reflect.New(rv.Elem().Type())
		newPtr.Elem().Set(rv.Elem())
		return newPtr.Interface().(Rule)
	}

	// Value type — already a copy.
	return r
}
rule.ByID function · go · L18-L25 (8 LOC)
internal/rule/registry.go
func ByID(id string) Rule {
	for _, r := range registry {
		if r.ID() == id {
			return r
		}
	}
	return nil
}
blanklinearoundfencedcode.Rule.Check method · go · L30-L87 (58 LOC)
internal/rules/blanklinearoundfencedcode/rule.go
func (r *Rule) Check(f *lint.File) []lint.Diagnostic {
	var diags []lint.Diagnostic

	_ = ast.Walk(f.AST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}
		fcb, ok := n.(*ast.FencedCodeBlock)
		if !ok {
			return ast.WalkContinue, nil
		}

		openStart, openEnd := fencedcodestyle.FenceOpenLineRange(f.Source, fcb)
		closeStart, _ := fencedcodestyle.FenceCloseLineRange(f.Source, fcb, openEnd)

		openLine := f.LineOfOffset(openStart)
		closeLine := f.LineOfOffset(closeStart)

		// Check blank line before opening fence
		if openLine > 1 {
			prevLineIdx := openLine - 2 // 0-based index of the line before
			if prevLineIdx >= 0 && prevLineIdx < len(f.Lines) {
				if !isBlank(f.Lines[prevLineIdx]) {
					diags = append(diags, lint.Diagnostic{
						File:     f.Path,
						Line:     openLine,
						Column:   1,
						RuleID:   r.ID(),
						RuleName: r.Name(),
						Severity: lint.Warning,
						Message:  "fenced code block should 
blanklinearoundfencedcode.Rule.Fix method · go · L90-L110 (21 LOC)
internal/rules/blanklinearoundfencedcode/rule.go
func (r *Rule) Fix(f *lint.File) []byte {
	insertBeforeLine, insertAfterLine := collectFenceBlankLineInsertions(f)

	if len(insertBeforeLine) == 0 && len(insertAfterLine) == 0 {
		return f.Source
	}

	var result []string
	for i, line := range f.Lines {
		lineNum := i + 1
		if insertBeforeLine[lineNum] {
			result = append(result, "")
		}
		result = append(result, string(line))
		if insertAfterLine[lineNum] {
			result = append(result, "")
		}
	}

	return []byte(strings.Join(result, "\n"))
}
blanklinearoundfencedcode.collectFenceBlankLineInsertions function · go · L114-L144 (31 LOC)
internal/rules/blanklinearoundfencedcode/rule.go
func collectFenceBlankLineInsertions(f *lint.File) (beforeSet, afterSet map[int]bool) {
	beforeSet = make(map[int]bool)
	afterSet = make(map[int]bool)

	_ = ast.Walk(f.AST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}
		fcb, ok := n.(*ast.FencedCodeBlock)
		if !ok {
			return ast.WalkContinue, nil
		}

		openStart, openEnd := fencedcodestyle.FenceOpenLineRange(f.Source, fcb)
		closeStart, _ := fencedcodestyle.FenceCloseLineRange(f.Source, fcb, openEnd)

		openLine := f.LineOfOffset(openStart)
		closeLine := f.LineOfOffset(closeStart)

		if needsBlankBefore(f, openLine) {
			beforeSet[openLine] = true
		}
		if needsBlankAfter(f, closeLine) {
			afterSet[closeLine] = true
		}

		return ast.WalkContinue, nil
	})

	return beforeSet, afterSet
}
blanklinearoundfencedcode.needsBlankBefore function · go · L148-L154 (7 LOC)
internal/rules/blanklinearoundfencedcode/rule.go
func needsBlankBefore(f *lint.File, line int) bool {
	if line <= 1 {
		return false
	}
	prevIdx := line - 2
	return prevIdx >= 0 && prevIdx < len(f.Lines) && !isBlank(f.Lines[prevIdx])
}
All rows above produced by Repobility · https://repobility.com
blanklinearoundheadings.Rule.Check method · go · L28-L89 (62 LOC)
internal/rules/blanklinearoundheadings/rule.go
func (r *Rule) Check(f *lint.File) []lint.Diagnostic {
	var diags []lint.Diagnostic
	codeLines := lint.CollectCodeBlockLines(f)

	_ = ast.Walk(f.AST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}
		heading, ok := n.(*ast.Heading)
		if !ok {
			return ast.WalkContinue, nil
		}

		line := headingLine(heading, f)

		// Skip headings whose lines overlap with code block regions.
		if codeLines[line] {
			return ast.WalkContinue, nil
		}
		lastLine := headingLastLine(heading, f)

		// Check blank line before (not needed for line 1)
		if line > 1 {
			prevLineIdx := line - 2 // 0-based index
			if prevLineIdx >= 0 && prevLineIdx < len(f.Lines) {
				prevLine := strings.TrimSpace(string(f.Lines[prevLineIdx]))
				if prevLine != "" {
					diags = append(diags, lint.Diagnostic{
						File:     f.Path,
						Line:     line,
						Column:   1,
						RuleID:   r.ID(),
						RuleName: r.Name(),
						Severity: lint.Warning,
						Messa
blanklinearoundheadings.Rule.Fix method · go · L92-L121 (30 LOC)
internal/rules/blanklinearoundheadings/rule.go
func (r *Rule) Fix(f *lint.File) []byte {
	insertBefore, insertAfter := collectHeadingBlankLineInsertions(f)

	if len(insertBefore) == 0 && len(insertAfter) == 0 {
		return f.Source
	}

	lines := make([]string, len(f.Lines))
	for i, l := range f.Lines {
		lines[i] = string(l)
	}

	var result []string
	for i, line := range lines {
		lineNum := i + 1
		if insertBefore[lineNum] {
			// Avoid inserting a blank line if one was just inserted
			// after the previous line (prevents double blank lines).
			if !insertAfter[lineNum-1] {
				result = append(result, "")
			}
		}
		result = append(result, line)
		if insertAfter[lineNum] {
			result = append(result, "")
		}
	}

	return []byte(strings.Join(result, "\n"))
}
blanklinearoundheadings.collectHeadingBlankLineInsertions function · go · L125-L163 (39 LOC)
internal/rules/blanklinearoundheadings/rule.go
func collectHeadingBlankLineInsertions(f *lint.File) (insertBefore, insertAfter map[int]bool) {
	insertBefore = make(map[int]bool)
	insertAfter = make(map[int]bool)
	codeLines := lint.CollectCodeBlockLines(f)

	type headingInfo struct {
		line     int
		lastLine int
	}
	var headings []headingInfo

	_ = ast.Walk(f.AST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}
		heading, ok := n.(*ast.Heading)
		if !ok {
			return ast.WalkContinue, nil
		}
		line := headingLine(heading, f)
		if codeLines[line] {
			return ast.WalkContinue, nil
		}
		headings = append(headings, headingInfo{line: line, lastLine: headingLastLine(heading, f)})
		return ast.WalkContinue, nil
	})

	lines := f.Lines
	for _, h := range headings {
		if h.line > 1 && isNonBlankLine(lines, h.line-2) {
			insertBefore[h.line] = true
		}
		if isNonBlankLine(lines, h.lastLine) {
			insertAfter[h.lastLine] = true
		}
	}

	return insertBefore, insertAfter
}
blanklinearoundheadings.isNonBlankLine function · go · L167-L172 (6 LOC)
internal/rules/blanklinearoundheadings/rule.go
func isNonBlankLine(lines [][]byte, idx int) bool {
	if idx < 0 || idx >= len(lines) {
		return false
	}
	return strings.TrimSpace(string(lines[idx])) != ""
}
blanklinearoundheadings.headingLine function · go · L174-L185 (12 LOC)
internal/rules/blanklinearoundheadings/rule.go
func headingLine(heading *ast.Heading, f *lint.File) int {
	lines := heading.Lines()
	if lines.Len() > 0 {
		return f.LineOfOffset(lines.At(0).Start)
	}
	for c := heading.FirstChild(); c != nil; c = c.NextSibling() {
		if t, ok := c.(*ast.Text); ok {
			return f.LineOfOffset(t.Segment.Start)
		}
	}
	return 1
}
blanklinearoundheadings.headingLastLine function · go · L187-L201 (15 LOC)
internal/rules/blanklinearoundheadings/rule.go
func headingLastLine(heading *ast.Heading, f *lint.File) int {
	lines := heading.Lines()
	if lines.Len() > 0 {
		// Setext headings: the underline is on the line after the text
		lastSeg := lines.At(lines.Len() - 1)
		textLine := f.LineOfOffset(lastSeg.Start)
		// Check if next line is an underline (setext)
		if isSetextHeading(heading, f.Source) {
			return textLine + 1
		}
		return textLine
	}
	// ATX heading is a single line
	return headingLine(heading, f)
}
blanklinearoundheadings.isSetextHeading function · go · L203-L217 (15 LOC)
internal/rules/blanklinearoundheadings/rule.go
func isSetextHeading(heading *ast.Heading, source []byte) bool {
	lines := heading.Lines()
	if lines.Len() == 0 {
		return false
	}
	seg := lines.At(0)
	lineStart := seg.Start
	for lineStart > 0 && source[lineStart-1] != '\n' {
		lineStart--
	}
	if lineStart < len(source) && source[lineStart] == '#' {
		return false
	}
	return true
}
blanklinearoundlists.Rule.Check method · go · L28-L64 (37 LOC)
internal/rules/blanklinearoundlists/rule.go
func (r *Rule) Check(f *lint.File) []lint.Diagnostic {
	var diags []lint.Diagnostic
	codeLines := lint.CollectCodeBlockLines(f)

	_ = ast.Walk(f.AST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}

		list, ok := n.(*ast.List)
		if !ok {
			return ast.WalkContinue, nil
		}

		if _, isListItem := list.Parent().(*ast.ListItem); isListItem {
			return ast.WalkContinue, nil
		}

		listStartLine := lineOfNode(f, list)
		listEndLine := lastLineOfNode(f, list)

		if codeLines[listStartLine] || codeLines[listEndLine] {
			return ast.WalkContinue, nil
		}

		if d, ok := r.checkAdjacentBlank(f, listStartLine, -1, "list should be preceded by a blank line"); ok {
			diags = append(diags, d)
		}
		if d, ok := r.checkAdjacentBlank(f, listEndLine, +1, "list should be followed by a blank line"); ok {
			diags = append(diags, d)
		}

		return ast.WalkContinue, nil
	})

	return diags
}
Repobility · open methodology · https://repobility.com/research/
blanklinearoundlists.Rule.checkAdjacentBlank method · go · L68-L86 (19 LOC)
internal/rules/blanklinearoundlists/rule.go
func (r *Rule) checkAdjacentBlank(f *lint.File, targetLine, direction int, msg string) (lint.Diagnostic, bool) {
	totalLines := len(f.Lines)
	adjLine := targetLine + direction
	if adjLine < 1 || adjLine > totalLines {
		return lint.Diagnostic{}, false
	}
	if isBlank(f.Lines[adjLine-1]) {
		return lint.Diagnostic{}, false
	}
	return lint.Diagnostic{
		File:     f.Path,
		Line:     targetLine,
		Column:   1,
		RuleID:   r.ID(),
		RuleName: r.Name(),
		Severity: lint.Warning,
		Message:  msg,
	}, true
}
blanklinearoundlists.isInlineNode function · go · L89-L96 (8 LOC)
internal/rules/blanklinearoundlists/rule.go
func isInlineNode(n ast.Node) bool {
	switch n.(type) {
	case *ast.Text, *ast.String, *ast.CodeSpan, *ast.Emphasis,
		*ast.Link, *ast.Image, *ast.AutoLink, *ast.RawHTML:
		return true
	}
	return false
}
blanklinearoundlists.lineOfNode function · go · L98-L129 (32 LOC)
internal/rules/blanklinearoundlists/rule.go
func lineOfNode(f *lint.File, n ast.Node) int {
	// Inline nodes do not have Lines(); use Segment for Text nodes.
	if t, ok := n.(*ast.Text); ok {
		return f.LineOfOffset(t.Segment.Start)
	}
	if isInlineNode(n) {
		// For other inline nodes, recurse into children.
		if n.HasChildren() {
			for c := n.FirstChild(); c != nil; c = c.NextSibling() {
				line := lineOfNode(f, c)
				if line > 0 {
					return line
				}
			}
		}
		return 0
	}
	if n.Lines().Len() > 0 {
		seg := n.Lines().At(0)
		return f.LineOfOffset(seg.Start)
	}
	// For container nodes, find the first child with lines.
	if n.HasChildren() {
		for c := n.FirstChild(); c != nil; c = c.NextSibling() {
			line := lineOfNode(f, c)
			if line > 0 {
				return line
			}
		}
	}
	return 0
}
blanklinearoundlists.lastLineOfNode function · go · L131-L161 (31 LOC)
internal/rules/blanklinearoundlists/rule.go
func lastLineOfNode(f *lint.File, n ast.Node) int {
	// Inline nodes do not have Lines(); use Segment for Text nodes.
	if t, ok := n.(*ast.Text); ok {
		return f.LineOfOffset(t.Segment.Stop - 1)
	}
	if isInlineNode(n) {
		if n.HasChildren() {
			for c := n.LastChild(); c != nil; c = c.PreviousSibling() {
				line := lastLineOfNode(f, c)
				if line > 0 {
					return line
				}
			}
		}
		return 0
	}
	if n.Lines().Len() > 0 {
		seg := n.Lines().At(n.Lines().Len() - 1)
		return f.LineOfOffset(seg.Start)
	}
	// For container nodes, find the last child with lines.
	if n.HasChildren() {
		for c := n.LastChild(); c != nil; c = c.PreviousSibling() {
			line := lastLineOfNode(f, c)
			if line > 0 {
				return line
			}
		}
	}
	return 0
}
blanklinearoundlists.Rule.Fix method · go · L168-L190 (23 LOC)
internal/rules/blanklinearoundlists/rule.go
func (r *Rule) Fix(f *lint.File) []byte {
	beforeSet, afterSet := r.collectBlankLineInsertions(f)

	if len(beforeSet) == 0 && len(afterSet) == 0 {
		result := make([]byte, len(f.Source))
		copy(result, f.Source)
		return result
	}

	var resultLines [][]byte
	for i, line := range f.Lines {
		lineNum := i + 1
		if beforeSet[lineNum] {
			resultLines = append(resultLines, []byte{})
		}
		resultLines = append(resultLines, line)
		if afterSet[lineNum] {
			resultLines = append(resultLines, []byte{})
		}
	}

	return bytes.Join(resultLines, []byte("\n"))
}
blanklinearoundlists.Rule.collectBlankLineInsertions method · go · L194-L231 (38 LOC)
internal/rules/blanklinearoundlists/rule.go
func (r *Rule) collectBlankLineInsertions(f *lint.File) (beforeSet, afterSet map[int]bool) {
	beforeSet = make(map[int]bool)
	afterSet = make(map[int]bool)
	codeLines := lint.CollectCodeBlockLines(f)

	_ = ast.Walk(f.AST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}

		list, ok := n.(*ast.List)
		if !ok {
			return ast.WalkContinue, nil
		}

		if _, isListItem := list.Parent().(*ast.ListItem); isListItem {
			return ast.WalkContinue, nil
		}

		listStartLine := lineOfNode(f, list)
		listEndLine := lastLineOfNode(f, list)

		if codeLines[listStartLine] || codeLines[listEndLine] {
			return ast.WalkContinue, nil
		}

		if needsBlankAdjacent(f, listStartLine, -1) {
			beforeSet[listStartLine] = true
		}
		if needsBlankAdjacent(f, listEndLine, +1) {
			afterSet[listEndLine] = true
		}

		return ast.WalkContinue, nil
	})

	return beforeSet, afterSet
}
blanklinearoundlists.needsBlankAdjacent function · go · L235-L241 (7 LOC)
internal/rules/blanklinearoundlists/rule.go
func needsBlankAdjacent(f *lint.File, targetLine, direction int) bool {
	adjLine := targetLine + direction
	if adjLine < 1 || adjLine > len(f.Lines) {
		return false
	}
	return !isBlank(f.Lines[adjLine-1])
}
catalog.renderTemplate function · go · L21-L65 (45 LOC)
internal/rules/catalog/generate.go
func renderTemplate(params map[string]string, entries []fileEntry, columns ...map[string]columnConfig) (string, error) {
	var buf strings.Builder

	header := params["header"]
	row := params["row"]
	footer := params["footer"]

	// Build column map from the row template if we have column constraints.
	var cols map[string]columnConfig
	var colMap map[int]string
	if len(columns) > 0 && columns[0] != nil && len(columns[0]) > 0 {
		cols = columns[0]
		colMap = buildColumnMap(row)
	}

	if header != "" {
		buf.WriteString(ensureTrailingNewline(header))
	}

	tmpl, err := template.New("row").Option("missingkey=zero").Parse(row)
	if err != nil {
		return "", err
	}

	for _, entry := range entries {
		var rowBuf bytes.Buffer
		if err := tmpl.Execute(&rowBuf, entry.fields); err != nil {
			return "", err
		}
		rendered := rowBuf.String()

		// Apply column constraints to table rows.
		if cols != nil && colMap != nil {
			rendered = applyColumnConstraints(rendered, cols, colMap)
		}

		buf.WriteStri
Repobility analyzer · published findings · https://repobility.com
catalog.renderMinimal function · go · L69-L77 (9 LOC)
internal/rules/catalog/generate.go
func renderMinimal(entries []fileEntry) string {
	var buf strings.Builder
	for _, entry := range entries {
		path := entry.fields["filename"]
		basename := filepath.Base(path)
		buf.WriteString("- [" + basename + "](" + path + ")\n")
	}
	return buf.String()
}
catalog.renderEmpty function · go · L80-L86 (7 LOC)
internal/rules/catalog/generate.go
func renderEmpty(params map[string]string) string {
	empty := params["empty"]
	if empty == "" {
		return ""
	}
	return ensureTrailingNewline(empty)
}
catalog.parseColumnConfig function · go · L15-L28 (14 LOC)
internal/rules/catalog/parse.go
func parseColumnConfig(raw map[string]any) map[string]columnConfig {
	gc := gensection.ParseColumnConfig(raw)
	if gc == nil {
		return nil
	}
	result := make(map[string]columnConfig, len(gc))
	for k, v := range gc {
		result[k] = columnConfig{
			maxWidth: v.MaxWidth,
			wrap:     v.Wrap,
		}
	}
	return result
}
‹ prevpage 4 / 10next ›