135 lines
4.5 KiB
Go
135 lines
4.5 KiB
Go
package compiler
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/collections"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/diagnostics"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tsoptions"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tspath"
|
|
)
|
|
|
|
type processingDiagnosticKind int
|
|
|
|
const (
|
|
processingDiagnosticKindUnknownReference processingDiagnosticKind = iota
|
|
processingDiagnosticKindExplainingFileInclude
|
|
)
|
|
|
|
type processingDiagnostic struct {
|
|
kind processingDiagnosticKind
|
|
data any
|
|
}
|
|
|
|
func (d *processingDiagnostic) asFileIncludeReason() *fileIncludeReason {
|
|
return d.data.(*fileIncludeReason)
|
|
}
|
|
|
|
type includeExplainingDiagnostic struct {
|
|
file tspath.Path
|
|
diagnosticReason *fileIncludeReason
|
|
message *diagnostics.Message
|
|
args []any
|
|
}
|
|
|
|
func (d *processingDiagnostic) asIncludeExplainingDiagnostic() *includeExplainingDiagnostic {
|
|
return d.data.(*includeExplainingDiagnostic)
|
|
}
|
|
|
|
func (d *processingDiagnostic) toDiagnostic(program *Program) *ast.Diagnostic {
|
|
switch d.kind {
|
|
case processingDiagnosticKindUnknownReference:
|
|
ref := d.asFileIncludeReason()
|
|
loc := ref.getReferencedLocation(program)
|
|
switch ref.kind {
|
|
case fileIncludeKindTypeReferenceDirective:
|
|
return loc.diagnosticAt(diagnostics.Cannot_find_type_definition_file_for_0, loc.ref.FileName)
|
|
case fileIncludeKindLibReferenceDirective:
|
|
libName := tspath.ToFileNameLowerCase(loc.ref.FileName)
|
|
unqualifiedLibName := strings.TrimSuffix(strings.TrimPrefix(libName, "lib."), ".d.ts")
|
|
suggestion := core.GetSpellingSuggestion(unqualifiedLibName, tsoptions.Libs, core.Identity)
|
|
return loc.diagnosticAt(core.IfElse(
|
|
suggestion != "",
|
|
diagnostics.Cannot_find_lib_definition_for_0_Did_you_mean_1,
|
|
diagnostics.Cannot_find_lib_definition_for_0,
|
|
), libName, suggestion)
|
|
default:
|
|
panic("unknown include kind")
|
|
}
|
|
case processingDiagnosticKindExplainingFileInclude:
|
|
return d.createDiagnosticExplainingFile(program)
|
|
default:
|
|
panic("unknown processingDiagnosticKind")
|
|
}
|
|
}
|
|
|
|
func (d *processingDiagnostic) createDiagnosticExplainingFile(program *Program) *ast.Diagnostic {
|
|
diag := d.asIncludeExplainingDiagnostic()
|
|
var includeDetails []*ast.Diagnostic
|
|
var relatedInfo []*ast.Diagnostic
|
|
var redirectInfo []*ast.Diagnostic
|
|
var preferredLocation *fileIncludeReason
|
|
var seenReasons collections.Set[*fileIncludeReason]
|
|
if diag.diagnosticReason.isReferencedFile() && !program.includeProcessor.getReferenceLocation(diag.diagnosticReason, program).isSynthetic {
|
|
preferredLocation = diag.diagnosticReason
|
|
}
|
|
|
|
processRelatedInfo := func(includeReason *fileIncludeReason) {
|
|
if preferredLocation == nil && includeReason.isReferencedFile() && !program.includeProcessor.getReferenceLocation(includeReason, program).isSynthetic {
|
|
preferredLocation = includeReason
|
|
} else {
|
|
info := program.includeProcessor.getRelatedInfo(includeReason, program)
|
|
if info != nil {
|
|
relatedInfo = append(relatedInfo, info)
|
|
}
|
|
}
|
|
}
|
|
processInclude := func(includeReason *fileIncludeReason) {
|
|
if !seenReasons.AddIfAbsent(includeReason) {
|
|
return
|
|
}
|
|
includeDetails = append(includeDetails, includeReason.toDiagnostic(program, false))
|
|
processRelatedInfo(includeReason)
|
|
}
|
|
|
|
// !!! todo sheetal caching
|
|
|
|
if diag.file != "" {
|
|
reasons := program.includeProcessor.fileIncludeReasons[diag.file]
|
|
includeDetails = make([]*ast.Diagnostic, 0, len(reasons))
|
|
for _, reason := range reasons {
|
|
processInclude(reason)
|
|
}
|
|
redirectInfo = program.includeProcessor.explainRedirectAndImpliedFormat(program, program.GetSourceFileByPath(diag.file), func(fileName string) string { return fileName })
|
|
}
|
|
if diag.diagnosticReason != nil {
|
|
processInclude(diag.diagnosticReason)
|
|
}
|
|
var chain []*ast.Diagnostic
|
|
if includeDetails != nil && (preferredLocation == nil || seenReasons.Len() != 1) {
|
|
fileReason := ast.NewCompilerDiagnostic(diagnostics.The_file_is_in_the_program_because_Colon)
|
|
fileReason.SetMessageChain(includeDetails)
|
|
chain = []*ast.Diagnostic{fileReason}
|
|
}
|
|
if redirectInfo != nil {
|
|
chain = append(chain, redirectInfo...)
|
|
}
|
|
|
|
var result *ast.Diagnostic
|
|
if preferredLocation != nil {
|
|
result = program.includeProcessor.getReferenceLocation(preferredLocation, program).diagnosticAt(diag.message, diag.args...)
|
|
}
|
|
if result == nil {
|
|
result = ast.NewCompilerDiagnostic(diag.message, diag.args...)
|
|
}
|
|
if chain != nil {
|
|
result.SetMessageChain(chain)
|
|
}
|
|
if relatedInfo != nil {
|
|
result.SetRelatedInfo(relatedInfo)
|
|
}
|
|
return result
|
|
}
|