Skip to content

Add symbol baseliner #191

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 15 commits into from
Jan 8, 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
2 changes: 1 addition & 1 deletion internal/ast/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ func IsDeclaration(node *Node) bool {

// True if `name` is the name of a declaration node
func IsDeclarationName(name *Node) bool {
return !IsSourceFile(name) && !IsBindingPattern(name) && IsDeclaration(name.Parent)
return !IsSourceFile(name) && !IsBindingPattern(name) && IsDeclaration(name.Parent) && name.Parent.Name() == name
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bug fix.

}

// Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`.
Expand Down
14 changes: 11 additions & 3 deletions internal/compiler/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8073,7 +8073,7 @@ func (c *Checker) isInPropertyInitializerOrClassStaticBlock(node *ast.Node) bool
}
return ast.FindAncestorQuit
default:
if isExpressionNode(node) {
if IsExpressionNode(node) {
return ast.FindAncestorFalse
}
return ast.FindAncestorQuit
Expand Down Expand Up @@ -22736,6 +22736,14 @@ func (c *Checker) getActualTypeVariable(t *Type) *Type {
return t
}

func (c *Checker) GetSymbolAtLocation(node *ast.Node) *ast.Symbol {
// !!!
// const node = getParseTreeNode(nodeIn);

// set ignoreErrors: true because any lookups invoked by the API shouldn't cause any new errors
return c.getSymbolAtLocation(node, true /*ignoreErrors*/)
}

func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Symbol {
if ast.IsSourceFile(node) {
if ast.IsExternalModule(node.AsSourceFile()) {
Expand Down Expand Up @@ -22963,7 +22971,7 @@ func (c *Checker) getSymbolOfNameOrPropertyAccessExpression(name *ast.Node) *ast
}
}

if isExpressionNode(name) {
if IsExpressionNode(name) {
if ast.NodeIsMissing(name) {
// Missing entity name.
return nil
Expand Down Expand Up @@ -23066,7 +23074,7 @@ func (c *Checker) getTypeOfNode(node *ast.Node) *Type {
return typeFromTypeNode
}

if isExpressionNode(node) {
if IsExpressionNode(node) {
return c.getRegularTypeOfExpression(node)
}

Expand Down
4 changes: 2 additions & 2 deletions internal/compiler/checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ foo.bar;`
}
p := NewProgram(opts)
p.bindSourceFiles()
c := p.getTypeChecker()
c := p.GetTypeChecker()
file := p.filesByPath["/foo.ts"]
interfaceId := file.Statements.Nodes[0].Name()
varId := file.Statements.Nodes[1].AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0].Name()
propAccess := file.Statements.Nodes[2].AsExpressionStatement().Expression
nodes := []*ast.Node{interfaceId, varId, propAccess}
for _, node := range nodes {
symbol := c.getSymbolAtLocation(node, true /*ignoreErrors*/)
symbol := c.GetSymbolAtLocation(node)
if symbol == nil {
t.Fatalf("Expected symbol to be non-nil")
}
Expand Down
2 changes: 1 addition & 1 deletion internal/compiler/grammarchecks.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (c *Checker) checkGrammarPrivateIdentifierExpression(privId *ast.PrivateIde
}

if !ast.IsForInStatement(privId.Parent) {
if !isExpressionNode(privIdAsNode) {
if !IsExpressionNode(privIdAsNode) {
return c.grammarErrorOnNode(privIdAsNode, diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression)
}

Expand Down
6 changes: 5 additions & 1 deletion internal/compiler/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ func (c *Checker) getTypePrecedence(t *Type) ast.TypePrecedence {
return ast.TypePrecedenceNonArray
}

func (c *Checker) SymbolToString(s *ast.Symbol) string {
return c.symbolToString(s)
}

func (c *Checker) symbolToString(s *ast.Symbol) string {
if s.ValueDeclaration != nil {
name := ast.GetNameOfDeclaration(s.ValueDeclaration)
Expand Down Expand Up @@ -571,7 +575,7 @@ func (c *Checker) getTextAndTypeOfNode(node *ast.Node) (string, *Type, bool) {
}
}
}
if isExpressionNode(node) && !isRightSideOfQualifiedNameOrPropertyAccess(node) {
if IsExpressionNode(node) && !isRightSideOfQualifiedNameOrPropertyAccess(node) {
return scanner.GetTextOfNode(node), c.getTypeOfExpression(node), false
}
return "", nil, false
Expand Down
13 changes: 9 additions & 4 deletions internal/compiler/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ func (p *Program) GetSemanticDiagnostics(sourceFile *ast.SourceFile) []*ast.Diag
}

func (p *Program) GetGlobalDiagnostics() []*ast.Diagnostic {
return sortAndDeduplicateDiagnostics(p.getTypeChecker().GetGlobalDiagnostics())
return sortAndDeduplicateDiagnostics(p.GetTypeChecker().GetGlobalDiagnostics())
}

func (p *Program) TypeCount() int {
Expand All @@ -370,7 +370,7 @@ func (p *Program) TypeCount() int {
return int(p.checker.typeCount)
}

func (p *Program) getTypeChecker() *Checker {
func (p *Program) GetTypeChecker() *Checker {
if p.checker == nil {
p.checker = NewChecker(p)
}
Expand All @@ -386,7 +386,7 @@ func (p *Program) getBindDiagnosticsForFile(sourceFile *ast.SourceFile) []*ast.D
}

func (p *Program) getSemanticDiagnosticsForFile(sourceFile *ast.SourceFile) []*ast.Diagnostic {
return core.Concatenate(sourceFile.BindDiagnostics(), p.getTypeChecker().GetDiagnostics(sourceFile))
return core.Concatenate(sourceFile.BindDiagnostics(), p.GetTypeChecker().GetDiagnostics(sourceFile))
}

func (p *Program) getDiagnosticsHelper(sourceFile *ast.SourceFile, ensureBound bool, getDiagnostics func(*ast.SourceFile) []*ast.Diagnostic) []*ast.Diagnostic {
Expand Down Expand Up @@ -414,7 +414,7 @@ type NodeCount struct {
func (p *Program) PrintSourceFileWithTypes() {
for _, file := range p.files {
if tspath.GetBaseFileName(file.FileName()) == "main.ts" {
fmt.Print(p.getTypeChecker().sourceFileWithTypes(file))
fmt.Print(p.GetTypeChecker().sourceFileWithTypes(file))
}
}
}
Expand Down Expand Up @@ -785,3 +785,8 @@ func (p *Program) Emit(options *EmitOptions) *EmitResult {
}
return result
}

func (p *Program) GetSourceFile(filename string) *ast.SourceFile {
path := tspath.ToPath(filename, p.host.GetCurrentDirectory(), p.host.FS().UseCaseSensitiveFileNames())
return p.filesByPath[path]
}
6 changes: 3 additions & 3 deletions internal/compiler/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ func isValidTypeOnlyAliasUseSite(useSite *ast.Node) bool {
ast.IsPartOfTypeQuery(useSite) ||
isIdentifierInNonEmittingHeritageClause(useSite) ||
isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite) ||
!(isExpressionNode(useSite) || isShorthandPropertyNameUseSite(useSite))
!(IsExpressionNode(useSite) || isShorthandPropertyNameUseSite(useSite))
}

func isIdentifierInNonEmittingHeritageClause(node *ast.Node) bool {
Expand Down Expand Up @@ -1062,7 +1062,7 @@ func nodeCanBeDecorated(useLegacyDecorators bool, node *ast.Node, parent *ast.No
return false
}

func isExpressionNode(node *ast.Node) bool {
func IsExpressionNode(node *ast.Node) bool {
switch node.Kind {
case ast.KindSuperKeyword, ast.KindNullKeyword, ast.KindTrueKeyword, ast.KindFalseKeyword, ast.KindRegularExpressionLiteral,
ast.KindArrayLiteralExpression, ast.KindObjectLiteralExpression, ast.KindPropertyAccessExpression, ast.KindElementAccessExpression,
Expand Down Expand Up @@ -1154,7 +1154,7 @@ func isInExpressionContext(node *ast.Node) bool {
case ast.KindSatisfiesExpression:
return parent.AsSatisfiesExpression().Expression == node
default:
return isExpressionNode(parent)
return IsExpressionNode(parent)
}
}

Expand Down
4 changes: 2 additions & 2 deletions internal/testutil/baseline/baseline.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ type Options struct {

const NoContent = "<no content>"

func Run(t testing.TB, fileName string, actual string, opts Options) {
func Run(t *testing.T, fileName string, actual string, opts Options) {
Copy link
Member Author

@gabritto gabritto Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to make this change from testing.TB to testing.T because I wanted to use t.Run in one symbol baseline function and so I changed it everywhere else, too.

writeComparison(t, actual, fileName, opts)
}

func writeComparison(t testing.TB, actual string, relativeFileName string, opts Options) {
func writeComparison(t *testing.T, actual string, relativeFileName string, opts Options) {
if actual == "" {
panic("The generated content was \"\". Return 'baseline.NoContent' if no baselining is required.")
}
Expand Down
26 changes: 3 additions & 23 deletions internal/testutil/baseline/error_baseline.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ import (
// IO
const harnessNewLine = "\r\n"

var (
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to internal/testutil/baseline/util.go

lineDelimiter = regexp.MustCompile("\r?\n")
nonWhitespace = regexp.MustCompile(`\S`)
tsExtension = regexp.MustCompile(`\.tsx?$`)
)

var formatOpts = &compiler.DiagnosticsFormattingOptions{
NewLine: harnessNewLine,
}
Expand All @@ -40,7 +34,7 @@ var (
diagnosticsLocationPattern = regexp.MustCompile(`(?i)(lib.*\.d\.ts):\d+:\d+`)
)

func DoErrorBaseline(t testing.TB, baselinePath string, inputFiles []*TestFile, errors []*ast.Diagnostic, pretty bool) {
func DoErrorBaseline(t *testing.T, baselinePath string, inputFiles []*TestFile, errors []*ast.Diagnostic, pretty bool) {
baselinePath = tsExtension.ReplaceAllString(baselinePath, ".errors.txt")
var errorBaseline string
if len(errors) > 0 {
Expand All @@ -61,7 +55,7 @@ func minimalDiagnosticsToString(diagnostics []*ast.Diagnostic, pretty bool) stri
return output.String()
}

func getErrorBaseline(t testing.TB, inputFiles []*TestFile, diagnostics []*ast.Diagnostic, pretty bool) string {
func getErrorBaseline(t *testing.T, inputFiles []*TestFile, diagnostics []*ast.Diagnostic, pretty bool) string {
t.Helper()
outputLines := iterateErrorBaseline(t, inputFiles, diagnostics, pretty)

Expand All @@ -77,7 +71,7 @@ func getErrorBaseline(t testing.TB, inputFiles []*TestFile, diagnostics []*ast.D
return strings.Join(outputLines, "")
}

func iterateErrorBaseline(t testing.TB, inputFiles []*TestFile, inputDiagnostics []*ast.Diagnostic, pretty bool) []string {
func iterateErrorBaseline(t *testing.T, inputFiles []*TestFile, inputDiagnostics []*ast.Diagnostic, pretty bool) []string {
t.Helper()
diagnostics := slices.Clone(inputDiagnostics)
slices.SortFunc(diagnostics, compiler.CompareDiagnostics)
Expand Down Expand Up @@ -225,7 +219,6 @@ func iterateErrorBaseline(t testing.TB, inputFiles []*TestFile, inputDiagnostics
// Verify we didn't miss any errors in this file
assert.Check(t, cmp.Equal(markedErrorCount, len(fileErrors)), "count of errors in "+inputFile.unitName)
_, isDupe := dupeCase[sanitizeTestFilePath(inputFile.unitName)]
checkDuplicatedFileName(inputFile.unitName, dupeCase)
result = append(result, outputLines.String())
if isDupe {
// Case-duplicated files on a case-insensitive build will have errors reported in both the dupe and the original
Expand Down Expand Up @@ -253,19 +246,6 @@ func iterateErrorBaseline(t testing.TB, inputFiles []*TestFile, inputDiagnostics
return result
}

func checkDuplicatedFileName(resultName string, dupeCase map[string]int) string {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized this was essentially unused in the old test infra.

resultName = sanitizeTestFilePath(resultName)
if _, ok := dupeCase[resultName]; ok {
// A different baseline filename should be manufactured if the names differ only in case, for windows compat
count := 1 + dupeCase[resultName]
dupeCase[resultName] = count
resultName = fmt.Sprintf("%s.dupe%d", resultName, count)
} else {
dupeCase[resultName] = 0
}
return resultName
}

func flattenDiagnosticMessage(d *ast.Diagnostic, newLine string) string {
var output strings.Builder
compiler.WriteFlattenedDiagnosticMessage(&output, d, newLine)
Expand Down
Loading
Loading