Skip to content

refactor tsconfigsourcefile to use ast.SourceFile, and use *ParsedCommandLine where possible #257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions internal/tsoptions/commandlineparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ func convertJsonOptionOfEnumType(
opt *CommandLineOption,
value string,
valueExpression *ast.Expression,
sourceFile *TsConfigSourceFile,
sourceFile *ast.SourceFile,
) (any, []*ast.Diagnostic) {
if value == "" {
return nil, nil
Expand All @@ -339,9 +339,5 @@ func convertJsonOptionOfEnumType(
if ok {
return validateJsonOptionValue(opt, val, valueExpression, sourceFile)
}
// todo: clean up use of `TsConfigSourceFile`
if sourceFile == nil {
return nil, []*ast.Diagnostic{createDiagnosticForInvalidEnumType(opt, nil, nil)}
}
return nil, []*ast.Diagnostic{createDiagnosticForInvalidEnumType(opt, sourceFile.SourceFile, valueExpression)}
return nil, []*ast.Diagnostic{createDiagnosticForInvalidEnumType(opt, sourceFile, valueExpression)}
}
62 changes: 35 additions & 27 deletions internal/tsoptions/tsconfigparsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ type parsedTsconfig struct {
}

func parseOwnConfigOfJsonSourceFile(
sourceFile *TsConfigSourceFile,
sourceFile *ast.SourceFile,
host ParseConfigHost,
basePath string,
configFileName string,
Expand Down Expand Up @@ -165,7 +165,7 @@ func parseOwnConfigOfJsonSourceFile(
propertySetErrors = append(propertySetErrors, err...)
} else if option == nil {
if keyText == "excludes" {
propertySetErrors = append(propertySetErrors, createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile.SourceFile, propertyAssignment.Name(), diagnostics.Unknown_option_excludes_Did_you_mean_exclude))
propertySetErrors = append(propertySetErrors, createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, propertyAssignment.Name(), diagnostics.Unknown_option_excludes_Did_you_mean_exclude))
}
if core.Find(optionsDeclarations, func(option *CommandLineOption) bool { return option.Name == keyText }) != nil {
rootCompilerOptions = append(rootCompilerOptions, propertyAssignment.Name())
Expand All @@ -176,7 +176,7 @@ func parseOwnConfigOfJsonSourceFile(
}

json, err := convertConfigFileToObject(
sourceFile.SourceFile,
sourceFile,
&jsonConversionNotifier{
tsconfigRootOptionsMap,
onPropertySet,
Expand All @@ -200,6 +200,14 @@ type TsConfigSourceFile struct {
configFileSpecs *configFileSpecs
SourceFile *ast.SourceFile
}

func tsconfigToSourceFile(tsconfigSourceFile *TsConfigSourceFile) *ast.SourceFile {
if tsconfigSourceFile == nil {
return nil
}
return tsconfigSourceFile.SourceFile
}

type jsonConversionNotifier struct {
rootOptions *CommandLineOption
onPropertySet func(keyText string, value any, propertyAssignment *ast.PropertyAssignment, parentOption *CommandLineOption, option *CommandLineOption) (any, []*ast.Diagnostic)
Expand Down Expand Up @@ -272,7 +280,7 @@ func validateJsonOptionValue(
opt *CommandLineOption,
val any,
valueExpression *ast.Expression,
sourceFile *TsConfigSourceFile,
sourceFile *ast.SourceFile,
) (any, []*ast.Diagnostic) {
if val == nil || val == "" {
return nil, nil
Expand All @@ -284,7 +292,7 @@ func validateJsonOptionValue(
if result == nil {
return val, nil
}
errors = append(errors, createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile.SourceFile, valueExpression, err))
errors = append(errors, createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, err))
} else {
return val, nil
}
Expand All @@ -297,7 +305,7 @@ func convertJsonOptionOfListType(
basePath string,
propertyAssignment *ast.PropertyAssignment,
valueExpression *ast.Node,
sourceFile *TsConfigSourceFile,
sourceFile *ast.SourceFile,
) ([]any, []*ast.Diagnostic) {
var expression *ast.Node
var errors []*ast.Diagnostic
Expand Down Expand Up @@ -350,7 +358,7 @@ func convertJsonOption(
basePath string,
propertyAssignment *ast.PropertyAssignment,
valueExpression *ast.Expression,
sourceFile *TsConfigSourceFile,
sourceFile *ast.SourceFile,
) (any, []*ast.Diagnostic) {
var errors []*ast.Diagnostic
if opt.isCommandLineOnly {
Expand All @@ -361,7 +369,7 @@ func convertJsonOption(
if sourceFile == nil && nodeValue == nil {
errors = append(errors, ast.NewCompilerDiagnostic(diagnostics.Option_0_can_only_be_specified_on_command_line, opt.Name))
} else {
errors = append(errors, createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile.SourceFile, nodeValue, diagnostics.Option_0_can_only_be_specified_on_command_line, opt.Name))
errors = append(errors, createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, nodeValue, diagnostics.Option_0_can_only_be_specified_on_command_line, opt.Name))
}
return nil, errors
}
Expand Down Expand Up @@ -390,7 +398,7 @@ func convertJsonOption(
return normalizeNonListOptionValue(opt, basePath, validatedValue), errors
}
} else {
errors = append(errors, createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile.SourceFile, valueExpression, diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.Name, getCompilerOptionValueTypeString(opt)))
errors = append(errors, createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.Name, getCompilerOptionValueTypeString(opt)))
return nil, errors
}
}
Expand All @@ -402,7 +410,7 @@ func getExtendsConfigPathOrArray(
configFileName string,
propertyAssignment *ast.PropertyAssignment,
valueExpression *ast.Expression,
sourceFile *TsConfigSourceFile,
sourceFile *ast.SourceFile,
) ([]string, []*ast.Diagnostic) {
var extendedConfigPathArray []string
newBase := basePath
Expand Down Expand Up @@ -446,13 +454,13 @@ func getExtendsConfigPath(
host ParseConfigHost,
basePath string,
valueExpression *ast.Expression,
sourceFile *TsConfigSourceFile,
sourceFile *ast.SourceFile,
) (string, []*ast.Diagnostic) {
extendedConfig = tspath.NormalizeSlashes(extendedConfig)
var errors []*ast.Diagnostic
var errorFile *ast.SourceFile
if sourceFile != nil {
errorFile = sourceFile.SourceFile
errorFile = sourceFile
}
if tspath.IsRootedDiskPath(extendedConfig) || strings.HasPrefix(extendedConfig, "./") || strings.HasPrefix(extendedConfig, "../") {
extendedConfigPath := tspath.GetNormalizedAbsolutePath(extendedConfig, basePath)
Expand Down Expand Up @@ -579,7 +587,7 @@ type resolverHost struct {

func (r *resolverHost) Trace(msg string) {}

func ParseJsonSourceFileConfigFileContent(sourceFile *TsConfigSourceFile, host ParseConfigHost, basePath string, existingOptions *core.CompilerOptions, configFileName string, resolutionStack []tspath.Path, extraFileExtensions []fileExtensionInfo, extendedConfigCache map[string]*extendedConfigCacheEntry) ParsedCommandLine {
func ParseJsonSourceFileConfigFileContent(sourceFile *TsConfigSourceFile, host ParseConfigHost, basePath string, existingOptions *core.CompilerOptions, configFileName string, resolutionStack []tspath.Path, extraFileExtensions []fileExtensionInfo, extendedConfigCache map[string]*extendedConfigCacheEntry) *ParsedCommandLine {
// tracing?.push(tracing.Phase.Parse, "parseJsonSourceFileConfigFileContent", { path: sourceFile.fileName });
result := parseJsonConfigFileContentWorker(nil /*json*/, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache)
// tracing?.pop();
Expand Down Expand Up @@ -719,7 +727,7 @@ func convertPropertyValueToJson(sourceFile *ast.SourceFile, valueExpression *ast
// jsonNode: The contents of the config file to parse
// host: Instance of ParseConfigHost used to enumerate files in folder.
// basePath: A root directory to resolve relative path entries in the config file to. e.g. outDir
func ParseJsonConfigFileContent(json any, host ParseConfigHost, basePath string, existingOptions *core.CompilerOptions, configFileName string, resolutionStack []tspath.Path, extraFileExtensions []fileExtensionInfo, extendedConfigCache map[string]*extendedConfigCacheEntry) ParsedCommandLine {
func ParseJsonConfigFileContent(json any, host ParseConfigHost, basePath string, existingOptions *core.CompilerOptions, configFileName string, resolutionStack []tspath.Path, extraFileExtensions []fileExtensionInfo, extendedConfigCache map[string]*extendedConfigCacheEntry) *ParsedCommandLine {
result := parseJsonConfigFileContentWorker(parseJsonToStringKey(json), nil /*sourceFile*/, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache)
return result
}
Expand Down Expand Up @@ -883,7 +891,7 @@ func parseConfig(
if json != nil {
ownConfig, err = parseOwnConfigOfJson(json, host, basePath, configFileName)
} else {
ownConfig, err = parseOwnConfigOfJsonSourceFile(sourceFile, host, basePath, configFileName)
ownConfig, err = parseOwnConfigOfJsonSourceFile(tsconfigToSourceFile(sourceFile), host, basePath, configFileName)
}
errors = append(errors, err...)
if ownConfig.options != nil && ownConfig.options.Paths != nil {
Expand Down Expand Up @@ -1004,7 +1012,7 @@ func parseJsonConfigFileContentWorker(
resolutionStack []tspath.Path,
extraFileExtensions []fileExtensionInfo,
extendedConfigCache map[string]*extendedConfigCacheEntry,
) ParsedCommandLine {
) *ParsedCommandLine {
// Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined));
var errors []*ast.Diagnostic
resolutionStackString := []string{}
Expand Down Expand Up @@ -1060,7 +1068,7 @@ func parseJsonConfigFileContentWorker(
fileName = "tsconfig.json"
}
diagnosticMessage := diagnostics.The_files_list_in_config_file_0_is_empty
nodeValue := forEachTsConfigPropArray(sourceFile, "files", func(property *ast.PropertyAssignment) *ast.Node { return property.Initializer })
nodeValue := forEachTsConfigPropArray(sourceFile.SourceFile, "files", func(property *ast.PropertyAssignment) *ast.Node { return property.Initializer })
errors = append(errors, ast.NewDiagnostic(sourceFile.SourceFile, core.NewTextRange(scanner.SkipTrivia(sourceFile.SourceFile.Text, nodeValue.Pos()), nodeValue.End()), diagnosticMessage, fileName))
} else {
errors = append(errors, ast.NewCompilerDiagnostic(diagnostics.The_files_list_in_config_file_0_is_empty, configFileName))
Expand Down Expand Up @@ -1099,7 +1107,7 @@ func parseJsonConfigFileContentWorker(
// file system.
if includeSpecs.sliceValue != nil {
var err []*ast.Diagnostic
validatedIncludeSpecsBeforeSubstitution, err = validateSpecs(includeSpecs.sliceValue, true /*disallowTrailingRecursion*/, sourceFile, "include")
validatedIncludeSpecsBeforeSubstitution, err = validateSpecs(includeSpecs.sliceValue, true /*disallowTrailingRecursion*/, tsconfigToSourceFile(sourceFile), "include")
errors = append(errors, err...)
validatedIncludeSpecs = getSubstitutedStringArrayWithConfigDirTemplate(
validatedIncludeSpecsBeforeSubstitution,
Expand All @@ -1111,7 +1119,7 @@ func parseJsonConfigFileContentWorker(
}
if excludeSpecs.sliceValue != nil {
var err []*ast.Diagnostic
validatedExcludeSpecsBeforeSubstitution, err = validateSpecs(excludeSpecs.sliceValue, false /*disallowTrailingRecursion*/, sourceFile, "exclude")
validatedExcludeSpecsBeforeSubstitution, err = validateSpecs(excludeSpecs.sliceValue, false /*disallowTrailingRecursion*/, tsconfigToSourceFile(sourceFile), "exclude")
errors = append(errors, err...)
validatedExcludeSpecs = getSubstitutedStringArrayWithConfigDirTemplate(
validatedExcludeSpecsBeforeSubstitution,
Expand Down Expand Up @@ -1193,7 +1201,7 @@ func parseJsonConfigFileContentWorker(
return projectReferences
}

return ParsedCommandLine{
return &ParsedCommandLine{
ParsedConfig: &core.ParsedOptions{
CompilerOptions: parsedConfig.options,
FileNames: getFileNames(basePathForFileNames),
Expand All @@ -1214,10 +1222,10 @@ func shouldReportNoInputFiles(fileNames []string, canJsonReportNoInutFiles bool,
return len(fileNames) == 0 && canJsonReportNoInutFiles && len(resolutionStack) == 0
}

func validateSpecs(specs any, disallowTrailingRecursion bool, jsonSourceFile *TsConfigSourceFile, specKey string) ([]string, []*ast.Diagnostic) {
func validateSpecs(specs any, disallowTrailingRecursion bool, jsonSourceFile *ast.SourceFile, specKey string) ([]string, []*ast.Diagnostic) {
createDiagnostic := func(message *diagnostics.Message, spec string) *ast.Diagnostic {
element := getTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec)
return createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(jsonSourceFile.SourceFile, element.AsNode(), message, spec)
return createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(jsonSourceFile, element.AsNode(), message, spec)
}
var errors []*ast.Diagnostic
var finalSpecs []string
Expand Down Expand Up @@ -1282,7 +1290,7 @@ func invalidDotDotAfterRecursiveWildcard(s string) bool {
// \/?$ # matches an optional trailing directory separator at the end of the string.
const invalidTrailingRecursionPattern = `(?:^|\/)\*\*\/?$`

func getTsConfigPropArrayElementValue(tsConfigSourceFile *TsConfigSourceFile, propKey string, elementValue string) *ast.StringLiteral {
func getTsConfigPropArrayElementValue(tsConfigSourceFile *ast.SourceFile, propKey string, elementValue string) *ast.StringLiteral {
return forEachTsConfigPropArray(tsConfigSourceFile, propKey, func(property *ast.PropertyAssignment) *ast.StringLiteral {
if ast.IsArrayLiteralExpression(property.Initializer) {
value := core.Find(property.Initializer.AsArrayLiteralExpression().Elements.Nodes, func(element *ast.Node) bool {
Expand All @@ -1296,7 +1304,7 @@ func getTsConfigPropArrayElementValue(tsConfigSourceFile *TsConfigSourceFile, pr
})
}

func forEachTsConfigPropArray[T any](tsConfigSourceFile *TsConfigSourceFile, propKey string, callback func(property *ast.PropertyAssignment) *T) *T {
func forEachTsConfigPropArray[T any](tsConfigSourceFile *ast.SourceFile, propKey string, callback func(property *ast.PropertyAssignment) *T) *T {
if tsConfigSourceFile != nil {
return forEachPropertyAssignment(getTsConfigObjectLiteralExpression(tsConfigSourceFile), propKey, callback)
}
Expand All @@ -1319,9 +1327,9 @@ func forEachPropertyAssignment[T any](objectLiteral *ast.ObjectLiteralExpression
return *new(T)
}

func getTsConfigObjectLiteralExpression(tsConfigSourceFile *TsConfigSourceFile) *ast.ObjectLiteralExpression {
if tsConfigSourceFile != nil && tsConfigSourceFile.SourceFile.Statements != nil && len(tsConfigSourceFile.SourceFile.Statements.Nodes) > 0 {
expression := tsConfigSourceFile.SourceFile.Statements.Nodes[0].AsExpressionStatement().Expression
func getTsConfigObjectLiteralExpression(tsConfigSourceFile *ast.SourceFile) *ast.ObjectLiteralExpression {
if tsConfigSourceFile != nil && tsConfigSourceFile.Statements != nil && len(tsConfigSourceFile.Statements.Nodes) > 0 {
expression := tsConfigSourceFile.Statements.Nodes[0].AsExpressionStatement().Expression
return expression.AsObjectLiteralExpression()
}
return nil
Expand Down
6 changes: 3 additions & 3 deletions internal/tsoptions/tsconfigparsing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ func TestParseJsonConfigFileContent(t *testing.T) {
for _, rec := range parseJsonConfigFileTests {
t.Run(rec.title+" with json api", func(t *testing.T) {
t.Parallel()
baselineParseConfigWith(t, rec.title+" with json api.js", rec.noSubmoduleBaseline, rec.input, func(config testConfig, host ParseConfigHost, basePath string) ParsedCommandLine {
baselineParseConfigWith(t, rec.title+" with json api.js", rec.noSubmoduleBaseline, rec.input, func(config testConfig, host ParseConfigHost, basePath string) *ParsedCommandLine {
parsed, _ := ParseConfigFileTextToJson(config.configFileName, config.basePath, config.jsonText)
return ParseJsonConfigFileContent(
parsed,
Expand All @@ -522,7 +522,7 @@ func TestParseJsonSourceFileConfigFileContent(t *testing.T) {
for _, rec := range parseJsonConfigFileTests {
t.Run(rec.title+" with jsonSourceFile api", func(t *testing.T) {
t.Parallel()
baselineParseConfigWith(t, rec.title+" with jsonSourceFile api.js", rec.noSubmoduleBaseline, rec.input, func(config testConfig, host ParseConfigHost, basePath string) ParsedCommandLine {
baselineParseConfigWith(t, rec.title+" with jsonSourceFile api.js", rec.noSubmoduleBaseline, rec.input, func(config testConfig, host ParseConfigHost, basePath string) *ParsedCommandLine {
parsed := parser.ParseJSONText(config.configFileName, config.jsonText)
tsConfigSourceFile := &TsConfigSourceFile{
SourceFile: parsed,
Expand All @@ -542,7 +542,7 @@ func TestParseJsonSourceFileConfigFileContent(t *testing.T) {
}
}

func baselineParseConfigWith(t *testing.T, baselineFileName string, noSubmoduleBaseline bool, input []testConfig, getParsed func(config testConfig, host ParseConfigHost, basePath string) ParsedCommandLine) {
func baselineParseConfigWith(t *testing.T, baselineFileName string, noSubmoduleBaseline bool, input []testConfig, getParsed func(config testConfig, host ParseConfigHost, basePath string) *ParsedCommandLine) {
var baselineContent strings.Builder
for i, config := range input {
basePath := config.basePath
Expand Down
Loading