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

Issue #20: Configuration Component #43

Merged
merged 1 commit into from
Jul 5, 2017
Merged

Conversation

Luolc
Copy link
Contributor

@Luolc Luolc commented Jun 29, 2017

#20

Missing the output to file function currently.

@Luolc Luolc force-pushed the issue20 branch 3 times, most recently from 4d2cc44 to 6044d29 Compare July 1, 2017 17:37
Copy link
Member

@rnveach rnveach left a comment

Choose a reason for hiding this comment

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

I noticed there was no discussion in issue on how we were going to implement this before coding, so we are back to long discussions in PR.

@Test
public void testGenerateConfigTextWithEmptyModuleInfos() throws Exception {
final String excepted = ""
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
Copy link
Member

Choose a reason for hiding this comment

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

Let's put expected XML files in external file similarly we do for main Checkstyle project.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

final Element moduleNode = document.createElement(ELEMENT_MODULE);
moduleNode.setAttribute(ATTR_NAME, moduleInfo.name());

for (ModuleInfo.Property property : moduleInfo.properties()) {
Copy link
Member

Choose a reason for hiding this comment

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

Please remove and ignore all property code until #5 .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

config/pmd.xml Outdated
@@ -189,6 +189,8 @@
<exclude name="MethodArgumentCouldBeFinal"/>
<!--not configurable, decreases readability-->
<exclude name="UseStringBufferForStringAppends"/>
<!--decreases readability when writing a muti-line string-->
<exclude name="AddEmptyString"/>
Copy link
Member

Choose a reason for hiding this comment

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

XML strings should be in their own file, so this can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


/** The config template. */
private static final String BASE_CONFIG = ""
+ "<?xml version=\"1.0\" standalone=\"yes\"?>"
Copy link
Member

Choose a reason for hiding this comment

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

This should be in it's own file and not hard coded into source.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

+ " <property name=\"charset\" value=\"UTF-8\"/>\n"
+ " <property name=\"severity\" value=\"warning\"/>\n"
+ " <property name=\"haltOnException\" value=\"false\"/>\n"
+ " <module name=\"BeforeExecutionExclusionFileFilter\">\n"
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

final Document document;

try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder()
Copy link
Member

Choose a reason for hiding this comment

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

This XML process shouldn't do any validating of DTD or request an internet connection to process.
Some users like to do regression solo when they are on a plane or such, so we need to limit internet connectivity when we can.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do do mean that document = DocumentBuilderFactory.newInstance().newDocumentBuilder()... this line shouldn't do internet request? I switch off my internet connection and run the UTs of this class and everything is fine. Is that OK?

Copy link
Member

Choose a reason for hiding this comment

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

That is fine. I just wanted you to be aware and verify. I am not familiar with the document builder.

returnValue = node;
break;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

empty line after for.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


/** The "doctype-public" value of the config. */
private static final String DOCTYPE_PUBLIC =
"-//Puppy Crawl//DTD Check Configuration 1.3//EN";
Copy link
Member

Choose a reason for hiding this comment

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

Can we add a test to verify this doctype is latest version from Checkstyle release?
If this changes, I want us to be required to update this and verify it has no repercussions on regression.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

latest version from Checkstyle release

Is it OK to grab the latest version from this https://github.com/checkstyle/checkstyle/blob/master/config/checkstyle_checks.xml? Is it required to be checkstyle release version but not SNAPSHOT version?

Copy link
Member

@rnveach rnveach Jul 3, 2017

Choose a reason for hiding this comment

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

We can try this but internet connection may be an issue as travis uses anonymous user to access github.
Snapshot might be an issue if it isn't released, but I am fine testing this out and removing it if there is a problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So are we able to find the latest version of it from somewhere else?

Copy link
Member

Choose a reason for hiding this comment

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

without an internet connection, no. Github is the only place that has the latest information and it is stored in a separate repo.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Add a testDtdVersion in the test class. CI goods fine.

+ " <property name=\"fileNamePattern\" value=\"module\\-info\\.java$\" />\n"
+ " </module>\n"
+ " <!-- Contents below are generated by regression-tool. -->\n"
+ " <module name=\"TreeWalker\"/></module>";
Copy link
Member

Choose a reason for hiding this comment

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

The tool can't add TreeWalker for us?
If so, please explain the reason. Someday we may add other TreeWalkers. Just like we don't embed these modules into our extract, I would like to avoid embedding into other areas.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Someday we may add other TreeWalkers

I don't know whats the meaning of this, maybe smth like MutiThreadTreeWalker in the future?

I think by now, it is OK to let the tool generate TreeWalker dynamically. But there would be some other questions:
If we assume that the module would have whatever parent(not just Checker and TreeWalker), so how to decide where to put the parent module? Should we gain the info from the module extract info map? If yes, then configuration component would depend on module component, otherwise we would have to pass the whole info map to configuration component, but I don't think it is a good idea.

Copy link
Member

Choose a reason for hiding this comment

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

I don't know whats the meaning of this, maybe smth like MutiThreadTreeWalker in the future?

TreeWalker = Java grammar.
If we add XML grammar, we will need something like XmlTreeWalker, etc.
MutiThreadTreeWalker is another possibility.

configuration component would depend on module component

All components already rely on previous component. Next components input is previous component's output. I don't see any reason to embed the 2 together right now.

how to decide where to put the parent module? Should we gain the info from the module extract info map?

Module extract info should already have this information ready for us to use.
This is why we have parent and it is just String.
Checker has no parent, so it is always root module. TreeWalker has parent Checker, so it goes as a sub-module of it. All checks have TreeWalker as parent, so they are sub-modules of it.
The extract can be looped through to understand hierarchy. If some hierarchy information is missing, we should throw an exception and say we can't continue.

I think by now, it is OK to let the tool generate TreeWalker dynamically

But will it still require hardcoding of hierarchy somewhere? If so, let's move this to a new issue and keep code as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But will it still require hardcoding of hierarchy somewhere?

Yep, by now we need to know the fact that "TreeWalker's parent is Checker", and that info should be gained through the module extract info map.

Copy link
Member

Choose a reason for hiding this comment

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

Please create new issue then. We should avoid hardcoding things that can change in a single PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please create new issue then. We should avoid hardcoding things that can change in a single PR.

#47 for this

@Luolc Luolc force-pushed the issue20 branch 2 times, most recently from 12f42a9 to 8532b26 Compare July 3, 2017 16:42
@rnveach
Copy link
Member

rnveach commented Jul 3, 2017

@Luolc appveyor should pass.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 3, 2017

@rnveach Seems like a CRLF problem again, I am fixing it.

https://github.com/checkstyle/contribution/blob/master/checkstyle-tester/my_check.xml#L4
https://github.com/checkstyle/checkstyle/blob/master/config/checkstyle_checks.xml#L4

http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd and http://www.puppycrawl.com/dtds/configuration_1_3.dtd, which one should we use? They are different in checkstyle project and contribution repo.

@rnveach
Copy link
Member

rnveach commented Jul 3, 2017

which one should we use?

We should always go by main project. We are forced to update and use things there.
Contribution is a 3rd party project that uses whatever they want. They aren't forced to use latest.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 3, 2017

@rnveach I updated the url to http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd. CRLF is fixed and a test of dtd version is added.

Copy link
Member

@rnveach rnveach left a comment

Choose a reason for hiding this comment

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

I don't see anything else.


final Node checkerNode = getCheckerModuleNode(document);
final Node treeWalkerNode = getTreeWalkerModuleNode(document);
for (ModuleInfo moduleInfo : moduleInfos) {
Copy link
Member

Choose a reason for hiding this comment

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

empty line before for.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

final Transformer transformer = createXmlTransformer();
final StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(document), new StreamResult(writer));
return writer.getBuffer().toString().replaceAll("\r\n", "\n");
Copy link
Member

Choose a reason for hiding this comment

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

.replaceAll("\r\n", "\n");

Does this really need to be in production code? We are no longer doing any processing on this and Checkstyle/XML doesn't care about whitespace.
I assume this was added just to make tests pass, so why don't we keep it in test code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

import com.github.checkstyle.regression.data.ModuleInfo;

/**
* Generates the config XML and output it to a specific file.
Copy link
Member

@rnveach rnveach Jul 3, 2017

Choose a reason for hiding this comment

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

You return a String, not a file.
If this component is returning a file, the public method needs to change to return a file. Otherwise this javadoc needs to change.

Copy link
Contributor Author

@Luolc Luolc Jul 4, 2017

Choose a reason for hiding this comment

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

Missing the output to file function currently.

I mentioned this at the first post of this PR.

I am not sure which one(string or output to a file) is better. Personally I prefer output it to file, but I am also fine with a String. So I just left this when I first push this PR. What't your opinion?

Copy link
Member

Choose a reason for hiding this comment

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

Returning string to me seems weird as we will not be doing any more String manipulation and just output it to a file anyways. I would prefer it to return a file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. generateConfig creates and output the xml plain text to a file. Related UTs are updated as well to directly compare whether two files are the same.

</module>

<!-- Contents below are generated by regression-tool. -->
<module name="TreeWalker"/></module>
Copy link
Member

Choose a reason for hiding this comment

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

Move </module> to next line.
You don't write code like:

void method() {
  if (condition) {} }

Copy link
Contributor Author

@Luolc Luolc Jul 4, 2017

Choose a reason for hiding this comment

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

I don't like this either, but there would be a strange indention problem if I put </module> to next line.

i.e. The generated XML would be smth like this. the last second line has wrong indention.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
<module name="Checker">
  ...
  <!-- Contents below are generated by regression-tool. -->
  <module name="TreeWalker"/>
<module name="FileLengthCheck"/>
</module>

You could have a try to put that to next line, I assume testGenerateConfigTextWithEmptyModuleInfos and testGenerateConfigTextWithCheckerParentModule would fail due to that indention problem

Copy link
Member

Choose a reason for hiding this comment

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

We shouldn't care about generated files as they are out of our control. I'm suprised that it even kept the comments.
Let's only concern ourselves with our files for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@Luolc Luolc force-pushed the issue20 branch 2 times, most recently from e637302 to 16c4dbd Compare July 4, 2017 04:04
}

/**
* Generates the config XML file from the given module inofs.
Copy link
Member

Choose a reason for hiding this comment

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

inofs => infos I assume?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

throws IOException, TransformerException {
final File file = new File(path);
Files.write(file.toPath(), generateConfigText(moduleInfos)
.getBytes(Charset.forName("UTF-8")), StandardOpenOption.CREATE_NEW);
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't we be using TRUNCATE_EXISTING instead of CREATE_NEW. We were told a path to place config, we should delete it if it already exists and not fail causing user to erase it manually.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. I used CREATE_NEW for I was worried that user might accidentally write a path to another existing important file. But it is not common, I am fine with erasing.

Copy link
Member

Choose a reason for hiding this comment

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

File name should be completely under our control. If user wants to save it, they should it move outside of our path. I don't expect users to have to supply a unique file path.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it.

}

@After
public void tearDown() throws Exception {
Copy link
Member

Choose a reason for hiding this comment

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

DiffParserTest had this at the top of the class while in here you put in the middle.
Let's be consistent and always have After/Before at the top of the class so it is the first thing users see when reading this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 5, 2017

@rnveach Sorry I commited the changes but forgot to push. Updated are pushed now.

@rnveach rnveach merged commit befb36a into checkstyle:master Jul 5, 2017
@Luolc Luolc deleted the issue20 branch July 5, 2017 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants