Skip to content
Permalink
Browse files

Lint components type (#102)

* Extend HooksRule on extension

* Add ComponentAsStructRule

* Fix typo

* Apply swiftformat

* Fix violation description

* Fix rule name
  • Loading branch information...
hodovani committed May 30, 2019
1 parent 30a2b9d commit 770e1c4b447dbe062e06a277ed81cf7583a41e86
@@ -0,0 +1,43 @@
//
// ComponentIsStructRule.swift
// TokamakLint
//
// Created by Matvii Hodovaniuk on 5/30/19.
//
import SwiftSyntax

struct ComponentIsStructRule: Rule {
static let description = RuleDescription(
type: ComponentIsStructRule.self,
name: "Component as struct",
description: "Components can only be declared as structs"
)

public static func validate(visitor: TokenVisitor) -> [StyleViolation] {
var violations: [StyleViolation] = []

// search usage of componentProtocols
componentProtocols.forEach { prot in
let components = visitor.root.children(with: prot)
components.forEach { component in

// check that components is struct
guard let componentCodeBlockItem = component.firstParent(of: .codeBlockItem) else { return }
guard componentCodeBlockItem.children.first?.text == SyntaxKind.structDecl.rawValue else {
violations.append(StyleViolation(
ruleDescription: ComponentIsStructRule.description,
location: Location(
file: visitor.path,
line: componentCodeBlockItem.range.startRow,
character: componentCodeBlockItem.range.startColumn
)
))
return
}
}
}

return violations
}
}
@@ -44,7 +44,7 @@ struct HooksRule: Rule {
!codeBlockItemList.children.contains(hookCodeBlockItem)
else { return }
violations.append(StyleViolation(
ruleDescription: OneRenderFunctionRule.description,
ruleDescription: HooksRule.description,
location: Location(
file: visitor.path,
line: hook.range.startRow,
@@ -81,7 +81,7 @@ struct HooksRule: Rule {
guard memberCodeBlockItemList.children.contains(safeState) else {
violations.append(
StyleViolation(
ruleDescription: OneRenderFunctionRule.description,
ruleDescription: HooksRule.description,
location: Location(
file: visitor.path,
line: state.range.startRow,
@@ -86,4 +86,16 @@ final class TokamakLintTests: XCTestCase {
XCTAssertEqual(result[i].location.line, line)
}
}

func testComponentIsStructRulePositive() throws {
let path = "\(try srcRoot())/ComponentAsStructPositive.swift"
let result = try ComponentIsStructRule.validate(path: path)
XCTAssertEqual(result.count, 0)
}

func testComponentIsStructRuleNegative() throws {
let path = "\(try srcRoot())/ComponentAsStructNegative.swift"
let result = try ComponentIsStructRule.validate(path: path)
XCTAssertEqual(result.count, 2)
}
}
@@ -34,6 +34,7 @@

/* Begin PBXBuildFile section */
A6BFBFEC229D301000F2B06F /* GetComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6BFBFEB229D301000F2B06F /* GetComponents.swift */; };
A6BFBFEE229FFEFF00F2B06F /* ComponentIsStructRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6BFBFED229FFEFF00F2B06F /* ComponentIsStructRule.swift */; };
A6E7BC612293D7B20042E787 /* HooksRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E7BC602293D7B20042E787 /* HooksRule.swift */; };
OBJ_325 /* ArgumentList.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_239 /* ArgumentList.swift */; };
OBJ_326 /* ArgumentListManipulator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_240 /* ArgumentListManipulator.swift */; };
@@ -400,6 +401,7 @@

/* Begin PBXFileReference section */
A6BFBFEB229D301000F2B06F /* GetComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetComponents.swift; sourceTree = "<group>"; };
A6BFBFED229FFEFF00F2B06F /* ComponentIsStructRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComponentIsStructRule.swift; sourceTree = "<group>"; };
A6E7BC602293D7B20042E787 /* HooksRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HooksRule.swift; sourceTree = "<group>"; };
OBJ_100 /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
OBJ_102 /* BaselineConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaselineConstraint.swift; sourceTree = "<group>"; };
@@ -908,6 +910,7 @@
OBJ_150 /* PropsIsEquatableRule.swift */,
OBJ_151 /* RenderGetsHooksRule.swift */,
A6E7BC602293D7B20042E787 /* HooksRule.swift */,
A6BFBFED229FFEFF00F2B06F /* ComponentIsStructRule.swift */,
);
path = Rules;
sourceTree = "<group>";
@@ -1919,6 +1922,7 @@
OBJ_550 /* Location.swift in Sources */,
OBJ_551 /* Node.swift in Sources */,
OBJ_552 /* RuleDescription.swift in Sources */,
A6BFBFEE229FFEFF00F2B06F /* ComponentIsStructRule.swift in Sources */,
OBJ_553 /* StyleViolation.swift in Sources */,
A6BFBFEC229D301000F2B06F /* GetComponents.swift in Sources */,
OBJ_554 /* TokamakLint.swift in Sources */,
@@ -0,0 +1,12 @@
class BeatlesComponents: CompositeComponent {
let willThereBeAnAnswer = true
let itBe = "Whisper words of wisdom"
}

class LedZeppelinLeaf: PureLeafComponent {
let doIhaveToGo = false
enum WhatMakeMe: String {
case mad = "the letter you wrote me"
case sad = "the news that letters told me"
}
}
@@ -0,0 +1,16 @@
struct List: PureLeafComponent {
struct Props: Equatable {
let model: [AppRoute]
let onSelect: Handler<CellPath>
}

static func render(props: Props) -> AnyNode {
return ListView<Cells>.node(.init(
Style([
Edges.equal(to: .parent),
]),
model: [props.model],
onSelect: props.onSelect
))
}
}
@@ -22,7 +22,7 @@ struct HookedLeafComponent: LeafComponent {
}
}

// don't use Hooks in extesion on non first level
// don't use Hooks in extension on non first level
extension Hooks {
var blah: State<Int> {
if true {

0 comments on commit 770e1c4

Please sign in to comment.
You can’t perform that action at this time.