[BAEL-5905] Spoon Library (#13853)

* [BAEL-4849] Article code

* [BAEL-4968] Article code

* [BAEL-4968] Article code

* [BAEL-4968] Article code

* [BAEL-4968] Remove extra comments

* [BAEL-5258] Article Code

* [BAEL-2765] PKCE Support for Secret Clients

* [BAEL-5698] Article code

* [BAEL-5698] Article code

* [BAEL-5905] Initial code

* [BAEL-5905] Article code

---------

Co-authored-by: Philippe Sevestre <psevestre@gmail.com>
This commit is contained in:
psevestre 2023-04-17 13:16:05 -03:00 committed by GitHub
parent ae04ab2510
commit 4663ee7fa8
10 changed files with 294 additions and 0 deletions

View File

@ -109,9 +109,30 @@
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>fr.inria.gforge.spoon</groupId>
<artifactId>spoon-core</artifactId>
<version>${spoon-core.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-core.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-annotations.version}</version>
</dependency>
</dependencies>
<properties>
<jackson-annotations.version>2.14.2</jackson-annotations.version>
<jackson-core.version>2.14.2</jackson-core.version>
<jdeferred.version>1.2.6</jdeferred.version>
<eclipse-collections.version>8.2.0</eclipse-collections.version>
<noexception.version>1.1.0</noexception.version>
@ -129,6 +150,7 @@
<glassfish.web.version>2.2.4</glassfish.web.version>
<olap4j.version>1.2.0</olap4j.version>
<javafx.version>19</javafx.version>
<spoon-core.version>10.3.0</spoon-core.version>
</properties>
</project>

View File

@ -0,0 +1,15 @@
package com.baeldung.spoon;
import spoon.processing.AbstractProcessor;
import spoon.reflect.code.CtComment;
import spoon.reflect.code.CtComment.CommentType;
import spoon.reflect.declaration.CtClass;
public class AddCopyrightProcessor extends AbstractProcessor<CtClass<?>> {
@Override
public void process(CtClass<?> clazz) {
CtComment comment = getFactory().createComment("Copyright(c) 2023 etc", CommentType.JAVADOC);
clazz.addComment(comment);
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.spoon;
import spoon.Launcher;
import spoon.SpoonAPI;
import spoon.reflect.CtModel;
import spoon.reflect.code.CtComment;
import spoon.reflect.code.CtComment.CommentType;
import spoon.reflect.declaration.CtClass;
public class AddCopyrightTransformer {
public void addCopyright(String source) {
SpoonAPI spoon = new Launcher();
spoon.addInputResource(source);
spoon.getEnvironment().setLevel("DEBUG");
CtModel model = spoon.buildModel();
model.filterChildren((el) -> el instanceof CtClass<?>)
.forEach((CtClass<?> cl) -> {
CtComment comment = cl.getFactory()
.createComment("Copyright(c) 2023 etc", CommentType.JAVADOC);
cl.addComment(comment);
});
spoon.setSourceOutputDirectory("./target");
spoon.prettyprint();
}
}

View File

@ -0,0 +1,111 @@
package com.baeldung.spoon;
import spoon.Launcher;
import spoon.SpoonAPI;
import spoon.reflect.CtModel;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtMethod;
import spoon.support.sniper.SniperJavaPrettyPrinter;
/**
* Loads a given class and creates a summary o
*/
public class ClassReporter {
public MethodSummary generateMethodSummaryReport(String source) {
SpoonAPI spoon = new Launcher();
spoon.addInputResource(source);
CtModel model = spoon.buildModel();
MethodSummary report = new MethodSummary();
model.filterChildren((el) -> el instanceof CtClass<?>)
.forEach((CtClass<?> clazz) -> processMethods(report,clazz));
return report;
}
private void processMethods(MethodSummary report, CtClass<?> ctClass) {
ctClass.filterChildren((c) -> c instanceof CtMethod<?> )
.forEach((CtMethod<?> m) -> {
if (m.isPublic()) {
report.addPublicMethod();
}
else if ( m.isPrivate()) {
report.addPrivateMethod();
}
else if ( m.isProtected()) {
report.addProtectedMethod();
}
else {
report.addPackagePrivateMethod();
}
});
}
public static class MethodSummary {
private int totalMethodCount;
private int publicMethodCount;
private int protectedMethodCount;
private int packagePrivateMethodCount;
private int privateMethodCount;
void addPublicMethod() {
totalMethodCount++;
publicMethodCount++;
}
void addPrivateMethod() {
totalMethodCount++;
privateMethodCount++;
}
void addProtectedMethod() {
totalMethodCount++;
protectedMethodCount++;
}
void addPackagePrivateMethod() {
totalMethodCount++;
packagePrivateMethodCount++;
}
/**
* @return the totalMethodCount
*/
public int getTotalMethodCount() {
return totalMethodCount;
}
/**
* @return the publicMethodCount
*/
public int getPublicMethodCount() {
return publicMethodCount;
}
/**
* @return the protectedMethodCount
*/
public int getProtectedMethodCount() {
return protectedMethodCount;
}
/**
* @return the privateMethodCount
*/
public int getPrivateMethodCount() {
return privateMethodCount;
}
/**
* @return the privateMethodCount
*/
public int getPackagePrivateMethodCount() {
return packagePrivateMethodCount;
}
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.spoon;
import org.junit.Test;
import spoon.Launcher;
import spoon.SpoonAPI;
public class AddCopyrightProcessorUnitTest {
@Test
public void whenAddCopyright_thenSuccess() {
SpoonAPI spoon = new Launcher();
spoon.addProcessor(new AddCopyrightProcessor());
spoon.addInputResource("src/test/resources/spoon/SpoonClassToTest.java");
spoon.setSourceOutputDirectory("./target/spoon-processed");
spoon.buildModel();
spoon.process();
spoon.prettyprint();
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.spoon;
import org.junit.Test;
public class AddCopyrightTransformerUnitTest {
@Test
public void whenAddCopyright_thenSuccess() {
AddCopyrightTransformer transformer = new AddCopyrightTransformer();
transformer.addCopyright("src/test/resources/spoon/SpoonClassToTest.java");
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.spoon;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import com.baeldung.spoon.ClassReporter.MethodSummary;
public class ClassReporterUnitTest {
@Test
public void givenBrokenClass_whenGenerateReport_thenSuccess() {
ClassReporter reporter = new ClassReporter();
MethodSummary report = reporter.generateMethodSummaryReport("src/test/resources/spoon/BrokenClass.java");
assertThat(report).isNotNull();
assertThat(report.getPrivateMethodCount()).isEqualTo(0);
assertThat(report.getPublicMethodCount()).isEqualTo(1);
assertThat(report.getProtectedMethodCount()).isEqualTo(1);
}
@Test
public void whenGenerateReport_thenSuccess() {
ClassReporter reporter = new ClassReporter();
MethodSummary report = reporter.generateMethodSummaryReport("src/test/resources/spoon/SpoonClassToTest.java");
assertThat(report).isNotNull();
assertThat(report.getPackagePrivateMethodCount()).isEqualTo(1);
assertThat(report.getPublicMethodCount()).isEqualTo(1);
assertThat(report.getPrivateMethodCount()).isEqualTo(1);
}
}

View File

@ -0,0 +1,12 @@
package spoon;
public class BrokenClass {
// Syntax error
pluvic void brokenMethod() {}
// Syntax error
protected void protectedMethod() thraws Exception {}
// Public method
public void publicMethod() {}
}

View File

@ -0,0 +1,28 @@
package spoon;
import some.superduper.HelperClass;
import some.superduper.SomeVO;
public class SpoonClassToTest {
private static HelperClass helper;
public SpoonClassToTest() {}
public int publicMethod() {}
private int internalStuff() {}
protected SomeVO protectedMethod() {
return new SomeVO();
}
void packageProtectedMethod() {
try {
HelperClass.callSomeMethodThatThrows();
}
catch(Exception ignored) {}
}
}

View File

@ -9,3 +9,4 @@ This module contains articles about RabbitMQ.
- [Channels and Connections in RabbitMQ](https://www.baeldung.com/java-rabbitmq-channels-connections)
- [Create Dynamic Queues in RabbitMQ](https://www.baeldung.com/rabbitmq-dynamic-queues)