Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ClassLiteralPropertyStyleRule = rule.CreateRule(rule.Rule{ Name: "class-literal-property-style", Run: func(ctx rule.RuleContext, options any) rule.RuleListeners { style := "fields" if options != nil { switch opts := options.(type) { case string: style = opts case []interface{}: if len(opts) > 0 { if s, ok := opts[0].(string); ok { style = s } } } } var propertiesInfoStack []*propertiesInfo listeners := rule.RuleListeners{} if style == "fields" { listeners[ast.KindGetAccessor] = func(node *ast.Node) { getter := node.AsGetAccessorDeclaration() if ast.HasSyntacticModifier(node, ast.ModifierFlagsOverride) { return } if getter.Body == nil { return } if !ast.IsBlock(getter.Body) { return } block := getter.Body.AsBlock() if block == nil || len(block.Statements.Nodes) == 0 { return } if len(block.Statements.Nodes) != 1 { return } stmt := block.Statements.Nodes[0] if !ast.IsReturnStatement(stmt) { return } returnStmt := stmt.AsReturnStatement() if returnStmt.Expression == nil || !isSupportedLiteral(returnStmt.Expression) { return } name := getStaticMemberAccessValue(ctx, node) if name != "" && node.Parent != nil { members := node.Parent.Members() for _, member := range members { if ast.IsSetAccessorDeclaration(member) && isStaticMemberAccessOfValue(ctx, member, name) { return } } } nameNode := getter.Name() var nameText string if nameNode.Kind == ast.KindComputedPropertyName { nameText = strings.TrimSpace(ctx.SourceFile.Text()[nameNode.Pos():nameNode.End()]) } else { nameText = nameNode.Text() } valueText := strings.TrimSpace(ctx.SourceFile.Text()[returnStmt.Expression.Pos():returnStmt.Expression.End()]) var fixText string fixText += printNodeModifiers(node, "readonly") fixText += nameText fixText += fmt.Sprintf(" = %s;", valueText) reportNode := getter.Name() if reportNode.Kind == ast.KindComputedPropertyName { computed := reportNode.AsComputedPropertyName() if computed.Expression != nil { reportNode = computed.Expression } } ctx.ReportNodeWithSuggestions(reportNode, buildPreferFieldStyleMessage(), rule.RuleSuggestion{ Message: buildPreferFieldStyleSuggestionMessage(), FixesArr: []rule.RuleFix{ rule.RuleFixReplace(ctx.SourceFile, node, fixText), }, }) } } if style == "getters" { enterClassBody := func() { propertiesInfoStack = append(propertiesInfoStack, &propertiesInfo{ excludeSet: make(map[string]bool), properties: []*ast.Node{}, }) } exitClassBody := func() { if len(propertiesInfoStack) == 0 { return } info := propertiesInfoStack[len(propertiesInfoStack)-1] propertiesInfoStack = propertiesInfoStack[:len(propertiesInfoStack)-1] for _, node := range info.properties { property := node.AsPropertyDeclaration() if property.Initializer == nil || !isSupportedLiteral(property.Initializer) { continue } name := getStaticMemberAccessValue(ctx, node) if name != "" && info.excludeSet[name] { continue } nameNode := property.Name() var nameText string if nameNode.Kind == ast.KindComputedPropertyName { nameText = strings.TrimSpace(ctx.SourceFile.Text()[nameNode.Pos():nameNode.End()]) } else { nameText = nameNode.Text() } valueText := strings.TrimSpace(ctx.SourceFile.Text()[property.Initializer.Pos():property.Initializer.End()]) var fixText string fixText += printNodeModifiers(node, "get") fixText += nameText fixText += fmt.Sprintf("() { return %s; }", valueText) reportNode := property.Name() if reportNode.Kind == ast.KindComputedPropertyName { computed := reportNode.AsComputedPropertyName() if computed.Expression != nil { reportNode = computed.Expression } } ctx.ReportNodeWithSuggestions(reportNode, buildPreferGetterStyleMessage(), rule.RuleSuggestion{ Message: buildPreferGetterStyleSuggestionMessage(), FixesArr: []rule.RuleFix{ rule.RuleFixReplace(ctx.SourceFile, node, fixText), }, }) } } listeners[ast.KindClassDeclaration] = func(node *ast.Node) { enterClassBody() } listeners[rule.ListenerOnExit(ast.KindClassDeclaration)] = func(node *ast.Node) { exitClassBody() } listeners[ast.KindClassExpression] = func(node *ast.Node) { enterClassBody() } listeners[rule.ListenerOnExit(ast.KindClassExpression)] = func(node *ast.Node) { exitClassBody() } listeners[ast.KindThisKeyword] = func(node *ast.Node) { if node.Parent == nil || (!ast.IsPropertyAccessExpression(node.Parent) && !ast.IsElementAccessExpression(node.Parent)) { return } memberExpr := node.Parent var propName string if ast.IsPropertyAccessExpression(memberExpr) { propAccess := memberExpr.AsPropertyAccessExpression() propName = extractPropertyName(ctx, propAccess.Name()) } else if ast.IsElementAccessExpression(memberExpr) { elemAccess := memberExpr.AsElementAccessExpression() if ast.IsLiteralExpression(elemAccess.ArgumentExpression) { propName = extractPropertyName(ctx, elemAccess.ArgumentExpression) } } if propName == "" { return } parent := memberExpr.Parent for parent != nil && !isFunction(parent) { parent = parent.Parent } if parent != nil && parent.Parent != nil { if ast.IsMethodDeclaration(parent.Parent) { method := parent.Parent.AsMethodDeclaration() if method != nil && method.Kind == ast.KindConstructorKeyword { if len(propertiesInfoStack) > 0 { info := propertiesInfoStack[len(propertiesInfoStack)-1] info.excludeSet[propName] = true } } } else if ast.IsConstructorDeclaration(parent.Parent) { if len(propertiesInfoStack) > 0 { info := propertiesInfoStack[len(propertiesInfoStack)-1] info.excludeSet[propName] = true } } } } listeners[ast.KindBinaryExpression] = func(node *ast.Node) { binary := node.AsBinaryExpression() if binary.OperatorToken.Kind != ast.KindEqualsToken { return } left := binary.Left if !ast.IsPropertyAccessExpression(left) && !ast.IsElementAccessExpression(left) { return } var thisExpr *ast.Node var propName string if ast.IsPropertyAccessExpression(left) { propAccess := left.AsPropertyAccessExpression() if propAccess.Expression.Kind == ast.KindThisKeyword { thisExpr = propAccess.Expression propName = extractPropertyName(ctx, propAccess.Name()) } } else if ast.IsElementAccessExpression(left) { elemAccess := left.AsElementAccessExpression() if elemAccess.Expression.Kind == ast.KindThisKeyword { thisExpr = elemAccess.Expression if ast.IsLiteralExpression(elemAccess.ArgumentExpression) { propName = extractPropertyName(ctx, elemAccess.ArgumentExpression) } } } if thisExpr == nil || propName == "" { return } current := node.Parent for current != nil && !ast.IsConstructorDeclaration(current) { if isFunction(current) && !ast.IsConstructorDeclaration(current) { return } current = current.Parent } if current != nil && len(propertiesInfoStack) > 0 { info := propertiesInfoStack[len(propertiesInfoStack)-1] info.excludeSet[propName] = true } } listeners[ast.KindPropertyDeclaration] = func(node *ast.Node) { if !ast.HasSyntacticModifier(node, ast.ModifierFlagsReadonly) { return } if ast.HasSyntacticModifier(node, ast.ModifierFlagsAmbient) { return } if ast.HasSyntacticModifier(node, ast.ModifierFlagsOverride) { return } if len(propertiesInfoStack) > 0 { info := propertiesInfoStack[len(propertiesInfoStack)-1] info.properties = append(info.properties, node) } } } return listeners }, })
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.