Skip to content

Commit 318a6f7

Browse files
committed
moved isWriteAccess and helpers from checker to ast
1 parent 9c1245e commit 318a6f7

File tree

4 files changed

+93
-94
lines changed

4 files changed

+93
-94
lines changed

internal/ast/ast.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,6 +2188,91 @@ type (
21882188
JsxAttributeList = NodeList // NodeList[*JsxAttributeLike]
21892189
)
21902190

2191+
func IsWriteOnlyAccess(node *Node) bool {
2192+
return accessKind(node) == AccessKindWrite
2193+
}
2194+
2195+
func IsWriteAccess(node *Node) bool {
2196+
return accessKind(node) != AccessKindRead
2197+
}
2198+
2199+
func accessKind(node *Node) AccessKind {
2200+
parent := node.Parent
2201+
switch parent.Kind {
2202+
case KindParenthesizedExpression:
2203+
return accessKind(parent)
2204+
case KindPrefixUnaryExpression:
2205+
operator := parent.AsPrefixUnaryExpression().Operator
2206+
if operator == KindPlusPlusToken || operator == KindMinusMinusToken {
2207+
return AccessKindReadWrite
2208+
}
2209+
return AccessKindRead
2210+
case KindPostfixUnaryExpression:
2211+
operator := parent.AsPostfixUnaryExpression().Operator
2212+
if operator == KindPlusPlusToken || operator == KindMinusMinusToken {
2213+
return AccessKindReadWrite
2214+
}
2215+
return AccessKindRead
2216+
case KindBinaryExpression:
2217+
if parent.AsBinaryExpression().Left == node {
2218+
operator := parent.AsBinaryExpression().OperatorToken
2219+
if IsAssignmentOperator(operator.Kind) {
2220+
if operator.Kind == KindEqualsToken {
2221+
return AccessKindWrite
2222+
}
2223+
return AccessKindReadWrite
2224+
}
2225+
}
2226+
return AccessKindRead
2227+
case KindPropertyAccessExpression:
2228+
if parent.AsPropertyAccessExpression().Name() != node {
2229+
return AccessKindRead
2230+
}
2231+
return accessKind(parent)
2232+
case KindPropertyAssignment:
2233+
parentAccess := accessKind(parent.Parent)
2234+
// In `({ x: varname }) = { x: 1 }`, the left `x` is a read, the right `x` is a write.
2235+
if node == parent.AsPropertyAssignment().Name() {
2236+
return reverseAccessKind(parentAccess)
2237+
}
2238+
return parentAccess
2239+
case KindShorthandPropertyAssignment:
2240+
// Assume it's the local variable being accessed, since we don't check public properties for --noUnusedLocals.
2241+
if node == parent.AsShorthandPropertyAssignment().ObjectAssignmentInitializer {
2242+
return AccessKindRead
2243+
}
2244+
return accessKind(parent.Parent)
2245+
case KindArrayLiteralExpression:
2246+
return accessKind(parent)
2247+
case KindForInStatement, KindForOfStatement:
2248+
if node == parent.AsForInOrOfStatement().Initializer {
2249+
return AccessKindWrite
2250+
}
2251+
return AccessKindRead
2252+
}
2253+
return AccessKindRead
2254+
}
2255+
2256+
func reverseAccessKind(a AccessKind) AccessKind {
2257+
switch a {
2258+
case AccessKindRead:
2259+
return AccessKindWrite
2260+
case AccessKindWrite:
2261+
return AccessKindRead
2262+
case AccessKindReadWrite:
2263+
return AccessKindReadWrite
2264+
}
2265+
panic("Unhandled case in reverseAccessKind")
2266+
}
2267+
2268+
type AccessKind int32
2269+
2270+
const (
2271+
AccessKindRead AccessKind = iota // Only reads from a variable
2272+
AccessKindWrite // Only writes to a variable without ever reading it. E.g.: `x=1;`.
2273+
AccessKindReadWrite // Reads from and writes to a variable. E.g.: `f(x++);`, `x/=1`.
2274+
)
2275+
21912276
// DeclarationBase
21922277

21932278
type DeclarationBase struct {

internal/checker/checker.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10873,15 +10873,15 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l
1087310873
c.checkPropertyNotUsedBeforeDeclaration(prop, node, right)
1087410874
c.markPropertyAsReferenced(prop, node, c.isSelfTypeAccess(left, parentSymbol))
1087510875
c.symbolNodeLinks.Get(node).resolvedSymbol = prop
10876-
c.checkPropertyAccessibility(node, left.Kind == ast.KindSuperKeyword, IsWriteAccess(node), apparentType, prop)
10876+
c.checkPropertyAccessibility(node, left.Kind == ast.KindSuperKeyword, ast.IsWriteAccess(node), apparentType, prop)
1087710877
if c.isAssignmentToReadonlyEntity(node, prop, assignmentKind) {
1087810878
c.error(right, diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, right.Text())
1087910879
return c.errorType
1088010880
}
1088110881
switch {
1088210882
case c.isThisPropertyAccessInConstructor(node, prop):
1088310883
propType = c.autoType
10884-
case writeOnly || isWriteOnlyAccess(node):
10884+
case writeOnly || ast.IsWriteOnlyAccess(node):
1088510885
propType = c.getWriteTypeOfSymbol(prop)
1088610886
default:
1088710887
propType = c.getTypeOfSymbol(prop)
@@ -13280,7 +13280,7 @@ func (c *Checker) getResolvedSymbol(node *ast.Node) *ast.Symbol {
1328013280
var symbol *ast.Symbol
1328113281
if !ast.NodeIsMissing(node) {
1328213282
symbol = c.resolveName(node, node.AsIdentifier().Text, ast.SymbolFlagsValue|ast.SymbolFlagsExportValue,
13283-
c.getCannotFindNameDiagnosticForName(node), !isWriteOnlyAccess(node), false /*excludeGlobals*/)
13283+
c.getCannotFindNameDiagnosticForName(node), !ast.IsWriteOnlyAccess(node), false /*excludeGlobals*/)
1328413284
}
1328513285
links.resolvedSymbol = core.OrElse(symbol, c.unknownSymbol)
1328613286
}
@@ -15715,9 +15715,9 @@ func (c *Checker) GetTypeOfSymbolAtLocation(symbol *ast.Symbol, location *ast.No
1571515715
if ast.IsRightSideOfQualifiedNameOrPropertyAccess(location) {
1571615716
location = location.Parent
1571715717
}
15718-
if ast.IsExpressionNode(location) && (!ast.IsAssignmentTarget(location) || IsWriteAccess(location)) {
15718+
if ast.IsExpressionNode(location) && (!ast.IsAssignmentTarget(location) || ast.IsWriteAccess(location)) {
1571915719
var t *Type
15720-
if IsWriteAccess(location) && location.Kind == ast.KindPropertyAccessExpression {
15720+
if ast.IsWriteAccess(location) && location.Kind == ast.KindPropertyAccessExpression {
1572115721
t = c.checkPropertyAccessExpression(location, CheckModeNormal, true /*writeOnly*/)
1572215722
} else {
1572315723
t = c.getTypeOfExpression(location)
@@ -15735,7 +15735,7 @@ func (c *Checker) GetTypeOfSymbolAtLocation(symbol *ast.Symbol, location *ast.No
1573515735
// to it at the given location. Since we have no control flow information for the
1573615736
// hypothetical reference (control flow information is created and attached by the
1573715737
// binder), we simply return the declared type of the symbol.
15738-
if isRightSideOfAccessExpression(location) && IsWriteAccess(location.Parent) {
15738+
if isRightSideOfAccessExpression(location) && ast.IsWriteAccess(location.Parent) {
1573915739
return c.getWriteTypeOfSymbol(symbol)
1574015740
}
1574115741
}
@@ -26707,7 +26707,7 @@ func (c *Checker) markPropertyAsReferenced(prop *ast.Symbol, nodeForCheckWriteOn
2670726707
if !hasPrivateModifier && !hasPrivateIdentifier {
2670826708
return
2670926709
}
26710-
if nodeForCheckWriteOnly != nil && isWriteOnlyAccess(nodeForCheckWriteOnly) && prop.Flags&ast.SymbolFlagsSetAccessor == 0 {
26710+
if nodeForCheckWriteOnly != nil && ast.IsWriteOnlyAccess(nodeForCheckWriteOnly) && prop.Flags&ast.SymbolFlagsSetAccessor == 0 {
2671126711
return
2671226712
}
2671326713
if isSelfTypeAccess {

internal/checker/utilities.go

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,91 +1074,6 @@ func isThisInitializedDeclaration(node *ast.Node) bool {
10741074
return node != nil && ast.IsVariableDeclaration(node) && node.AsVariableDeclaration().Initializer != nil && node.AsVariableDeclaration().Initializer.Kind == ast.KindThisKeyword
10751075
}
10761076

1077-
func isWriteOnlyAccess(node *ast.Node) bool {
1078-
return accessKind(node) == AccessKindWrite
1079-
}
1080-
1081-
func IsWriteAccess(node *ast.Node) bool {
1082-
return accessKind(node) != AccessKindRead
1083-
}
1084-
1085-
type AccessKind int32
1086-
1087-
const (
1088-
AccessKindRead AccessKind = iota // Only reads from a variable
1089-
AccessKindWrite // Only writes to a variable without ever reading it. E.g.: `x=1;`.
1090-
AccessKindReadWrite // Reads from and writes to a variable. E.g.: `f(x++);`, `x/=1`.
1091-
)
1092-
1093-
func accessKind(node *ast.Node) AccessKind {
1094-
parent := node.Parent
1095-
switch parent.Kind {
1096-
case ast.KindParenthesizedExpression:
1097-
return accessKind(parent)
1098-
case ast.KindPrefixUnaryExpression:
1099-
operator := parent.AsPrefixUnaryExpression().Operator
1100-
if operator == ast.KindPlusPlusToken || operator == ast.KindMinusMinusToken {
1101-
return AccessKindReadWrite
1102-
}
1103-
return AccessKindRead
1104-
case ast.KindPostfixUnaryExpression:
1105-
operator := parent.AsPostfixUnaryExpression().Operator
1106-
if operator == ast.KindPlusPlusToken || operator == ast.KindMinusMinusToken {
1107-
return AccessKindReadWrite
1108-
}
1109-
return AccessKindRead
1110-
case ast.KindBinaryExpression:
1111-
if parent.AsBinaryExpression().Left == node {
1112-
operator := parent.AsBinaryExpression().OperatorToken
1113-
if ast.IsAssignmentOperator(operator.Kind) {
1114-
if operator.Kind == ast.KindEqualsToken {
1115-
return AccessKindWrite
1116-
}
1117-
return AccessKindReadWrite
1118-
}
1119-
}
1120-
return AccessKindRead
1121-
case ast.KindPropertyAccessExpression:
1122-
if parent.AsPropertyAccessExpression().Name() != node {
1123-
return AccessKindRead
1124-
}
1125-
return accessKind(parent)
1126-
case ast.KindPropertyAssignment:
1127-
parentAccess := accessKind(parent.Parent)
1128-
// In `({ x: varname }) = { x: 1 }`, the left `x` is a read, the right `x` is a write.
1129-
if node == parent.AsPropertyAssignment().Name() {
1130-
return reverseAccessKind(parentAccess)
1131-
}
1132-
return parentAccess
1133-
case ast.KindShorthandPropertyAssignment:
1134-
// Assume it's the local variable being accessed, since we don't check public properties for --noUnusedLocals.
1135-
if node == parent.AsShorthandPropertyAssignment().ObjectAssignmentInitializer {
1136-
return AccessKindRead
1137-
}
1138-
return accessKind(parent.Parent)
1139-
case ast.KindArrayLiteralExpression:
1140-
return accessKind(parent)
1141-
case ast.KindForInStatement, ast.KindForOfStatement:
1142-
if node == parent.AsForInOrOfStatement().Initializer {
1143-
return AccessKindWrite
1144-
}
1145-
return AccessKindRead
1146-
}
1147-
return AccessKindRead
1148-
}
1149-
1150-
func reverseAccessKind(a AccessKind) AccessKind {
1151-
switch a {
1152-
case AccessKindRead:
1153-
return AccessKindWrite
1154-
case AccessKindWrite:
1155-
return AccessKindRead
1156-
case AccessKindReadWrite:
1157-
return AccessKindReadWrite
1158-
}
1159-
panic("Unhandled case in reverseAccessKind")
1160-
}
1161-
11621077
func isInfinityOrNaNString(name string) bool {
11631078
return name == "Infinity" || name == "-Infinity" || name == "NaN"
11641079
}

internal/ls/documenthighlights.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55

66
"github.com/microsoft/typescript-go/internal/ast"
77
"github.com/microsoft/typescript-go/internal/astnav"
8-
"github.com/microsoft/typescript-go/internal/checker"
98
"github.com/microsoft/typescript-go/internal/collections"
109
"github.com/microsoft/typescript-go/internal/compiler"
1110
"github.com/microsoft/typescript-go/internal/lsutil"
@@ -82,7 +81,7 @@ func (l *LanguageService) toDocumentHighlight(entry *referenceEntry) (string, *l
8281
}
8382

8483
// Determine write access for node references.
85-
if checker.IsWriteAccess(entry.node) {
84+
if ast.IsWriteAccess(entry.node) {
8685
kind = lsproto.DocumentHighlightKindWrite
8786
}
8887

0 commit comments

Comments
 (0)