51
51
import java .nio .file .Path ;
52
52
import java .util .ArrayList ;
53
53
import java .util .Collections ;
54
+ import java .util .Objects ;
54
55
import java .util .zip .GZIPInputStream ;
55
56
import org .junit .Before ;
56
57
import org .junit .Test ;
62
63
public final class TypedAstIntegrationTest extends IntegrationTestCase {
63
64
64
65
private ArrayList <Path > shards ;
65
- private ArrayList <SourceFile > externFiles ;
66
- private ArrayList <SourceFile > sourceFiles ;
66
+ private ArrayList <SourceFile > stubExternFiles ;
67
+ private ArrayList <SourceFile > stubSourceFiles ;
67
68
68
69
@ Override
69
70
@ Before
70
71
public void setUp () {
71
72
super .setUp ();
72
73
this .shards = new ArrayList <>();
73
- this .externFiles = new ArrayList <>();
74
- this .sourceFiles = new ArrayList <>();
74
+ this .stubExternFiles = new ArrayList <>();
75
+ this .stubSourceFiles = new ArrayList <>();
76
+ }
77
+
78
+ @ Test
79
+ public void compilerGeneratesErrorReportWithoutCrashing () throws IOException {
80
+ SourceFile lib1 =
81
+ code ("\n \n class Lib1 { m() { return 'lib1'; } n() { return 'delete me'; } }" );
82
+ SourceFile lib2 =
83
+ code ("\n \n class Lib2 { m() { return 'delete me'; } n() { return 'lib2'; } }" );
84
+ precompileLibrary (lib1 );
85
+ precompileLibrary (lib2 );
86
+ precompileLibrary (
87
+ extern (new TestExternsBuilder ().addAlert ().build ()),
88
+ typeSummary (lib1 ),
89
+ typeSummary (lib2 ),
90
+ code ("\n \n alert(new Lib1().m()); \n \n alert(new Lib2().n());" ));
91
+ // assigning an instance of Lib1 to a variable of type 'string' causes the disambiguator to
92
+ // 'invalidate' the type of Lib1 and any associated properties.
93
+ SourceFile invalidating =
94
+ code ("/** @suppress {checkTypes} @type {string} */ \n \n \n const str = new Lib1();" );
95
+ precompileLibrary (typeSummary (lib1 ), invalidating );
96
+
97
+ CompilerOptions options = new CompilerOptions ();
98
+ CompilationLevel .ADVANCED_OPTIMIZATIONS .setOptionsForCompilationLevel (options );
99
+ options .setDependencyOptions (DependencyOptions .none ());
100
+ options .setDisambiguateProperties (true );
101
+ options .setPropertiesThatMustDisambiguate (ImmutableSet .of ("m" ));
102
+
103
+ Compiler compiler = compileTypedAstShardsWithoutErrorChecks (options );
104
+
105
+ assertThat (compiler .getErrors ())
106
+ .comparingElementsUsing (JSCompCorrespondences .DESCRIPTION_EQUALITY )
107
+ .containsExactly (
108
+ "Property 'm' was required to be disambiguated but was invalidated."
109
+ );
110
+
111
+ // This code path pipes through the {@link ErrorManager} which extends the
112
+ // {@link BasicErrorManager}. The {@link BasicErrorManager} uses a {@link
113
+ // LightweightMessageFormatter} to format the error messages seen by the compiler. When doing
114
+ // so, it tries to format the error message using the compiler which extends the {@link
115
+ // SourceExceptProvider} to attach the relevant snippet of the source files. It invokes
116
+ // {@link SourceExceptProvider}'s methods such as {@link getSourceLine()}, etc to get the source
117
+ // code. For stage 2 and stage 3 passes, the compiler (and these tests) does not receive the
118
+ // source files. So, the {@link SourceExceptProvider} backs off from reading the source files.
119
+ // TODO(b/379868495): The `JSC_DISAMBIGUATE2_PROPERTY_INVALIDATION` error in this test is not a
120
+ // good example to test the crashing behavior when it is reported by the compiler. It is not a
121
+ // good example because it is a `JSError` that is created in the disambiguator pass without
122
+ // source details (line number, column number, etc) -
123
+ // https://source.corp.google.com/piper///depot/google3/third_party/java_src/jscomp/java/com/google/javascript/jscomp/disambiguate/DisambiguateProperties.java;rcl=665086807;l=235. When such an error is formatted, the {@link
124
+ // LightweightMessageFormatter}
125
+ // anyway backs off from extracting the source snippet and formatting it -
126
+ // https://source.corp.google.com/piper///depot/google3/third_party/java_src/jscomp/java/com/google/javascript/jscomp/LightweightMessageFormatter.java;rcl=645071015;l=175.
127
+ // A better example would be an error that is reported in the stage 2 or stage 3 pass and
128
+ // includes the relevant source code details.
129
+ compiler .generateReport ();
75
130
}
76
131
77
132
@ Test
@@ -230,8 +285,10 @@ public void disambiguatesAndDeletesMethodsAcrossLibraries_ignoresInvalidationsIn
230
285
// However, leave in the associated TypedAST in this.shards.
231
286
// We want to verify that JSCompiler is able to disambiguate properties on Lib1 despite the
232
287
// invalidation in the unused TypedAST shard.
233
- Preconditions .checkState (this .sourceFiles .get (3 ) == invalidating , this .sourceFiles );
234
- this .sourceFiles .remove (3 );
288
+ Preconditions .checkState (
289
+ Objects .equals (this .stubSourceFiles .get (3 ).getName (), invalidating .getName ()),
290
+ this .stubSourceFiles );
291
+ this .stubSourceFiles .remove (3 );
235
292
236
293
Compiler compiler = compileTypedAstShards (options );
237
294
@@ -298,9 +355,9 @@ public void exportAnnotationOnProperty_ignoredInUnusedTypedAstShard() throws IOE
298
355
// However, leave in the associated TypedAST in this.shards.
299
356
// We want to verify that JSCompiler does /not/ pay attention to the @export in
300
357
// the unusedLib file, as it's not part of the compilation.
301
- Preconditions .checkState (this .sourceFiles .size () == 2 , this .sourceFiles );
358
+ Preconditions .checkState (this .stubSourceFiles .size () == 2 , this .stubSourceFiles );
302
359
Preconditions .checkState (this .shards .size () == 2 , this .shards );
303
- this .sourceFiles .remove (1 );
360
+ this .stubSourceFiles .remove (1 );
304
361
305
362
Compiler compiler = compileTypedAstShards (options );
306
363
@@ -512,7 +569,7 @@ public void runsJ2clOptimizations() throws IOException {
512
569
" InternalWidget.$clinit();" ,
513
570
"};" ,
514
571
"InternalWidget.$clinit();" ));
515
- sourceFiles .add (f );
572
+ stubSourceFiles .add (f );
516
573
precompileLibrary (f );
517
574
518
575
CompilerOptions options = new CompilerOptions ();
@@ -576,7 +633,7 @@ public void testCrossChunkMethodMotion() throws IOException {
576
633
// run compilation
577
634
try (InputStream inputStream = toInputStream (this .shards )) {
578
635
compiler .initChunksWithTypedAstFilesystem (
579
- ImmutableList .copyOf (this .externFiles ),
636
+ ImmutableList .copyOf (this .stubExternFiles ),
580
637
ImmutableList .of (chunk1 , chunk2 ),
581
638
options ,
582
639
inputStream );
@@ -842,8 +899,8 @@ private Compiler compileTypedAstShardsWithoutErrorChecks(CompilerOptions options
842
899
compiler .initOptions (options );
843
900
try (InputStream inputStream = toInputStream (this .shards )) {
844
901
compiler .initWithTypedAstFilesystem (
845
- ImmutableList .copyOf (this .externFiles ),
846
- ImmutableList .copyOf (this .sourceFiles ),
902
+ ImmutableList .copyOf (this .stubExternFiles ),
903
+ ImmutableList .copyOf (this .stubSourceFiles ),
847
904
options ,
848
905
inputStream );
849
906
}
@@ -852,6 +909,8 @@ private Compiler compileTypedAstShardsWithoutErrorChecks(CompilerOptions options
852
909
compiler .stage3Passes ();
853
910
}
854
911
912
+ compiler .generateReport ();
913
+
855
914
return compiler ;
856
915
}
857
916
@@ -864,15 +923,19 @@ private Compiler compileTypedAstShards(CompilerOptions options) throws IOExcepti
864
923
865
924
private SourceFile code (String ... code ) {
866
925
SourceFile sourceFile =
867
- SourceFile .fromCode ("input_" + (sourceFiles .size () + 1 ), lines (code ), SourceKind .STRONG );
868
- this .sourceFiles .add (sourceFile );
926
+ SourceFile .fromCode (
927
+ "input_" + (stubSourceFiles .size () + 1 ), lines (code ), SourceKind .STRONG );
928
+ SourceFile stubFile = SourceFile .stubSourceFile (sourceFile .getName (), SourceKind .STRONG );
929
+ this .stubSourceFiles .add (stubFile );
869
930
return sourceFile ;
870
931
}
871
932
872
933
private SourceFile extern (String ... code ) {
873
934
SourceFile sourceFile =
874
- SourceFile .fromCode ("extern_" + (externFiles .size () + 1 ), lines (code ), SourceKind .EXTERN );
875
- this .externFiles .add (sourceFile );
935
+ SourceFile .fromCode (
936
+ "extern_" + (stubExternFiles .size () + 1 ), lines (code ), SourceKind .EXTERN );
937
+ SourceFile stubFile = SourceFile .stubSourceFile (sourceFile .getName (), SourceKind .STRONG );
938
+ this .stubExternFiles .add (stubFile );
876
939
return sourceFile ;
877
940
}
878
941
0 commit comments