diff options
author | Eugene Susla <eugenesusla@google.com> | 2019-07-31 15:12:54 -0700 |
---|---|---|
committer | Eugene Susla <eugenesusla@google.com> | 2019-07-31 15:12:54 -0700 |
commit | 1410e008c8ea196afec98d7766e6dca5c9d555b4 (patch) | |
tree | 68586f4fd910c3b08a9608d7be5e186c9df572c6 /javaparser-core-serialization | |
parent | 1b2211eaf2fa78358abe0b16f82ccf0b689aa56a (diff) | |
download | javaparser-1410e008c8ea196afec98d7766e6dca5c9d555b4.tar.gz |
Pull commits from upstream for java 11 compatibility!
Change-Id: I27826ba60af5c54848e2eae40930d8fb8a302919
Diffstat (limited to 'javaparser-core-serialization')
5 files changed, 757 insertions, 0 deletions
diff --git a/javaparser-core-serialization/pom.xml b/javaparser-core-serialization/pom.xml new file mode 100644 index 000000000..23e7655b2 --- /dev/null +++ b/javaparser-core-serialization/pom.xml @@ -0,0 +1,71 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>javaparser-parent</artifactId> + <groupId>com.github.javaparser</groupId> + <version>3.14.10-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>javaparser-core-serialization</artifactId> + <description>Serializers for the JavaParser AST.</description> + + <licenses> + <license> + <name>GNU Lesser General Public License</name> + <url>http://www.gnu.org/licenses/lgpl-3.0.html</url> + <distribution>repo</distribution> + </license> + <license> + <name>Apache License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + <distribution>repo</distribution> + <comments>A business-friendly OSS license</comments> + </license> + </licenses> + + <properties> + <java.version>1.8</java.version> + <build.timestamp>${maven.build.timestamp}</build.timestamp> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifestEntries> + <Automatic-Module-Name>com.github.javaparser.core.serialization</Automatic-Module-Name> + </manifestEntries> + </archive> + </configuration> + </plugin> + + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + </dependency> + <dependency> + <groupId>com.github.javaparser</groupId> + <artifactId>javaparser-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>javax.json</groupId> + <artifactId>javax.json-api</artifactId> + <version>1.1.4</version> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>javax.json</artifactId> + <version>1.1.4</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> diff --git a/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonDeserializer.java b/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonDeserializer.java new file mode 100644 index 000000000..d77e127ae --- /dev/null +++ b/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonDeserializer.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2018 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ +package com.github.javaparser.serialization; + +import com.github.javaparser.*; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.comments.Comment; +import com.github.javaparser.metamodel.BaseNodeMetaModel; +import com.github.javaparser.metamodel.PropertyMetaModel; +import com.github.javaparser.utils.Log; + +import javax.json.*; +import java.util.*; + +import static com.github.javaparser.ast.NodeList.toNodeList; +import static com.github.javaparser.metamodel.JavaParserMetaModel.getNodeMetaModel; +import static com.github.javaparser.serialization.JavaParserJsonSerializer.*; + +/** + * Deserializes the JSON file that was built by {@link JavaParserJsonSerializer}. + */ +public class JavaParserJsonDeserializer { + /** + * Deserializes json, contained by JsonReader, into AST node. + * The root node and all its child nodes will be deserialized. + * @param reader json-p reader (object-level reader, <a href="https://javaee.github.io/jsonp/">see their docs</a>) + * @return the root level deserialized node + */ + public Node deserializeObject(JsonReader reader) { + Log.info("Deserializing JSON to Node."); + JsonObject jsonObject = reader.readObject(); + return deserializeObject(jsonObject); + } + + /** + * Recursive depth-first deserializing method that creates a Node instance from JsonObject. + * + * @param nodeJson json object at current level containg values as properties + * @return deserialized node including all children. + * @implNote the Node instance will be constructed by the properties defined in the meta model. + * Non meta properties will be set after Node is instantiated. + * @implNote comment is included in the propertyKey meta model, but not set when constructing the Node instance. + * That is, comment is not included in the constructor propertyKey list, and therefore needs to be set + * after constructing the node. + * See {@link com.github.javaparser.metamodel.BaseNodeMetaModel#construct(Map)} how the node is contructed + */ + private Node deserializeObject(JsonObject nodeJson) { + try { + String serializedNodeType = nodeJson.getString(JsonNode.CLASS.propertyKey); + BaseNodeMetaModel nodeMetaModel = getNodeMetaModel(Class.forName(serializedNodeType)) + .orElseThrow(() -> new IllegalStateException("Trying to deserialize an unknown node type: " + serializedNodeType)); + Map<String, Object> parameters = new HashMap<>(); + Map<String, JsonValue> deferredJsonValues = new HashMap<>(); + + for (String name : nodeJson.keySet()) { + if (name.equals(JsonNode.CLASS.propertyKey)) { + continue; + } + + Optional<PropertyMetaModel> optionalPropertyMetaModel = nodeMetaModel.getAllPropertyMetaModels().stream() + .filter(mm -> mm.getName().equals(name)) + .findFirst(); + if (!optionalPropertyMetaModel.isPresent()) { + deferredJsonValues.put(name, nodeJson.get(name)); + continue; + } + + PropertyMetaModel propertyMetaModel = optionalPropertyMetaModel.get(); + if (propertyMetaModel.isNodeList()) { + JsonArray nodeListJson = nodeJson.getJsonArray(name); + parameters.put(name, deserializeNodeList(nodeListJson)); + } else if (propertyMetaModel.isNode()) { + parameters.put(name, deserializeObject(nodeJson.getJsonObject(name))); + } else { + Class<?> type = propertyMetaModel.getType(); + if (type == String.class) { + parameters.put(name, nodeJson.getString(name)); + } else if (type == boolean.class) { + parameters.put(name, Boolean.parseBoolean(nodeJson.getString(name))); + } else if (Enum.class.isAssignableFrom(type)) { + parameters.put(name, Enum.valueOf((Class<? extends Enum>) type, nodeJson.getString(name))); + } else { + throw new IllegalStateException("Don't know how to convert: " + type); + } + } + } + + Node node = nodeMetaModel.construct(parameters); + // COMMENT is in the propertyKey meta model, but not required as constructor parameter. + // Set it after construction + if (parameters.containsKey(JsonNode.COMMENT.propertyKey)) { + node.setComment((Comment)parameters.get(JsonNode.COMMENT.propertyKey)); + } + + for (String name : deferredJsonValues.keySet()) { + if (!readNonMetaProperties(name, deferredJsonValues.get(name), node)) { + throw new IllegalStateException("Unknown propertyKey: " + nodeMetaModel.getQualifiedClassName() + "." + name); + } + } + setSymbolResolverIfCompilationUnit(node); + + return node; + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + private NodeList<?> deserializeNodeList(JsonArray nodeListJson) { + return nodeListJson.stream().map(nodeJson -> deserializeObject((JsonObject) nodeJson)).collect(toNodeList()); + } + + /** + * Reads properties from json not included in meta model (i.e., RANGE and TOKEN_RANGE). + * When read, it sets the deserialized value to the node instance. + * @param name propertyKey name for json value + * @param jsonValue json value that needs to be deserialized for this propertyKey + * @param node instance to which the deserialized value will be set to + * @return true if propertyKey is read from json and set to Node instance + */ + protected boolean readNonMetaProperties(String name, JsonValue jsonValue, Node node) { + return readRange(name, jsonValue, node) + || readTokenRange(name, jsonValue, node); + } + + protected boolean readRange(String name, JsonValue jsonValue, Node node) { + if (name.equals(JsonNode.RANGE.propertyKey)) { + JsonObject jsonObject = (JsonObject)jsonValue; + Position begin = new Position( + jsonObject.getInt(JsonRange.BEGIN_LINE.propertyKey), + jsonObject.getInt(JsonRange.BEGIN_COLUMN.propertyKey) + ); + Position end = new Position( + jsonObject.getInt(JsonRange.END_LINE.propertyKey), + jsonObject.getInt(JsonRange.END_COLUMN.propertyKey) + ); + node.setRange(new Range(begin, end)); + return true; + } + return false; + } + + protected boolean readTokenRange(String name, JsonValue jsonValue, Node node) { + if (name.equals(JsonNode.TOKEN_RANGE.propertyKey)) { + JsonObject jsonObject = (JsonObject)jsonValue; + JavaToken begin = readToken( + JsonTokenRange.BEGIN_TOKEN.propertyKey, jsonObject + ); + JavaToken end = readToken( + JsonTokenRange.END_TOKEN.propertyKey, jsonObject + ); + node.setTokenRange(new TokenRange(begin, end)); + return true; + } + return false; + } + + protected JavaToken readToken(String name, JsonObject jsonObject) { + JsonObject tokenJson = jsonObject.getJsonObject(name); + return new JavaToken( + tokenJson.getInt(JsonToken.KIND.propertyKey), + tokenJson.getString(JsonToken.TEXT.propertyKey) + ); + } + + /** + * This method sets symbol resolver to Node if it is an instance of CompilationUnit + * and a SymbolResolver is configured in the static configuration. This is necessary to be able to resolve symbols + * within the cu after deserialization. Normally, when parsing java with JavaParser, the symbol resolver is injected + * to the cu as a data element with key SYMBOL_RESOLVER_KEY. + * @param node instance to which symbol resolver will be set to when instance of a Compilation Unit + * @see com.github.javaparser.ast.Node#SYMBOL_RESOLVER_KEY + * @see com.github.javaparser.ParserConfiguration#ParserConfiguration() + */ + private void setSymbolResolverIfCompilationUnit(Node node) { + if (node instanceof CompilationUnit && StaticJavaParser.getConfiguration().getSymbolResolver().isPresent()) { + CompilationUnit cu = (CompilationUnit)node; + cu.setData(Node.SYMBOL_RESOLVER_KEY, StaticJavaParser.getConfiguration().getSymbolResolver().get()); + } + } + + +} diff --git a/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonSerializer.java b/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonSerializer.java new file mode 100644 index 000000000..743b57ddd --- /dev/null +++ b/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonSerializer.java @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2018 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ +package com.github.javaparser.serialization; + +import com.github.javaparser.JavaToken; +import com.github.javaparser.Range; +import com.github.javaparser.TokenRange; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.metamodel.BaseNodeMetaModel; +import com.github.javaparser.metamodel.JavaParserMetaModel; +import com.github.javaparser.metamodel.PropertyMetaModel; +import com.github.javaparser.utils.Log; + +import javax.json.stream.JsonGenerator; + +import static com.github.javaparser.utils.Utils.decapitalize; +import static java.util.Objects.requireNonNull; + +/** + * Serializes an AST or a partial AST to JSON. + */ +public class JavaParserJsonSerializer { + + /** + * Serializes node and all its children into json. Any node siblings will be ignored. + * + * @param node the node that will be the root level json object + * @param generator the json-p generator for writing the json + * @see <a href="https://javaee.github.io/jsonp/">json-p</a> + */ + public void serialize(Node node, JsonGenerator generator) { + requireNonNull(node); + Log.info("Serializing Node to JSON."); + try { + serialize(null, node, generator); + } finally { + generator.close(); + } + } + + /** + * Recursive depth-first method that serializes nodes into json + * + * @param nodeName nullable String. If null, it is the root object, otherwise it is the property key for the object + * @param node the current node to be serialized + * @param generator the json-p generator for writing the json + */ + + private void serialize(String nodeName, Node node, JsonGenerator generator) { + requireNonNull(node); + BaseNodeMetaModel nodeMetaModel = JavaParserMetaModel.getNodeMetaModel(node.getClass()).orElseThrow(() -> new IllegalStateException("Unknown Node: " + node.getClass())); + + if (nodeName == null) { + generator.writeStartObject(); + } else { + generator.writeStartObject(nodeName); + } + generator.write(JsonNode.CLASS.propertyKey, node.getClass().getName()); + this.writeNonMetaProperties(node, generator); + for (PropertyMetaModel propertyMetaModel : nodeMetaModel.getAllPropertyMetaModels()) { + String name = propertyMetaModel.getName(); + Object value = propertyMetaModel.getValue(node); + if (value != null) { + if (propertyMetaModel.isNodeList()) { + NodeList<Node> list = (NodeList<Node>) value; + generator.writeStartArray(name); + for (Node n : list) { + serialize(null, n, generator); + } + generator.writeEnd(); + } else if (propertyMetaModel.isNode()) { + serialize(name, (Node) value, generator); + } else { + generator.write(name, value.toString()); + } + } + } + generator.writeEnd(); + } + + /*** + * This method writes json for properties not included in meta model (i.e., RANGE and TOKEN_RANGE). + * This method could be overriden so that - for example - tokens are not written to json to save space + * + * @see com.github.javaparser.metamodel.BaseNodeMetaModel#getAllPropertyMetaModels() + */ + + protected void writeNonMetaProperties(Node node, JsonGenerator generator) { + this.writeRange(node, generator); + this.writeTokens(node, generator); + } + + protected void writeRange(Node node, JsonGenerator generator) { + if (node.getRange().isPresent()) { + Range range = node.getRange().get(); + generator.writeStartObject(JsonNode.RANGE.propertyKey); + generator.write(JsonRange.BEGIN_LINE.propertyKey, range.begin.line); + generator.write(JsonRange.BEGIN_COLUMN.propertyKey, range.begin.column); + generator.write(JsonRange.END_LINE.propertyKey, range.end.line); + generator.write(JsonRange.END_COLUMN.propertyKey, range.end.column); + generator.writeEnd(); + } + } + + protected void writeTokens(Node node, JsonGenerator generator) { + if (node.getTokenRange().isPresent()) { + TokenRange tokenRange = node.getTokenRange().get(); + generator.writeStartObject(JsonNode.TOKEN_RANGE.propertyKey); + writeToken(JsonTokenRange.BEGIN_TOKEN.propertyKey, tokenRange.getBegin(), generator); + writeToken(JsonTokenRange.END_TOKEN.propertyKey, tokenRange.getEnd(), generator); + generator.writeEnd(); + } + } + + protected void writeToken(String name, JavaToken token, JsonGenerator generator) { + generator.writeStartObject(name); + generator.write(JsonToken.KIND.propertyKey, token.getKind()); + generator.write(JsonToken.TEXT.propertyKey, token.getText()); + generator.writeEnd(); + } + + /** + * excludes properties from meta model (except comment) + **/ + public enum JsonNode { + RANGE("range"), + TOKEN_RANGE("tokenRange"), + COMMENT(decapitalize(JavaParserMetaModel.commentMetaModel.getTypeName())), + CLASS("!"); + final String propertyKey; + + JsonNode(String p) { + this.propertyKey = p; + } + + public String toString() { + return this.propertyKey; + } + } + + public enum JsonRange { + BEGIN_LINE("beginLine"), + BEGIN_COLUMN("beginColumn"), + END_LINE("endLine"), + END_COLUMN("endColumn"); + final String propertyKey; + + JsonRange(String p) { + this.propertyKey = p; + } + + public String toString() { + return this.propertyKey; + } + } + + public enum JsonTokenRange { + BEGIN_TOKEN("beginToken"), + END_TOKEN("endToken"); + final String propertyKey; + + JsonTokenRange(String p) { + this.propertyKey = p; + } + + public String toString() { + return this.propertyKey; + } + } + + public enum JsonToken { + TEXT("text"), + KIND("kind"); + final String propertyKey; + + JsonToken(String p) { + this.propertyKey = p; + } + + public String toString() { + return this.propertyKey; + } + } +} diff --git a/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonDeserializerTest.java b/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonDeserializerTest.java new file mode 100644 index 000000000..4c7f0001f --- /dev/null +++ b/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonDeserializerTest.java @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2018 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ +package com.github.javaparser.serialization; + +import com.github.javaparser.*; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.comments.Comment; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.type.Type; +import com.github.javaparser.javadoc.Javadoc; +import com.github.javaparser.javadoc.JavadocBlockTag; +import com.github.javaparser.resolution.SymbolResolver; +import com.github.javaparser.resolution.types.ResolvedType; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import javax.json.Json; +import java.io.StringReader; + +import static com.github.javaparser.StaticJavaParser.*; +import static com.github.javaparser.serialization.JavaParserJsonSerializerTest.serialize; +import static com.github.javaparser.utils.Utils.EOL; +import static com.github.javaparser.utils.Utils.normalizeEolInTextBlock; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class JavaParserJsonDeserializerTest { + private final JavaParserJsonDeserializer deserializer = new JavaParserJsonDeserializer(); + + @Test + void simpleTest() { + CompilationUnit cu = parse("public class X{} class Z{}"); + String serialized = serialize(cu, false); + + Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + + assertEqualsNoEol("public class X {\n}\n\nclass Z {\n}\n", deserialized.toString()); + assertEquals(cu.hashCode(), deserialized.hashCode()); + } + + @Test + void testRawType() { + Type type = parseType("Blub"); + String serialized = serialize(type, false); + + Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + + assertEqualsNoEol("Blub", deserialized.toString()); + assertEquals(type.hashCode(), deserialized.hashCode()); + } + + @Test + void testDiamondType() { + Type type = parseType("Blub<>"); + String serialized = serialize(type, false); + + Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + + assertEqualsNoEol("Blub<>", deserialized.toString()); + assertEquals(type.hashCode(), deserialized.hashCode()); + } + + @Test + void testGenerics() { + Type type = parseType("Blub<Blab, Bleb>"); + String serialized = serialize(type, false); + + Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + + assertEqualsNoEol("Blub<Blab, Bleb>", deserialized.toString()); + assertEquals(type.hashCode(), deserialized.hashCode()); + } + + @Test + void testOperator() { + Expression expr = parseExpression("1+1"); + String serialized = serialize(expr, false); + + Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + + assertEqualsNoEol("1 + 1", deserialized.toString()); + assertEquals(expr.hashCode(), deserialized.hashCode()); + } + + @Test + void testPrimitiveType() { + Type type = parseType("int"); + String serialized = serialize(type, false); + + Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + + assertEqualsNoEol("int", deserialized.toString()); + assertEquals(type.hashCode(), deserialized.hashCode()); + } + + @Test + void testComment() { + CompilationUnit cu = parse("/* block comment */\npublic class X{ \n // line comment\npublic void test() {}\n}"); + String serialized = serialize(cu, false); + + CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + ClassOrInterfaceDeclaration classXDeclaration = deserialized.getClassByName("X").get(); + assertTrue(classXDeclaration.getComment().isPresent()); + + Comment comment = classXDeclaration.getComment().get(); + assertEquals("com.github.javaparser.ast.comments.BlockComment", comment.getClass().getName()); + assertEquals(" block comment ", comment.getContent()); + + MethodDeclaration methodDeclaration = classXDeclaration.getMethods().get(0); + assertTrue(methodDeclaration.getComment().isPresent()); + assertEquals("com.github.javaparser.ast.comments.LineComment", methodDeclaration.getComment().get().getClass().getName()); + assertEquals(" line comment", methodDeclaration.getComment().get().getContent()); + } + + @Test + void testJavaDocComment() { + CompilationUnit cu = parse("public class X{ " + + " /**\n" + + " * Woke text.\n" + + " * @param a blub\n" + + " * @return true \n" + + " */" + + " public boolean test(int a) { return true; }\n" + + "}"); + String serialized = serialize(cu, false); + + CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + ClassOrInterfaceDeclaration classDeclaration = deserialized.getClassByName("X").get(); + MethodDeclaration methodDeclaration = classDeclaration.getMethods().get(0); + assertTrue(methodDeclaration.getJavadoc().isPresent()); + Javadoc javadoc = methodDeclaration.getJavadoc().get(); + + JavadocBlockTag paramBlockTag = javadoc.getBlockTags().get(0); + assertEquals("param", paramBlockTag.getTagName()); + assertEquals("blub", paramBlockTag.getContent().toText()); + + JavadocBlockTag returnBlockTag = javadoc.getBlockTags().get(1); + assertEquals("return", returnBlockTag.getTagName()); + assertEquals("true", returnBlockTag.getContent().toText()); + } + + @Test + void testNonMetaProperties() { + CompilationUnit cu = parse("public class X{} class Z{}"); + String serialized = serialize(cu, false); + + CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + + assertTrue(deserialized.getRange().isPresent()); + Range range = deserialized.getRange().get(); + assertEquals(1, range.begin.line); + assertEquals(1, range.begin.line); + assertEquals(26, range.end.column); + + assertTrue(deserialized.getTokenRange().isPresent()); + TokenRange tokenRange = deserialized.getTokenRange().get(); + assertEquals("public", tokenRange.getBegin().getText()); + assertEquals("", tokenRange.getEnd().getText()); + } + + @Test + void testAttachingSymbolResolver() { + SymbolResolver stubResolver = new SymbolResolver() { + @Override + public <T> T resolveDeclaration(Node node, Class<T> resultClass) { + return null; + } + + @Override + public <T> T toResolvedType(Type javaparserType, Class<T> resultClass) { + return null; + } + + @Override + public ResolvedType calculateType(Expression expression) { + return null; + } + }; + StaticJavaParser.getConfiguration().setSymbolResolver(stubResolver); + CompilationUnit cu = parse("public class X{} class Z{}"); + String serialized = serialize(cu, false); + + CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized))); + assertTrue(deserialized.containsData(Node.SYMBOL_RESOLVER_KEY)); + assertEquals(stubResolver, deserialized.getData(Node.SYMBOL_RESOLVER_KEY)); + } + + @AfterAll + static void clearConfiguration() { + StaticJavaParser.setConfiguration(new ParserConfiguration()); + } + + /** + * Assert that "actual" equals "expected", and that any EOL characters in "actual" are correct for the platform. + */ + private static void assertEqualsNoEol(String expected, String actual) { + assertEquals(normalizeEolInTextBlock(expected, EOL), actual); + } + +} diff --git a/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonSerializerTest.java b/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonSerializerTest.java new file mode 100644 index 000000000..078a11cf3 --- /dev/null +++ b/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonSerializerTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2018 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ +package com.github.javaparser.serialization; + +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.Node; +import org.junit.jupiter.api.Test; + +import javax.json.Json; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonGeneratorFactory; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +import static com.github.javaparser.StaticJavaParser.parse; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class JavaParserJsonSerializerTest { + @Test + void test() { + CompilationUnit cu = parse("class X{java.util.Y y;}"); + + String serialized = serialize(cu, false); + + assertEquals("{\"!\":\"com.github.javaparser.ast.CompilationUnit\",\"range\":{\"beginLine\":1,\"beginColumn\":1,\"endLine\":1,\"endColumn\":23},\"tokenRange\":{\"beginToken\":{\"kind\":19,\"text\":\"class\"},\"endToken\":{\"kind\":0,\"text\":\"\"}},\"imports\":[],\"types\":[{\"!\":\"com.github.javaparser.ast.body.ClassOrInterfaceDeclaration\",\"range\":{\"beginLine\":1,\"beginColumn\":1,\"endLine\":1,\"endColumn\":23},\"tokenRange\":{\"beginToken\":{\"kind\":19,\"text\":\"class\"},\"endToken\":{\"kind\":95,\"text\":\"}\"}},\"extendedTypes\":[],\"implementedTypes\":[],\"isInterface\":\"false\",\"typeParameters\":[],\"members\":[{\"!\":\"com.github.javaparser.ast.body.FieldDeclaration\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":22},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":98,\"text\":\";\"}},\"modifiers\":[],\"variables\":[{\"!\":\"com.github.javaparser.ast.body.VariableDeclarator\",\"range\":{\"beginLine\":1,\"beginColumn\":21,\"endLine\":1,\"endColumn\":21},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"y\"},\"endToken\":{\"kind\":89,\"text\":\"y\"}},\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":21,\"endLine\":1,\"endColumn\":21},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"y\"},\"endToken\":{\"kind\":89,\"text\":\"y\"}},\"identifier\":\"y\"},\"type\":{\"!\":\"com.github.javaparser.ast.type.ClassOrInterfaceType\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":19},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":89,\"text\":\"Y\"}},\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":19,\"endLine\":1,\"endColumn\":19},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"Y\"},\"endToken\":{\"kind\":89,\"text\":\"Y\"}},\"identifier\":\"Y\"},\"scope\":{\"!\":\"com.github.javaparser.ast.type.ClassOrInterfaceType\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":17},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":89,\"text\":\"util\"}},\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":14,\"endLine\":1,\"endColumn\":17},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"util\"},\"endToken\":{\"kind\":89,\"text\":\"util\"}},\"identifier\":\"util\"},\"scope\":{\"!\":\"com.github.javaparser.ast.type.ClassOrInterfaceType\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":12},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":89,\"text\":\"java\"}},\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":12},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":89,\"text\":\"java\"}},\"identifier\":\"java\"},\"annotations\":[]},\"annotations\":[]},\"annotations\":[]}}],\"annotations\":[]}],\"modifiers\":[],\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":7,\"endLine\":1,\"endColumn\":7},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"X\"},\"endToken\":{\"kind\":89,\"text\":\"X\"}},\"identifier\":\"X\"},\"annotations\":[]}]}", serialized); + } + + static String serialize(Node node, boolean prettyPrint) { + Map<String, ?> config = new HashMap<>(); + if (prettyPrint) { + config.put(JsonGenerator.PRETTY_PRINTING, null); + } + JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(config); + JavaParserJsonSerializer serializer = new JavaParserJsonSerializer(); + StringWriter jsonWriter = new StringWriter(); + try (JsonGenerator generator = generatorFactory.createGenerator(jsonWriter)) { + serializer.serialize(node, generator); + } + return jsonWriter.toString(); + } +} |