Skip to content

Issue #13399: Implement module properties macro#13407

Merged
nrmancuso merged 1 commit into
checkstyle:masterfrom
stoyanK7:13399
Aug 31, 2023
Merged

Issue #13399: Implement module properties macro#13407
nrmancuso merged 1 commit into
checkstyle:masterfrom
stoyanK7:13399

Conversation

@stoyanK7

@stoyanK7 stoyanK7 commented Jul 18, 2023

Copy link
Copy Markdown
Collaborator

Resolves #13399

Creates PropertiesMacro which is responsible for creating the table with 5 properties - name, description, type, default value, since. Lots of code has been taken from XdocsPagesTest as it already does what we want to.

The way the macro works is:

  1. Call ClassAndPropertiesSettersJavadocScraper to scrape all the setter javadocs of parent classes - for example AbstractNameCheck which holds properties such as applyToPublic, applyToProtected. Properties that are not specified in checks classes but are inherited. This step is done only once when the macro is executed for the first time.

  2. Process the module given to the macro - gather the class and setters javadocs from the file

  3. Write the header row - name, description, type, default value, since

  4. Get a set of the properties via the class property descriptors

  5. Filter this set of properties - remove ones that are not supposed to be documented and add ones that are supposed to be - tokens, fileExtensions, etc..

  6. Iterate trough this set of properties and write the 5 columns

    • Property name is coming from the set
    • Description is scraped off the setter javadoc. A description is any text from the beginning of the Javadoc until we meet a single asterisk on a line. For example:
    /**
     * This over here is a setter description. The alone asterisk below is what says the description is over
     *   <---- end of description
     * @param ..l.
     */
    • Type comes from the methods taken from XdocsPagesTest
    • Same for default value - from XdocsPagesTest
    • Since version comes from one of 3 places(in order)
      1. Exception list - This is a list where properties are inherited from a parent but the property was introduced in a version after the creation of the check
      2. If property is inerited from parent and not part of module file - use @since xxx from class javadoc
      3. Else use the @since xxx version from property setter Javadoc

@romani

romani commented Aug 8, 2023

Copy link
Copy Markdown
Member

@stoyanK7 , please share some hints of this PR status and challenges that you facing.

@nrmancuso

Copy link
Copy Markdown
Contributor

@stoyanK7 let's get to reviewable state

@romani

romani commented Aug 26, 2023

Copy link
Copy Markdown
Member

@stoyanK7 , please keep fixing CI failures - https://ci.appveyor.com/project/Checkstyle/checkstyle/builds/47874621/job/t52fqlfkkwhbsbsm#L310 to be ready for merge at any time.

@nrmancuso nrmancuso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@stoyanK7, think like a reviewer and do first pass on your own PRs, this will shorten feedback loop for non-obvious items and get PRs merged faster :)

Items:

Comment thread src/test/java/com/puppycrawl/tools/checkstyle/internal/AllChecksTest.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java
Comment thread config/checkstyle-non-main-files-checks.xml
@nrmancuso nrmancuso self-assigned this Aug 26, 2023

@romani romani left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

items:

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated

@nrmancuso nrmancuso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Few more:

Comment on lines +757 to +777
result = '"' + value.toString().replace("\n", "\\n").replace("\t", "\\t")
.replace("\r", "\\r").replace("\f", "\\f") + '"';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please share an example of a check that requires this replacement. Also, is it safe to just always assume that we need to do \ -> \\?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This method and others I have taken as-is from XdocsPagesTest - getProperties, fixCapturedProperties, getType, getDefaultValue, getPatternArrayPropertyValue, getStringArrayPropertyValue, getIntArrayPropertyValue, getFieldClass, subtractTokens.

To answer your question - running the code from XdocsPagesTest, JavadocStyle.endOfSentenceFormat pops up
Screenshot from 2023-08-29 14-15-51

Also, is it safe to just always assume that we need to do \ -> \

I think so. Makes value readable:

Value before

([.?!][ 	

<])|([.?!]$)

Value after

([.?!][ \t\n\r\f<])|([.?!]$)

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment on lines +281 to +155
final Object instance = SiteUtil.getModuleInstance(moduleName);
final Class<?> clss = instance.getClass();

@nrmancuso nrmancuso Aug 27, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we do final AbstractCheck checkInstance = (AbstractCheck) SiteUtil.getModuleInstance(moduleName); and do checkInstance.getClass() in called methods to reduce the number of parameters and casts?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It's not certain that it's always an AbstractCheck. For example filters.

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
@stoyanK7 stoyanK7 marked this pull request as draft August 28, 2023 18:06
@stoyanK7

Copy link
Copy Markdown
Collaborator Author

Resolving comments right now, will move to ready for review when done.

@stoyanK7 stoyanK7 marked this pull request as ready for review August 29, 2023 15:22
@stoyanK7

Copy link
Copy Markdown
Collaborator Author

Moving back to ready for review even though CI will fail. Moved quite a bit of stuff around.

Comment on lines +68 to +77
* Property {@code allowSamelineSingleParameterlessAnnotation} - Allow single parameterless
* Property {@code allowSamelineParameterizedAnnotation} - Allow one and only parameterized
* annotation to be located on the same line as target element.
* Type is {@code boolean}.
* Default value is {@code true}.
* Default value is {@code false}.
* </li>
* <li>
* Property {@code allowSamelineParameterizedAnnotation} - Allow one and only parameterized
* Property {@code allowSamelineSingleParameterlessAnnotation} - Allow single parameterless
* annotation to be located on the same line as target element.
* Type is {@code boolean}.
* Default value is {@code false}.
* Default value is {@code true}.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The reason why the metadata file and the javadoc are changed is because of the order of the properties. Properties didn't have any order until now(or do they?) so it's impossible to match their order. The order now follows the order of the setters in the module class.

@rnveach rnveach Aug 29, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

XDocs Order:

XdocsJavaDocsTest took XDoc as it is (order and all) and made sure it was in the correct format as the Javadoc.

JavadocMetadataScraper just took what was in Javadoc and placed it into meta file in the same order as the Javadoc since it uses an array list.

private final List<ModulePropertyDetails> properties = new ArrayList<>();

It seems to me, javadoc should be ordered just like xdoc, which is alphabetical order by TreeSet.

@rnveach rnveach Aug 29, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks like your issue is at:

final Set<String> result = new LinkedHashSet<>(properties);

You switch over from the TreeSet to a LinkedHashSet. You shouldn't use hash sorting as different VMs can possibly create different hashes. Even if we were guaranteed hashes, we want alpha ordering here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

You're right, getProperties uses TreeSet and then I used LinkedHashSet in this subsequent method for some reason. Changed to TreeSet.

But still. Until now, xdoc does not seem to follow alphabetical order. The only ordering asserted is whether tokens/javadocTokens is last:

private static void validatePropertySectionProperties(String fileName, String sectionName,
Node table, Object instance, Set<String> properties) throws Exception {
boolean skip = true;
boolean didJavadocTokens = false;
boolean didTokens = false;
for (Node row : XmlUtil.getChildrenElements(table)) {
final List<Node> columns = new ArrayList<>(XmlUtil.getChildrenElements(row));
assertWithMessage(fileName + " section '" + sectionName
+ "' should have the requested columns")
.that(columns)
.hasSize(5);
if (skip) {
assertWithMessage(fileName + " section '" + sectionName
+ "' should have the specific title")
.that(columns.get(0).getTextContent())
.isEqualTo("name");
assertWithMessage(fileName + " section '" + sectionName
+ "' should have the specific title")
.that(columns.get(1).getTextContent())
.isEqualTo("description");
assertWithMessage(fileName + " section '" + sectionName
+ "' should have the specific title")
.that(columns.get(2).getTextContent())
.isEqualTo("type");
assertWithMessage(fileName + " section '" + sectionName
+ "' should have the specific title")
.that(columns.get(3).getTextContent())
.isEqualTo("default value");
assertWithMessage(fileName + " section '" + sectionName
+ "' should have the specific title")
.that(columns.get(4).getTextContent())
.isEqualTo("since");
skip = false;
continue;
}
assertWithMessage(fileName + " section '" + sectionName
+ "' should have token properties last")
.that(didTokens)
.isFalse();
final String propertyName = columns.get(0).getTextContent();
assertWithMessage(fileName + " section '" + sectionName
+ "' should not contain the property: " + propertyName)
.that(properties.remove(propertyName))
.isTrue();
if ("tokens".equals(propertyName)) {
final AbstractCheck check = (AbstractCheck) instance;
validatePropertySectionPropertyTokens(fileName, sectionName, check, columns);
didTokens = true;
}
else if ("javadocTokens".equals(propertyName)) {
final AbstractJavadocCheck check = (AbstractJavadocCheck) instance;
validatePropertySectionPropertyJavadocTokens(fileName, sectionName, check, columns);
didJavadocTokens = true;
}
else {
assertWithMessage(fileName + " section '" + sectionName
+ "' should have javadoc token properties next to last, before tokens")
.that(didJavadocTokens)
.isFalse();
validatePropertySectionPropertyEx(fileName, sectionName, instance, columns,
propertyName);
}

Take https://checkstyle.org/checks/annotation/annotationusestyle.html for example

  • elementStyle
  • closingParens
  • trailingArrayComma

@rnveach rnveach Aug 29, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The only ordering asserted is whether tokens/javadocTokens is last

This was intentional as that was the ordering of tokens when I built the test.

Take https://checkstyle.org/checks/annotation/annotationusestyle.html for example
elementStyle
closingParens
trailingArrayComma

I could have sworn we ordered properties. It looks like we just ensure all properties are listed, and the order in XDoc is the order they should be in, regardless if it is alpha or random.

I recommend creating a new issue for this and this being done first. It won't be easy to review if there is a bunch of property changes like this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I recommend creating a new issue for this and this being done first. It won't be easy to review if there is a bunch of property changes like this.

I second this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we implement alphabet ordering now, but do not migrate numerous checks for now. So we can do:
1)migration to macroses in smaller batches

2)make massive updates for ordering first and then separate PRs wave to use macroses.

We will see later on what is less on effort.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Opened an issue at #13666 and PR at #13667


/**
* Sets whether we should apply the check to public members.
* Setter to control whether we should apply the check to public members.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Changed so we can match what's already in the documentation:
https://checkstyle.org/checks/naming/constantname.html#Properties

name description
applyToPublic Controls whether to apply the check to public member.
applyToProtected Controls whether to apply the check to protected member.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This was a limitation since Checkstyle does not support multi-file.

@romani romani left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

items:

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated

@romani romani left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

items:

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated

@nrmancuso nrmancuso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Few more:

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated

@nrmancuso nrmancuso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Few more:

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java Outdated
* @param moduleName the module name.
*/
public static void setModuleName(String moduleName) {
ClassAndPropertiesSettersJavadocScraper.moduleName = moduleName;

@romani romani Aug 30, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we can get name of class from file name, do we need this setter ?
May be it is same question as making Module as stateless that I raised above.

Comment on lines +1087 to +1103
private static boolean isInCodeLiteral;
/** Variable that tells if we are in an HTML_ELEMENT token. */
private static boolean isInHtmlElement;
/** Variable that tells if we are in an HREF attribute. */
private static boolean isInHrefAttribute;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

IDEA inspections:
https://app.circleci.com/pipelines/github/checkstyle/checkstyle/20544/workflows/29b03a15-8b8d-485a-bd8a-2bd63d1b2aa4/jobs/373704/artifacts

Static field <code>isInHrefAttribute</code> may not be initialized during class initialization #loc
...

Initialize it with false and checkstyle complains it is initialized to default value. Place it back in method and method becomes too complex. I am stuck with this one.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

https://sonarcloud.io/project/issues?resolved=false&types=CODE_SMELL&sinceLeakPeriod=true&pullRequest=13407&id=org.checkstyle%3Acheckstyle
Regarding the Sonarqube code smells - the first 2 ones with the brackets are not applicable because line length would become more than 100

Regarding the 2 methods that are too complex getDescriptionFromJavadoc and getDefaultValue, I don't think there's anything to gain from splitting them.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

for Inspecton: put @noisnpection StaticVariableInitialization look at more example in our code on how to do this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For Sonar: I agree, we can merge with violations and I suppress them in Sonar UI after merge.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

@romani romani left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I relaunched failed CircleCIs

last items:

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated

@romani romani left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

item

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated

@nrmancuso nrmancuso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Last from me:

Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/PropertiesMacro.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java Outdated
Comment thread src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java Outdated

@romani romani left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ok to merge.

Thanks a lot for your hard work on this

@nrmancuso nrmancuso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is good for now, let's merge this and improve later.

@nrmancuso nrmancuso merged commit 97f5591 into checkstyle:master Aug 31, 2023
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.

Implement module properties macro

4 participants