no_unsafe_member_access

package
v0.1.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2025 License: MIT Imports: 5 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var NoUnsafeMemberAccessRule = rule.CreateRule(rule.Rule{
	Name: "no-unsafe-member-access",
	Run: func(ctx rule.RuleContext, options any) rule.RuleListeners {
		compilerOptions := ctx.Program.Options()
		isNoImplicitThis := utils.IsStrictCompilerOptionEnabled(
			compilerOptions,
			compilerOptions.NoImplicitThis,
		)

		stateCache := map[*ast.Node]state{}

		var checkMemberExpression func(node *ast.Node) state
		checkMemberExpression = func(node *ast.Node) state {
			cachedState, ok := stateCache[node]
			if ok {
				return cachedState
			}

			parent := node.Parent
			for !ast.IsSourceFile(parent) {

				if ast.IsHeritageClause(parent) {
					return stateSafe
				}
				parent = parent.Parent
			}

			expression := node.Expression()
			if ast.IsAccessExpression(expression) {
				objectState := checkMemberExpression(expression)
				if objectState == stateUnsafe {

					stateCache[node] = objectState
					return objectState
				}
			}

			t := ctx.TypeChecker.GetTypeAtLocation(expression)
			state := stateSafe
			if utils.IsTypeAnyType(t) {
				state = stateUnsafe
			}
			stateCache[node] = state

			if state == stateUnsafe {
				var property *ast.Node
				var propertyName string
				if ast.IsPropertyAccessExpression(node) {
					property = node.Name()
					loc := utils.TrimNodeTextRange(ctx.SourceFile, property)
					propertyName = "." + ctx.SourceFile.Text()[loc.Pos():loc.End()]
				} else if ast.IsElementAccessExpression(node) {
					property = node.AsElementAccessExpression().ArgumentExpression
					loc := utils.TrimNodeTextRange(ctx.SourceFile, property)
					propertyName = "[" + ctx.SourceFile.Text()[loc.Pos():loc.End()] + "]"
				}

				if !isNoImplicitThis {

					thisExpression := utils.GetThisExpression(node)

					if thisExpression != nil && utils.IsTypeAnyType(
						utils.GetConstrainedTypeAtLocation(ctx.TypeChecker, thisExpression)) {
						ctx.ReportNode(property, buildUnsafeThisMemberExpressionMessage(propertyName))
						return state
					}
				}

				ctx.ReportNode(property, buildUnsafeMemberExpressionMessage(propertyName, createDataType(t)))
			}

			return state
		}

		return rule.RuleListeners{
			ast.KindPropertyAccessExpression: func(node *ast.Node) {
				checkMemberExpression(node)
			},
			ast.KindElementAccessExpression: func(node *ast.Node) {
				checkMemberExpression(node)

				arg := node.AsElementAccessExpression().ArgumentExpression

				if ast.IsLiteralExpression(arg) {

					return
				}

				unaryOperatorKind := ast.KindUnknown
				if ast.IsPrefixUnaryExpression(arg) {
					unaryOperatorKind = arg.AsPrefixUnaryExpression().Operator
				} else if arg.Kind == ast.KindPostfixUnaryExpression {
					unaryOperatorKind = arg.AsPostfixUnaryExpression().Operator
				}
				if unaryOperatorKind == ast.KindPlusPlusToken || unaryOperatorKind == ast.KindMinusMinusToken {
					return
				}

				t := ctx.TypeChecker.GetTypeAtLocation(arg)

				if utils.IsTypeAnyType(t) {
					loc := utils.TrimNodeTextRange(ctx.SourceFile, arg)
					propertyName := "[" + ctx.SourceFile.Text()[loc.Pos():loc.End()] + "]"
					ctx.ReportNode(arg, buildUnsafeComputedMemberAccessMessage(propertyName, createDataType(t)))
				}
			},
		}
	},
})

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL