Skip to content
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

Handle reporters with absolute path as output path #49

Merged
merged 1 commit into from
Dec 29, 2016
Merged

Handle reporters with absolute path as output path #49

merged 1 commit into from
Dec 29, 2016

Conversation

mihai8804858
Copy link
Contributor

@mihai8804858 mihai8804858 commented Dec 21, 2016

This PR will fix #48 issue.

Also, slightly refactored reporter coordinators.

@codecov-io
Copy link

codecov-io commented Dec 21, 2016

Current coverage is 93.10% (diff: 100%)

Merging #49 into master will increase coverage by 0.34%

@@             master        #49   diff @@
==========================================
  Files            61         61          
  Lines          1657       1683    +26   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits           1537       1567    +30   
+ Misses          120        116     -4   
  Partials          0          0          

Powered by Codecov. Last update ff5d8a6...f788f8a

Copy link
Contributor

@lexorus lexorus left a comment

Choose a reason for hiding this comment

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

The mentioned issue itself is fixed.

@@ -33,14 +33,14 @@ func !=(lhs: [String:AnyObject], rhs: [String:AnyObject]) -> Bool {

class ReporterComparator {

func compareReporters(_ firstReporterPath: String, secondReporterPath: String) -> Bool {
var violations1 = JSONToViolationParser().parseFile(firstReporterPath)
func compareReporter(atPath path1: String, withReporterAtPath path2: String) -> Bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the function that gets two paths, then parses this files to get violations, then compares each violation through iteration.
All this is happening in compareReporter(atPath:withReporterAtPath:) function of ReporterComparator class.
The Reporter word leads to a delusion here(we also have reporters in this project).
Can you think about a better name, like compareViolations, or for a better place/implementation of this functionality(extension)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This class takes 2 paths to reports and compare them. I'm not interested how it compares the reports, it's his problem. Also, If I would see compareViolations function I would think that I should give it an array of Violation.

Copy link
Contributor

@lexorus lexorus Dec 22, 2016

Choose a reason for hiding this comment

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

Then, maybe will be better to name it compareReport(atPath:withReportAtPath:) (report and not reporter)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Already done that.

}
}

private func writeOutput(with violations: [Violation], reporter: Reporter) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can get rid of the Output word here.

@lexorus
Copy link
Contributor

lexorus commented Dec 22, 2016

Also, there is a Typo in commit:
Handle absolute paths when specifie reporter's output path in arguments

@mihai8804858 mihai8804858 changed the title Handle absolute paths when specifie reporter's output path in arguments Handle reporters with absolute path as output path Dec 22, 2016
@thelvis4
Copy link
Contributor

@mihai8804858 Tests are failing 😢

@mihai8804858
Copy link
Contributor Author

@thelvis4 Don't know why 😢 Have you tried to run the tests on your machine? On my machine and on @lexorus's the tests are passing.

@thelvis4
Copy link
Contributor

@mihai8804858 @lexorus Checks are failing because code coverage decreased. 😢

private func addElements(to xml: XMLDocument, from violations: [Violation]) {
for path in filePaths(from: violations) {
guard let fileElement = xmlElement(withFilePath: path) else { continue }
violations.filter { $0.path == path }
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like we do a lot of iteration here. A big number of violations can lead to a computation time growth.
One way we can reduce the numbers of loops is by iterating through violations (just once), group them into a dictionary that uses paths as keys:

private typealias ViolationsMap = [Path: [Violation]]

final class PMDCoordinator: WritingCoordinator {
    
    func writeViolations(_ violations: [Violation], atPath path: String) {
        FileManager().removeFileAtPath(path)
        let map = mapViolations(violations)
        let xml = generateXML(from: map)
        let xmlData = xml.xmlData(withOptions: Int(XMLNode.Options.nodePrettyPrint.rawValue))
        do {
            try xmlData.write(to: URL(fileURLWithPath: path), options: .atomic)
        } catch let error {
            let message = "Error while writing XML object at path: " + path + "\n" +
                "Reason: " + error.localizedDescription
            Printer(verbosityLevel: .error).printError(message)
        }
    }
    
    private func mapViolations(_ violations: [Violation]) -> ViolationsMap {
        return violations.reduce([Path : [Violation]]()) { result, violation in
            let path = violation.path
            
            // Add violation to the group with the same path
            var violations = result[path] ?? []
            violations.append(violation)
            
            // Update the result
            var nextResult = result
            nextResult[path] = violations
            
            return result
        }
    }
    
    private func generateXML(from violationsMap: ViolationsMap) -> XMLDocument {
        let xml = XMLDocument(rootElement: XMLElement(name: "pmd"))
        xml.version = "1.0"
        xml.characterEncoding = "UTF-8"
        
        let fileElements = violationsMap.map(generateFileElement)
        xml.rootElement()?.addChildren(fileElements)
        
        return xml
    }
    
    private func generateFileElement(path: Path, violations: [Violation]) -> XMLElement {
        let element = XMLElement(name: "file")
        let attribute = XMLNode(kind: .attribute)
        attribute.setValue(path, forKey: "name")
        element.addAttribute(attribute)
        
        violations.forEach { element.addChild($0.toXMLElement()) }
        
        return element
    }
}

extension XMLElement {
    func addChildren(_ children: [XMLElement]) {
        children.forEach { child in
            addChild(child)
        }
    }
}

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you did a good job! 👍

@@ -17,7 +17,7 @@ enum IntegrationTestsError: Error {

class TaylorIntegrationTests: QuickSpec {

var runTaskPath : String {
var taylorExecutablePath : String {
Copy link
Contributor

Choose a reason for hiding this comment

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

How about executableFilePath?
If we rename the tool, we don't want to be needed to make too many changes.

@@ -88,6 +88,23 @@ class TaylorIntegrationTests: QuickSpec {
}
}

fileprivate func runTaylorWithArguments(_ arguments: String...) {
Copy link
Contributor

Choose a reason for hiding this comment

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

runWithArguments?

}
} catch let error {
print(error)
context("when specifie report with relative path") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo here at specifie

}
}

context("when specifie report with absolute path") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same tipo (specifie) here 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Typo here: tipo -> typo 😉

Copy link
Contributor

Choose a reason for hiding this comment

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

🤣

@thelvis4
Copy link
Contributor

@mihai8804858 There is a typo in the commit message. Could you please fix it?

@@ -26,6 +36,18 @@ class NSFileManagerTests: QuickSpec {
manager.removeFileAtPath(filePath)
expect(manager.fileExists(atPath: filePath)).to(beFalse())
}

it("should't remove file at path if it's not deleatable") {
Copy link
Contributor

Choose a reason for hiding this comment

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

There is no such word deleatable. You can use deletable or delible, but I recommend to use removable here as it's less pretentious.

Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: should't

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is a method in 'FileManager' called 'isDeleatableFileAtPath', I throught there is such word. 🙂

@mihai8804858
Copy link
Contributor Author

@thelvis4 Fixed typos.

@thelvis4
Copy link
Contributor

@mihai8804858 It seems like we introduced a bug here.
Before we had

<file name="/Some/path/to/file.swift">

but now we have

<file /Some/path/to/file.swift="">

Could you please investigate and also write some tests to make sure the bug is fixed and we won't have regressions?

expect(manager.fileExists(atPath: filePath)).to(beTrue())
FileManager.default.removeFileAtPath(filePath)
}

it("should't remove directory at path") {
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like we have the same typo here: should't

@mihai8804858
Copy link
Contributor Author

@thelvis4 Done.

@thelvis4
Copy link
Contributor

@mihai8804858 How about the issue with file element? It's still reproducing to me.

@mihai8804858
Copy link
Contributor Author

Oops, I missed that comment. 😕

Slightly refactored reporter coordinators
@thelvis4
Copy link
Contributor

@mihai8804858 Thanks for working on this! 👍
You just made Taylor better! 👧 😊

@thelvis4 thelvis4 merged commit b9fee76 into yopeso:master Dec 29, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot specify report with absolute path
4 participants