Skip to content

Commit 87995c6

Browse files
spannmslawekjaranowski
authored andcommitted
[JXR-170] NullPointerException while parsing Java 15 multi-line String source
- Add support for parsing sources with Java 15 multi-line Strings - Add JUnit test case - Implement toString on class BaseType - Require non-null name on BaseType construtor - Prevent construction of types with null name - Add version to maven-enforcer-plugin plugin to prevent failure of integration test JXR-143_nofork
1 parent a803fbf commit 87995c6

File tree

8 files changed

+107
-28
lines changed

8 files changed

+107
-28
lines changed

maven-jxr-plugin/src/it/JXR-143_nofork/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ under the License.
4444
<plugin>
4545
<groupId>org.apache.maven.plugins</groupId>
4646
<artifactId>maven-enforcer-plugin</artifactId>
47+
<version>3.1.0</version>
4748
<executions>
4849
<execution>
4950
<goals>

maven-jxr/src/main/java/org/apache/maven/jxr/pacman/BaseType.java

+16-13
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,26 @@
1919
* under the License.
2020
*/
2121

22+
import java.util.Objects;
23+
2224
/**
2325
* put your documentation comment here
2426
*
2527
* @author jvanzyl
2628
*/
2729
public abstract class BaseType
2830
{
29-
private String name = null;
31+
private final String name;
3032

33+
/**
34+
* Construct type and set its name.
35+
*
36+
* @param name type name
37+
*/
38+
public BaseType( String name )
39+
{
40+
this.name = Objects.requireNonNull( name );
41+
}
3142

3243
/**
3344
* Get the name for this type
@@ -36,22 +47,14 @@ public abstract class BaseType
3647
*/
3748
public String getName()
3849
{
39-
if ( name == null )
40-
{
41-
return "";
42-
}
4350
return this.name;
4451
}
4552

46-
47-
/**
48-
* Set the name for this type
49-
*
50-
* @param name The new name value
51-
*/
52-
public void setName( String name )
53+
@Override
54+
public String toString()
5355
{
54-
this.name = name;
56+
return getClass().getSimpleName() + "[name=" + name + "]";
5557
}
58+
5659
}
5760

maven-jxr/src/main/java/org/apache/maven/jxr/pacman/ClassType.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class ClassType
4141
@Deprecated
4242
public ClassType( String name )
4343
{
44-
this.setName( name );
44+
this( name, null );
4545
}
4646

4747
/**
@@ -52,7 +52,8 @@ public ClassType( String name )
5252
*/
5353
public ClassType( String name, String filename )
5454
{
55-
this.setName( name );
55+
super( name );
56+
5657
this.setFilename( filename );
5758
}
5859

maven-jxr/src/main/java/org/apache/maven/jxr/pacman/ImportType.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class ImportType
3939
*/
4040
public ImportType( String name )
4141
{
42-
this.setName( name );
42+
super( name );
4343

4444
//compute member variables
4545

maven-jxr/src/main/java/org/apache/maven/jxr/pacman/JavaFileImpl.java

+33-9
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ private void parseRecursive( String nestedPrefix, StreamTokenizer stok )
8484
{
8585
int openBracesCount = 0;
8686

87+
char prevttype = Character.MIN_VALUE; // previous token type
88+
boolean inTripleQuote = false; // used to toggle between inside/outside triple-quoted multi-line strings
89+
8790
while ( stok.nextToken() != StreamTokenizer.TT_EOF )
8891
{
8992

@@ -103,12 +106,28 @@ else if ( stok.ttype == '}' )
103106
}
104107
continue;
105108
}
109+
else
110+
{
111+
if ( '"' == stok.ttype && '"' == prevttype )
112+
{
113+
inTripleQuote = !inTripleQuote;
114+
}
115+
prevttype = (char) stok.ttype;
116+
if ( inTripleQuote )
117+
{
118+
// skip content found inside triple-quoted multi-line Java 15 String
119+
continue;
120+
}
121+
}
106122

107123
//set the package
108124
if ( "package".equals( stok.sval ) && stok.ttype != '\"' )
109125
{
110126
stok.nextToken();
111-
this.setPackageType( new PackageType( stok.sval ) );
127+
if ( stok.sval != null )
128+
{
129+
this.setPackageType( new PackageType( stok.sval ) );
130+
}
112131
}
113132

114133
//set the imports
@@ -125,23 +144,28 @@ and packages that are imported with this (ex "test.*") will be
125144
stripped( and become "test." ). Here we need to test for this
126145
and if necessary re-add the char.
127146
*/
128-
if ( name.charAt( name.length() - 1 ) == '.' )
147+
if ( name != null )
129148
{
130-
name = name + '*';
149+
if ( name.charAt( name.length() - 1 ) == '.' )
150+
{
151+
name = name + '*';
152+
}
153+
this.addImportType( new ImportType( name ) );
131154
}
132-
133-
this.addImportType( new ImportType( name ) );
134155
}
135156

136157
// Add the class or classes. There can be several classes in one file so
137158
// continue with the while loop to get them all.
138159
if ( ( "class".equals( stok.sval ) || "interface".equals( stok.sval ) || "enum".equals( stok.sval ) )
139-
&& stok.ttype != '\"' )
160+
&& stok.ttype != '"' )
140161
{
141162
stok.nextToken();
142-
this.addClassType( new ClassType( nestedPrefix + stok.sval,
143-
getFilenameWithoutPathOrExtension( this.getPath() ) ) );
144-
parseRecursive( nestedPrefix + stok.sval + ".", stok );
163+
if ( stok.sval != null )
164+
{
165+
this.addClassType( new ClassType( nestedPrefix + stok.sval,
166+
getFilenameWithoutPathOrExtension( this.getPath() ) ) );
167+
parseRecursive( nestedPrefix + stok.sval + ".", stok );
168+
}
145169
}
146170

147171
}

maven-jxr/src/main/java/org/apache/maven/jxr/pacman/PackageType.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ public class PackageType
3939
*/
4040
public PackageType( String name )
4141
{
42-
this.setName( name );
42+
super( name );
4343
}
4444

4545
/**
4646
* Create a Java package with no name IE the default Java package.
4747
*/
4848
public PackageType()
4949
{
50+
super( "" );
5051
}
5152

52-
5353
/**
5454
* Get all the known classes
5555
*/

maven-jxr/src/test/java/org/apache/maven/jxr/pacman/JavaFileImplTest.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,14 @@ public void testJXR_135_lotsOfNested() throws IOException
4646
assertEquals( "NotNested", classTypes.next().getName() );
4747
}
4848

49-
}
49+
@Test
50+
public void testJXR_170_multiLineString() throws IOException
51+
{
52+
JavaFileImpl javaFile = new JavaFileImpl( Paths.get(
53+
"src/test/resources/jxr170/org/apache/maven/jxr/pacman/ClassWithMultiLineString.java" ),
54+
"UTF-8" );
55+
assertEquals( 1, javaFile.getClassTypes().size() );
56+
assertEquals( "ClassWithMultiLineString", javaFile.getClassTypes().get(0).getName() );
57+
assertEquals( "[ImportType[name=java.lang.*]]", javaFile.getImportTypes().toString() );
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.apache.maven.jxr;
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
/**
23+
* Test Java source of the test for JXR-170.
24+
*
25+
* @author Markus Spann
26+
*/
27+
public class ClassWithMultiLineString {
28+
29+
private final String str;
30+
31+
public ClassWithMultiLineString(String _str) {
32+
str = _str;
33+
}
34+
35+
public static void main(String[] args) {
36+
new ClassWithMultiLineString("""
37+
import java.util.List;
38+
""");
39+
}
40+
}

0 commit comments

Comments
 (0)