From 3f4f702e8e61802c9cb8f68a804da60642e12458 Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Sun, 24 Sep 2017 20:47:36 -0500 Subject: [PATCH] Oxygen (SR1a) JDT Patch for Groovy Eclipse: JDT commit 2cf2e0d Fix for issue #318: Groovy and Java 9 support --- .../regression/AbstractRegressionTest.java | 22 +- .../core/tests/util/AbstractCompilerTest.java | 160 +- .../compiler/ast/GroovyClassFile.java | 13 +- .../GroovyProposalTypeSearchRequestor.java | 12 +- .../core/builder/GroovyNameLookup.java | 7 +- .../feature.xml | 2 +- .../.settings/.api_filters | 1200 ++++++++++++ .../org.eclipse.jdt.core/META-INF/MANIFEST.MF | 3 +- jdt-patch/e47/org.eclipse.jdt.core/about.html | 2 +- .../internal/compiler/batch/BasicModule.java | 278 +++ .../compiler/batch/ClasspathDirectory.java | 100 +- .../internal/compiler/batch/ClasspathJar.java | 142 +- .../internal/compiler/batch/ClasspathJrt.java | 361 ++++ .../compiler/batch/ClasspathLocation.java | 38 +- .../compiler/batch/ClasspathSourceJar.java | 22 +- .../compiler/batch/CompilationUnit.java | 38 +- .../internal/compiler/batch/FileFinder.java | 27 +- .../internal/compiler/batch/FileSystem.java | 330 +++- .../jdt/internal/compiler/batch/Main.java | 821 ++++++-- .../internal/compiler/batch/ModuleFinder.java | 253 +++ .../compiler/batch/messages.properties | 28 +- .../internal/codeassist/CompletionEngine.java | 512 ++++- .../internal/codeassist/ISearchRequestor.java | 2 + .../codeassist/ISelectionRequestor.java | 16 +- .../InternalCompletionProposal.java | 18 +- .../codeassist/MissingTypesGuesser.java | 4 + .../codeassist/RelevanceConstants.java | 1 + .../internal/codeassist/SelectionEngine.java | 122 +- .../complete/CompletionOnExportReference.java | 47 + .../complete/CompletionOnKeywordModule2.java | 37 + .../CompletionOnKeywordModuleDeclaration.java | 37 + .../CompletionOnKeywordModuleInfo.java | 44 + .../CompletionOnModuleDeclaration.java | 23 + .../complete/CompletionOnModuleReference.java | 45 + ...ompletionOnPackageVisibilityReference.java | 51 + ...ImplementationsQualifiedTypeReference.java | 21 + ...desImplementationsSingleTypeReference.java | 18 + ...videsInterfacesQualifiedTypeReference.java | 21 + ...ProvidesInterfacesSingleTypeReference.java | 18 + ...ompletionOnUsesQualifiedTypeReference.java | 20 + .../CompletionOnUsesSingleTypeReference.java | 18 + .../codeassist/complete/CompletionParser.java | 230 ++- .../codeassist/impl/AssistParser.java | 233 ++- .../jdt/internal/codeassist/impl/Engine.java | 11 +- .../internal/codeassist/impl/Keywords.java | 10 +- .../select/SelectionOnModuleDeclaration.java | 31 + .../select/SelectionOnModuleReference.java | 42 + ...SelectionOnPackageVisibilityReference.java | 43 + .../codeassist/select/SelectionParser.java | 25 +- .../jdt/core/compiler/CategorizedProblem.java | 7 +- .../jdt/core/compiler/CharOperation.java | 150 +- .../eclipse/jdt/core/compiler/IProblem.java | 96 +- .../jdt/internal/compiler/ASTVisitor.java | 5 +- .../jdt/internal/compiler/ClassFile.java | 420 +++- .../jdt/internal/compiler/ClassFilePool.java | 23 +- .../internal/compiler/CompilationResult.java | 4 +- .../jdt/internal/compiler/Compiler.java | 22 +- .../jdt/internal/compiler/ast/ASTNode.java | 31 +- .../compiler/ast/AllocationExpression.java | 24 +- .../jdt/internal/compiler/ast/Annotation.java | 22 +- .../ast/AnnotationMethodDeclaration.java | 6 +- .../compiler/ast/ClassLiteralAccess.java | 6 +- .../ast/CompilationUnitDeclaration.java | 37 +- .../compiler/ast/ExportsStatement.java | 32 + .../compiler/ast/ImportReference.java | 20 +- .../compiler/ast/LambdaExpression.java | 6 + .../internal/compiler/ast/MessageSend.java | 8 +- .../compiler/ast/MethodDeclaration.java | 5 +- .../compiler/ast/ModuleDeclaration.java | 382 ++++ .../compiler/ast/ModuleReference.java | 46 + .../compiler/ast/ModuleStatement.java | 23 + .../internal/compiler/ast/NameReference.java | 2 +- .../internal/compiler/ast/OpensStatement.java | 35 + .../ast/PackageVisibilityStatement.java | 94 + .../compiler/ast/ProvidesStatement.java | 131 ++ .../ast/QualifiedAllocationExpression.java | 215 ++- .../compiler/ast/QualifiedTypeReference.java | 24 +- .../compiler/ast/ReferenceExpression.java | 2 +- .../compiler/ast/RequiresStatement.java | 56 + .../internal/compiler/ast/TryStatement.java | 213 ++- .../internal/compiler/ast/UsesStatement.java | 29 + .../compiler/classfmt/AnnotationInfo.java | 1 - .../compiler/classfmt/ClassFileConstants.java | 20 +- .../compiler/classfmt/ClassFileReader.java | 62 +- .../classfmt/ExternalAnnotationDecorator.java | 9 +- .../compiler/classfmt/ModuleInfo.java | 389 ++++ .../codegen/AttributeNamesConstants.java | 5 +- .../internal/compiler/codegen/CodeStream.java | 4 +- .../compiler/codegen/ConstantPool.java | 66 +- .../compiler/env/AutomaticModuleNaming.java | 132 ++ .../internal/compiler/env/IBinaryModule.java | 16 + .../internal/compiler/env/IBinaryType.java | 9 +- .../compiler/env/ICompilationUnit.java | 35 +- .../jdt/internal/compiler/env/IModule.java | 134 ++ .../env/IModuleAwareNameEnvironment.java | 123 ++ .../compiler/env/IModulePathEntry.java | 88 + .../compiler/env/IMultiModuleEntry.java | 35 + .../compiler/env/INameEnvironment.java | 108 +- .../env/INameEnvironmentExtension.java | 11 +- .../compiler/env/IUpdatableModule.java | 62 + .../compiler/env/ModuleReferenceImpl.java | 40 + .../compiler/env/NameEnvironmentAnswer.java | 52 +- .../compiler/env/PackageExportImpl.java | 41 + .../compiler/impl/CompilerOptions.java | 89 +- .../internal/compiler/impl/IrritantSet.java | 6 +- .../compiler/lookup/AnnotationBinding.java | 38 +- .../compiler/lookup/BinaryModuleBinding.java | 186 ++ .../compiler/lookup/BinaryTypeBinding.java | 40 +- .../jdt/internal/compiler/lookup/Binding.java | 12 +- .../internal/compiler/lookup/BlockScope.java | 4 +- .../compiler/lookup/CaptureBinding.java | 2 + .../internal/compiler/lookup/ClassScope.java | 31 +- .../compiler/lookup/CompilationUnitScope.java | 105 +- .../lookup/ConstraintExpressionFormula.java | 8 +- .../lookup/IntersectionTypeBinding18.java | 6 +- .../compiler/lookup/LookupEnvironment.java | 598 ++++-- .../compiler/lookup/MemberTypeBinding.java | 8 +- .../compiler/lookup/MethodBinding.java | 2 +- .../internal/compiler/lookup/MethodScope.java | 100 +- .../compiler/lookup/MethodVerifier.java | 4 +- .../compiler/lookup/ModuleBinding.java | 820 ++++++++ .../compiler/lookup/PackageBinding.java | 177 +- .../lookup/ParameterizedMethodBinding.java | 8 +- .../lookup/ParameterizedTypeBinding.java | 1 + ...PolyParameterizedGenericMethodBinding.java | 66 +- .../compiler/lookup/ProblemReasons.java | 3 +- .../compiler/lookup/ReferenceBinding.java | 16 +- .../jdt/internal/compiler/lookup/Scope.java | 108 +- .../compiler/lookup/SourceModuleBinding.java | 165 ++ .../compiler/lookup/SourceTypeBinding.java | 51 +- .../compiler/lookup/SplitPackageBinding.java | 293 +++ .../lookup/SyntheticMethodBinding.java | 10 +- .../jdt/internal/compiler/lookup/TagBits.java | 10 +- .../compiler/lookup/TypeConstants.java | 20 +- .../compiler/lookup/TypeVariableBinding.java | 10 + .../lookup/UnresolvedReferenceBinding.java | 13 +- .../compiler/lookup/WildcardBinding.java | 6 +- .../compiler/parser/ConflictedParser.java | 6 + .../compiler/parser/JavadocTagConstants.java | 6 +- .../jdt/internal/compiler/parser/Parser.java | 1694 +++++++++++------ .../parser/ParserBasicInformation.java | 37 +- .../compiler/parser/RecoveredElement.java | 21 +- .../compiler/parser/RecoveredExport.java | 94 + .../parser/RecoveredExportsStatement.java | 24 + .../compiler/parser/RecoveredModule.java | 284 +++ .../parser/RecoveredModuleReference.java | 56 + .../parser/RecoveredModuleStatement.java | 55 + .../parser/RecoveredOpensStatement.java | 24 + .../RecoveredPackageVisibilityStatement.java | 76 + .../parser/RecoveredProvidesStatement.java | 42 + .../parser/RecoveredRequiresStatement.java | 27 + .../parser/RecoveredTypeReference.java | 46 + .../compiler/parser/RecoveredUnit.java | 18 +- .../parser/RecoveredUsesStatement.java | 30 + .../jdt/internal/compiler/parser/Scanner.java | 377 +++- .../compiler/parser/ScannerHelper.java | 40 +- .../compiler/parser/TerminalTokens.java | 254 +-- .../parser/diagnose/DiagnoseParser.java | 6 + .../jdt/internal/compiler/parser/parser1.rsc | Bin 32890 -> 33634 bytes .../jdt/internal/compiler/parser/parser12.rsc | Bin 582 -> 582 bytes .../jdt/internal/compiler/parser/parser13.rsc | Bin 582 -> 582 bytes .../jdt/internal/compiler/parser/parser14.rsc | Bin 2322 -> 2322 bytes .../jdt/internal/compiler/parser/parser15.rsc | Bin 1454 -> 1466 bytes .../jdt/internal/compiler/parser/parser16.rsc | Bin 2206 -> 2306 bytes .../jdt/internal/compiler/parser/parser17.rsc | Bin 801 -> 852 bytes .../jdt/internal/compiler/parser/parser18.rsc | Bin 7756 -> 7491 bytes .../jdt/internal/compiler/parser/parser19.rsc | 13 +- .../jdt/internal/compiler/parser/parser2.rsc | Bin 31288 -> 31930 bytes .../jdt/internal/compiler/parser/parser20.rsc | Bin 15402 -> 16468 bytes .../jdt/internal/compiler/parser/parser21.rsc | Bin 6408 -> 6816 bytes .../jdt/internal/compiler/parser/parser22.rsc | Bin 722 -> 778 bytes .../jdt/internal/compiler/parser/parser23.rsc | Bin 90 -> 90 bytes .../jdt/internal/compiler/parser/parser24.rsc | Bin 722 -> 778 bytes .../jdt/internal/compiler/parser/parser3.rsc | Bin 2206 -> 2306 bytes .../jdt/internal/compiler/parser/parser4.rsc | Bin 3178 -> 3356 bytes .../jdt/internal/compiler/parser/parser5.rsc | Bin 2206 -> 2306 bytes .../jdt/internal/compiler/parser/parser6.rsc | Bin 1292 -> 1380 bytes .../jdt/internal/compiler/parser/parser7.rsc | Bin 238 -> 258 bytes .../jdt/internal/compiler/parser/parser8.rsc | Bin 722 -> 778 bytes .../jdt/internal/compiler/parser/parser9.rsc | Bin 15410 -> 14858 bytes .../compiler/parser/unicode7/part0.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode7/part1.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode7/part14.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode7/part2.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode7/start0.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode7/start1.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode7/start2.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode8/part0.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode8/part1.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode8/part14.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode8/part2.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode8/start0.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode8/start1.rsc | Bin 0 -> 8192 bytes .../compiler/parser/unicode8/start2.rsc | Bin 0 -> 8192 bytes .../compiler/problem/DefaultProblem.java | 4 +- .../compiler/problem/ProblemReporter.java | 338 +++- .../compiler/problem/messages.properties | 52 +- .../compiler/util/HashtableOfModule.java | 106 ++ .../jdt/internal/compiler/util/JRTUtil.java | 453 +++++ .../internal/compiler/util/ObjectVector.java | 19 +- .../compiler/util/SuffixConstants.java | 4 +- .../jdt/internal/compiler/util/Util.java | 120 +- .../dom/org/eclipse/jdt/core/dom/AST.java | 166 +- .../eclipse/jdt/core/dom/ASTConverter.java | 420 ++-- .../org/eclipse/jdt/core/dom/ASTMatcher.java | 201 +- .../dom/org/eclipse/jdt/core/dom/ASTNode.java | 95 +- .../org/eclipse/jdt/core/dom/ASTParser.java | 42 +- .../jdt/core/dom/ASTRecoveryPropagator.java | 5 +- .../core/dom/ASTSyntaxErrorPropagator.java | 9 +- .../org/eclipse/jdt/core/dom/ASTVisitor.java | 212 ++- .../eclipse/jdt/core/dom/AnnotatableType.java | 4 +- .../jdt/core/dom/AnnotationBinding.java | 9 +- .../org/eclipse/jdt/core/dom/ArrayType.java | 12 +- .../jdt/core/dom/BindingComparator.java | 21 +- .../eclipse/jdt/core/dom/BindingResolver.java | 40 +- .../eclipse/jdt/core/dom/CompilationUnit.java | 105 +- .../jdt/core/dom/CompilationUnitResolver.java | 9 +- .../jdt/core/dom/DefaultASTVisitor.java | 14 +- .../jdt/core/dom/DefaultBindingResolver.java | 62 +- .../jdt/core/dom/DocCommentParser.java | 2 +- .../jdt/core/dom/ExportsDirective.java | 124 ++ .../org/eclipse/jdt/core/dom/IBinding.java | 15 +- .../eclipse/jdt/core/dom/IModuleBinding.java | 100 + .../eclipse/jdt/core/dom/ITypeBinding.java | 4 +- .../jdt/core/dom/MethodDeclaration.java | 16 +- .../eclipse/jdt/core/dom/ModuleBinding.java | 237 +++ .../jdt/core/dom/ModuleDeclaration.java | 364 ++++ .../eclipse/jdt/core/dom/ModuleDirective.java | 33 + .../eclipse/jdt/core/dom/ModuleModifier.java | 360 ++++ .../jdt/core/dom/ModulePackageAccess.java | 204 ++ .../core/dom/NameEnvironmentWithProgress.java | 18 +- .../eclipse/jdt/core/dom/OpensDirective.java | 123 ++ .../eclipse/jdt/core/dom/PackageBinding.java | 6 +- .../eclipse/jdt/core/dom/PrimitiveType.java | 4 +- .../jdt/core/dom/ProvidesDirective.java | 223 +++ .../eclipse/jdt/core/dom/QualifiedType.java | 4 +- .../jdt/core/dom/RequiresDirective.java | 248 +++ .../org/eclipse/jdt/core/dom/SimpleType.java | 4 +- .../core/dom/SingleVariableDeclaration.java | 12 +- .../eclipse/jdt/core/dom/TryStatement.java | 56 +- .../eclipse/jdt/core/dom/TypeParameter.java | 6 +- .../eclipse/jdt/core/dom/UsesDirective.java | 187 ++ .../jdt/core/dom/VariableDeclaration.java | 2 +- .../core/dom/VariableDeclarationFragment.java | 6 +- .../eclipse/jdt/core/dom/WildcardType.java | 4 +- .../jdt/core/dom/rewrite/ImportRewrite.java | 9 +- .../internal/core/dom/NaiveASTFlattener.java | 138 +- .../core/dom/rewrite/ASTRewriteAnalyzer.java | 160 +- .../core/dom/rewrite/ASTRewriteFlattener.java | 121 +- .../core/dom/rewrite/ASTRewriteFormatter.java | 8 +- .../internal/eval/CodeSnippetClassFile.java | 2 +- .../internal/eval/CodeSnippetEnvironment.java | 2 +- .../jdt/internal/eval/CodeSnippetScope.java | 4 +- .../internal/eval/CodeSnippetSkeleton.java | 7 +- .../internal/eval/CodeSnippetToCuMapper.java | 4 + .../jdt/internal/eval/EvaluationContext.java | 11 +- .../eclipse/jdt/internal/eval/Evaluator.java | 7 +- .../jdt/core/formatter/CodeFormatter.java | 49 +- .../formatter/CodeFormatterApplication.java | 5 +- .../DefaultCodeFormatterConstants.java | 11 + .../formatter/CommentsPreparator.java | 6 +- .../formatter/DefaultCodeFormatter.java | 118 +- .../DefaultCodeFormatterOptions.java | 8 + .../formatter/LineBreaksPreparator.java | 24 + .../internal/formatter/SpacePreparator.java | 38 +- .../formatter/linewrap/WrapPreparator.java | 36 +- .../e47/org.eclipse.jdt.core/grammar/java.g | 132 +- .../jdtCompilerAdapter.jar | Bin 14525 -> 14525 bytes .../eclipse/jdt/core/CompletionProposal.java | 38 +- .../model/org/eclipse/jdt/core/Flags.java | 22 +- .../org/eclipse/jdt/core/IClassFile.java | 13 +- .../eclipse/jdt/core/IClasspathAttribute.java | 87 +- .../org/eclipse/jdt/core/IClasspathEntry.java | 2 +- .../org/eclipse/jdt/core/IJavaElement.java | 10 +- .../org/eclipse/jdt/core/IJavaProject.java | 33 +- .../eclipse/jdt/core/IModularClassFile.java | 29 + .../eclipse/jdt/core/IModuleDescription.java | 29 + .../eclipse/jdt/core/IOrdinaryClassFile.java | 31 + .../eclipse/jdt/core/IPackageFragment.java | 71 +- .../jdt/core/IPackageFragmentRoot.java | 15 +- .../model/org/eclipse/jdt/core/ITypeRoot.java | 15 +- .../org/eclipse/jdt/core/JavaConventions.java | 91 +- .../model/org/eclipse/jdt/core/JavaCore.java | 128 +- .../eclipse/jdt/core/JavaModelException.java | 11 +- .../jdt/core/compiler/ReconcileContext.java | 67 +- .../jdt/core/provisional/JavaModelAccess.java | 72 + .../jdt/core/util/CompilationUnitSorter.java | 3 +- .../core/util/IAttributeNamesConstants.java | 20 +- .../jdt/core/util/IClassFileReader.java | 10 +- .../eclipse/jdt/core/util/IConstantPool.java | 8 +- .../jdt/core/util/IConstantPoolConstant.java | 20 +- .../jdt/core/util/IConstantPoolEntry.java | 7 +- .../jdt/core/util/IConstantPoolEntry3.java | 60 + .../jdt/core/util/IModifierConstants.java | 26 +- .../jdt/core/util/IModuleAttribute.java | 138 ++ .../core/util/IModuleMainClassAttribute.java | 35 + .../core/util/IModulePackagesAttribute.java | 42 + .../jdt/core/util/IPackageVisibilityInfo.java | 62 + .../eclipse/jdt/core/util/IProvidesInfo.java | 57 + .../eclipse/jdt/core/util/IRequiresInfo.java | 57 + .../compiler/ISourceElementRequestor.java | 40 +- .../compiler/SourceElementNotifier.java | 108 +- .../compiler/SourceElementParser.java | 23 +- .../compiler/parser/SourceTypeConverter.java | 5 +- .../jdt/internal/core/AbstractClassFile.java | 462 +++++ .../jdt/internal/core/AbstractModule.java | 93 + .../internal/core/BasicCompilationUnit.java | 72 +- .../jdt/internal/core/BinaryMethod.java | 4 +- .../jdt/internal/core/BinaryModule.java | 99 + .../eclipse/jdt/internal/core/BinaryType.java | 4 +- .../core/CancelableNameEnvironment.java | 8 +- .../eclipse/jdt/internal/core/ClassFile.java | 463 +---- .../jdt/internal/core/ClassFileInfo.java | 26 +- .../internal/core/ClassFileWorkingCopy.java | 15 +- .../jdt/internal/core/ClasspathChange.java | 7 +- .../jdt/internal/core/ClasspathEntry.java | 33 +- .../jdt/internal/core/CompilationUnit.java | 33 +- .../core/CompilationUnitProblemFinder.java | 15 +- .../CompilationUnitStructureRequestor.java | 56 +- .../core/CopyResourceElementsOperation.java | 4 +- .../core/CreateElementInCUOperation.java | 4 +- .../core/CreateTypeMemberOperation.java | 6 +- .../core/DeleteElementsOperation.java | 4 +- .../jdt/internal/core/DeltaProcessor.java | 33 +- .../internal/core/IJavaElementRequestor.java | 2 + .../core/JModPackageFragmentRoot.java | 63 + .../jdt/internal/core/JarEntryDirectory.java | 2 +- .../jdt/internal/core/JarEntryFile.java | 53 +- .../jdt/internal/core/JarEntryResource.java | 2 +- .../jdt/internal/core/JarPackageFragment.java | 10 +- .../internal/core/JarPackageFragmentRoot.java | 64 +- .../jdt/internal/core/JavaElement.java | 6 +- .../internal/core/JavaElementRequestor.java | 30 + .../eclipse/jdt/internal/core/JavaModel.java | 14 +- .../jdt/internal/core/JavaModelManager.java | 45 +- .../jdt/internal/core/JavaProject.java | 358 +++- .../internal/core/JavaProjectElementInfo.java | 2 +- .../jdt/internal/core/JavadocConstants.java | 5 +- .../jdt/internal/core/JavadocContents.java | 30 +- .../internal/core/JrtPackageFragmentRoot.java | 151 ++ .../jdt/internal/core/ModularClassFile.java | 307 +++ .../org/eclipse/jdt/internal/core/Module.java | 61 + .../internal/core/ModuleDescriptionInfo.java | 399 ++++ .../internal/core/ModulePathContainer.java | 80 + .../core/ModulePathContainerInitializer.java | 46 + .../core/ModuleSourcePathManager.java | 130 ++ .../jdt/internal/core/ModuleUpdater.java | 111 ++ .../eclipse/jdt/internal/core/NameLookup.java | 396 +++- .../jdt/internal/core/NamedMember.java | 15 + .../internal/core/OpenableElementInfo.java | 11 +- .../jdt/internal/core/PackageFragment.java | 74 +- .../internal/core/PackageFragmentRoot.java | 78 +- .../core/PackageFragmentRootInfo.java | 2 + .../jdt/internal/core/ProjectEntry.java | 90 + .../internal/core/SearchableEnvironment.java | 350 +++- .../core/SearchableEnvironmentRequestor.java | 4 + .../jdt/internal/core/SelectionRequestor.java | 16 +- .../internal/core/SingleTypeRequestor.java | 7 + .../jdt/internal/core/SourceMapper.java | 257 ++- .../jdt/internal/core/SourceModule.java | 34 + .../core/builder/AbstractImageBuilder.java | 13 +- .../core/builder/BatchImageBuilder.java | 1 - .../core/builder/ClasspathDirectory.java | 90 +- .../internal/core/builder/ClasspathJMod.java | 99 + .../internal/core/builder/ClasspathJar.java | 178 +- .../internal/core/builder/ClasspathJrt.java | 303 +++ .../core/builder/ClasspathLocation.java | 78 +- .../core/builder/ClasspathMultiDirectory.java | 30 +- .../core/builder/IncrementalImageBuilder.java | 10 +- .../core/builder/ModuleEntryProcessor.java | 103 + .../core/builder/ModuleInfoBuilder.java | 102 + .../core/builder/ModulePathEntry.java | 164 ++ .../core/builder/NameEnvironment.java | 362 +++- .../jdt/internal/core/builder/SourceFile.java | 10 +- .../jdt/internal/core/builder/State.java | 24 +- .../core/hierarchy/HierarchyBinaryType.java | 7 +- .../core/hierarchy/HierarchyBuilder.java | 18 +- .../core/hierarchy/HierarchyResolver.java | 1 - .../hierarchy/IndexBasedHierarchyBuilder.java | 3 +- .../RegionBasedHierarchyBuilder.java | 6 +- .../internal/core/jdom/CompilationUnit.java | 7 +- .../internal/core/util/BindingKeyParser.java | 49 +- .../core/util/BindingKeyResolver.java | 14 +- .../internal/core/util/ClassFileReader.java | 21 +- .../jdt/internal/core/util/ConstantPool.java | 20 +- .../internal/core/util/ConstantPoolEntry.java | 3 +- .../core/util/ConstantPoolEntry2.java | 51 +- .../jdt/internal/core/util/DOMFinder.java | 9 +- .../jdt/internal/core/util/Disassembler.java | 207 +- .../jdt/internal/core/util/HandleFactory.java | 8 +- .../internal/core/util/JavaElementFinder.java | 11 +- .../internal/core/util/MementoTokenizer.java | 9 +- .../jdt/internal/core/util/Messages.java | 15 +- .../internal/core/util/ModuleAttribute.java | 221 +++ .../core/util/ModuleMainClassAttribute.java | 54 + .../core/util/ModulePackagesAttribute.java | 76 + .../jdt/internal/core/util/ModuleUtil.java | 150 ++ .../core/util/PackageVisibilityInfo.java | 93 + .../jdt/internal/core/util/ProvidesInfo.java | 77 + .../jdt/internal/core/util/RequiresInfo.java | 77 + .../core/util/ResourceCompilationUnit.java | 13 +- .../eclipse/jdt/internal/core/util/Util.java | 25 +- .../internal/core/util/messages.properties | 15 +- jdt-patch/e47/org.eclipse.jdt.core/plugin.xml | 11 + jdt-patch/e47/org.eclipse.jdt.core/pom.bak | 6 +- jdt-patch/e47/org.eclipse.jdt.core/pom.xml | 4 +- jdt-patch/e47/org.eclipse.jdt.core/readme.txt | 1 + .../e47/org.eclipse.jdt.core/scripts/ecj.1 | 44 +- .../jdt/core/search/IJavaSearchConstants.java | 8 +- .../core/search/ModuleDeclarationMatch.java | 41 + .../jdt/core/search/ModuleReferenceMatch.java | 43 + .../jdt/core/search/SearchPattern.java | 13 +- .../nd/indexer/HierarchicalASTVisitor.java | 83 +- .../jdt/internal/core/nd/indexer/Indexer.java | 9 +- .../nd/java/model/BinaryModuleDescriptor.java | 63 + .../nd/java/model/BinaryModuleFactory.java | 159 ++ .../core/nd/java/model/BinaryTypeFactory.java | 15 +- .../core/nd/java/model/IndexBinaryType.java | 8 +- .../internal/core/search/IndexSelector.java | 5 +- .../core/search/JavaSearchDocument.java | 8 +- .../search/NameMatchRequestorWrapper.java | 40 +- .../core/search/indexing/AbstractIndexer.java | 13 +- .../search/indexing/AddJarFileToIndex.java | 51 +- .../core/search/indexing/AddJrtToIndex.java | 310 +++ .../core/search/indexing/BinaryContainer.java | 66 + .../core/search/indexing/BinaryIndexer.java | 69 +- .../core/search/indexing/IIndexConstants.java | 6 +- .../core/search/indexing/IndexManager.java | 21 +- .../indexing/SourceIndexerRequestor.java | 27 + .../matching/ClassFileMatchLocator.java | 3 +- .../matching/ClasspathSourceDirectory.java | 27 +- .../IndexBasedJavaSearchEnvironment.java | 4 +- .../matching/JavaSearchNameEnvironment.java | 205 +- .../core/search/matching/MatchLocator.java | 220 ++- .../search/matching/MatchLocatorParser.java | 52 +- .../ModularClassFileMatchLocator.java | 220 +++ .../core/search/matching/ModuleLocator.java | 84 + .../core/search/matching/ModulePattern.java | 117 ++ .../matching/PackageReferenceLocator.java | 2 +- .../core/search/matching/PatternLocator.java | 13 +- .../core/search/matching/PossibleMatch.java | 57 +- .../search/matching/PossibleMatchSet.java | 9 +- .../matching/SuperTypeNamesCollector.java | 6 +- 443 files changed, 28871 insertions(+), 3537 deletions(-) create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/.settings/.api_filters create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExportReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModule2.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleDeclaration.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleDeclaration.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageVisibilityReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsQualifiedTypeReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsSingleTypeReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesQualifiedTypeReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesSingleTypeReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesQualifiedTypeReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesSingleTypeReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleDeclaration.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageVisibilityReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExportsStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ProvidesStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RequiresStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UsesStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AutomaticModuleNaming.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleEntry.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ModuleReferenceImpl.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/PackageExportImpl.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExport.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExportsStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredOpensStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredPackageVisibilityStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredProvidesStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredRequiresStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredTypeReference.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUsesStatement.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part0.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part1.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part14.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part2.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start0.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start1.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start2.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part0.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part1.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part14.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part2.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start0.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start1.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start2.rsc create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExportsDirective.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IModuleBinding.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleBinding.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDeclaration.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDirective.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleModifier.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModulePackageAccess.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/OpensDirective.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ProvidesDirective.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RequiresDirective.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/UsesDirective.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModularClassFile.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModuleDescription.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOrdinaryClassFile.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/provisional/JavaModelAccess.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry3.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModuleAttribute.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModuleMainClassAttribute.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModulePackagesAttribute.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPackageVisibilityInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IProvidesInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRequiresInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractClassFile.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JModPackageFragmentRoot.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JrtPackageFragmentRoot.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModularClassFile.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Module.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleDescriptionInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainer.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainerInitializer.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleSourcePathManager.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectEntry.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceModule.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleEntryProcessor.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleInfoBuilder.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleAttribute.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleMainClassAttribute.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModulePackagesAttribute.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PackageVisibilityInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ProvidesInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RequiresInfo.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ModuleDeclarationMatch.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ModuleReferenceMatch.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryModuleDescriptor.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryModuleFactory.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJrtToIndex.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryContainer.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModularClassFileMatchLocator.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModuleLocator.java create mode 100644 jdt-patch/e47/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModulePattern.java diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java index 4da993f61c..bfc25f527b 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java @@ -13,8 +13,8 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; -import java.io.FileOutputStream; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; @@ -109,19 +109,19 @@ static class JavacCompiler { } } } - if (rawVersion.indexOf("1.4") != -1 || - this.javacPathName.indexOf("1.4") != -1 - /* in fact, SUN javac 1.4 does not support the -version option; - * this is a imperfect heuristic to catch the case */) { + if (rawVersion.indexOf(JavaCore.VERSION_1_4) != -1 || this.javacPathName.indexOf(JavaCore.VERSION_1_4) != -1 + /* in fact, SUN javac 1.4 does not support the -version option; this is a imperfect heuristic to catch the case */) { this.version = JavaCore.VERSION_1_4; - } else if (rawVersion.indexOf("1.5") != -1) { + } else if (rawVersion.indexOf(JavaCore.VERSION_1_5) != -1) { this.version = JavaCore.VERSION_1_5; - } else if (rawVersion.indexOf("1.6") != -1) { + } else if (rawVersion.indexOf(JavaCore.VERSION_1_6) != -1) { this.version = JavaCore.VERSION_1_6; - } else if (rawVersion.indexOf("1.7") != -1) { + } else if (rawVersion.indexOf(JavaCore.VERSION_1_7) != -1) { this.version = JavaCore.VERSION_1_7; - } else if (rawVersion.indexOf("1.8") != -1) { - this.version = "1.8";//JavaCore.VERSION_1_8; + } else if (rawVersion.indexOf(VERSION_1_8) != -1) { + this.version = VERSION_1_8; + } else if (rawVersion.indexOf(VERSION_1_9) != -1) { + this.version = VERSION_1_9; } else { throw new RuntimeException("unknown javac version: " + rawVersion); } @@ -824,6 +824,8 @@ protected void compileAndDeploy(String source, String directoryName, String clas buffer.append("\" -1.7"); } else if (this.complianceLevel == JDK1_8) { buffer.append("\" -1.8"); + } else if (this.complianceLevel == JDK1_9) { + buffer.append("\" -1.9"); } buffer .append(" -preserveAllLocals -nowarn -g -classpath \"") diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java index bc25201e8a..5c80e72d7f 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java @@ -20,7 +20,6 @@ import junit.framework.Test; import junit.framework.TestSuite; - import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.tests.compiler.regression.RegressionTestSetup; @@ -36,11 +35,20 @@ public abstract class AbstractCompilerTest extends TestCase { public static final int F_1_6 = 0x08; public static final int F_1_7 = 0x10; public static final int F_1_8 = 0x20; + public static final int F_1_9 = 0x40; + + // here for now as CompilerOptions.version_1_8 exists only if using the java8 patched jdt + protected static final String VERSION_1_8 = "1.8"; + protected static final String VERSION_1_9 = "1.9"; + protected static final int MAJOR_VERSION_1_8 = 52; + protected static final int MAJOR_VERSION_1_9 = 53; + public static final long JDK1_8 = ((long) MAJOR_VERSION_1_8 << 16) + ClassFileConstants.MINOR_VERSION_0; + public static final long JDK1_9 = ((long) MAJOR_VERSION_1_9 << 16) + ClassFileConstants.MINOR_VERSION_0; - public static final boolean RUN_JAVAC = CompilerOptions.ENABLED.equals(System.getProperty("run.javac")); private static final int UNINITIALIZED = -1; private static final int NONE = 0; private static int possibleComplianceLevels = UNINITIALIZED; + public static final boolean RUN_JAVAC = CompilerOptions.ENABLED.equals(System.getProperty("run.javac")); protected long complianceLevel; @@ -59,25 +67,28 @@ public static Test buildAllCompliancesTestSuite(Class evaluation } public static void buildAllCompliancesTestSuite(TestSuite suite, Class evaluationTestClass) { - int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels(); - if ((complianceLevels & AbstractCompilerTest.F_1_3) != 0) { + int complianceLevels = getPossibleComplianceLevels(); + if ((complianceLevels & F_1_3) != 0) { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_3)); } - if ((complianceLevels & AbstractCompilerTest.F_1_4) != 0) { + if ((complianceLevels & F_1_4) != 0) { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_4)); } - if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) { + if ((complianceLevels & F_1_5) != 0) { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_5)); } - if ((complianceLevels & AbstractCompilerTest.F_1_6) != 0) { + if ((complianceLevels & F_1_6) != 0) { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_6)); } - if ((complianceLevels & AbstractCompilerTest.F_1_7) != 0) { + if ((complianceLevels & F_1_7) != 0) { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_7)); } - if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) { + if ((complianceLevels & F_1_8) != 0) { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, JDK1_8)); } + if ((complianceLevels & F_1_9) != 0) { + suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, JDK1_9)); + } } /** @@ -92,25 +103,28 @@ public static void buildAllCompliancesTestSuite(TestSuite suite, Class testSuiteClass, Class setupClass, List> testClasses) { TestSuite suite = new TestSuite(testSuiteClass.getName()); - int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels(); - if ((complianceLevels & AbstractCompilerTest.F_1_3) != 0) { + int complianceLevels = getPossibleComplianceLevels(); + if ((complianceLevels & F_1_3) != 0) { suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_3)); } - if ((complianceLevels & AbstractCompilerTest.F_1_4) != 0) { + if ((complianceLevels & F_1_4) != 0) { suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_4)); } - if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) { + if ((complianceLevels & F_1_5) != 0) { suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_5)); } - if ((complianceLevels & AbstractCompilerTest.F_1_6) != 0) { + if ((complianceLevels & F_1_6) != 0) { suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_6)); } - if ((complianceLevels & AbstractCompilerTest.F_1_7) != 0) { + if ((complianceLevels & F_1_7) != 0) { suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_7)); } - if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) { + if ((complianceLevels & F_1_8) != 0) { suite.addTest(buildComplianceTestSuite(testClasses, setupClass, JDK1_8)); } + if ((complianceLevels & F_1_9) != 0) { + suite.addTest(buildComplianceTestSuite(testClasses, setupClass, JDK1_9)); + } return suite; } @@ -181,55 +195,63 @@ private static Test buildComplianceTestSuite(List> testCla */ public static Test buildMinimalComplianceTestSuite(Class evaluationTestClass, int minimalCompliance) { TestSuite suite = new TestSuite(evaluationTestClass.getName()); - int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels(); - int level13 = complianceLevels & AbstractCompilerTest.F_1_3; - if (level13 != 0) { - if (level13 < minimalCompliance) { + int complianceLevels = getPossibleComplianceLevels(); + int level3 = complianceLevels & F_1_3; + if (level3 != 0) { + if (level3 < minimalCompliance) { System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_3)+"!"); } else { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_3)); } } - int level14 = complianceLevels & AbstractCompilerTest.F_1_4; - if (level14 != 0) { - if (level14 < minimalCompliance) { + int level4 = complianceLevels & F_1_4; + if (level4 != 0) { + if (level4 < minimalCompliance) { System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_4)+"!"); } else { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_4)); } } - int level15 = complianceLevels & AbstractCompilerTest.F_1_5; - if (level15 != 0) { - if (level15 < minimalCompliance) { + int level5 = complianceLevels & F_1_5; + if (level5 != 0) { + if (level5 < minimalCompliance) { System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_5)+"!"); } else { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_5)); } } - int level16 = complianceLevels & AbstractCompilerTest.F_1_6; - if (level16 != 0) { - if (level16 < minimalCompliance) { + int level6 = complianceLevels & F_1_6; + if (level6 != 0) { + if (level6 < minimalCompliance) { System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_6)+"!"); } else { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_6)); } } - int level17 = complianceLevels & AbstractCompilerTest.F_1_7; - if (level17 != 0) { - if (level17 < minimalCompliance) { + int level7 = complianceLevels & F_1_7; + if (level7 != 0) { + if (level7 < minimalCompliance) { System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_7)+"!"); } else { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_7)); } } - int level18 = complianceLevels & AbstractCompilerTest.F_1_8; - if (level18 != 0) { - if (level18 < minimalCompliance) { + int level8 = complianceLevels & F_1_8; + if (level8 != 0) { + if (level8 < minimalCompliance) { System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(JDK1_8)+"!"); } else { suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, JDK1_8)); } } + int level9 = complianceLevels & F_1_9; + if (level9 != 0) { + if (level9 < minimalCompliance) { + System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(JDK1_9)+"!"); + } else { + suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, JDK1_9)); + } + } return suite; } @@ -260,30 +282,28 @@ public static Test buildUniqueComplianceTestSuite(Class evaluati * Returns the highest compliance level this VM instance can run. */ public static long highestComplianceLevels() { - int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels(); - if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) { + int complianceLevels = getPossibleComplianceLevels(); + if ((complianceLevels & F_1_9) != 0) { + return JDK1_9; + } + if ((complianceLevels & F_1_8) != 0) { return JDK1_8; } - if ((complianceLevels & AbstractCompilerTest.F_1_7) != 0) { + if ((complianceLevels & F_1_7) != 0) { return ClassFileConstants.JDK1_7; } - if ((complianceLevels & AbstractCompilerTest.F_1_6) != 0) { + if ((complianceLevels & F_1_6) != 0) { return ClassFileConstants.JDK1_6; } - if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) { + if ((complianceLevels & F_1_5) != 0) { return ClassFileConstants.JDK1_5; } - if ((complianceLevels & AbstractCompilerTest.F_1_4) != 0) { + if ((complianceLevels & F_1_4) != 0) { return ClassFileConstants.JDK1_4; } return ClassFileConstants.JDK1_3; } - // here for now as CompilerOptions.version_1_8 exists only if using the java8 patched jdt - protected static final String VERSION_1_8 = "1.8"; - protected static final int MAJOR_VERSION_1_8 = 52; - public static final long JDK1_8 = ((long) MAJOR_VERSION_1_8 << 16) + ClassFileConstants.MINOR_VERSION_0; - /* * Returns the possible compliance levels this VM instance can run. */ @@ -303,6 +323,8 @@ public static int getPossibleComplianceLevels() { possibleComplianceLevels = F_1_7; } else if (VERSION_1_8.equals(compliance)) { possibleComplianceLevels = F_1_8; + } else if (VERSION_1_9.equals(compliance)) { + possibleComplianceLevels = F_1_9; } else { System.out.println("Invalid compliance specified (" + compliance + ")"); System.out.print("Use one of "); @@ -312,6 +334,7 @@ public static int getPossibleComplianceLevels() { System.out.print(CompilerOptions.VERSION_1_6 + ", "); System.out.print(CompilerOptions.VERSION_1_7 + ", "); System.out.println(VERSION_1_8); + System.out.println(VERSION_1_9); System.out.println("Defaulting to all possible compliances"); } } @@ -319,10 +342,10 @@ public static int getPossibleComplianceLevels() { String specVersion = System.getProperty("java.specification.version"); if (!RUN_JAVAC) { possibleComplianceLevels = F_1_3; - boolean canRun1_4 = !"1.0".equals(specVersion) - && !CompilerOptions.VERSION_1_1.equals(specVersion) - && !CompilerOptions.VERSION_1_2.equals(specVersion) - && !CompilerOptions.VERSION_1_3.equals(specVersion); + boolean canRun1_4 = !"1.0".equals(specVersion) && + !CompilerOptions.VERSION_1_1.equals(specVersion) && + !CompilerOptions.VERSION_1_2.equals(specVersion) && + !CompilerOptions.VERSION_1_3.equals(specVersion); if (canRun1_4) { possibleComplianceLevels |= F_1_4; } @@ -342,11 +365,15 @@ public static int getPossibleComplianceLevels() { if (canRun1_8) { possibleComplianceLevels |= F_1_8; } - } else if ("1.0".equals(specVersion) - || CompilerOptions.VERSION_1_1.equals(specVersion) - || CompilerOptions.VERSION_1_2.equals(specVersion) - || CompilerOptions.VERSION_1_3.equals(specVersion) - || CompilerOptions.VERSION_1_4.equals(specVersion)) { + boolean canRun1_9 = canRun1_7 && !VERSION_1_8.equals(specVersion); + if (canRun1_9) { + possibleComplianceLevels |= F_1_9; + } + } else if ("1.0".equals(specVersion) || + CompilerOptions.VERSION_1_1.equals(specVersion) || + CompilerOptions.VERSION_1_2.equals(specVersion) || + CompilerOptions.VERSION_1_3.equals(specVersion) || + CompilerOptions.VERSION_1_4.equals(specVersion)) { possibleComplianceLevels = NONE; } else { possibleComplianceLevels = F_1_5; @@ -356,6 +383,9 @@ public static int getPossibleComplianceLevels() { possibleComplianceLevels |= F_1_7; if (!CompilerOptions.VERSION_1_7.equals(specVersion)) { possibleComplianceLevels |= F_1_8; + if (!CompilerOptions.VERSION_1_8.equals(specVersion)) { + possibleComplianceLevels |= F_1_9; + } } } } @@ -374,14 +404,14 @@ public static int getPossibleComplianceLevels() { */ public static Test suite(String suiteName, Class setupClass, List> testClasses) { TestSuite all = new TestSuite(suiteName); - int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels(); - if ((complianceLevels & AbstractCompilerTest.F_1_3) != 0) { + int complianceLevels = getPossibleComplianceLevels(); + if ((complianceLevels & F_1_3) != 0) { all.addTest(suiteForComplianceLevel(ClassFileConstants.JDK1_3, setupClass, testClasses)); } - if ((complianceLevels & AbstractCompilerTest.F_1_4) != 0) { + if ((complianceLevels & F_1_4) != 0) { all.addTest(suiteForComplianceLevel(ClassFileConstants.JDK1_4, setupClass, testClasses)); } - if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) { + if ((complianceLevels & F_1_5) != 0) { all.addTest(suiteForComplianceLevel(ClassFileConstants.JDK1_5, setupClass, testClasses)); } return all; @@ -454,7 +484,7 @@ public static Test buildTestSuite(Class evaluationTestClass, lon public static boolean isJRELevel(int compliance) { - return (AbstractCompilerTest.getPossibleComplianceLevels() & compliance) != 0; + return (getPossibleComplianceLevels() & compliance) != 0; } public AbstractCompilerTest(String name) { @@ -485,9 +515,13 @@ protected Map getCompilerOptions() { options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7); options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7); } else if (this.complianceLevel == JDK1_8) { - options.put(CompilerOptions.OPTION_Compliance, "1.8"/*CompilerOptions.VERSION_1_8*/); - options.put(CompilerOptions.OPTION_Source, "1.8"/*CompilerOptions.VERSION_1_8*/); - options.put(CompilerOptions.OPTION_TargetPlatform, "1.8"/*CompilerOptions.VERSION_1_8*/); + options.put(CompilerOptions.OPTION_Compliance, VERSION_1_8); + options.put(CompilerOptions.OPTION_Source, VERSION_1_8); + options.put(CompilerOptions.OPTION_TargetPlatform, VERSION_1_8); + } else if (this.complianceLevel == JDK1_9) { + options.put(CompilerOptions.OPTION_Compliance, VERSION_1_9); + options.put(CompilerOptions.OPTION_Source, VERSION_1_9); + options.put(CompilerOptions.OPTION_TargetPlatform, VERSION_1_9); } return options; } diff --git a/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/GroovyClassFile.java b/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/GroovyClassFile.java index 1ccc78d6ab..cee8518c7b 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/GroovyClassFile.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/GroovyClassFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding; @@ -243,11 +244,14 @@ public char[][] getCompoundName() { return name; } - @Override protected void initByteArrays() { throw new UnsupportedOperationException(); } + protected void initByteArrays(int members) { + throw new UnsupportedOperationException(); + } + @Override public void initialize(SourceTypeBinding type, ClassFile parentClassFile, boolean createProblemType) { throw new UnsupportedOperationException(); @@ -265,11 +269,14 @@ public void recordInnerClasses(TypeBinding binding) { throw new UnsupportedOperationException(); } - @Override public void reset(SourceTypeBinding typeBinding) { throw new UnsupportedOperationException(); } + public void reset(SourceTypeBinding typeBinding, CompilerOptions options) { + throw new UnsupportedOperationException(); + } + @Override public void setForMethodInfos() { throw new UnsupportedOperationException(); diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/GroovyProposalTypeSearchRequestor.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/GroovyProposalTypeSearchRequestor.java index e51c450142..cc0413313c 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/GroovyProposalTypeSearchRequestor.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/GroovyProposalTypeSearchRequestor.java @@ -57,7 +57,6 @@ import org.eclipse.jdt.internal.codeassist.CompletionEngine; import org.eclipse.jdt.internal.codeassist.ISearchRequestor; import org.eclipse.jdt.internal.codeassist.RelevanceConstants; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.lookup.ImportBinding; import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; @@ -156,6 +155,9 @@ public GroovyProposalTypeSearchRequestor(ContentAssistContext context, } } + public void acceptModule(char[] moduleName) { + } + public void acceptPackage(char[] packageName) { checkCancel(); @@ -179,7 +181,7 @@ public void acceptConstructor(int modifiers, char[] simpleTypeName, checkCancel(); // do not propose enum constructors - if ((typeModifiers & ClassFileConstants.AccEnum) != 0) + if (Flags.isEnum(typeModifiers)) return; if (TypeFilter.isFiltered(packageName, simpleTypeName)) { @@ -470,7 +472,7 @@ List processAcceptedConstructors(Set usedParams, JD AcceptedCtor acceptedConstructor = (AcceptedCtor) this.acceptedConstructors.elementAt(i); final int typeModifiers = acceptedConstructor.typeModifiers; - if (isInterfaceAnnotationAbstractOrEnum(typeModifiers)) { + if (Flags.isInterface(typeModifiers) || Flags.isAnnotation(typeModifiers) || Flags.isEnum(typeModifiers)) { continue; } @@ -535,10 +537,6 @@ List processAcceptedConstructors(Set usedParams, JD return proposals; } - private boolean isInterfaceAnnotationAbstractOrEnum(int typeModifiers) { - return (typeModifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation)) != 0; - } - private ICompletionProposal proposeConstructor(char[] simpleTypeName, int parameterCount, char[] signature, char[][] parameterTypes, char[][] parameterNames, int modifiers, char[] packageName, diff --git a/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/builder/GroovyNameLookup.java b/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/builder/GroovyNameLookup.java index 9853fbe34c..88d61e6775 100644 --- a/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/builder/GroovyNameLookup.java +++ b/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/builder/GroovyNameLookup.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,9 +34,6 @@ import org.eclipse.jdt.internal.core.util.Util; /** - * @author Andrew Eisenberg - * @created Aug 18, 2009 - * * A NameLookup for Groovy classes to help look for non-tope level types and member types */ public class GroovyNameLookup extends NameLookup { @@ -47,7 +44,7 @@ public GroovyNameLookup(NameLookup other) { this.packageFragmentRoots = (IPackageFragmentRoot[]) ReflectionUtils.getPrivateField(NameLookup.class, "packageFragmentRoots", other); this.packageFragments = (HashtableOfArrayToObject) ReflectionUtils.getPrivateField(NameLookup.class, "packageFragments", other); this.typesInWorkingCopies = (HashMap) ReflectionUtils.getPrivateField(NameLookup.class, "typesInWorkingCopies", other); - this.rootToResolvedEntries = (Map) ReflectionUtils.getPrivateField(NameLookup.class, "rootToResolvedEntries", other); + this.rootToResolvedEntries = (Map/**/) ReflectionUtils.getPrivateField(NameLookup.class, "rootToResolvedEntries", other); } public GroovyNameLookup(IPackageFragmentRoot[] packageFragmentRoots, HashtableOfArrayToObject packageFragments, ICompilationUnit[] workingCopies, Map rootToResolvedEntries) { diff --git a/jdt-patch/e47/Feature-org.codehaus.groovy.jdt.patch/feature.xml b/jdt-patch/e47/Feature-org.codehaus.groovy.jdt.patch/feature.xml index 3454c53a49..a4ce609f85 100644 --- a/jdt-patch/e47/Feature-org.codehaus.groovy.jdt.patch/feature.xml +++ b/jdt-patch/e47/Feature-org.codehaus.groovy.jdt.patch/feature.xml @@ -19,7 +19,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdt-patch/e47/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/jdt-patch/e47/org.eclipse.jdt.core/META-INF/MANIFEST.MF index a58dc31b23..f3b41e333b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/META-INF/MANIFEST.MF +++ b/jdt-patch/e47/org.eclipse.jdt.core/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Main-Class: org.eclipse.jdt.internal.compiler.batch.Main Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true -Bundle-Version: 3.13.0.qualifier +Bundle-Version: 3.13.50.qualifier Bundle-Activator: org.eclipse.jdt.core.JavaCore Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -20,6 +20,7 @@ Export-Package: org.codehaus.jdt.groovy.integration, org.eclipse.jdt.core.jdom, org.eclipse.jdt.core.search, org.eclipse.jdt.core.util, + org.eclipse.jdt.core.provisional;x-friends:="org.eclipse.jdt.ui", org.eclipse.jdt.internal.codeassist;x-internal:=true, org.eclipse.jdt.internal.codeassist.complete;x-internal:=true, org.eclipse.jdt.internal.codeassist.impl;x-internal:=true, diff --git a/jdt-patch/e47/org.eclipse.jdt.core/about.html b/jdt-patch/e47/org.eclipse.jdt.core/about.html index c5eab079c1..e2de55aa2f 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/about.html +++ b/jdt-patch/e47/org.eclipse.jdt.core/about.html @@ -8,7 +8,7 @@

About This Content

-

March 17, 2011

+

April 2, 2015

License

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java new file mode 100644 index 0000000000..18a7f96b23 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java @@ -0,0 +1,278 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.batch; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; +import org.eclipse.jdt.internal.compiler.ast.OpensStatement; +import org.eclipse.jdt.internal.compiler.ast.RequiresStatement; +import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.ast.UsesStatement; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModulePathEntry; +import org.eclipse.jdt.internal.compiler.env.ModuleReferenceImpl; +import org.eclipse.jdt.internal.compiler.env.PackageExportImpl; + +public class BasicModule implements IModule { + static class Service implements IModule.IService { + char[] provides; + char[][] with; + @Override + public char[] name() { + return this.provides; + } + + @Override + public char[][] with() { + return this.with; + } + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("provides"); //$NON-NLS-1$ + buffer.append(this.provides); + buffer.append(" with "); //$NON-NLS-1$ + buffer.append(this.with); + buffer.append(';'); + return buffer.toString(); + } + } + private static PackageExportImpl createPackageExport(ExportsStatement[] refs, int i) { + ExportsStatement ref = refs[i]; + PackageExportImpl exp = new PackageExportImpl(); + exp.pack = ref.pkgName; + ModuleReference[] imp = ref.targets; + if (imp != null) { + exp.exportedTo = new char[imp.length][]; + for(int j = 0; j < imp.length; j++) { + exp.exportedTo = imp[j].tokens; + } + } + return exp; + } + private static Service createService(TypeReference service, TypeReference[] with) { + Service ser = new Service(); + ser.provides = CharOperation.concatWith(service.getTypeName(), '.'); + ser.with = new char[with.length][]; + for (int i = 0; i < with.length; i++) { + ser.with[i] = CharOperation.concatWith(with[i].getTypeName(), '.'); + } + return ser; + } + private static PackageExportImpl createPackageOpen(OpensStatement ref) { + PackageExportImpl exp = new PackageExportImpl(); + exp.pack = ref.pkgName; + ModuleReference[] imp = ref.targets; + if (imp != null) { + exp.exportedTo = new char[imp.length][]; + for(int j = 0; j < imp.length; j++) { + exp.exportedTo = imp[j].tokens; + } + } + return exp; + } + + boolean isAutomodule; + private boolean isOpen = false; + char[] name; + IModule.IModuleReference[] requires; + IModule.IPackageExport[] exports; + char[][] uses; + Service[] provides; + IModule.IPackageExport[] opens; + public BasicModule(ModuleDeclaration descriptor, IModulePathEntry root) { + this.name = descriptor.moduleName; + if (descriptor.requiresCount > 0) { + RequiresStatement[] refs = descriptor.requires; + this.requires = new ModuleReferenceImpl[refs.length]; + for (int i = 0; i < refs.length; i++) { + ModuleReferenceImpl ref = new ModuleReferenceImpl(); + ref.name = CharOperation.concatWith(refs[i].module.tokens, '.'); + ref.modifiers = refs[i].modifiers; + this.requires[i] = ref; + } + } else { + this.requires = new ModuleReferenceImpl[0]; + } + if (descriptor.exportsCount > 0) { + ExportsStatement[] refs = descriptor.exports; + this.exports = new PackageExportImpl[refs.length]; + for (int i = 0; i < refs.length; i++) { + PackageExportImpl exp = createPackageExport(refs, i); + this.exports[i] = exp; + } + } else { + this.exports = new PackageExportImpl[0]; + } + if (descriptor.usesCount > 0) { + UsesStatement[] u = descriptor.uses; + this.uses = new char[u.length][]; + for(int i = 0; i < u.length; i++) { + this.uses[i] = CharOperation.concatWith(u[i].serviceInterface.getTypeName(), '.'); + } + } + if (descriptor.servicesCount > 0) { + ProvidesStatement[] services = descriptor.services; + this.provides = new Service[descriptor.servicesCount]; + for (int i = 0; i < descriptor.servicesCount; i++) { + this.provides[i] = createService(services[i].serviceInterface, services[i].implementations); + } + } + if (descriptor.opensCount > 0) { + OpensStatement[] refs = descriptor.opens; + this.opens = new PackageExportImpl[refs.length]; + for (int i = 0; i < refs.length; i++) { + PackageExportImpl exp = createPackageOpen(refs[i]); + this.opens[i] = exp; + } + } else { + this.opens = new PackageExportImpl[0]; + } + this.isAutomodule = false; // Just to be explicit + this.isOpen = descriptor.isOpen(); + } + public BasicModule(char[] name, boolean isAuto) { + this.name = name; + this.exports = IModule.NO_EXPORTS; + this.requires = IModule.NO_MODULE_REFS; + this.isAutomodule = isAuto; + } + @Override + public char[] name() { + return this.name; + } + @Override + public IModule.IModuleReference[] requires() { + return this.requires; + } + @Override + public IModule.IPackageExport[] exports() { + return this.exports; + } + @Override + public char[][] uses() { + return this.uses; + } + @Override + public IService[] provides() { + return this.provides; + } + @Override + public IModule.IPackageExport[] opens() { + return this.opens; + } + @Override + public boolean isAutomatic() { + return this.isAutomodule; + } + @Override + public boolean isOpen() { + return this.isOpen; + } + public void addReads(char[] modName) { + Predicate shouldAdd = m -> { + return Stream.of(this.requires).map(ref -> ref.name()).noneMatch(n -> CharOperation.equals(modName, n)); + }; + if (shouldAdd.test(modName)) { + int len = this.requires.length; + this.requires = Arrays.copyOf(this.requires, len + 1); + ModuleReferenceImpl info = new ModuleReferenceImpl(); + info.name = modName; + this.requires[len] = info; + } + } + public void addExports(IModule.IPackageExport[] toAdd) { + Predicate shouldAdd = m -> { + return Stream.of(this.exports).map(ref -> ((PackageExportImpl) ref).pack).noneMatch(n -> CharOperation.equals(m, n)); + }; + Collection merged = Stream.concat(Stream.of(this.exports), Stream.of(toAdd) + .filter(e -> shouldAdd.test(e.name())) + .map(e -> { + PackageExportImpl exp = new PackageExportImpl(); + exp.pack = ((PackageExportImpl )e).name(); + exp.exportedTo = ((PackageExportImpl )e).targets(); + return exp; + })) + .collect( + ArrayList::new, + ArrayList::add, + ArrayList::addAll); + this.exports = merged.toArray(new PackageExportImpl[merged.size()]); + } + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof IModule)) + return false; + IModule mod = (IModule) o; + if (!CharOperation.equals(this.name, mod.name())) + return false; + return Arrays.equals(this.requires, mod.requires()); + } + @Override + public int hashCode() { + int result = 17; + int c = this.name.hashCode(); + result = 31 * result + c; + c = Arrays.hashCode(this.requires); + result = 31 * result + c; + return result; + } + public String toString() { + StringBuffer buffer = new StringBuffer(getClass().getName()); + toStringContent(buffer); + return buffer.toString(); + } + protected void toStringContent(StringBuffer buffer) { + buffer.append("\nmodule "); //$NON-NLS-1$ + buffer.append(this.name).append(' '); + buffer.append('{').append('\n'); + if (this.requires != null) { + for(int i = 0; i < this.requires.length; i++) { + buffer.append("\trequires "); //$NON-NLS-1$ + if (this.requires[i].isTransitive()) { + buffer.append(" public "); //$NON-NLS-1$ + } + buffer.append(this.requires[i].name()); + buffer.append(';').append('\n'); + } + } + if (this.exports != null) { + buffer.append('\n'); + for(int i = 0; i < this.exports.length; i++) { + buffer.append("\texports "); //$NON-NLS-1$ + buffer.append(this.exports[i].toString()); + } + } + if (this.uses != null) { + buffer.append('\n'); + for (char[] cs : this.uses) { + buffer.append(cs); + buffer.append(';').append('\n'); + } + } + if (this.provides != null) { + buffer.append('\n'); + for(Service ser : this.provides) { + buffer.append(ser.toString()); + } + } + buffer.append('\n').append('}').toString(); + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java index 0ff1a5be64..7335a6bf3a 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -23,6 +23,7 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; @@ -38,6 +39,9 @@ import java.util.Hashtable; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; @SuppressWarnings({"rawtypes", "unchecked"}) public class ClasspathDirectory extends ClasspathLocation { @@ -108,17 +112,15 @@ boolean doesFileExist(String fileName, String qualifiedPackageName) { public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) { return null; } -public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) { - return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false); -} -public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) { - if (!isPackage(qualifiedPackageName)) return null; // most common case - +private NameEnvironmentAnswer findClassInternal(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + if (!isPackage(qualifiedPackageName, null)) return null; // most common case TODO(SHMOD): use module name from this.module? String fileName = new String(typeName); boolean binaryExists = ((this.mode & BINARY) != 0) && doesFileExist(fileName + SUFFIX_STRING_class, qualifiedPackageName); boolean sourceExists = ((this.mode & SOURCE) != 0) && doesFileExist(fileName + SUFFIX_STRING_java, qualifiedPackageName); if (sourceExists && !asBinaryOnly) { String fullSourcePath = this.path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java; + CompilationUnit unit = new CompilationUnit(null, fullSourcePath, this.encoding, this.destinationPath); + unit.module = this.module == null ? null : this.module.name(); if (!binaryExists) return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding, this.destinationPath), @@ -141,10 +143,13 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN if (!CharOperation.equals(reader.getName(), typeSearched.toCharArray())) { reader = null; } - if (reader != null) + if (reader != null) { + char[] modName = reader.moduleName != null ? reader.moduleName : this.module != null ? this.module.name() : null; return new NameEnvironmentAnswer( reader, - fetchAccessRestriction(qualifiedBinaryFileName)); + fetchAccessRestriction(qualifiedBinaryFileName), + modName); + } } catch (IOException e) { // treat as if file is missing } catch (ClassFormatException e) { @@ -160,7 +165,8 @@ public NameEnvironmentAnswer findSecondaryInClass(char[] typeName, String qualif } String typeNameString = new String(typeName); - boolean prereqs = this.options != null && isPackage(qualifiedPackageName) && ((this.mode & SOURCE) != 0) && doesFileExist(typeNameString + SUFFIX_STRING_java, qualifiedPackageName); + String moduleName = this.module != null ? String.valueOf(this.module.name()) : null; // TODO(SHMOD): test for ModuleBinding.ANY & UNNAMED + boolean prereqs = this.options != null && isPackage(qualifiedPackageName, moduleName) && ((this.mode & SOURCE) != 0) && doesFileExist(typeNameString + SUFFIX_STRING_java, qualifiedPackageName); return prereqs ? null : findSourceSecondaryType(typeNameString, qualifiedPackageName, qualifiedBinaryFileName); /* only secondary types */ } @@ -173,12 +179,20 @@ public boolean hasAnnotationFileFor(String qualifiedTypeName) { } return false; } +public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName) { + return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false); +} +public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + if (File.separatorChar == '/') + return findClassInternal(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly); - + return findClassInternal(typeName, qualifiedPackageName.replace('/', File.separatorChar), + qualifiedBinaryFileName.replace('/', File.separatorChar), asBinaryOnly); +} /** * Add all the secondary types in the package */ -private Hashtable getPackageTypes(String qualifiedPackageName) { +private Hashtable getSecondaryTypes(String qualifiedPackageName) { Hashtable packageEntry = new Hashtable<>(); String[] dirList = (String[]) this.directoryCache.get(qualifiedPackageName); @@ -197,7 +211,7 @@ private Hashtable getPackageTypes(String qualifiedPackageName) { if (s == null) continue; if (!(s.endsWith(SUFFIX_STRING_java) || s.endsWith(SUFFIX_STRING_JAVA))) continue; CompilationUnit cu = new CompilationUnit(null, s, this.encoding, this.destinationPath); - CompilationResult compilationResult = new CompilationResult(cu.getContents(), 1, 1, 10); + CompilationResult compilationResult = new CompilationResult(s.toCharArray(), 1, 1, 10); ProblemReporter problemReporter = new ProblemReporter( DefaultErrorHandlingPolicies.proceedWithAllProblems(), @@ -223,7 +237,7 @@ private NameEnvironmentAnswer findSourceSecondaryType(String typeName, String qu if (this.packageSecondaryTypes == null) this.packageSecondaryTypes = new Hashtable<>(); Hashtable packageEntry = this.packageSecondaryTypes.get(qualifiedPackageName); if (packageEntry == null) { - packageEntry = getPackageTypes(qualifiedPackageName); + packageEntry = getSecondaryTypes(qualifiedPackageName); this.packageSecondaryTypes.put(qualifiedPackageName, packageEntry); } String fileName = packageEntry.get(typeName); @@ -233,8 +247,8 @@ private NameEnvironmentAnswer findSourceSecondaryType(String typeName, String qu } -public char[][][] findTypeNames(String qualifiedPackageName) { - if (!isPackage(qualifiedPackageName)) { +public char[][][] findTypeNames(String qualifiedPackageName, String moduleName) { + if (!isPackage(qualifiedPackageName, moduleName)) { return null; // most common case } File dir = new File(this.path + qualifiedPackageName); @@ -251,20 +265,60 @@ public boolean accept(File directory1, String name) { if (listFiles == null || (length = listFiles.length) == 0) { return null; } - char[][][] result = new char[length][][]; + Set secondary = getSecondaryTypes(qualifiedPackageName).keySet(); + char[][][] result = new char[length + secondary.size()][][]; char[][] packageName = CharOperation.splitOn(File.separatorChar, qualifiedPackageName.toCharArray()); for (int i = 0; i < length; i++) { String fileName = listFiles[i]; int indexOfLastDot = fileName.indexOf('.'); - result[i] = CharOperation.arrayConcat(packageName, fileName.substring(0, indexOfLastDot).toCharArray()); + String typeName = indexOfLastDot > 0 ? fileName.substring(0, indexOfLastDot) : fileName; + result[i] = CharOperation.arrayConcat(packageName, typeName.toCharArray()); + } + if (secondary.size() > 0) { + int idx = length; + for (String type : secondary) { + result[idx++] = CharOperation.arrayConcat(packageName, type.toCharArray()); + } } return result; } public void initialize() throws IOException { // nothing to do } -public boolean isPackage(String qualifiedPackageName) { - return directoryList(qualifiedPackageName) != null; +public char[][] getModulesDeclaringPackage(String qualifiedPackageName, /*@Nullable*/String moduleName) { + String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar); + return singletonModuleNameIf(directoryList(qp2) != null); +} +@Override +public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) { + String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar); + String[] dirList = directoryList(qp2); + if (dirList != null) { + for (String entry : dirList) { + String entryLC = entry.toLowerCase(); + if (entryLC.endsWith(SUFFIX_STRING_java) || entryLC.endsWith(SUFFIX_STRING_class)) + return true; + } + } + return false; +} +public boolean hasCUDeclaringPackage(String qualifiedPackageName, Function pkgNameExtractor) { + String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar); + return Stream.of(directoryList(qp2)).anyMatch(entry -> { + String entryLC = entry.toLowerCase(); + boolean hasDeclaration = false; + String fullPath = this.path + qp2 + "/" + entry; //$NON-NLS-1$ + String pkgName = null; + if (entryLC.endsWith(SUFFIX_STRING_class)) { + return true; + } else if (entryLC.endsWith(SUFFIX_STRING_java)) { + CompilationUnit cu = new CompilationUnit(null, fullPath, this.encoding); + pkgName = pkgNameExtractor.apply(cu); + } + if (pkgName != null && pkgName.equals(qp2.replace(File.separatorChar, '.'))) + hasDeclaration = true; + return hasDeclaration; + }); } public void reset() { this.directoryCache = new Hashtable(11); @@ -287,4 +341,10 @@ public String getPath() { public int getMode() { return this.mode; } +public IModule getModule() { + if (this.isAutoModule && this.module == null) { + return this.module = IModule.createAutomatic(this.path, false, null/*no manifest*/); + } + return this.module; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java index ea7baa5514..93b4610251 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,20 +18,25 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Enumeration; -import java.util.Hashtable; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; +import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator; import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; -import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus; import org.eclipse.jdt.internal.compiler.util.ManifestAnalyzer; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; @@ -44,7 +49,7 @@ public class ClasspathJar extends ClasspathLocation { protected ZipFile zipFile; protected ZipFile annotationZipFile; protected boolean closeZipFileAtEnd; -protected Hashtable packageCache; +private Set packageCache; protected List annotationPaths; public ClasspathJar(File file, boolean closeZipFileAtEnd, @@ -54,14 +59,14 @@ public ClasspathJar(File file, boolean closeZipFileAtEnd, this.closeZipFileAtEnd = closeZipFileAtEnd; } -public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) { +public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) { // expected to be called once only - if multiple calls desired, consider // using a cache InputStream inputStream = null; try { initialize(); - ArrayList result = new ArrayList(); - ZipEntry manifest = this.zipFile.getEntry("META-INF/MANIFEST.MF"); //$NON-NLS-1$ + ArrayList result = new ArrayList<>(); + ZipEntry manifest = this.zipFile.getEntry(TypeConstants.META_INF_MANIFEST_MF); if (manifest != null) { // non-null implies regular file inputStream = this.zipFile.getInputStream(manifest); ManifestAnalyzer analyzer = new ManifestAnalyzer(); @@ -85,7 +90,9 @@ public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemRe } } return result; - } catch (IOException e) { + } catch (IOException | IllegalArgumentException e) { + // JRE 9 could throw an IAE if the path is incorrect. We are to ignore such + // linked jars return null; } finally { if (inputStream != null) { @@ -97,16 +104,24 @@ public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemRe } } } -public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) { - return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false); +public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName) { + return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false); } -public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) { - if (!isPackage(qualifiedPackageName)) +public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case try { IBinaryType reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName); if (reader != null) { + char[] modName = this.module == null ? null : this.module.name(); + if (reader instanceof ClassFileReader) { + ClassFileReader classReader = (ClassFileReader) reader; + if (classReader.moduleName == null) + classReader.moduleName = modName; + else + modName = classReader.moduleName; + } searchPaths: if (this.annotationPaths != null) { String qualifiedClassName = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length()-SuffixConstants.EXTENSION_CLASS.length()-1); @@ -127,7 +142,7 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN // location is configured for external annotations, but no .eea found, decorate in order to answer NO_EEA_FILE: reader = new ExternalAnnotationDecorator(reader, null); } - return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName)); + return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), modName); } } catch(ClassFormatException e) { // treat as if class file is missing @@ -140,17 +155,17 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN public boolean hasAnnotationFileFor(String qualifiedTypeName) { return this.zipFile.getEntry(qualifiedTypeName+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX) != null; } -public char[][][] findTypeNames(String qualifiedPackageName) { - if (!isPackage(qualifiedPackageName)) +public char[][][] findTypeNames(final String qualifiedPackageName, String moduleName) { + if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case - - ArrayList answers = new ArrayList(); + final char[] packageArray = qualifiedPackageName.toCharArray(); + final ArrayList answers = new ArrayList(); nextEntry : for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { String fileName = ((ZipEntry) e.nextElement()).getName(); // add the package name & all of its parent packages int last = fileName.lastIndexOf('/'); - while (last > 0) { + if (last > 0) { // extract the package name String packageName = fileName.substring(0, last); if (!qualifiedPackageName.equals(packageName)) @@ -158,7 +173,6 @@ public char[][][] findTypeNames(String qualifiedPackageName) { int indexOfDot = fileName.lastIndexOf('.'); if (indexOfDot != -1) { String typeName = fileName.substring(last + 1, indexOfDot); - char[] packageArray = packageName.toCharArray(); answers.add( CharOperation.arrayConcat( CharOperation.splitOn('/', packageArray), @@ -170,37 +184,72 @@ public char[][][] findTypeNames(String qualifiedPackageName) { if (size != 0) { char[][][] result = new char[size][][]; answers.toArray(result); - return null; + return result; } return null; } + public void initialize() throws IOException { if (this.zipFile == null) { this.zipFile = new ZipFile(this.file); } } -public boolean isPackage(String qualifiedPackageName) { +void acceptModule(ClassFileReader reader) { + if (reader != null) { + acceptModule(reader.getModuleDeclaration()); + } +} +void acceptModule(byte[] content) { + if (content == null) + return; + ClassFileReader reader = null; + try { + reader = new ClassFileReader(content, IModule.MODULE_INFO_CLASS.toCharArray()); + } catch (ClassFormatException e) { + e.printStackTrace(); + } + if (reader != null && reader.getModuleDeclaration() != null) { + acceptModule(reader); + } +} +protected void addToPackageCache(String fileName, boolean endsWithSep) { + int last = endsWithSep ? fileName.length() : fileName.lastIndexOf('/'); + while (last > 0) { + // extract the package name + String packageName = fileName.substring(0, last); + if (this.packageCache.contains(packageName)) + return; + this.packageCache.add(packageName); + last = packageName.lastIndexOf('/'); + } +} +public synchronized char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) { if (this.packageCache != null) - return this.packageCache.containsKey(qualifiedPackageName); - - this.packageCache = new Hashtable(41); - this.packageCache.put(Util.EMPTY_STRING, Util.EMPTY_STRING); + return singletonModuleNameIf(this.packageCache.contains(qualifiedPackageName)); - nextEntry : for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { + this.packageCache = new HashSet<>(41); + this.packageCache.add(Util.EMPTY_STRING); + + for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { String fileName = ((ZipEntry) e.nextElement()).getName(); - - // add the package name & all of its parent packages - int last = fileName.lastIndexOf('/'); - while (last > 0) { - // extract the package name - String packageName = fileName.substring(0, last); - if (this.packageCache.containsKey(packageName)) - continue nextEntry; - this.packageCache.put(packageName, packageName); - last = packageName.lastIndexOf('/'); - } + addToPackageCache(fileName, false); } - return this.packageCache.containsKey(qualifiedPackageName); + return singletonModuleNameIf(this.packageCache.contains(qualifiedPackageName)); +} +@Override +public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) { + qualifiedPackageName += '/'; + for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { + String fileName = e.nextElement().getName(); + if (fileName.startsWith(qualifiedPackageName) && fileName.length() > qualifiedPackageName.length()) { + String tail = fileName.substring(qualifiedPackageName.length()); + if (tail.indexOf('/') != -1) + continue; + if (tail.toLowerCase().endsWith(SUFFIX_STRING_class)) + return true; + } + } + return false; } public void reset() { if (this.closeZipFileAtEnd) { @@ -222,6 +271,7 @@ public void reset() { } } this.packageCache = null; + this.annotationPaths = null; } public String toString() { return "Classpath for jar file " + this.file.getPath(); //$NON-NLS-1$ @@ -251,4 +301,20 @@ public String getPath() { public int getMode() { return BINARY; } + +public IModule getModule() { + if (this.isAutoModule && this.module == null) { + Manifest manifest = null; + try { + initialize(); + ZipEntry entry = this.zipFile.getEntry(TypeConstants.META_INF_MANIFEST_MF); + if (entry != null) + manifest = new Manifest(this.zipFile.getInputStream(entry)); + } catch (IOException e) { + // no usable manifest + } + return this.module = IModule.createAutomatic(this.file.getName(), true, manifest); + } + return this.module; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java new file mode 100644 index 0000000000..be2e520d8e --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java @@ -0,0 +1,361 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.batch; + +import java.io.File; +import java.io.IOException; + +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.zip.ZipFile; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator; +import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; +import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IMultiModuleEntry; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; +import org.eclipse.jdt.internal.compiler.util.SuffixConstants; + +@SuppressWarnings({"rawtypes", "unchecked"}) +public class ClasspathJrt extends ClasspathLocation implements IMultiModuleEntry { + public File file; + protected ZipFile annotationZipFile; + protected boolean closeZipFileAtEnd; + private static HashMap> ModulesCache = new HashMap<>(); + public HashMap modulePathMap; + //private Set packageCache; + protected List annotationPaths; + + public ClasspathJrt(File file, boolean closeZipFileAtEnd, + AccessRuleSet accessRuleSet, String destinationPath) { + super(accessRuleSet, destinationPath); + this.file = file; + this.closeZipFileAtEnd = closeZipFileAtEnd; + this.modulePathMap = new HashMap<>(); + } + + public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) { + return null; + } + public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) { + List modules = JRTUtil.getModulesDeclaringPackage(this.file, qualifiedPackageName, moduleName); + return CharOperation.toCharArrays(modules); + } + @Override + public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) { + return JRTUtil.hasCompilationUnit(this.file, qualifiedPackageName, moduleName); + } + public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName) { + return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false); + } + public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + if (!isPackage(qualifiedPackageName, moduleName)) + return null; // most common case + + try { + IBinaryType reader = ClassFileReader.readFromModule(this.file, moduleName, qualifiedBinaryFileName); + + if (reader != null) { + searchPaths: + if (this.annotationPaths != null) { + String qualifiedClassName = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length()-SuffixConstants.EXTENSION_CLASS.length()-1); + for (String annotationPath : this.annotationPaths) { + try { + if (this.annotationZipFile == null) { + this.annotationZipFile = ExternalAnnotationDecorator.getAnnotationZipFile(annotationPath, null); + } + reader = ExternalAnnotationDecorator.create(reader, annotationPath, qualifiedClassName, this.annotationZipFile); + + if (reader.getExternalAnnotationStatus() == ExternalAnnotationStatus.TYPE_IS_ANNOTATED) { + break searchPaths; + } + } catch (IOException e) { + // don't let error on annotations fail class reading + } + } + // location is configured for external annotations, but no .eea found, decorate in order to answer NO_EEA_FILE: + reader = new ExternalAnnotationDecorator(reader, null); + } + char[] answerModuleName = reader.getModule(); + if (answerModuleName == null && moduleName != null) + answerModuleName = moduleName.toCharArray(); + return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), answerModuleName); + } + } catch(ClassFormatException e) { + // treat as if class file is missing + } catch (IOException e) { + // treat as if class file is missing + } + return null; + } + @Override + public boolean hasAnnotationFileFor(String qualifiedTypeName) { + return false; // TODO(SHMOD): implement + } + public char[][][] findTypeNames(final String qualifiedPackageName, final String moduleName) { + if (!isPackage(qualifiedPackageName, moduleName)) + return null; // most common case + final char[] packageArray = qualifiedPackageName.toCharArray(); + final ArrayList answers = new ArrayList(); + + try { + JRTUtil.walkModuleImage(this.file, new JRTUtil.JrtFileVisitor() { + + @Override + public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path modPath, BasicFileAttributes attrs) throws IOException { + if (qualifiedPackageName.startsWith(dir.toString())) { + return FileVisitResult.CONTINUE; + } + return FileVisitResult.SKIP_SUBTREE; + } + + @Override + public FileVisitResult visitFile(java.nio.file.Path dir, java.nio.file.Path modPath, BasicFileAttributes attrs) throws IOException { + Path parent = dir.getParent(); + if (parent == null) + return FileVisitResult.CONTINUE; + if (!parent.toString().equals(qualifiedPackageName)) { + return FileVisitResult.CONTINUE; + } + String fileName = dir.getName(dir.getNameCount() - 1).toString(); + // The path already excludes the folders and all the '/', hence the -1 for last index of '/' + addTypeName(answers, fileName, -1, packageArray); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitModule(java.nio.file.Path modPath) throws IOException { + if (moduleName == null) + return FileVisitResult.CONTINUE; + if (!moduleName.equals(modPath.toString())) { + return FileVisitResult.SKIP_SUBTREE; + } + return FileVisitResult.CONTINUE; + } + + }, JRTUtil.NOTIFY_ALL); + } catch (IOException e) { + // Ignore and move on + } + + int size = answers.size(); + if (size != 0) { + char[][][] result = new char[size][][]; + answers.toArray(result); + return result; + } + return null; + } + + protected void addTypeName(final ArrayList answers, String fileName, int last, char[] packageName) { + int indexOfDot = fileName.lastIndexOf('.'); + if (indexOfDot != -1) { + String typeName = fileName.substring(last + 1, indexOfDot); + answers.add( + CharOperation.arrayConcat( + CharOperation.splitOn('/', packageName), + typeName.toCharArray())); + } + } + public void initialize() throws IOException { + loadModules(); + } +// public void acceptModule(IModuleDeclaration mod) { +// if (this.isJrt) +// return; +// this.module = mod; +// } + public void loadModules() { + Map cache = ModulesCache.get(this.file.getPath()); + + if (cache == null) { + try { + org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(this.file, + new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor() { + + @Override + public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs) + throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path f, Path mod, BasicFileAttributes attrs) + throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitModule(Path mod) throws IOException { + try { + ClasspathJrt.this.acceptModule(JRTUtil.getClassfileContent(ClasspathJrt.this.file, IModule.MODULE_INFO_CLASS, mod.toString())); + ClasspathJrt.this.modulePathMap.put(mod.getFileName().toString(), mod); + } catch (ClassFormatException e) { + e.printStackTrace(); + } + return FileVisitResult.SKIP_SUBTREE; + } + }, JRTUtil.NOTIFY_MODULES); + } catch (IOException e) { + // TODO: Java 9 Should report better + } + } + } + void acceptModule(ClassFileReader reader) { + if (reader != null) { + IModule moduleDecl = reader.getModuleDeclaration(); + if (moduleDecl != null) { + Map cache = ModulesCache.get(this.file.getPath()); + if (cache == null) { + ModulesCache.put(this.file.getPath(), cache = new HashMap()); + } + cache.put(String.valueOf(moduleDecl.name()), moduleDecl); + } + } + + } + void acceptModule(byte[] content) { + if (content == null) + return; + ClassFileReader reader = null; + try { + reader = new ClassFileReader(content, IModule.MODULE_INFO_CLASS.toCharArray()); + } catch (ClassFormatException e) { + e.printStackTrace(); + } + if (reader != null) { + acceptModule(reader); + } + } + + @Override + public Collection getModuleNames(Collection limitModule) { + return ModulesCache.values().stream() + .flatMap(entryMap -> entryMap.keySet().stream()) + .filter(m -> limitModule == null || limitModule.contains(m)) // TODO: implement algo from JEP 261 (root selection & transitive closure) + .collect(Collectors.toList()); + } +// protected void addToPackageCache(String fileName, boolean endsWithSep) { +// int last = endsWithSep ? fileName.length() : fileName.lastIndexOf('/'); +// while (last > 0) { +// // extract the package name +// String packageName = fileName.substring(0, last); +// if (this.packageCache.contains(packageName)) +// return; +// this.packageCache.add(packageName); +// last = packageName.lastIndexOf('/'); +// } +// } +// public synchronized boolean isPackage(String qualifiedPackageName) { +// if (this.packageCache != null) +// return this.packageCache.contains(qualifiedPackageName); +// +// this.packageCache = new HashSet<>(41); +// this.packageCache.add(Util.EMPTY_STRING); +// +// try { +// JRTUtil.walkModuleImage(this.file, new JRTUtil.JrtFileVisitor() { +// +// @Override +// public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException { +// addToPackageCache(dir.toString(), true); +// return FileVisitResult.CONTINUE; +// } +// +// @Override +// public FileVisitResult visitFile(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException { +// return FileVisitResult.CONTINUE; +// } +// +// @Override +// public FileVisitResult visitModule(java.nio.file.Path mod) throws IOException { +// return FileVisitResult.CONTINUE; +// } +// +// }, JRTUtil.NOTIFY_PACKAGES); +// } catch (IOException e) { +// // Ignore and move on +// } +// return this.packageCache.contains(qualifiedPackageName); +// } + public void reset() { + if (this.closeZipFileAtEnd) { + if (this.annotationZipFile != null) { + try { + this.annotationZipFile.close(); + } catch(IOException e) { + // ignore + } + this.annotationZipFile = null; + } + } + if (this.annotationPaths != null) { + //this.packageCache = null; + this.annotationPaths = null; + } + } + public String toString() { + return "Classpath for JRT System " + this.file.getPath(); //$NON-NLS-1$ + } + public char[] normalizedPath() { + if (this.normalizedPath == null) { + String path2 = this.getPath(); + char[] rawName = path2.toCharArray(); + if (File.separatorChar == '\\') { + CharOperation.replace(rawName, '\\', '/'); + } + this.normalizedPath = CharOperation.subarray(rawName, 0, CharOperation.lastIndexOf('.', rawName)); + } + return this.normalizedPath; + } + public String getPath() { + if (this.path == null) { + try { + this.path = this.file.getCanonicalPath(); + } catch (IOException e) { + // in case of error, simply return the absolute path + this.path = this.file.getAbsolutePath(); + } + } + return this.path; + } + public int getMode() { + return BINARY; + } + @Override + public boolean hasModule() { + return true; + } + public IModule getModule(char[] moduleName) { + Map modules = ModulesCache.get(this.file.getPath()); + if (modules != null) { + return modules.get(String.valueOf(moduleName)); + } + return null; + } + @Override + public boolean servesModule(char[] moduleName) { + return getModule(moduleName) != null; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java index f0c5c076ec..4b2d5085c2 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,10 +11,14 @@ package org.eclipse.jdt.internal.compiler.batch; import java.io.File; +import java.util.Collection; +import java.util.Collections; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; public abstract class ClasspathLocation implements FileSystem.Classpath, @@ -26,6 +30,8 @@ public abstract class ClasspathLocation implements FileSystem.Classpath, String path; char[] normalizedPath; public AccessRuleSet accessRuleSet; + IModule module; + protected boolean isAutoModule; public String destinationPath; // destination path for compilation units that are reached through this @@ -100,4 +106,34 @@ public boolean equals(Object obj) { public String getPath() { return this.path; } + public String getDestinationPath() { + return this.destinationPath; + } + + public void acceptModule(IModule mod) { + this.module = mod; + this.isAutoModule = mod.isAutomatic(); + } + @Override + public boolean isAutomaticModule() { + return this.isAutoModule; + } + @Override + public Collection getModuleNames(Collection limitModules) { + if (this.module != null) + return Collections.singletonList(String.valueOf(this.module.name())); + return Collections.emptyList(); + } + + public boolean isPackage(String qualifiedPackageName, String moduleName) { + return getModulesDeclaringPackage(qualifiedPackageName, moduleName) != null; + } + + protected char[][] singletonModuleNameIf(boolean condition) { + if (!condition) + return null; + if (this.module != null) + return new char[][] { this.module.name() }; + return new char[][] { ModuleBinding.UNNAMED }; + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java index fc94aa189e..d28cc62bf8 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2010 IBM Corporation and others. + * Copyright (c) 2006, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -29,8 +29,8 @@ public ClasspathSourceJar(File file, boolean closeZipFileAtEnd, this.encoding = encoding; } - public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) { - if (!isPackage(qualifiedPackageName)) + public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case ZipEntry sourceEntry = this.zipFile.getEntry(qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java); @@ -45,12 +45,14 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN if (stream != null) stream.close(); } + CompilationUnit compilationUnit = new CompilationUnit( + contents, + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java, + this.encoding, + this.destinationPath); + compilationUnit.module = this.module == null ? null : this.module.name(); return new NameEnvironmentAnswer( - new CompilationUnit( - contents, - qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java, - this.encoding, - this.destinationPath), + compilationUnit, fetchAccessRestriction(qualifiedBinaryFileName)); } catch (IOException e) { // treat as if source file is missing @@ -58,9 +60,7 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN } return null; } - public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) { - return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false); - } + public int getMode() { return SOURCE; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java index 64d3d89879..da0ebf9ef8 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,9 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; import org.eclipse.jdt.internal.compiler.util.Util; @@ -24,6 +27,7 @@ public class CompilationUnit implements ICompilationUnit { public char[] mainTypeName; String encoding; public String destinationPath; + public char[] module; // a specific destination path for this compilation unit; coding is // aligned with Main.destinationPath: // == null: unspecified, use whatever value is set by the enclosing @@ -32,17 +36,21 @@ public class CompilationUnit implements ICompilationUnit { // else: use as the path of the directory into which class files must // be written. private boolean ignoreOptionalProblems; + private CompilationUnit modCU; + private ModuleBinding moduleBinding; public CompilationUnit(char[] contents, String fileName, String encoding) { this(contents, fileName, encoding, null); } public CompilationUnit(char[] contents, String fileName, String encoding, String destinationPath) { - this(contents, fileName, encoding, destinationPath, false); + this(contents, fileName, encoding, destinationPath, false, null); } public CompilationUnit(char[] contents, String fileName, String encoding, - String destinationPath, boolean ignoreOptionalProblems) { + String destinationPath, boolean ignoreOptionalProblems, String modName) { this.contents = contents; + if (modName != null) + this.module = modName.toCharArray(); char[] fileNameCharArray = fileName.toCharArray(); switch(File.separatorChar) { case '/' : @@ -98,4 +106,28 @@ public boolean ignoreOptionalProblems() { public String toString() { return "CompilationUnit[" + new String(this.fileName) + "]"; //$NON-NLS-2$ //$NON-NLS-1$ } +public void setModule(CompilationUnit compilationUnit) { + this.modCU = compilationUnit; +} +@Override +public char[] getModuleName() { + return this.module; +} +@Override +public ModuleBinding module(LookupEnvironment rootEnvironment) { + if (this.moduleBinding != null) + return this.moduleBinding; + if (this.modCU != null) + return this.moduleBinding = this.modCU.module(rootEnvironment); + if (CharOperation.endsWith(this.fileName, TypeConstants.MODULE_INFO_FILE_NAME)) { + this.moduleBinding = rootEnvironment.getModule(this.module); + if (this.moduleBinding == null) + throw new IllegalStateException("Module should be known"); //$NON-NLS-1$ + return this.moduleBinding; + } + return rootEnvironment.UnNamedModule; +} +public String getDestinationPath() { + return this.destinationPath; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java index f707fc0df4..65e6a4ca50 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,18 +12,26 @@ import java.io.File; import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.internal.compiler.env.IModule; -@SuppressWarnings({"rawtypes", "unchecked"}) public class FileFinder { +/** + * Although the file finder is meant to be generic for any file name patters, + * at the moment it is used only for *.java files. This method handles the + * module-info.java in a special way by always placing it as the first element + * of the resulting array. + */ public static String[] find(File f, String pattern) { - ArrayList files = new ArrayList(); + List files = new ArrayList<>(); find0(f, pattern, files); String[] result = new String[files.size()]; files.toArray(result); return result; } -private static void find0(File f, String pattern, ArrayList collector) { +private static void find0(File f, String pattern, List collector) { if (f.isDirectory()) { String[] files = f.list(); if (files == null) return; @@ -32,8 +40,15 @@ private static void find0(File f, String pattern, ArrayList collector) { if (current.isDirectory()) { find0(current, pattern, collector); } else { - if (current.getName().toUpperCase().endsWith(pattern)) { - collector.add(current.getAbsolutePath()); + String name = current.getName().toLowerCase(); + if (name.endsWith(pattern)) { + // NOTE: This handles only the lower case name. Check with the spec about + // Naming of the module descriptor before making this code code insensitive. + if (name.endsWith(IModule.MODULE_INFO_JAVA)) { + collector.add(0, current.getAbsolutePath()); + } else { + collector.add(current.getAbsolutePath()); + } } } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java index bc3e10de26..b8fc121004 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java @@ -15,29 +15,61 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; import java.util.zip.ZipFile; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; -import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.env.IModulePathEntry; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.parser.Parser; +import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; +import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdatesByKind; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.compiler.util.Util; -@SuppressWarnings({ "rawtypes", "unchecked" }) -public class FileSystem implements INameEnvironment, SuffixConstants { - public interface Classpath { - char[][][] findTypeNames(String qualifiedPackageName); - NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName); - NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly); - boolean isPackage(String qualifiedPackageName); +public class FileSystem implements IModuleAwareNameEnvironment, SuffixConstants { + + // Keep the type as ArrayList and not List as there are clients that are already written to expect ArrayList. + public static ArrayList EMPTY_CLASSPATH = new ArrayList<>(); + + /** + * A Classpath, even though an IModuleLocation, can represent a plain + * classpath location too. The FileSystem tells the Classpath whether to behave as a module or regular class + * path via {@link Classpath#acceptModule(IModule)}. + * + * Sub types of classpath are responsible for appropriate behavior based on this. + */ + public interface Classpath extends IModulePathEntry { + char[][][] findTypeNames(String qualifiedPackageName, String moduleName); + NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName); + NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly); + boolean isPackage(String qualifiedPackageName, /*@Nullable*/String moduleName); + default boolean hasModule() { return getModule() != null; } + default boolean hasCUDeclaringPackage(String qualifiedPackageName, Function pkgNameExtractor) { + return hasCompilationUnit(qualifiedPackageName, null); + } /** * Return a list of the jar file names defined in the Class-Path section * of the jar file manifest if any, null else. Only ClasspathJar (and @@ -47,7 +79,7 @@ public interface Classpath { * @return a list of the jar file names defined in the Class-Path * section of the jar file manifest if any */ - List fetchLinkedJars(ClasspathSectionProblemReporter problemReporter); + List fetchLinkedJars(ClasspathSectionProblemReporter problemReporter); /** * This method resets the environment. The resulting state is equivalent to * a new name environment without creating a new object. @@ -79,6 +111,14 @@ public interface Classpath { * @param qualifiedTypeName type name in qualified /-separated notation. */ boolean hasAnnotationFileFor(String qualifiedTypeName); + /** + * Accepts to represent a module location with the given module description. + * + * @param module + */ + public void acceptModule(IModule module); + public String getDestinationPath(); + Collection getModuleNames(Collection limitModules); } public interface ClasspathSectionProblemReporter { void invalidClasspathSection(String jarFilePath); @@ -98,11 +138,11 @@ public static class ClasspathNormalizer { * @param classpaths the given classpath entries * @return the normalized classpath entries */ - public static ArrayList normalize(ArrayList classpaths) { - ArrayList normalizedClasspath = new ArrayList(); - HashSet cache = new HashSet(); - for (Iterator iterator = classpaths.iterator(); iterator.hasNext(); ) { - FileSystem.Classpath classpath = (FileSystem.Classpath) iterator.next(); + public static ArrayList normalize(ArrayList classpaths) { + ArrayList normalizedClasspath = new ArrayList<>(); + HashSet cache = new HashSet<>(); + for (Iterator iterator = classpaths.iterator(); iterator.hasNext(); ) { + FileSystem.Classpath classpath = iterator.next(); if (!cache.contains(classpath)) { normalizedClasspath.add(classpath); cache.add(classpath); @@ -111,10 +151,19 @@ public static ArrayList normalize(ArrayList classpaths) { return normalizedClasspath; } } - + protected Classpath[] classpaths; - Set knownFileNames; + // Used only in single-module mode when the module descriptor is + // provided via command line. + protected IModule module; + Set knownFileNames; protected boolean annotationsFromClasspath; // should annotation files be read from the classpath (vs. explicit separate path)? + private static HashMap JRT_CLASSPATH_CACHE = null; + + Map moduleLocations = new HashMap<>(); + + /** Tasks resulting from --add-reads or --add-exports command line options. */ + Map moduleUpdates = new HashMap<>(); /* classPathNames is a collection is Strings representing the full path of each class path @@ -128,6 +177,8 @@ public FileSystem(String[] classpathNames, String[] initialFileNames, String enc Classpath classpath = getClasspath(classpathNames[i], encoding, null, null); try { classpath.initialize(); + for (String moduleName : classpath.getModuleNames(null)) // TODO limit-modules? + this.moduleLocations.put(moduleName, classpath); this.classpaths[counter++] = classpath; } catch (IOException e) { // ignore @@ -146,8 +197,11 @@ protected FileSystem(Classpath[] paths, String[] initialFileNames, boolean annot final Classpath classpath = paths[i]; try { classpath.initialize(); + for (String moduleName : classpath.getModuleNames(null)) // TODO limit-modules? + this.moduleLocations.put(moduleName, classpath); this.classpaths[counter++] = classpath; - } catch(IOException exception) { + } catch(IOException | IllegalArgumentException exception) { + // JRE 9 could throw an IAE if the linked JAR paths have invalid chars, such as ":" // ignore } } @@ -161,12 +215,15 @@ protected FileSystem(Classpath[] paths, String[] initialFileNames, boolean annot public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet) { return getClasspath(classpathName, encoding, false, accessRuleSet, null, null); } -public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet, Map options) { +public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet, Map options) { return getClasspath(classpathName, encoding, false, accessRuleSet, null, options); } +public static Classpath getJrtClasspath(String jdkHome, String encoding, AccessRuleSet accessRuleSet, Map options) { + return new ClasspathJrt(new File(convertPathSeparators(jdkHome)), true, accessRuleSet, null); +} public static Classpath getClasspath(String classpathName, String encoding, boolean isSourceOnly, AccessRuleSet accessRuleSet, - String destinationPath, Map options) { + String destinationPath, Map options) { Classpath result = null; File file = new File(convertPathSeparators(classpathName)); if (file.isDirectory()) { @@ -180,7 +237,8 @@ public static Classpath getClasspath(String classpathName, String encoding, convertPathSeparators(destinationPath), options); } } else { - if (Util.isPotentialZipArchive(classpathName)) { + int format = Util.archiveFormat(classpathName); + if (format == Util.ZIP_FILE) { if (isSourceOnly) { // source only mode result = new ClasspathSourceJar(file, true, accessRuleSet, @@ -190,18 +248,38 @@ public static Classpath getClasspath(String classpathName, String encoding, convertPathSeparators(destinationPath)); } else if (destinationPath == null) { // class file only mode - result = new ClasspathJar(file, true, accessRuleSet, null); + if (classpathName.endsWith(JRTUtil.JRT_FS_JAR)) { + if (JRT_CLASSPATH_CACHE == null) { + JRT_CLASSPATH_CACHE = new HashMap<>(); + } else { + result = JRT_CLASSPATH_CACHE.get(file); + } + if (result == null) { + result = new ClasspathJrt(file, true, accessRuleSet, null); + try { + result.initialize(); + } catch (IOException e) { + // Broken entry, but let clients have it anyway. + } + JRT_CLASSPATH_CACHE.put(file, result); + } + } else { + result = new ClasspathJar(file, true, accessRuleSet, null); + } } + } else if (format == Util.JMOD_FILE) { + // TODO Java 9: we need new type of classpath to handle Jmod files in batch compiler. } + } return result; } private void initializeKnownFileNames(String[] initialFileNames) { if (initialFileNames == null) { - this.knownFileNames = new HashSet(0); + this.knownFileNames = new HashSet<>(0); return; } - this.knownFileNames = new HashSet(initialFileNames.length * 2); + this.knownFileNames = new HashSet<>(initialFileNames.length * 2); for (int i = initialFileNames.length; --i >= 0;) { File compilationUnitFile = new File(initialFileNames[i]); char[] fileName = null; @@ -254,6 +332,15 @@ private void initializeKnownFileNames(String[] initialFileNames) { matchingPathName = null; } } +/** TESTS ONLY */ +public void scanForModules(Parser parser) { + for (int i = 0, max = this.classpaths.length; i < max; i++) { + File file = new File(this.classpaths[i].getPath()); + IModule iModule = ModuleFinder.scanForModule(this.classpaths[i], file, parser, false); + if (iModule != null) + this.moduleLocations.put(String.valueOf(iModule.name()), this.classpaths[i]); + } +} public void cleanup() { for (int i = 0, max = this.classpaths.length; i < max; i++) this.classpaths[i].reset(); @@ -263,8 +350,8 @@ private static String convertPathSeparators(String path) { ? path.replace('\\', '/') : path.replace('/', '\\'); } -private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly){ - NameEnvironmentAnswer answer = internalFindClass(qualifiedTypeName, typeName, asBinaryOnly); +private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly, /*NonNull*/char[] moduleName) { + NameEnvironmentAnswer answer = internalFindClass(qualifiedTypeName, typeName, asBinaryOnly, moduleName); if (this.annotationsFromClasspath && answer != null && answer.getBinaryType() instanceof ClassFileReader) { for (int i = 0, length = this.classpaths.length; i < length; i++) { Classpath classpathEntry = this.classpaths[i]; @@ -295,7 +382,7 @@ private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeNam } return answer; } -private NameEnvironmentAnswer internalFindClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly){ +private NameEnvironmentAnswer internalFindClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly, /*NonNull*/char[] moduleName) { if (this.knownFileNames.contains(qualifiedTypeName)) return null; // looking for a file which we know was provided at the beginning of the compilation String qualifiedBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class; @@ -303,11 +390,26 @@ private NameEnvironmentAnswer internalFindClass(String qualifiedTypeName, char[] qualifiedTypeName.length() == typeName.length ? Util.EMPTY_STRING : qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1); + + LookupStrategy strategy = LookupStrategy.get(moduleName); + if (strategy == LookupStrategy.Named) { + if (this.moduleLocations != null) { + // searching for a specific named module: + String moduleNameString = String.valueOf(moduleName); + Classpath classpath = this.moduleLocations.get(moduleNameString); + if (classpath != null) { + return classpath.findClass(typeName, qualifiedPackageName, moduleNameString, qualifiedBinaryFileName); + } + } + return null; + } String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar); NameEnvironmentAnswer suggestedAnswer = null; if (qualifiedPackageName == qp2) { for (int i = 0, length = this.classpaths.length; i < length; i++) { - NameEnvironmentAnswer answer = this.classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly); + if (!strategy.matches(this.classpaths[i], Classpath::hasModule)) + continue; + NameEnvironmentAnswer answer = this.classpaths[i].findClass(typeName, qualifiedPackageName, null, qualifiedBinaryFileName, asBinaryOnly); if (answer != null) { if (!answer.ignoreIfBetter()) { if (answer.isBetter(suggestedAnswer)) @@ -321,9 +423,11 @@ private NameEnvironmentAnswer internalFindClass(String qualifiedTypeName, char[] String qb2 = qualifiedBinaryFileName.replace('/', File.separatorChar); for (int i = 0, length = this.classpaths.length; i < length; i++) { Classpath p = this.classpaths[i]; - NameEnvironmentAnswer answer = (p instanceof ClasspathJar) - ? p.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly) - : p.findClass(typeName, qp2, qb2, asBinaryOnly); + if (!strategy.matches(p, Classpath::hasModule)) + continue; + NameEnvironmentAnswer answer = !(p instanceof ClasspathDirectory) + ? p.findClass(typeName, qualifiedPackageName, null, qualifiedBinaryFileName, asBinaryOnly) + : p.findClass(typeName, qp2, null, qb2, asBinaryOnly); if (answer != null) { if (!answer.ignoreIfBetter()) { if (answer.isBetter(suggestedAnswer)) @@ -334,17 +438,16 @@ private NameEnvironmentAnswer internalFindClass(String qualifiedTypeName, char[] } } } - if (suggestedAnswer != null) - // no better answer was found - return suggestedAnswer; - return null; + return suggestedAnswer; } -public NameEnvironmentAnswer findType(char[][] compoundName) { + +public NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName) { if (compoundName != null) return findClass( new String(CharOperation.concatWith(compoundName, '/')), compoundName[compoundName.length - 1], - false); + false, + moduleName); return null; } public char[][][] findTypeNames(char[][] packageName) { @@ -354,7 +457,7 @@ public char[][][] findTypeNames(char[][] packageName) { String qualifiedPackageName2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar); if (qualifiedPackageName == qualifiedPackageName2) { for (int i = 0, length = this.classpaths.length; i < length; i++) { - char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName); + char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName, null); if (answers != null) { // concat with previous answers if (result == null) { @@ -370,9 +473,8 @@ public char[][][] findTypeNames(char[][] packageName) { } else { for (int i = 0, length = this.classpaths.length; i < length; i++) { Classpath p = this.classpaths[i]; - char[][][] answers = (p instanceof ClasspathJar) - ? p.findTypeNames(qualifiedPackageName) - : p.findTypeNames(qualifiedPackageName2); + char[][][] answers = !(p instanceof ClasspathDirectory) ? p.findTypeNames(qualifiedPackageName, null) + : p.findTypeNames(qualifiedPackageName2, null); if (answers != null) { // concat with previous answers if (result == null) { @@ -380,7 +482,8 @@ public char[][][] findTypeNames(char[][] packageName) { } else { int resultLength = result.length; int answersLength = answers.length; - System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength); + System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, + resultLength); System.arraycopy(answers, 0, result, resultLength, answersLength); } } @@ -389,36 +492,137 @@ public char[][][] findTypeNames(char[][] packageName) { } return result; } -public NameEnvironmentAnswer findType(char[][] compoundName, boolean asBinaryOnly) { - if (compoundName != null) - return findClass( - new String(CharOperation.concatWith(compoundName, '/')), - compoundName[compoundName.length - 1], - asBinaryOnly); - return null; -} -public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { + +public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName) { if (typeName != null) return findClass( new String(CharOperation.concatWith(packageName, typeName, '/')), typeName, + false, + moduleName); + return null; +} + +public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] packageName, char[] moduleName) { + String qualifiedPackageName = new String(CharOperation.concatWith(parentPackageName, packageName, '/')); + String moduleNameString = String.valueOf(moduleName); + + LookupStrategy strategy = LookupStrategy.get(moduleName); + if (strategy == LookupStrategy.Named) { + if (this.moduleLocations != null) { + // specific search in a given module: + Classpath classpath = this.moduleLocations.get(moduleNameString); + if (classpath != null) { + if (classpath.isPackage(qualifiedPackageName, moduleNameString)) + return new char[][] {moduleName}; + } + } + return null; + } + // search the entire environment and answer which modules declare that package: + char[][] allNames = null; + for (Classpath cp : this.classpaths) { + if (strategy.matches(cp, Classpath::hasModule)) { + if (strategy == LookupStrategy.Unnamed) { + // short-cut + if (cp.isPackage(qualifiedPackageName, moduleNameString)) + return new char[][] { ModuleBinding.UNNAMED }; + } else { + char[][] declaringModules = cp.getModulesDeclaringPackage(qualifiedPackageName, null); + if (declaringModules != null) { + if (allNames == null) + allNames = declaringModules; + else + allNames = CharOperation.arrayConcat(allNames, declaringModules); + } + } + } + } + return allNames; +} +private Parser getParser() { + Map opts = new HashMap(); + opts.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9); + return new Parser( + new ProblemReporter(DefaultErrorHandlingPolicies.exitOnFirstError(), new CompilerOptions(opts), new DefaultProblemFactory(Locale.getDefault())), false); +} +@Override +public boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs) { + String qPackageName = String.valueOf(CharOperation.concatWith(qualifiedPackageName, '/')); + String moduleNameString = String.valueOf(moduleName); + LookupStrategy strategy = LookupStrategy.get(moduleName); + Parser parser = checkCUs ? getParser() : null; + Function pkgNameExtractor = (sourceUnit) -> { + String pkgName = null; + CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 1); + char[][] name = parser.parsePackageDeclaration(sourceUnit.getContents(), compilationResult); + if (name != null) { + pkgName = CharOperation.toString(name); + } + return pkgName; + }; + switch (strategy) { + case Named: + if (this.moduleLocations != null) { + Classpath location = this.moduleLocations.get(moduleNameString); + if (location != null) + return checkCUs ? location.hasCUDeclaringPackage(qPackageName, pkgNameExtractor) + : location.hasCompilationUnit(qPackageName, moduleNameString); + } + return false; + default: + for (int i = 0; i < this.classpaths.length; i++) { + Classpath location = this.classpaths[i]; + if (strategy.matches(location, Classpath::hasModule)) + if (location.hasCompilationUnit(qPackageName, moduleNameString)) + return true; + } + return false; + } +} + +@Override +public IModule getModule(char[] name) { + if (this.module != null && CharOperation.equals(name, this.module.name())) { + return this.module; + } + for (Classpath classpath : this.classpaths) { + IModule mod = classpath.getModule(name); + if (mod != null) { + return mod; + } + } return null; } -public boolean isPackage(char[][] compoundName, char[] packageName) { - String qualifiedPackageName = new String(CharOperation.concatWith(compoundName, packageName, '/')); - String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar); - if (qualifiedPackageName == qp2) { - for (int i = 0, length = this.classpaths.length; i < length; i++) - if (this.classpaths[i].isPackage(qualifiedPackageName)) - return true; - } else { - for (int i = 0, length = this.classpaths.length; i < length; i++) { - Classpath p = this.classpaths[i]; - if ((p instanceof ClasspathJar) ? p.isPackage(qualifiedPackageName) : p.isPackage(qp2)) - return true; + +@Override +public char[][] getAllAutomaticModules() { + Set set = new HashSet<>(); + for (int i = 0, l = this.classpaths.length; i < l; i++) { + if (this.classpaths[i].isAutomaticModule()) { + set.add(this.classpaths[i].getModule().name()); + } + } + return set.toArray(new char[set.size()][]); +} + +void addModuleUpdate(String moduleName, Consumer update, UpdateKind kind) { + UpdatesByKind updates = this.moduleUpdates.get(moduleName); + if (updates == null) { + this.moduleUpdates.put(moduleName, updates = new UpdatesByKind()); + } + updates.getList(kind, true).add(update); +} +@Override +public void applyModuleUpdates(IUpdatableModule compilerModule, IUpdatableModule.UpdateKind kind) { + char[] name = compilerModule.name(); + if (name != ModuleBinding.UNNAMED) { // can't update the unnamed module + UpdatesByKind updates = this.moduleUpdates.get(String.valueOf(name)); + if (updates != null) { + for (Consumer update : updates.getList(kind, false)) + update.accept(compilerModule); } } - return false; } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java index 33a76e5324..d69aeb5f7c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java @@ -35,6 +35,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; @@ -45,10 +46,13 @@ import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.DateFormat; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; @@ -57,6 +61,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.MissingResourceException; import java.util.Properties; import java.util.ResourceBundle; @@ -75,16 +80,25 @@ import org.eclipse.jdt.internal.compiler.ICompilerRequestor; import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; import org.eclipse.jdt.internal.compiler.IProblemFactory; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.env.AccessRule; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.CompilerStats; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; @@ -95,7 +109,6 @@ import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.compiler.util.Util; -@SuppressWarnings({ "rawtypes", "unchecked" }) public class Main implements ProblemSeverities, SuffixConstants { public static class Logger { @@ -103,7 +116,7 @@ public static class Logger { private PrintWriter log; private Main main; private PrintWriter out; - private HashMap parameters; + private HashMap parameters; int tagBits; private static final String CLASS = "class"; //$NON-NLS-1$ private static final String CLASS_FILE = "classfile"; //$NON-NLS-1$ @@ -175,7 +188,7 @@ public static class Logger { private static final String XML_DTD_DECLARATION = ""; //$NON-NLS-1$ static { try { - Class c = IProblem.class; + Class c = IProblem.class; Field[] fields = c.getFields(); for (int i = 0, max = fields.length; i < max; i++) { Field field = fields[i]; @@ -199,7 +212,7 @@ public static class Logger { public Logger(Main main, PrintWriter out, PrintWriter err) { this.out = out; this.err = err; - this.parameters = new HashMap(); + this.parameters = new HashMap<>(); this.main = main; } @@ -510,10 +523,14 @@ public void logClasspath(FileSystem.Classpath[] classpaths) { File f = new File(classpath); String id = null; if (f.isFile()) { - if (Util.isPotentialZipArchive(classpath)) { - id = Logger.CLASSPATH_JAR; - } else { - id = Logger.CLASSPATH_FILE; + int kind = Util.archiveFormat(classpath); + switch (kind) { + case Util.ZIP_FILE: + id = Logger.CLASSPATH_JAR; + break; + default: + id = Logger.CLASSPATH_FILE; + break; } } else if (f.isDirectory()) { id = Logger.CLASSPATH_FOLDER; @@ -632,7 +649,7 @@ private void logExtraProblem(CategorizedProblem problem, int localErrorCount, in } public void loggingExtraProblems(Main currentMain) { - ArrayList problems = currentMain.extraProblems; + ArrayList problems = currentMain.extraProblems; final int count = problems.size(); int localProblemCount = 0; if (count != 0) { @@ -640,7 +657,7 @@ public void loggingExtraProblems(Main currentMain) { int warnings = 0; int infos = 0; for (int i = 0; i < count; i++) { - CategorizedProblem problem = (CategorizedProblem) problems.get(i); + CategorizedProblem problem = problems.get(i); if (problem != null) { currentMain.globalProblemsCount++; logExtraProblem(problem, localProblemCount, currentMain.globalProblemsCount); @@ -661,7 +678,7 @@ public void loggingExtraProblems(Main currentMain) { if ((errors + warnings + infos) != 0) { startLoggingExtraProblems(count); for (int i = 0; i < count; i++) { - CategorizedProblem problem = (CategorizedProblem) problems.get(i); + CategorizedProblem problem = problems.get(i); if (problem!= null) { if (problem.getID() != IProblem.Task) { logXmlExtraProblem(problem, localProblemCount, currentMain.globalProblemsCount); @@ -1207,7 +1224,7 @@ public void printStats() { } } - private void printTag(String name, HashMap params, boolean insertNewLine, boolean closeTag) { + private void printTag(String name, HashMap params, boolean insertNewLine, boolean closeTag) { if (this.log != null) { ((GenericXMLWriter) this.log).printTag(name, this.parameters, true, insertNewLine, closeTag); } @@ -1314,9 +1331,9 @@ public void startLoggingTasks(int tasks) { * Resource bundle factory to share bundles for the same locale */ public static class ResourceBundleFactory { - private static HashMap Cache = new HashMap(); + private static HashMap Cache = new HashMap<>(); public static synchronized ResourceBundle getBundle(Locale locale) { - ResourceBundle bundle = (ResourceBundle) Cache.get(locale); + ResourceBundle bundle = Cache.get(locale); if (bundle == null) { bundle = ResourceBundle.getBundle(Main.bundleName, locale); Cache.put(locale, bundle); @@ -1338,10 +1355,15 @@ public static synchronized ResourceBundle getBundle(Locale locale) { /* Bundle containing messages */ public ResourceBundle bundle; protected FileSystem.Classpath[] checkedClasspaths; + // For single module mode + protected IModule module; // paths to external annotations: protected List annotationPaths; protected boolean annotationsFromClasspath; + private List addonExports = Collections.EMPTY_LIST; + private List addonReads = Collections.EMPTY_LIST; + public Locale compilerLocale; public CompilerOptions compilerOptions; // read-only public CompilationProgress progress; @@ -1360,6 +1382,7 @@ public static synchronized ResourceBundle getBundle(Locale locale) { public String[] encodings; public int exportedClassFilesCounter; public String[] filenames; + public String[] modNames; public String[] classNames; // overrides of destinationPath on a directory argument basis public int globalErrorsCount; @@ -1379,6 +1402,7 @@ public static synchronized ResourceBundle getBundle(Locale locale) { public Logger logger; public int maxProblems; public Map options; + long complianceLevel; public char[][] ignoreOptionalProblemsFromFolders; protected PrintWriter out; public boolean proceed = true; @@ -1387,7 +1411,7 @@ public static synchronized ResourceBundle getBundle(Locale locale) { public int currentRepetition, maxRepetition; public boolean showProgress = false; public long startTime; - public ArrayList pendingErrors; + public ArrayList pendingErrors; public boolean systemExitWhenFinished = true; public static final int TIMING_DISABLED = 0; @@ -1401,7 +1425,7 @@ public static synchronized ResourceBundle getBundle(Locale locale) { private PrintWriter err; - protected ArrayList extraProblems; + protected ArrayList extraProblems; public final static String bundleName = "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$ // two uses: recognize 'none' in options; code the singleton none // for the '-d none' option (wherever it may be found) @@ -1434,7 +1458,7 @@ public static boolean compile(String[] commandLineArguments, PrintWriter outWrit public static File[][] getLibrariesFiles(File[] files) { FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { - return Util.isPotentialZipArchive(name); + return Util.archiveFormat(name) > -1; } }; final int filesLength = files.length; @@ -1518,7 +1542,7 @@ public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhen * @deprecated - use {@link #Main(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead * e.g. Main(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions, null) */ -public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions) { +public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions) { this(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions, null /* progress */); } @@ -1529,12 +1553,12 @@ public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhen public void addExtraProblems(CategorizedProblem problem) { if (this.extraProblems == null) { - this.extraProblems = new ArrayList(); + this.extraProblems = new ArrayList<>(); } this.extraProblems.add(problem); } -protected void addNewEntry(ArrayList paths, String currentClasspathName, - ArrayList currentRuleSpecs, String customEncoding, +protected void addNewEntry(ArrayList paths, String currentClasspathName, + ArrayList currentRuleSpecs, String customEncoding, String destPath, boolean isSourceOnly, boolean rejectDestinationPathOnJars) { @@ -1543,10 +1567,10 @@ protected void addNewEntry(ArrayList paths, String currentClasspathName, if (rulesSpecsSize != 0) { AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()]; boolean rulesOK = true; - Iterator i = currentRuleSpecs.iterator(); + Iterator i = currentRuleSpecs.iterator(); int j = 0; while (i.hasNext()) { - String ruleSpec = (String) i.next(); + String ruleSpec = i.next(); char key = ruleSpec.charAt(0); String pattern = ruleSpec.substring(1); if (pattern.length() > 0) { @@ -1590,8 +1614,9 @@ protected void addNewEntry(ArrayList paths, String currentClasspathName, if (NONE.equals(destPath)) { destPath = NONE; // keep == comparison valid } + if (rejectDestinationPathOnJars && destPath != null && - Util.isPotentialZipArchive(currentClasspathName)) { + Util.archiveFormat(currentClasspathName) > -1) { throw new IllegalArgumentException( this.bind("configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$ currentClasspathName)); @@ -1611,7 +1636,7 @@ protected void addNewEntry(ArrayList paths, String currentClasspathName, } void addPendingErrors(String message) { if (this.pendingErrors == null) { - this.pendingErrors = new ArrayList(); + this.pendingErrors = new ArrayList<>(); } this.pendingErrors.add(message); } @@ -1707,6 +1732,8 @@ private boolean checkVMVersion(long minimalSupportedVersion) { return ClassFileConstants.JDK1_7 >= minimalSupportedVersion; case ClassFileConstants.MAJOR_VERSION_1_8: // 1.8 return ClassFileConstants.JDK1_8 >= minimalSupportedVersion; + case ClassFileConstants.MAJOR_VERSION_9: // 9 + return ClassFileConstants.JDK9 >= minimalSupportedVersion; } // unknown version return false; @@ -1758,7 +1785,8 @@ public boolean compile(String[] argv) { System.exit(-1); } return false; - } catch (RuntimeException e) { // internal compiler failure + } catch (Exception e) { // internal compiler failure + e.printStackTrace(); this.logger.logException(e); if (this.systemExitWhenFinished) { this.logger.flush(); @@ -1806,14 +1834,22 @@ public void configure(String[] argv) { final int INSIDE_CLASS_NAMES = 20; final int INSIDE_WARNINGS_PROPERTIES = 21; final int INSIDE_ANNOTATIONPATH_start = 22; + final int INSIDE_MODULEPATH_start = 23; + final int INSIDE_MODULESOURCEPATH_start = 24; + final int INSIDE_ADD_EXPORTS = 25; + final int INSIDE_ADD_READS = 26; + final int INSIDE_SYSTEM = 27; + final int INSIDE_PROCESSOR_MODULE_PATH_start = 28; final int DEFAULT = 0; - ArrayList bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); + ArrayList bootclasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); String sourcepathClasspathArg = null; - ArrayList sourcepathClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); - ArrayList classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); - ArrayList extdirsClasspaths = null; - ArrayList endorsedDirClasspaths = null; + String modulepathArg = null; + String moduleSourcepathArg = null; + ArrayList sourcepathClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); + ArrayList classpaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); + ArrayList extdirsClasspaths = null; + ArrayList endorsedDirClasspaths = null; this.annotationPaths = null; this.annotationsFromClasspath = false; @@ -1838,8 +1874,9 @@ public void configure(String[] argv) { String customDestinationPath = null; String currentSourceDirectory = null; String currentArg = Util.EMPTY_STRING; + String moduleName = null; - Set specifiedEncodings = null; + Set specifiedEncodings = null; // expand the command line if necessary boolean needExpansion = false; @@ -1974,9 +2011,21 @@ public void configure(String[] argv) { } // GROOVY end if (encounteredGroovySourceFile || currentArg.endsWith(SuffixConstants.SUFFIX_STRING_java)) { + if (moduleName == null) { + // If the module-info.java was supplied via command line, that will be the + // de facto module for the other source files supplied via command line. + // TODO: This needs revisit in case a source file specified in command line is + // part of a --module-source-path + IModule mod = extractModuleDesc(currentArg); + if (mod != null) { + moduleName = new String(mod.name()); + this.module = mod; + } + } if (this.filenames == null) { this.filenames = new String[argCount - index]; this.encodings = new String[argCount - index]; + this.modNames = new String[argCount - index]; this.destinationPaths = new String[argCount - index]; } else if (filesCount == this.filenames.length) { int length = this.filenames.length; @@ -1998,8 +2047,15 @@ public void configure(String[] argv) { (this.destinationPaths = new String[length + argCount - index]), 0, length); + System.arraycopy( + this.modNames, + 0, + (this.modNames = new String[length + argCount - index]), + 0, + length); } this.filenames[filesCount] = currentArg; + this.modNames[filesCount] = moduleName; this.encodings[filesCount++] = customEncoding; // destination path cannot be specified upon an individual file customEncoding = null; @@ -2095,6 +2151,16 @@ public void configure(String[] argv) { mode = DEFAULT; continue; } + if (currentArg.equals("-1.9") || currentArg.equals("-9") || currentArg.equals("-9.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + if (didSpecifyCompliance) { + throw new IllegalArgumentException( + this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$ + } + didSpecifyCompliance = true; + this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_9); + mode = DEFAULT; + continue; + } if (currentArg.equals("-d")) { //$NON-NLS-1$ if (this.destinationPath != null) { StringBuffer errorMessage = new StringBuffer(); @@ -2128,6 +2194,29 @@ public void configure(String[] argv) { mode = INSIDE_BOOTCLASSPATH_start; continue; } + if (currentArg.equals("--system")) { //$NON-NLS-1$ + mode = INSIDE_SYSTEM; + continue; + } + if (currentArg.equals("--module-path") || currentArg.equals("-p") || currentArg.equals("--processor-module-path")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + mode = INSIDE_MODULEPATH_start; + continue; + } + if (currentArg.equals("--module-source-path")) { //$NON-NLS-1$ + if (sourcepathClasspathArg != null) { + throw new IllegalArgumentException(this.bind("configure.OneOfModuleOrSourcePath")); //$NON-NLS-1$ + } + mode = INSIDE_MODULESOURCEPATH_start; + continue; + } + if (currentArg.equals("--add-exports")) { //$NON-NLS-1$ + mode = INSIDE_ADD_EXPORTS; + continue; + } + if (currentArg.equals("--add-reads")) { //$NON-NLS-1$ + mode = INSIDE_ADD_READS; + continue; + } if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$ if (sourcepathClasspathArg != null) { StringBuffer errorMessage = new StringBuffer(); @@ -2139,6 +2228,9 @@ public void configure(String[] argv) { throw new IllegalArgumentException( this.bind("configure.duplicateSourcepath", errorMessage.toString())); //$NON-NLS-1$ } + if (moduleSourcepathArg != null) { + throw new IllegalArgumentException(this.bind("configure.OneOfModuleOrSourcePath")); //$NON-NLS-1$ + } mode = INSIDE_SOURCE_PATH_start; continue; } @@ -2513,6 +2605,10 @@ public void configure(String[] argv) { mode = INSIDE_PROCESSOR_start; continue; } + if (currentArg.equals("--processor-module-path")) { //$NON-NLS-1$ + mode = INSIDE_PROCESSOR_MODULE_PATH_start; + continue; + } if (currentArg.equals("-proc:only")) { //$NON-NLS-1$ this.options.put( CompilerOptions.OPTION_GenerateClassFiles, @@ -2589,6 +2685,8 @@ public void configure(String[] argv) { this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7); } else if (currentArg.equals("1.8") || currentArg.equals("8") || currentArg.equals("8.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8); + } else if (currentArg.equals("1.9") || currentArg.equals("9") || currentArg.equals("9.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9); } else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_JSR14); @@ -2645,6 +2743,8 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7); } else if (currentArg.equals("1.8") || currentArg.equals("8") || currentArg.equals("8.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8); + } else if (currentArg.equals("1.9") || currentArg.equals("9") || currentArg.equals("9.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9); } else { throw new IllegalArgumentException(this.bind("configure.source", currentArg)); //$NON-NLS-1$ } @@ -2667,7 +2767,7 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ } } } else { - specifiedEncodings = new HashSet(); + specifiedEncodings = new HashSet<>(); } try { // ensure encoding is supported new InputStreamReader(new ByteArrayInputStream(new byte[0]), currentArg); @@ -2683,6 +2783,37 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ setDestinationPath(currentArg.equals(NONE) ? NONE : currentArg); mode = DEFAULT; continue; + case INSIDE_SYSTEM: + mode = DEFAULT; + setJavaHome(currentArg); + continue; + case INSIDE_MODULEPATH_start: + mode = DEFAULT; + String[] modulepaths = new String[1]; + index += processPaths(newCommandLineArgs, index, currentArg, modulepaths); + modulepathArg = modulepaths[0]; + continue; + case INSIDE_MODULESOURCEPATH_start: + mode = DEFAULT; + String[] moduleSourcepaths = new String[1]; + index += processPaths(newCommandLineArgs, index, currentArg, moduleSourcepaths); + moduleSourcepathArg = moduleSourcepaths[0]; + continue; + case INSIDE_ADD_EXPORTS: + mode = DEFAULT; + // TODO: better to validate the option before processing it further? + if (this.addonExports == Collections.EMPTY_LIST) { + this.addonExports = new ArrayList<>(); + } + this.addonExports.add(currentArg); + continue; + case INSIDE_ADD_READS: + mode = DEFAULT; + if (this.addonReads == Collections.EMPTY_LIST) { + this.addonReads = new ArrayList<>(); + } + this.addonReads.add(currentArg); + continue; case INSIDE_CLASSPATH_start: mode = DEFAULT; index += processPaths(newCommandLineArgs, index, currentArg, classpaths); @@ -2704,7 +2835,7 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ "-extdir")); //$NON-NLS-1$ } StringTokenizer tokenizer = new StringTokenizer(currentArg, File.pathSeparator, false); - extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); + extdirsClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); while (tokenizer.hasMoreTokens()) extdirsClasspaths.add(tokenizer.nextToken()); mode = DEFAULT; @@ -2715,7 +2846,7 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ this.bind("configure.unexpectedDestinationPathEntry", //$NON-NLS-1$ "-endorseddirs")); //$NON-NLS-1$ } tokenizer = new StringTokenizer(currentArg, File.pathSeparator, false); - endorsedDirClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); + endorsedDirClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); while (tokenizer.hasMoreTokens()) endorsedDirClasspaths.add(tokenizer.nextToken()); mode = DEFAULT; @@ -2738,6 +2869,9 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ // nothing to do here. This is consumed again by the AnnotationProcessorManager mode = DEFAULT; continue; + case INSIDE_PROCESSOR_MODULE_PATH_start : + mode = DEFAULT; + continue; case INSIDE_S_start : // nothing to do here. This is consumed again by the AnnotationProcessorManager mode = DEFAULT; @@ -2799,7 +2933,7 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ throw new IllegalArgumentException( this.bind("configure.unrecognizedOption", currentSourceDirectory)); //$NON-NLS-1$ } - String[] result = FileFinder.find(dir, SuffixConstants.SUFFIX_STRING_JAVA); + String[] result = FileFinder.find(dir, SuffixConstants.SUFFIX_STRING_java); if (NONE.equals(customDestinationPath)) { customDestinationPath = NONE; // ensure == comparison } @@ -2824,10 +2958,17 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ (this.destinationPaths = new String[length + filesCount]), 0, filesCount); + System.arraycopy( + this.modNames, + 0, + (this.modNames = new String[length + filesCount]), + 0, + filesCount); System.arraycopy(result, 0, this.filenames, filesCount, length); for (int i = 0; i < length; i++) { this.encodings[filesCount + i] = customEncoding; this.destinationPaths[filesCount + i] = customDestinationPath; + this.modNames[filesCount + i] = moduleName; } filesCount += length; customEncoding = null; @@ -2838,6 +2979,7 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ filesCount = this.filenames.length; this.encodings = new String[filesCount]; this.destinationPaths = new String[filesCount]; + this.modNames = new String[filesCount]; for (int i = 0; i < filesCount; i++) { this.encodings[i] = customEncoding; this.destinationPaths[i] = customDestinationPath; @@ -2955,6 +3097,8 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ sourcepathClasspathArg, sourcepathClasspaths, classpaths, + modulepathArg, + moduleSourcepathArg, extdirsClasspaths, endorsedDirClasspaths, customEncoding); @@ -2965,13 +3109,45 @@ else if (currentArg.equals("jsr14")) { //$NON-NLS-1$ getAllEncodings(specifiedEncodings))); } if (this.pendingErrors != null) { - for (Iterator iterator = this.pendingErrors.iterator(); iterator.hasNext(); ) { - String message = (String) iterator.next(); + for (Iterator iterator = this.pendingErrors.iterator(); iterator.hasNext(); ) { + String message = iterator.next(); this.logger.logPendingError(message); } this.pendingErrors = null; } } +private Parser getNewParser() { + return new Parser(new ProblemReporter(getHandlingPolicy(), + new CompilerOptions(this.options), getProblemFactory()), false); +} +private IModule extractModuleDesc(String fileName) { + IModule mod = null; + // this.options may not be completely populated yet, and definitely not + // validated. Make sure the source level is set for the parser + Map opts = new HashMap(this.options); + opts.put(CompilerOptions.OPTION_Source, this.options.get(CompilerOptions.OPTION_Compliance)); + Parser parser = new Parser(new ProblemReporter(getHandlingPolicy(), + new CompilerOptions(opts), getProblemFactory()), false); + if (fileName.toLowerCase().endsWith(IModule.MODULE_INFO_JAVA)) { + + ICompilationUnit cu = new CompilationUnit(null, fileName, null); + CompilationResult compilationResult = new CompilationResult(cu, 0, 1, 10); + CompilationUnitDeclaration unit = parser.parse(cu, compilationResult); + if (unit.isModuleInfo() && unit.moduleDeclaration != null) { + mod = new BasicModule(unit.moduleDeclaration, null); + } + } else if (fileName.toLowerCase().endsWith(IModule.MODULE_INFO_CLASS)) { + try { + ClassFileReader reader = ClassFileReader.read(fileName); // Check the absolute path? + mod = reader.getModuleDeclaration(); + } catch (ClassFormatException | IOException e) { + e.printStackTrace(); + throw new IllegalArgumentException( + this.bind("configure.invalidModuleDescriptor", fileName)); //$NON-NLS-1$ + } + } + return mod; +} private static char[][] decodeIgnoreOptionalProblemsFromFolders(String folders) { StringTokenizer tokenizer = new StringTokenizer(folders, File.pathSeparator); @@ -2997,7 +3173,7 @@ private static char[][] decodeIgnoreOptionalProblemsFromFolders(String folders) return result; } -private static String getAllEncodings(Set encodings) { +private static String getAllEncodings(Set encodings) { int size = encodings.size(); String[] allEncodings = new String[size]; encodings.toArray(allEncodings); @@ -3011,7 +3187,7 @@ private static String getAllEncodings(Set encodings) { } return String.valueOf(buffer); } - +@SuppressWarnings("rawtypes") private void initializeWarnings(String propertiesFile) { File file = new File(propertiesFile); if (!file.exists()) { @@ -3035,7 +3211,7 @@ private void initializeWarnings(String propertiesFile) { } } } - for (Iterator iterator = properties.entrySet().iterator(); iterator.hasNext(); ) { + for(Iterator iterator = properties.entrySet().iterator(); iterator.hasNext(); ) { Map.Entry entry = (Map.Entry) iterator.next(); final String key = entry.getKey().toString(); if (key.startsWith("org.eclipse.jdt.core.compiler.")) { //$NON-NLS-1$ @@ -3088,15 +3264,10 @@ protected void disableAll(int severity) { checkedValue = CompilerOptions.INFO; break; } - Object[] entries = this.options.entrySet().toArray(); - for (int i = 0, max = entries.length; i < max; i++) { - Map.Entry entry = (Map.Entry) entries[i]; - if (!(entry.getKey() instanceof String)) - continue; - if (!(entry.getValue() instanceof String)) - continue; - if (((String) entry.getValue()).equals(checkedValue)) { - this.options.put((String) entry.getKey(), CompilerOptions.IGNORE); + Set> entrySet = this.options.entrySet(); + for (Entry entry : entrySet) { + if (entry.getValue().equals(checkedValue)) { + this.options.put(entry.getKey(), CompilerOptions.IGNORE); } } if (severity == ProblemSeverities.Warning) { @@ -3135,27 +3306,48 @@ public CompilationUnit[] getCompilationUnits() { String defaultEncoding = this.options.get(CompilerOptions.OPTION_Encoding); if (Util.EMPTY_STRING.equals(defaultEncoding)) defaultEncoding = null; - - for (int i = 0; i < fileCount; i++) { - char[] charName = this.filenames[i].toCharArray(); - if (knownFileNames.get(charName) != null) - throw new IllegalArgumentException(this.bind("unit.more", this.filenames[i])); //$NON-NLS-1$ - knownFileNames.put(charName, charName); - File file = new File(this.filenames[i]); - if (!file.exists()) - throw new IllegalArgumentException(this.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$ - String encoding = this.encodings[i]; - if (encoding == null) - encoding = defaultEncoding; - String fileName; - try { - fileName = file.getCanonicalPath(); - } catch (IOException e) { - // if we got exception during canonicalization, fall back to the name that was specified - fileName = this.filenames[i]; + + Map pathToModCU = new HashMap<>(); + + for (int round = 0; round < 2; round++) { + for (int i = 0; i < fileCount; i++) { + char[] charName = this.filenames[i].toCharArray(); + boolean isModuleInfo = CharOperation.endsWith(charName, TypeConstants.MODULE_INFO_FILE_NAME); + if (isModuleInfo == (round==0)) { // 1st round: modules, 2nd round others (to ensure populating pathToModCU well in time) + if (knownFileNames.get(charName) != null) + throw new IllegalArgumentException(this.bind("unit.more", this.filenames[i])); //$NON-NLS-1$ + knownFileNames.put(charName, charName); + File file = new File(this.filenames[i]); + if (!file.exists()) + throw new IllegalArgumentException(this.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$ + String encoding = this.encodings[i]; + if (encoding == null) + encoding = defaultEncoding; + String fileName; + try { + fileName = file.getCanonicalPath(); + } catch (IOException e) { + // if we got exception during canonicalization, fall back to the name that was specified + fileName = this.filenames[i]; + } + units[i] = new CompilationUnit(null, fileName, encoding, this.destinationPaths[i], + shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray()), + this.modNames[i]); + if (isModuleInfo) { + int lastSlash = CharOperation.lastIndexOf(File.separatorChar, units[i].fileName); + if (lastSlash != -1) { + pathToModCU.put(String.valueOf(CharOperation.subarray(units[i].fileName, 0, lastSlash)), units[i]); + } + } else { + for (Entry entry : pathToModCU.entrySet()) { + if (fileName.startsWith(entry.getKey())) { // associate CUs to module by common prefix + units[i].setModule(entry.getValue()); + break; + } + } + } + } } - units[i] = new CompilationUnit(null, fileName, encoding, this.destinationPaths[i], - shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray())); } return units; } @@ -3178,7 +3370,20 @@ public boolean ignoreAllErrors() { } }; } - +private void setJavaHome(String javaHome) { + File release = new File(javaHome, "release"); //$NON-NLS-1$ + Properties prop = new Properties(); + try { + prop.load(new FileReader(release)); + String ver = prop.getProperty("JAVA_VERSION"); //$NON-NLS-1$ + if (ver != null) + ver = ver.replace("\"", ""); //$NON-NLS-1$//$NON-NLS-2$ + this.javaHomeCache = new File(javaHome); + this.javaHomeChecked = true; + } catch (IOException e) { + throw new IllegalArgumentException(this.bind("configure.invalidSystem", javaHome)); //$NON-NLS-1$ + } +} /* * External API */ @@ -3191,8 +3396,11 @@ public File getJavaHome() { } public FileSystem getLibraryAccess() { - return new FileSystem(this.checkedClasspaths, this.filenames, + FileSystem nameEnvironment = new FileSystem(this.checkedClasspaths, this.filenames, this.annotationsFromClasspath && CompilerOptions.ENABLED.equals(this.options.get(CompilerOptions.OPTION_AnnotationBasedNullAnalysis))); + nameEnvironment.module = this.module; + processAddonModuleOptions(nameEnvironment); + return nameEnvironment; } /* @@ -3205,55 +3413,142 @@ public IProblemFactory getProblemFactory() { /* * External API */ -protected ArrayList handleBootclasspath(ArrayList bootclasspaths, String customEncoding) { +protected ArrayList handleBootclasspath(ArrayList bootclasspaths, String customEncoding) { final int bootclasspathsSize; + ArrayList result = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); if ((bootclasspaths != null) - && ((bootclasspathsSize = bootclasspaths.size()) != 0)) - { - String[] paths = new String[bootclasspathsSize]; - bootclasspaths.toArray(paths); - bootclasspaths.clear(); - for (int i = 0; i < bootclasspathsSize; i++) { - processPathEntries(DEFAULT_SIZE_CLASSPATH, bootclasspaths, - paths[i], customEncoding, false, true); + && ((bootclasspathsSize = bootclasspaths.size()) != 0)) { + result = new ArrayList<>(bootclasspathsSize); + for (String path : bootclasspaths) { + processPathEntries(DEFAULT_SIZE_CLASSPATH, result, path, customEncoding, false, true); } } else { - bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); try { - Util.collectRunningVMBootclasspath(bootclasspaths); + Util.collectVMBootclasspath(result, this.javaHomeCache); } catch(IllegalStateException e) { - this.logger.logWrongJDK(); - this.proceed = false; - return null; + throw new IllegalArgumentException(this.bind("configure.invalidSystem", this.javaHomeCache.toString())); //$NON-NLS-1$ } } - return bootclasspaths; + return result; +} +private void processAddonModuleOptions(FileSystem env) { + Map exports = new HashMap<>(); + for (String option : this.addonExports) { + IModule mod = ModuleFinder.extractAddonExport(option); + if (mod != null) { + String modName = new String(mod.name()); + IPackageExport export = mod.exports()[0]; + IPackageExport[] existing = exports.get(modName); + if (existing == null) { + existing = new IPackageExport[1]; + existing[0] = export; + exports.put(modName, existing); + } else { + for (IPackageExport iPackageExport : existing) { + if (CharOperation.equals(iPackageExport.name(), export.name())) { + throw new IllegalArgumentException(this.bind("configure.duplicateExport")); //$NON-NLS-1$ + } + } + IPackageExport[] updated = new IPackageExport[existing.length + 1]; + System.arraycopy(existing, 0, updated, 0, existing.length); + updated[existing.length] = export; + exports.put(modName, updated); + } + env.addModuleUpdate(modName, m -> m.addExports(export.name(), export.targets()), UpdateKind.PACKAGE); + } else { + throw new IllegalArgumentException(this.bind("configure.invalidModuleOption", "--add-exports " + option)); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + for (String option : this.addonReads) { + String[] result = ModuleFinder.extractAddonRead(option); + if (result != null && result.length == 2) { + env.addModuleUpdate(result[0], m -> m.addReads(result[1].toCharArray()), UpdateKind.MODULE); + } else { + throw new IllegalArgumentException(this.bind("configure.invalidModuleOption", "--add-reads " + option)); //$NON-NLS-1$ //$NON-NLS-2$ + } + } +} +protected ArrayList handleModulepath(String arg) { + ArrayList modulePaths = processModulePathEntries(arg); + ArrayList result = new ArrayList<>(); + if ((modulePaths != null && modulePaths.size() > 0)) { + for (String path : modulePaths) { + File file = new File(path); + if (file.isDirectory()) { + result = + (ArrayList) ModuleFinder.findModules(file, null, getNewParser(), this.options, true); + } else { + Classpath modulePath = ModuleFinder.findModule(file, null, getNewParser(), this.options, true); + if (modulePath != null) + result.add(modulePath); + } + } + } + // TODO: What about chained jars from MANIFEST.MF? Check with spec + return result; +} +protected ArrayList handleModuleSourcepath(String arg) { + ArrayList modulePaths = processModulePathEntries(arg); + ArrayList result = new ArrayList<>(); + if ((modulePaths != null) + && (modulePaths.size() != 0)) { + + if (this.destinationPath == null) { + addPendingErrors(this.bind("configure.missingDestinationPath"));//$NON-NLS-1$ + } + String[] paths = new String[modulePaths.size()]; + modulePaths.toArray(paths); + for (int i = 0; i < paths.length; i++) { + File dir = new File(paths[i]); + if (dir.isDirectory()) { + // 1. Create FileSystem.Classpath for each module + // 2. Iterator each module in case of directory for source files and add to this.fileNames + + List modules = ModuleFinder.findModules(dir, this.destinationPath, getNewParser(), this.options, false); + for (Classpath classpath : modules) { + result.add(classpath); + Path modLocation = Paths.get(classpath.getPath()).toAbsolutePath(); + String destPath = classpath.getDestinationPath(); + IModule mod = classpath.getModule(); + String moduleName = mod == null ? null : new String(mod.name()); + for(int j = 0; j < this.filenames.length; j++) { + Path filePath; + try { + // Get canonical path just as the classpath location is stored with the same. + // To avoid mismatch of /USER_JAY and /USE~1 in windows systems. + filePath = new File(this.filenames[j]).getCanonicalFile().toPath(); + if (filePath.startsWith(modLocation)) { + this.modNames[j] = moduleName; + this.destinationPaths[j] = destPath; + } + } catch (IOException e) { + // Files doesn't exist and perhaps doesn't belong in a module, move on to other files + } + } + } + } + } + + } + return result; } - /* * External API */ -protected ArrayList handleClasspath(ArrayList classpaths, String customEncoding) { - final int classpathsSize; - if ((classpaths != null) - && ((classpathsSize = classpaths.size()) != 0)) - { - String[] paths = new String[classpathsSize]; - classpaths.toArray(paths); - classpaths.clear(); - for (int i = 0; i < classpathsSize; i++) { - processPathEntries(DEFAULT_SIZE_CLASSPATH, classpaths, paths[i], - customEncoding, false, true); +protected ArrayList handleClasspath(ArrayList classpaths, String customEncoding) { + ArrayList initial = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); + if (classpaths != null && classpaths.size() > 0) { + for (String path : classpaths) { + processPathEntries(DEFAULT_SIZE_CLASSPATH, initial, path, customEncoding, false, true); } } else { // no user classpath specified. - classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$ if ((classProp == null) || (classProp.length() == 0)) { addPendingErrors(this.bind("configure.noClasspath")); //$NON-NLS-1$ final Classpath classpath = FileSystem.getClasspath(System.getProperty("user.dir"), customEncoding, null, this.options);//$NON-NLS-1$ if (classpath != null) { - classpaths.add(classpath); + initial.add(classpath); } } else { StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator); @@ -3263,15 +3558,15 @@ protected ArrayList handleClasspath(ArrayList classpaths, String customEncoding) FileSystem.Classpath currentClasspath = FileSystem .getClasspath(token, customEncoding, null, this.options); if (currentClasspath != null) { - classpaths.add(currentClasspath); + initial.add(currentClasspath); } else if (token.length() != 0) { addPendingErrors(this.bind("configure.incorrectClasspath", token));//$NON-NLS-1$ } } } } - ArrayList result = new ArrayList(); - HashMap knownNames = new HashMap(); + ArrayList result = new ArrayList<>(); + HashMap knownNames = new HashMap<>(); FileSystem.ClasspathSectionProblemReporter problemReporter = new FileSystem.ClasspathSectionProblemReporter() { public void invalidClasspathSection(String jarFilePath) { @@ -3281,15 +3576,15 @@ public void multipleClasspathSections(String jarFilePath) { addPendingErrors(bind("configure.multipleClasspathSections", jarFilePath)); //$NON-NLS-1$ } }; - while (! classpaths.isEmpty()) { - Classpath current = (Classpath) classpaths.remove(0); + while (! initial.isEmpty()) { + Classpath current = initial.remove(0); String currentPath = current.getPath(); if (knownNames.get(currentPath) == null) { knownNames.put(currentPath, current); result.add(current); - List linkedJars = current.fetchLinkedJars(problemReporter); + List linkedJars = current.fetchLinkedJars(problemReporter); if (linkedJars != null) { - classpaths.addAll(0, linkedJars); + initial.addAll(0, linkedJars); } } } @@ -3298,7 +3593,7 @@ public void multipleClasspathSections(String jarFilePath) { /* * External API */ -protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) { +protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) { final File javaHome = getJavaHome(); /* * Feed endorsedDirClasspath according to: @@ -3307,7 +3602,7 @@ protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) { * - else default extensions directory for the platform. (/lib/endorsed) */ if (endorsedDirClasspaths == null) { - endorsedDirClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); + endorsedDirClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); String endorsedDirsStr = System.getProperty("java.endorsed.dirs"); //$NON-NLS-1$ if (endorsedDirsStr == null) { if (javaHome != null) { @@ -3326,10 +3621,10 @@ protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) { * extdirsNames. */ if (endorsedDirClasspaths.size() != 0) { + ArrayList result = new ArrayList<>(); File[] directoriesToCheck = new File[endorsedDirClasspaths.size()]; for (int i = 0; i < directoriesToCheck.length; i++) - directoriesToCheck[i] = new File((String) endorsedDirClasspaths.get(i)); - endorsedDirClasspaths.clear(); + directoriesToCheck[i] = new File(endorsedDirClasspaths.get(i)); File[][] endorsedDirsJars = getLibrariesFiles(directoriesToCheck); if (endorsedDirsJars != null) { for (int i = 0, max = endorsedDirsJars.length; i < max; i++) { @@ -3341,7 +3636,7 @@ protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) { current[j].getAbsolutePath(), null, null, this.options); if (classpath != null) { - endorsedDirClasspaths.add(classpath); + result.add(classpath); } } } else if (directoriesToCheck[i].isFile()) { @@ -3352,15 +3647,16 @@ protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) { } } } + return result; } - return endorsedDirClasspaths; + return FileSystem.EMPTY_CLASSPATH; } /* * External API * Handle extdirs processing */ -protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) { +protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) { final File javaHome = getJavaHome(); /* @@ -3370,7 +3666,7 @@ protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) { * - else default extensions directory for the platform. */ if (extdirsClasspaths == null) { - extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH); + extdirsClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH); String extdirsStr = System.getProperty("java.ext.dirs"); //$NON-NLS-1$ if (extdirsStr == null) { extdirsClasspaths.add(javaHome.getAbsolutePath() + "/lib/ext"); //$NON-NLS-1$ @@ -3386,10 +3682,10 @@ protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) { * extdirsNames. */ if (extdirsClasspaths.size() != 0) { + ArrayList result = new ArrayList<>(); File[] directoriesToCheck = new File[extdirsClasspaths.size()]; for (int i = 0; i < directoriesToCheck.length; i++) - directoriesToCheck[i] = new File((String) extdirsClasspaths.get(i)); - extdirsClasspaths.clear(); + directoriesToCheck[i] = new File(extdirsClasspaths.get(i)); File[][] extdirsJars = getLibrariesFiles(directoriesToCheck); if (extdirsJars != null) { for (int i = 0, max = extdirsJars.length; i < max; i++) { @@ -3401,7 +3697,7 @@ protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) { current[j].getAbsolutePath(), null, null, this.options); if (classpath != null) { - extdirsClasspaths.add(classpath); + result.add(classpath); } } } else if (directoriesToCheck[i].isFile()) { @@ -3411,9 +3707,10 @@ protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) { } } } + return result; } - return extdirsClasspaths; + return FileSystem.EMPTY_CLASSPATH; } /* @@ -3475,6 +3772,7 @@ private void handleErrorOrWarningToken(String token, boolean isEnabling, int sev case 'a' : if (token.equals("allDeprecation")) { //$NON-NLS-1$ setSeverity(CompilerOptions.OPTION_ReportDeprecation, severity, isEnabling); + setSeverity(CompilerOptions.OPTION_ReportTerminalDeprecation, severity, isEnabling); this.options.put( CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED); @@ -3588,6 +3886,9 @@ private void handleErrorOrWarningToken(String token, boolean isEnabling, int sev } else if (token.equals("enumIdentifier")) { //$NON-NLS-1$ setSeverity(CompilerOptions.OPTION_ReportEnumIdentifier, severity, isEnabling); return; + } else if (token.equals("exports")) { //$NON-NLS-1$ + setSeverity(CompilerOptions.OPTION_ReportAPILeak, severity, isEnabling); + return; } break; case 'f' : @@ -3920,6 +4221,15 @@ private void handleErrorOrWarningToken(String token, boolean isEnabling, int sev setSeverity(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, severity, isEnabling); setSeverity(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, severity, isEnabling); return; + } else if (token.equals("removal")) { //$NON-NLS-1$ + setSeverity(CompilerOptions.OPTION_ReportTerminalDeprecation, severity, isEnabling); + this.options.put( + CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, + CompilerOptions.DISABLED); + this.options.put( + CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, + CompilerOptions.DISABLED); + return; } break; case 's' : @@ -4144,7 +4454,7 @@ protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean * @deprecated - use {@link #initialize(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead * e.g. initialize(outWriter, errWriter, systemExit, customDefaultOptions, null) */ -protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map customDefaultOptions) { +protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map customDefaultOptions) { this.initialize(outWriter, errWriter, systemExit, customDefaultOptions, null /* progress */); } protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map customDefaultOptions, CompilationProgress compilationProgress) { @@ -4173,7 +4483,7 @@ protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean protected void initializeAnnotationProcessorManager() { String className = "org.eclipse.jdt.internal.compiler.apt.dispatch.BatchAnnotationProcessorManager"; //$NON-NLS-1$ try { - Class c = Class.forName(className); + Class c = Class.forName(className); AbstractAnnotationProcessorManager annotationManager = (AbstractAnnotationProcessorManager) c.newInstance(); annotationManager.configure(this, this.expandedCommandLine); annotationManager.setErr(this.err); @@ -4267,61 +4577,63 @@ public void outputClassFiles(CompilationResult unitResult) { * Low-level API performing the actual compilation */ public void performCompilation() { - this.startTime = System.currentTimeMillis(); FileSystem environment = getLibraryAccess(); - this.compilerOptions = new CompilerOptions(this.options); - this.compilerOptions.performMethodsFullRecovery = false; - this.compilerOptions.performStatementsRecovery = false; - this.batchCompiler = - new Compiler( - environment, - getHandlingPolicy(), - this.compilerOptions, - getBatchRequestor(), - getProblemFactory(), - this.out, - this.progress); - this.batchCompiler.remainingIterations = this.maxRepetition-this.currentRepetition/*remaining iterations including this one*/; - // temporary code to allow the compiler to revert to a single thread - String setting = System.getProperty("jdt.compiler.useSingleThread"); //$NON-NLS-1$ - this.batchCompiler.useSingleThread = setting != null && setting.equals("true"); //$NON-NLS-1$ - - if (this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_6 - && this.compilerOptions.processAnnotations) { - if (checkVMVersion(ClassFileConstants.JDK1_6)) { - initializeAnnotationProcessorManager(); - if (this.classNames != null) { - this.batchCompiler.setBinaryTypes(processClassNames(this.batchCompiler.lookupEnvironment)); + try { + this.compilerOptions = new CompilerOptions(this.options); + this.compilerOptions.performMethodsFullRecovery = false; + this.compilerOptions.performStatementsRecovery = false; + this.batchCompiler = + new Compiler( + environment, + getHandlingPolicy(), + this.compilerOptions, + getBatchRequestor(), + getProblemFactory(), + this.out, + this.progress); + this.batchCompiler.remainingIterations = this.maxRepetition-this.currentRepetition/*remaining iterations including this one*/; + // temporary code to allow the compiler to revert to a single thread + String setting = System.getProperty("jdt.compiler.useSingleThread"); //$NON-NLS-1$ + this.batchCompiler.useSingleThread = setting != null && setting.equals("true"); //$NON-NLS-1$ + + if (this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_6 + && this.compilerOptions.processAnnotations) { + if (checkVMVersion(ClassFileConstants.JDK1_6)) { + initializeAnnotationProcessorManager(); + if (this.classNames != null) { + this.batchCompiler.setBinaryTypes(processClassNames(this.batchCompiler.lookupEnvironment)); + } + } else { + // report a warning + this.logger.logIncorrectVMVersionForAnnotationProcessing(); } - } else { - // report a warning - this.logger.logIncorrectVMVersionForAnnotationProcessing(); } - } - // set the non-externally configurable options. - this.compilerOptions.verbose = this.verbose; - this.compilerOptions.produceReferenceInfo = this.produceRefInfo; - try { - this.logger.startLoggingSources(); - this.batchCompiler.compile(getCompilationUnits()); - } finally { - this.logger.endLoggingSources(); - } + // set the non-externally configurable options. + this.compilerOptions.verbose = this.verbose; + this.compilerOptions.produceReferenceInfo = this.produceRefInfo; + try { + this.logger.startLoggingSources(); + this.batchCompiler.compile(getCompilationUnits()); + } finally { + this.logger.endLoggingSources(); + } - if (this.extraProblems != null) { - loggingExtraProblems(); - this.extraProblems = null; - } - if (this.compilerStats != null) { - this.compilerStats[this.currentRepetition] = this.batchCompiler.stats; + if (this.extraProblems != null) { + loggingExtraProblems(); + this.extraProblems = null; + } + if (this.compilerStats != null) { + this.compilerStats[this.currentRepetition] = this.batchCompiler.stats; + } + this.logger.printStats(); } - this.logger.printStats(); - + finally { // cleanup - environment.cleanup(); + environment.cleanup(); + } } protected void loggingExtraProblems() { this.logger.loggingExtraProblems(this); @@ -4345,40 +4657,82 @@ private ReferenceBinding[] processClassNames(LookupEnvironment environment) { // check for .class file presence in case of apt processing int length = this.classNames.length; ReferenceBinding[] referenceBindings = new ReferenceBinding[length]; + ModuleBinding[] modules = new ModuleBinding[length]; + Set modSet = new HashSet<>(); + String[] typeNames = new String[length]; + if (this.complianceLevel <= ClassFileConstants.JDK1_8) { + typeNames = this.classNames; + } else { + for (int i = 0; i < length; i++) { + String currentName = this.classNames[i]; + int idx = currentName.indexOf('/'); + ModuleBinding mod = null; + if (idx > 0) { + String m = currentName.substring(0, idx); + mod = environment.getModule(m.toCharArray()); + if (mod == null) { + throw new IllegalArgumentException(this.bind("configure.invalidModuleName", m)); //$NON-NLS-1$ + } + modules[i] = mod; + modSet.add(mod); + currentName = currentName.substring(idx + 1); + } + typeNames[i] = currentName; + } + for (ModuleBinding mod : modSet) { + mod.getExports(); + mod.getRequires(); + mod.getOpens(); + mod.getServices(); + } + } + for (int i = 0; i < length; i++) { - String currentName = this.classNames[i]; char[][] compoundName = null; - if (currentName.indexOf('.') != -1) { + String cls = typeNames[i]; + if (cls.indexOf('.') != -1) { // consider names with '.' as fully qualified names - char[] typeName = currentName.toCharArray(); + char[] typeName = cls.toCharArray(); compoundName = CharOperation.splitOn('.', typeName); } else { - compoundName = new char[][] { currentName.toCharArray() }; + compoundName = new char[][] { cls.toCharArray() }; } - ReferenceBinding type = environment.getType(compoundName); + ModuleBinding mod = modules[i]; + ReferenceBinding type = mod != null ? environment.getType(compoundName, mod) : environment.getType(compoundName); if (type != null && type.isValidBinding()) { if (type.isBinaryBinding()) { referenceBindings[i] = type; + type.superclass(); } } else { throw new IllegalArgumentException( - this.bind("configure.invalidClassName", currentName));//$NON-NLS-1$ + this.bind("configure.invalidClassName", this.classNames[i]));//$NON-NLS-1$ } } return referenceBindings; } +private ArrayList processModulePathEntries(String arg) { + ArrayList paths = new ArrayList<>(); + if (arg == null) + return paths; + StringTokenizer tokenizer = new StringTokenizer(arg, File.pathSeparator, false); + while (tokenizer.hasMoreTokens()) { + paths.add(tokenizer.nextToken()); + } + return paths; +} /* * External API */ -public void processPathEntries(final int defaultSize, final ArrayList paths, +public void processPathEntries(final int defaultSize, final ArrayList paths, final String currentPath, String customEncoding, boolean isSourceOnly, boolean rejectDestinationPathOnJars) { String currentClasspathName = null; String currentDestinationPath = null; - ArrayList currentRuleSpecs = new ArrayList(defaultSize); + ArrayList currentRuleSpecs = new ArrayList<>(defaultSize); StringTokenizer tokenizer = new StringTokenizer(currentPath, File.pathSeparator + "[]", true); //$NON-NLS-1$ - ArrayList tokens = new ArrayList(); + ArrayList tokens = new ArrayList<>(); while (tokenizer.hasMoreTokens()) { tokens.add(tokenizer.nextToken()); } @@ -4412,7 +4766,7 @@ public void processPathEntries(final int defaultSize, final ArrayList paths, String token = null; int cursor = 0, tokensNb = tokens.size(), bracket = -1; while (cursor < tokensNb && state != error) { - token = (String) tokens.get(cursor++); + token = tokens.get(cursor++); if (token.equals(File.pathSeparator)) { switch (state) { case start: @@ -4517,7 +4871,7 @@ public void processPathEntries(final int defaultSize, final ArrayList paths, break; case bracketClosed: for (int i = bracket; i < cursor ; i++) { - currentClasspathName += (String) tokens.get(i); + currentClasspathName += tokens.get(i); } state = readyToClose; break; @@ -4552,7 +4906,7 @@ public void processPathEntries(final int defaultSize, final ArrayList paths, } } -private int processPaths(String[] args, int index, String currentArg, ArrayList paths) { +private int processPaths(String[] args, int index, String currentArg, ArrayList paths) { int localIndex = index; int count = 0; for (int i = 0, max = currentArg.length(); i < max; i++) { @@ -4703,21 +5057,44 @@ public void setLocale(Locale locale) { /* * External API */ -protected void setPaths(ArrayList bootclasspaths, +protected void setPaths(ArrayList bootclasspaths, String sourcepathClasspathArg, - ArrayList sourcepathClasspaths, - ArrayList classpaths, - ArrayList extdirsClasspaths, - ArrayList endorsedDirClasspaths, + ArrayList sourcepathClasspaths, + ArrayList classpaths, + String modulePath, + String moduleSourcepath, + ArrayList extdirsClasspaths, + ArrayList endorsedDirClasspaths, String customEncoding) { + if (this.complianceLevel == 0) { + String version = this.options.get(CompilerOptions.OPTION_Compliance); + this.complianceLevel = CompilerOptions.versionToJdkLevel(version); + } + + if (this.complianceLevel > ClassFileConstants.JDK1_8) { + if (bootclasspaths != null && bootclasspaths.size() > 0) + throw new IllegalArgumentException( + this.bind("configure.unsupportedOption", "-bootclasspath")); //$NON-NLS-1$ //$NON-NLS-2$ + if (extdirsClasspaths != null && extdirsClasspaths.size() > 0) + throw new IllegalArgumentException( + this.bind("configure.unsupportedOption", "-extdirs")); //$NON-NLS-1$ //$NON-NLS-2$ + if (endorsedDirClasspaths != null && endorsedDirClasspaths.size() > 0) + throw new IllegalArgumentException( + this.bind("configure.unsupportedOption", "-endorseddirs")); //$NON-NLS-1$ //$NON-NLS-2$ + } // process bootclasspath, classpath and sourcepaths - bootclasspaths = handleBootclasspath(bootclasspaths, customEncoding); + ArrayList allPaths = handleBootclasspath(bootclasspaths, customEncoding); + + List cp = handleClasspath(classpaths, customEncoding); + + List mp = handleModulepath(modulePath); - classpaths = handleClasspath(classpaths, customEncoding); + List msp = handleModuleSourcepath(moduleSourcepath); + ArrayList sourcepaths = new ArrayList<>(); if (sourcepathClasspathArg != null) { - processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepathClasspaths, + processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepaths, sourcepathClasspathArg, customEncoding, true, false); } @@ -4727,9 +5104,9 @@ protected void setPaths(ArrayList bootclasspaths, * - else java.ext.dirs if defined; * - else default extensions directory for the platform. */ - extdirsClasspaths = handleExtdirs(extdirsClasspaths); + List extdirs = handleExtdirs(extdirsClasspaths); - endorsedDirClasspaths = handleEndorseddirs(endorsedDirClasspaths); + List endorsed = handleEndorseddirs(endorsedDirClasspaths); /* * Concatenate classpath entries @@ -4739,20 +5116,23 @@ protected void setPaths(ArrayList bootclasspaths, * entries are searched for both sources and binaries except * the sourcepath entries which are searched for sources only. */ - bootclasspaths.addAll(0, endorsedDirClasspaths); - bootclasspaths.addAll(extdirsClasspaths); - bootclasspaths.addAll(sourcepathClasspaths); - bootclasspaths.addAll(classpaths); - classpaths = bootclasspaths; - classpaths = FileSystem.ClasspathNormalizer.normalize(classpaths); - this.checkedClasspaths = new FileSystem.Classpath[classpaths.size()]; - classpaths.toArray(this.checkedClasspaths); + allPaths.addAll(0, endorsed); + allPaths.addAll(extdirs); + allPaths.addAll(sourcepaths); + allPaths.addAll(cp); + allPaths.addAll(mp); + allPaths.addAll(msp); + allPaths = FileSystem.ClasspathNormalizer.normalize(allPaths); + this.checkedClasspaths = new FileSystem.Classpath[allPaths.size()]; + allPaths.toArray(this.checkedClasspaths); this.logger.logClasspath(this.checkedClasspaths); if (this.annotationPaths != null && CompilerOptions.ENABLED.equals(this.options.get(CompilerOptions.OPTION_AnnotationBasedNullAnalysis))) { - for (FileSystem.Classpath cp : this.checkedClasspaths) { - if (cp instanceof ClasspathJar) - ((ClasspathJar) cp).annotationPaths = this.annotationPaths; + for (FileSystem.Classpath c : this.checkedClasspaths) { + if (c instanceof ClasspathJar) + ((ClasspathJar) c).annotationPaths = this.annotationPaths; + else if (c instanceof ClasspathJrt) + ((ClasspathJrt) c).annotationPaths = this.annotationPaths; } } } @@ -4847,6 +5227,26 @@ protected void validateOptions(boolean didSpecifyCompliance) { this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8); if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8); } + } else if (CompilerOptions.VERSION_9.equals(version)) { + if (this.didSpecifySource) { + Object source = this.options.get(CompilerOptions.OPTION_Source); + if (CompilerOptions.VERSION_1_3.equals(source) + || CompilerOptions.VERSION_1_4.equals(source)) { + if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4); + } else if (CompilerOptions.VERSION_1_5.equals(source) + || CompilerOptions.VERSION_1_6.equals(source)) { + if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6); + } else if (CompilerOptions.VERSION_1_7.equals(source)) { + if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7); + } else if (CompilerOptions.VERSION_1_8.equals(source)) { + if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8); + } else if (CompilerOptions.VERSION_9.equals(source)) { + if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9); + } + } else { + this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9); + if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9); + } } } else if (this.didSpecifySource) { Object version = this.options.get(CompilerOptions.OPTION_Source); @@ -4870,25 +5270,28 @@ protected void validateOptions(boolean didSpecifyCompliance) { } final String sourceVersion = this.options.get(CompilerOptions.OPTION_Source); - final String compliance = this.options.get(CompilerOptions.OPTION_Compliance); + if (this.complianceLevel == 0) { + final String compliance = this.options.get(CompilerOptions.OPTION_Compliance); + this.complianceLevel = CompilerOptions.versionToJdkLevel(compliance); + } if (sourceVersion.equals(CompilerOptions.VERSION_1_8) - && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_8) { + && this.complianceLevel < ClassFileConstants.JDK1_8) { // compliance must be 1.8 if source is 1.8 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_8)); //$NON-NLS-1$ } else if (sourceVersion.equals(CompilerOptions.VERSION_1_7) - && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_7) { + && this.complianceLevel < ClassFileConstants.JDK1_7) { // compliance must be 1.7 if source is 1.7 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_7)); //$NON-NLS-1$ } else if (sourceVersion.equals(CompilerOptions.VERSION_1_6) - && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_6) { + && this.complianceLevel < ClassFileConstants.JDK1_6) { // compliance must be 1.6 if source is 1.6 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_6)); //$NON-NLS-1$ } else if (sourceVersion.equals(CompilerOptions.VERSION_1_5) - && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_5) { + && this.complianceLevel < ClassFileConstants.JDK1_5) { // compliance must be 1.5 if source is 1.5 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$ } else if (sourceVersion.equals(CompilerOptions.VERSION_1_4) - && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_4) { + && this.complianceLevel < ClassFileConstants.JDK1_4) { // compliance must be 1.4 if source is 1.4 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$ } @@ -4906,7 +5309,7 @@ protected void validateOptions(boolean didSpecifyCompliance) { if (this.didSpecifySource && CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4) { throw new IllegalArgumentException(this.bind("configure.incompatibleSourceForCldcTarget", targetVersion, sourceVersion)); //$NON-NLS-1$ } - if (CompilerOptions.versionToJdkLevel(compliance) >= ClassFileConstants.JDK1_5) { + if (this.complianceLevel >= ClassFileConstants.JDK1_5) { throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForCldcTarget", targetVersion, sourceVersion)); //$NON-NLS-1$ } } else { @@ -4936,7 +5339,7 @@ protected void validateOptions(boolean didSpecifyCompliance) { throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", targetVersion, CompilerOptions.VERSION_1_4)); //$NON-NLS-1$ } // target cannot be greater than compliance level - if (CompilerOptions.versionToJdkLevel(compliance) < CompilerOptions.versionToJdkLevel(targetVersion)){ + if (this.complianceLevel < CompilerOptions.versionToJdkLevel(targetVersion)){ throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForTarget", this.options.get(CompilerOptions.OPTION_Compliance), targetVersion)); //$NON-NLS-1$ } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java new file mode 100644 index 0000000000..450ab1e76a --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.batch; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.zip.ZipFile; + +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.PackageExportImpl; +import org.eclipse.jdt.internal.compiler.parser.Parser; +import org.eclipse.jdt.internal.compiler.util.Util; + +public class ModuleFinder { + + public static List findModules(File f, String destinationPath, Parser parser, Map options, boolean isModulepath) { + List collector = new ArrayList<>(); + scanForModules(destinationPath, parser, options, isModulepath, false, collector, f); + return collector; + } + + protected static FileSystem.Classpath findModule(final File file, String destinationPath, Parser parser, + Map options, boolean isModulepath) { + FileSystem.Classpath modulePath = FileSystem.getClasspath(file.getAbsolutePath(), null, !isModulepath, null, + destinationPath == null ? null : (destinationPath + File.separator + file.getName()), options); + if (modulePath != null) { + scanForModule(modulePath, file, parser, isModulepath); + } + return modulePath; + } + protected static void scanForModules(String destinationPath, Parser parser, Map options, boolean isModulepath, + boolean thisAnAutomodule, List collector, final File file) { + FileSystem.Classpath entry = FileSystem.getClasspath( + file.getAbsolutePath(), + null, + !isModulepath, + null, + destinationPath == null ? null : (destinationPath + File.separator + file.getName()), + options); + if (entry != null) { + IModule module = scanForModule(entry, file, parser, thisAnAutomodule); + if (module != null) { + collector.add(entry); + } else { + if (file.isDirectory()) { + File[] files = file.listFiles(); + for (File f : files) { + scanForModules(destinationPath, parser, options, isModulepath, isModulepath, collector, f); + } + } + } + } + } + protected static IModule scanForModule(FileSystem.Classpath modulePath, final File file, Parser parser, boolean considerAutoModules) { + IModule module = null; + if (file.isDirectory()) { + String[] list = file.list(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + if (dir == file && (name.equalsIgnoreCase(IModule.MODULE_INFO_CLASS) + || name.equalsIgnoreCase(IModule.MODULE_INFO_JAVA))) { + return true; + } + return false; + } + }); + if (list.length > 0) { + String fileName = list[0]; + switch (fileName) { + case IModule.MODULE_INFO_CLASS: + module = ModuleFinder.extractModuleFromClass(new File(file, fileName), modulePath); + break; + case IModule.MODULE_INFO_JAVA: + module = ModuleFinder.extractModuleFromSource(new File(file, fileName), parser, modulePath); + String modName = new String(module.name()); + if (!modName.equals(file.getName())) { + throw new IllegalArgumentException("module name " + modName + " does not match expected name " + file.getName()); //$NON-NLS-1$ //$NON-NLS-2$ + } + break; + } + } + } else if (isJar(file)) { + module = extractModuleFromJar(file, modulePath); + } + if (considerAutoModules && module == null && !(modulePath instanceof ClasspathJrt)) { + module = IModule.createAutomatic(getFileName(file), file.isFile(), getManifest(file)); + } + if (module != null) + modulePath.acceptModule(module); + return module; + } + private static Manifest getManifest(File file) { + if (!isJar(file)) + return null; + try (JarFile jar = new JarFile(file)) { + return jar.getManifest(); + } catch (IOException e) { + return null; + } + } + private static String getFileName(File file) { + String name = file.getName(); + int index = name.lastIndexOf('.'); + if (index == -1) + return name; + return name.substring(0, index); + } + /** + * Extracts the single reads clause from the given + * command line option (--add-reads). The result is a String[] with two + * element, first being the source module and second being the target module. + * The expected format is: + * --add-reads = + * @param option + * @return a String[] with source and target module of the "reads" clause. + */ + protected static String[] extractAddonRead(String option) { + StringTokenizer tokenizer = new StringTokenizer(option, "="); //$NON-NLS-1$ + String source = null; + String target = null; + if (tokenizer.hasMoreTokens()) { + source = tokenizer.nextToken(); + } else { + // Handle error + return null; + } + if (tokenizer.hasMoreTokens()) { + target = tokenizer.nextToken(); + } else { + // Handle error + return null; + } + return new String[]{source, target}; + } + /** + * Parses the --add-exports command line option and returns the package export definitions + * in the form of an IModule. Note the IModule returned only holds this specific exports-to + * clause and can't by itself be used as a module description. + * + * The expected format is: + * --add-exports /=(,)* + * @param option + * @return a dummy module object with package exports + */ + protected static IModule extractAddonExport(String option) { + StringTokenizer tokenizer = new StringTokenizer(option, "/"); //$NON-NLS-1$ + String source = null; + String pack = null; + List targets = new ArrayList<>(); + if (tokenizer.hasMoreTokens()) { + source = tokenizer.nextToken("/"); //$NON-NLS-1$ + } else { + // Handle error + return null; + } + if (tokenizer.hasMoreTokens()) { + pack = tokenizer.nextToken("/="); //$NON-NLS-1$ + } else { + // Handle error + return null; + } + while (tokenizer.hasMoreTokens()) { + targets.add(tokenizer.nextToken("=,")); //$NON-NLS-1$ + } + PackageExportImpl export = new PackageExportImpl(); + export.pack = pack.toCharArray(); + export.exportedTo = new char[targets.size()][]; + for(int i = 0; i < export.exportedTo.length; i++) { + export.exportedTo[i] = targets.get(i).toCharArray(); + } + BasicModule module = new BasicModule(source.toCharArray(), false); + module.exports = new IModule.IPackageExport[]{export}; + return module; + } + + private static boolean isJar(File file) { + int format = Util.archiveFormat(file.getAbsolutePath()); + return format >= Util.ZIP_FILE; + } + private static IModule extractModuleFromJar(File file, Classpath pathEntry) { + ZipFile zipFile = null; + try { + zipFile = new ZipFile(file); + ClassFileReader reader = ClassFileReader.read(zipFile, IModule.MODULE_INFO_CLASS); + IModule module = getModule(reader); + if (module != null) { + return reader.getModuleDeclaration(); + } + return null; + } catch (ClassFormatException | IOException e) { + // Nothing to be done here + } finally { + if (zipFile != null) { + try { + zipFile.close(); + } catch (IOException e) { + // Nothing much to do here + } + } + } + return null; + } + private static IModule extractModuleFromClass(File classfilePath, Classpath pathEntry) { + ClassFileReader reader; + try { + reader = ClassFileReader.read(classfilePath); + IModule module = getModule(reader); + if (module != null) { + return reader.getModuleDeclaration(); + } + return null; + } catch (ClassFormatException | IOException e) { + e.printStackTrace(); + } + return null; + } + private static IModule getModule(ClassFileReader classfile) { + if (classfile != null) { + return classfile.getModuleDeclaration(); + } + return null; + } + private static IModule extractModuleFromSource(File file, Parser parser, Classpath pathEntry) { + ICompilationUnit cu = new CompilationUnit(null, file.getAbsolutePath(), null); + CompilationResult compilationResult = new CompilationResult(cu, 0, 1, 10); + CompilationUnitDeclaration unit = parser.parse(cu, compilationResult); + if (unit.isModuleInfo() && unit.moduleDeclaration != null) { + return new BasicModule(unit.moduleDeclaration, pathEntry); + } + return null; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties index 6c6f2651c9..2cd29ba2d9 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties +++ b/jdt-patch/e47/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties @@ -60,8 +60,16 @@ configure.duplicateMaxProblems = duplicate max problems specification: {0} configure.duplicateCompliance = duplicate compliance setting specification: {0} configure.duplicateSource = duplicate source compliance setting specification: {0} configure.duplicateTarget = duplicate target compliance setting specification: {0} -configure.source = source level should be comprised in between ''1.3'' and ''1.8'' (or ''5'', ''5.0'', ..., ''8'' or ''8.0''): {0} +configure.source = source level should be comprised in between ''1.3'' and ''1.9'' (or ''5'', ''5.0'', ..., ''9'' or ''9.0''): {0} +configure.invalidSystem = invalid location for system libraries: {0} +configure.unsupportedOption = option {0} not supported at compliance level 9 and above configure.duplicateOutputPath = duplicate output path specification: {0} +configure.duplicateModulePath = duplicate module path specification: {0} +configure.duplicateModuleSourcepath = duplicate source module path specification: {0} +configure.invalidModuleDescriptor = cannot open the module descriptor from {0} +configure.invalidModuleOption = incorrectly formatted option: {0} +configure.duplicateExport = can specify a package in a module only once with --add-export +configure.OneOfModuleOrSourcePath = cannot specify both -source-path and --module-source-path configure.duplicateBootClasspath = duplicate bootclasspath specification: {0} configure.duplicateExtDirs = duplicate extdirs specification: {0} configure.duplicateSourcepath = duplicate sourcepath specification: {0} @@ -69,7 +77,7 @@ configure.invalidDebugOption = invalid debug option: {0} configure.invalidWarningConfiguration = invalid warning configuration: ''{0}'' configure.invalidWarning = invalid warning token: ''{0}''. Ignoring warning and compiling configure.invalidWarningOption = invalid warning option: ''{0}''. Must specify a warning token -configure.targetJDK = target level should be comprised in between ''1.1'' and ''1.8'' (or ''5'', ''5.0'', ..., ''8'' or ''8.0'') or cldc1.1: {0} +configure.targetJDK = target level should be comprised in between ''1.1'' and ''1.9'' (or ''5'', ''5.0'', ..., ''9'' or ''9.0'') or cldc1.1: {0} configure.incompatibleTargetForSource = Target level ''{0}'' is incompatible with source level ''{1}''. A target level ''{1}'' or better is required configure.incompatibleTargetForGenericSource = Target level ''{0}'' is incompatible with source level ''{1}''. A source level ''1.5'' or better is required configure.incompatibleComplianceForSource = Compliance level ''{0}'' is incompatible with source level ''{1}''. A compliance level ''{1}'' or better is required @@ -101,6 +109,7 @@ configure.invalidTaskTag ={0} is an invalid task tag configure.incorrectExtDirsEntry = incorrect ext dir entry; {0} must be a directory configure.incorrectEndorsedDirsEntry = incorrect endorsed dir entry; {0} must be a directory configure.duplicateEndorsedDirs = duplicate endorseddirs specification: {0} +configure.missingDestinationPath = destination path must be provided with module source path configure.incorrectDestinationPathEntry = incorrect destination path entry: {0} configure.unexpectedBracket = unexpected bracket: {0} configure.unexpectedDestinationPathEntry = unexpected destination path entry in {0} option @@ -108,6 +117,7 @@ configure.unexpectedDestinationPathEntryFile = unexpected destination path entry configure.accessRuleAfterDestinationPath = access rules cannot follow destination path entries: {0} configure.duplicateDestinationPathEntry = duplicate destination path entry in {0} option configure.invalidClassName = invalid class name: {0} +configure.invalidModuleName = invalid module name: {0} configure.unavailableAPT = Unable to load annotation processing manager {0} from classpath. configure.incorrectVMVersionforAPT = Annotation processing got disabled, since it requires a 1.6 compliant JVM configure.incompatibleSourceForCldcTarget=Target level ''{0}'' is incompatible with source level ''{1}''. A source level ''1.3'' or lower is required @@ -192,6 +202,14 @@ misc.usage = {1} {2}\n\ \ If multiple default encodings are specified, the last\n\ \ one will be used.\n\ \ \n\ +\ Module compilation options:\n\ +\ These options are meaningful only in Java 9 environment or later.\n\ +\ --module-source-path \n\ +\ specify where to find source files for multiple modules\n\ +\ -p --module-path \n\ +\ specify where to find application modules\n\ +\ --system Override location of system modules\ +\ \n\ \ Compliance options:\n\ \ -1.3 use 1.3 compliance (-source 1.3 -target 1.1)\n\ \ -1.4 + use 1.4 compliance (-source 1.3 -target 1.2)\n\ @@ -199,8 +217,9 @@ misc.usage = {1} {2}\n\ \ -1.6 -6 -6.0 use 1.6 compliance (-source 1.6 -target 1.6)\n\ \ -1.7 -7 -7.0 use 1.7 compliance (-source 1.7 -target 1.7)\n\ \ -1.8 -8 -8.0 use 1.8 compliance (-source 1.8 -target 1.8)\n\ -\ -source set source level: 1.3 to 1.8 (or 5, 5.0, etc)\n\ -\ -target set classfile target: 1.1 to 1.8 (or 5, 5.0, etc)\n\ +\ -1.9 -9 -9.0 use 1.9 compliance (-source 1.9 -target 1.9)\n\ +\ -source set source level: 1.3 to 1.9 (or 6, 6.0, etc)\n\ +\ -target set classfile target: 1.1 to 1.9 (or 6, 6.0, etc)\n\ \ cldc1.1 can also be used to generate the StackMap\n\ \ attribute\n\ \ \n\ @@ -392,6 +411,7 @@ misc.usage.warn = {1} {2}\n\ \ paramAssign assignment to a parameter\n\ \ pkgDefaultMethod + attempt to override package-default method\n\ \ raw + usage of raw type\n\ +\ removal + deprecation marked for removal\n\ \ resource + (pot.) unsafe usage of resource of type Closeable\n\ \ semicolon unnecessary semicolon, empty statement\n\ \ serial + missing serialVersionUID\n\ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java index f7925b9874..129ba2bc4d 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java @@ -18,10 +18,13 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import org.codehaus.jdt.groovy.integration.LanguageSupportFactory; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jdt.core.CompletionContext; @@ -30,8 +33,11 @@ import org.eclipse.jdt.core.CompletionRequestor; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IAccessRule; +import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; @@ -42,6 +48,12 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.search.IJavaSearchConstants; +import org.eclipse.jdt.core.search.IJavaSearchScope; +import org.eclipse.jdt.core.search.SearchEngine; +import org.eclipse.jdt.core.search.SearchMatch; +import org.eclipse.jdt.core.search.SearchParticipant; +import org.eclipse.jdt.core.search.SearchPattern; +import org.eclipse.jdt.core.search.SearchRequestor; import org.eclipse.jdt.internal.codeassist.complete.CompletionNodeDetector; import org.eclipse.jdt.internal.codeassist.complete.CompletionNodeFound; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnAnnotationOfType; @@ -63,6 +75,8 @@ import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocTypeParamReference; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeyword; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeyword3; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeywordModuleDeclaration; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeywordModuleInfo; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnLocalName; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMarkerAnnotationName; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMemberAccess; @@ -71,8 +85,15 @@ import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMessageSendName; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMethodName; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMethodReturnType; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnModuleDeclaration; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnModuleReference; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnPackageReference; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnPackageVisibilityReference; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnParameterizedQualifiedTypeReference; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesImplementationsQualifiedTypeReference; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesImplementationsSingleTypeReference; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesInterfacesQualifiedTypeReference; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesInterfacesSingleTypeReference; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedAllocationExpression; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedNameReference; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedTypeReference; @@ -80,6 +101,8 @@ import org.eclipse.jdt.internal.codeassist.complete.CompletionOnSingleNameReference; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnSingleTypeReference; import org.eclipse.jdt.internal.codeassist.complete.CompletionOnStringLiteral; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnUsesQualifiedTypeReference; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnUsesSingleTypeReference; import org.eclipse.jdt.internal.codeassist.complete.CompletionParser; import org.eclipse.jdt.internal.codeassist.complete.CompletionScanner; import org.eclipse.jdt.internal.codeassist.complete.InvalidCursorLocation; @@ -123,16 +146,21 @@ import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; import org.eclipse.jdt.internal.compiler.ast.NameReference; import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; import org.eclipse.jdt.internal.compiler.ast.OperatorExpression; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; +import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression; +import org.eclipse.jdt.internal.compiler.ast.RequiresStatement; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; +import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.SuperReference; @@ -144,6 +172,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.ast.UnaryExpression; import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; +import org.eclipse.jdt.internal.compiler.ast.UsesStatement; import org.eclipse.jdt.internal.compiler.ast.WhileStatement; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; @@ -200,12 +229,15 @@ import org.eclipse.jdt.internal.core.BinaryTypeConverter; import org.eclipse.jdt.internal.core.INamingRequestor; import org.eclipse.jdt.internal.core.InternalNamingConventions; +import org.eclipse.jdt.internal.core.JavaElementRequestor; import org.eclipse.jdt.internal.core.JavaModelManager; -import org.eclipse.jdt.internal.core.SearchableEnvironment; +import org.eclipse.jdt.internal.core.ModuleSourcePathManager; import org.eclipse.jdt.internal.core.SourceMethod; import org.eclipse.jdt.internal.core.SourceMethodElementInfo; import org.eclipse.jdt.internal.core.SourceType; +import org.eclipse.jdt.internal.core.SearchableEnvironment; import org.eclipse.jdt.internal.core.SourceTypeElementInfo; +import org.eclipse.jdt.internal.core.search.BasicSearchEngine; import org.eclipse.jdt.internal.core.search.matching.IndexBasedJavaSearchEnvironment; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; @@ -679,7 +711,9 @@ private static boolean hasMemberTypesInEnclosingScope(SourceTypeBinding typeBind ProblemReporter problemReporter; private INameEnvironment noCacheNameEnvironment; char[] source; + ModuleDeclaration moduleDeclaration; char[] completionToken; + char[] qualifiedCompletionToken; boolean resolvingImports = false; boolean resolvingStaticImports = false; @@ -694,6 +728,7 @@ private static boolean hasMemberTypesInEnclosingScope(SourceTypeBinding typeBind String complianceLevel; SimpleSetOfCharArray validPackageNames = new SimpleSetOfCharArray(10); SimpleSetOfCharArray invalidPackageNames = new SimpleSetOfCharArray(1); + HashtableOfObject knownModules = new HashtableOfObject(10); HashtableOfObject knownPkgs = new HashtableOfObject(10); HashtableOfObject knownTypes = new HashtableOfObject(10); @@ -1249,6 +1284,42 @@ private void acceptConstructors(Scope scope) { this.acceptedTypes = null; // reset } } + + /** + * One result of the search consists of a new module. + * + * NOTE - All module names are presented in their readable form: + * Module names are in the form "a.b.c". + * The default module is represented by an empty array. + */ + public void acceptModule(char[] moduleName) { + if (this.knownModules.containsKey(moduleName)) return; + if (CharOperation.equals(moduleName, this.moduleDeclaration.moduleName)) return; + if (CharOperation.equals(moduleName, CharOperation.NO_CHAR)) return; + this.knownModules.put(moduleName, this); + char[] completion = moduleName; + int relevance = computeBaseRelevance(); + relevance += computeRelevanceForResolution(); + relevance += computeRelevanceForInterestingProposal(); + relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, moduleName); + relevance += computeRelevanceForQualification(true); + relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); + this.noProposal = false; + if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) { + InternalCompletionProposal proposal = createProposal(CompletionProposal.MODULE_REF, this.actualCompletionPosition); + proposal.setModuleName(moduleName); + proposal.setDeclarationSignature(moduleName); + proposal.setCompletion(completion); + proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); + proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); + proposal.setRelevance(relevance); + this.requestor.accept(proposal); + if(DEBUG) { + this.printDebug(proposal); + } + } + + } /** * One result of the search consists of a new package. @@ -1852,6 +1923,14 @@ private boolean complete( completionOnMethodReturnType(astNode, scope); } else if (astNode instanceof CompletionOnSingleNameReference) { completionOnSingleNameReference(astNode, astNodeParent, scope, insideTypeAnnotation); + } else if (astNode instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) { + completionOnProvidesInterfacesQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope); + } else if (astNode instanceof CompletionOnProvidesInterfacesSingleTypeReference) { + completionOnProvidesInterfacesSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope); + } else if (astNode instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) { + completionOnProvidesImplementationsQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope); + } else if (astNode instanceof CompletionOnProvidesImplementationsSingleTypeReference) { + completionOnProvidesImplementationsSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope); } else if (astNode instanceof CompletionOnSingleTypeReference) { completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope); } else if (astNode instanceof CompletionOnQualifiedNameReference) { @@ -1959,6 +2038,100 @@ public void complete(ICompilationUnit sourceUnit, int completionPosition, int po System.out.println(parsedUnit.toString()); } + if (parsedUnit.isModuleInfo()) { + this.moduleDeclaration = parsedUnit.moduleDeclaration; + if (this.moduleDeclaration == null) return; + if (this.moduleDeclaration instanceof CompletionOnModuleDeclaration) { + contextAccepted = true; + buildContext(parsedUnit.moduleDeclaration, null, parsedUnit, null, null); + //this.requestor.setIgnored(CompletionProposal.MODULE_DECLARATION, false); //TODO: Hack until ui fixes this issue. + if(!this.requestor.isIgnored(CompletionProposal.MODULE_DECLARATION)) { + findModuleName(parsedUnit); + } + debugPrintf(); + return; + } + if (this.moduleDeclaration instanceof CompletionOnKeywordModuleDeclaration) { + contextAccepted = true; + processModuleKeywordCompletion(parsedUnit, this.moduleDeclaration, (CompletionOnKeyword) this.moduleDeclaration); + return; + } + if (this.moduleDeclaration.exports != null) { + contextAccepted = completeOnPackageVisibilityStatements(contextAccepted, parsedUnit, this.moduleDeclaration.exports); + if (contextAccepted) return; + } + if (this.moduleDeclaration.opens != null) { + contextAccepted = completeOnPackageVisibilityStatements(contextAccepted, parsedUnit, this.moduleDeclaration.opens); + if (contextAccepted) return; + } + RequiresStatement[] moduleRefs = this.moduleDeclaration.requires; + if (moduleRefs != null) { + for (int i = 0, l = moduleRefs.length; i < l; ++i) { + ModuleReference reference = moduleRefs[i].module; + if (reference instanceof CompletionOnModuleReference) { + contextAccepted = true; + buildContext(reference, null, parsedUnit, null, null); + if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) { + findModules((CompletionOnModuleReference) reference, false /* targetted */); + } + debugPrintf(); + return; + } + } + } + UsesStatement[] uses = this.moduleDeclaration.uses; + if (uses != null) { + for (int i = 0, l = uses.length; i < l; ++i) { + TypeReference usesReference = uses[i].serviceInterface; + if (usesReference instanceof CompletionOnUsesSingleTypeReference || + usesReference instanceof CompletionOnUsesQualifiedTypeReference) { + this.lookupEnvironment.buildTypeBindings(parsedUnit, null); + if ((this.unitScope = parsedUnit.scope) != null) { + contextAccepted = true; + buildContext(usesReference, null, parsedUnit, null, null); + findTypeReferences(usesReference, true); + debugPrintf(); + return; + } + } + } + } + ProvidesStatement[] providesStmts = this.moduleDeclaration.services; + for (int i = 0, l = providesStmts != null ? providesStmts.length : 0; i < l; ++i) { + ProvidesStatement providesStmt = providesStmts[i]; + TypeReference pInterface = providesStmt.serviceInterface; + if (pInterface instanceof CompletionOnProvidesInterfacesSingleTypeReference || + pInterface instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) { + this.lookupEnvironment.buildTypeBindings(parsedUnit, null); + if ((this.unitScope = parsedUnit.scope) != null) { + contextAccepted = true; + buildContext(pInterface, null, parsedUnit, null, null); + findTypeReferences(pInterface, true); + debugPrintf(); + return; + } + } + TypeReference[] implementations = providesStmt.implementations; + for (int j = 0, k = implementations.length; j < k; ++j) { + TypeReference implementation = implementations[i]; + + if (implementation instanceof CompletionOnProvidesImplementationsSingleTypeReference || + implementation instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) { + this.lookupEnvironment.buildTypeBindings(parsedUnit, null); + if ((this.unitScope = parsedUnit.scope) != null) { + contextAccepted = true; + buildContext(implementation, null, parsedUnit, null, null); + findImplementations(providesStmt, i/* stmtIndex */, j/* implIndex */); + debugPrintf(); + return; + } + } else if (implementation instanceof CompletionOnKeyword) { + contextAccepted = true; + processModuleKeywordCompletion(parsedUnit, implementation, (CompletionOnKeyword) implementation); + } + } + } + } // scan the package & import statements first if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) { contextAccepted = true; @@ -1966,12 +2139,7 @@ public void complete(ICompilationUnit sourceUnit, int completionPosition, int po if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { findPackages((CompletionOnPackageReference) parsedUnit.currentPackage); } - if(this.noProposal && this.problem != null) { - this.requestor.completionFailure(this.problem); - if(DEBUG) { - this.printDebug(this.problem); - } - } + debugPrintf(); return; } @@ -2021,12 +2189,7 @@ public void complete(ICompilationUnit sourceUnit, int completionPosition, int po } } - if(this.noProposal && this.problem != null) { - this.requestor.completionFailure(this.problem); - if(DEBUG) { - this.printDebug(this.problem); - } - } + debugPrintf(); } return; } else if(importReference instanceof CompletionOnKeyword) { @@ -2037,12 +2200,7 @@ public void complete(ICompilationUnit sourceUnit, int completionPosition, int po CompletionOnKeyword keyword = (CompletionOnKeyword)importReference; findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, parsedUnit.currentPackage != null); } - if(this.noProposal && this.problem != null) { - this.requestor.completionFailure(this.problem); - if(DEBUG) { - this.printDebug(this.problem); - } - } + debugPrintf(); return; } } @@ -2150,6 +2308,68 @@ public void complete(ICompilationUnit sourceUnit, int completionPosition, int po } } + private boolean completeOnPackageVisibilityStatements(boolean contextAccepted, + CompilationUnitDeclaration parsedUnit, PackageVisibilityStatement[] pvsStmts) { + for (int i = 0, l = pvsStmts.length; i < l; ++i) { + PackageVisibilityStatement pvs = pvsStmts[i]; + if (pvs instanceof CompletionOnKeywordModuleInfo) { // dummy pvs statement + contextAccepted = true; + processModuleKeywordCompletion(parsedUnit, pvs, (CompletionOnKeyword) pvs); + return contextAccepted; + } + if (pvs.pkgRef instanceof CompletionOnPackageVisibilityReference) { + contextAccepted = true; + buildContext(pvs, null, parsedUnit, null, null); + if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { + findPackages((CompletionOnPackageVisibilityReference) pvs.pkgRef); + } + debugPrintf(); + return contextAccepted; + } + ModuleReference[] targets = pvs.targets; + if (targets == null) continue; + HashSet skipSet = new HashSet<>(); + for (int j = 0, lj = targets.length; j < lj; j++) { + ModuleReference target = targets[j]; + if (target == null) break; + if (target instanceof CompletionOnModuleReference) { + buildContext(target, null, parsedUnit, null, null); + contextAccepted = true; + if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) { + findTargettedModules((CompletionOnModuleReference) target, skipSet); + } + debugPrintf(); + return contextAccepted; + } else if (target instanceof CompletionOnKeyword) { + contextAccepted = true; + processModuleKeywordCompletion(parsedUnit, target, (CompletionOnKeyword) target); + } else { + if (target.moduleName != null || target.moduleName.equals(CharOperation.NO_CHAR)) + skipSet.add(new String(target.moduleName)); + } + } + } + return contextAccepted; + } + + private void debugPrintf() { + if(this.noProposal && this.problem != null) { + this.requestor.completionFailure(this.problem); + if(DEBUG) { + this.printDebug(this.problem); + } + } + } + + private void processModuleKeywordCompletion(CompilationUnitDeclaration parsedUnit, ASTNode node, CompletionOnKeyword keyword) { + buildContext(node, null, parsedUnit, null, null); + if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { + setSourceAndTokenRange(node.sourceStart, node.sourceEnd); + findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, parsedUnit.currentPackage != null); + } + debugPrintf(); + } + public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){ if(this.requestor != null){ this.requestor.beginReporting(); @@ -3396,6 +3616,16 @@ private void completionOnQualifiedTypeReference(ASTNode astNode, ASTNode astNode } } + private void completionOnProvidesInterfacesQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) { + // TODO: Filter the results wrt accessibility and add relevance to the results. + completionOnQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope); + } + + private void completionOnProvidesImplementationsQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) { + // TODO: Filter the results wrt accessibility and add relevance to the results. + completionOnQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope); + } + private void completionOnSingleNameReference(ASTNode astNode, ASTNode astNodeParent, Scope scope, boolean insideTypeAnnotation) { CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode; @@ -3529,6 +3759,15 @@ private void completionOnSingleTypeReference(ASTNode astNode, ASTNode astNodePar } } + private void completionOnProvidesInterfacesSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) { + // TODO : filter the results. + completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope); + } + private void completionOnProvidesImplementationsSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) { + // TODO : filter the results. + completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope); + } + private char[][] computeAlreadyDefinedName( BlockScope scope, InvocationSite invocationSite) { @@ -10094,7 +10333,7 @@ private char[][] findMethodParameterNames(MethodBinding method, char[][] paramet sourceType = (ISourceType) type; } } else { - NameEnvironmentAnswer answer = this.nameEnvironment.findType(bindingType.compoundName); + NameEnvironmentAnswer answer = this.nameEnvironment.findTypeInModules(bindingType.compoundName, this.unitScope.module()); if(answer != null && answer.isSourceType()) { sourceType = answer.getSourceTypes()[0]; this.typeCache.put(compoundName, sourceType); @@ -10384,12 +10623,84 @@ private void findNestedTypes( } } - private void findPackages(CompletionOnPackageReference packageStatement) { + private void findModuleName(CompilationUnitDeclaration parsedUnit) { + char[] fileName1 = parsedUnit.getFileName(); + if (fileName1 == null || !CharOperation.endsWith(fileName1, MODULE_INFO_FILE_NAME)) return; + int lastFileSeparatorIndex = fileName1.length - (MODULE_INFO_FILE_NAME.length + 1); + if (lastFileSeparatorIndex <= 0) return; + int prevFileSeparatorIndex = CharOperation.lastIndexOf(fileName1[lastFileSeparatorIndex], fileName1, 0, lastFileSeparatorIndex - 1); + prevFileSeparatorIndex = prevFileSeparatorIndex < 0 ? 0 : prevFileSeparatorIndex + 1; + char[] moduleName = CharOperation.subarray(fileName1, prevFileSeparatorIndex, lastFileSeparatorIndex); + if (moduleName == null || moduleName.length == 0) return; + this.completionToken = CharOperation.concatWith(this.moduleDeclaration.tokens, '.'); + if (this.completionToken.length > 0 && !CharOperation.prefixEquals(this.completionToken, moduleName)) return; + + InternalCompletionProposal proposal = createProposal(CompletionProposal.MODULE_DECLARATION, this.actualCompletionPosition); + proposal.setName(moduleName); + proposal.setCompletion(moduleName); + proposal.setReplaceRange((this.startPosition < 0) ? 0 : this.startPosition - this.offset, this.endPosition - this.offset); + proposal.setTokenRange((this.tokenStart < 0) ? 0 : this.tokenStart - this.offset, this.tokenEnd - this.offset); + proposal.setRelevance(R_MODULE_DECLARATION); + this.requestor.accept(proposal); + if(DEBUG) { + this.printDebug(proposal); + } + } + + private void findTargettedModules(char[] prefix, HashSet skipSet) { + ModuleSourcePathManager mManager = JavaModelManager.getModulePathManager(); + JavaElementRequestor javaElementRequestor = new JavaElementRequestor(); + try { + mManager.seekModule(this.completionToken, true, javaElementRequestor); + IModuleDescription[] modules = javaElementRequestor.getModules(); + for (IModuleDescription module : modules) { + String name = module.getElementName(); + if (name == null || name.equals("") || skipSet.contains(name)) //$NON-NLS-1$ + continue; + this.acceptModule(name.toCharArray()); + } + } catch (JavaModelException e) { + // TODO ignore for now + } + } + private void findTargettedModules(CompletionOnModuleReference moduleReference, HashSet skipSet) { + setCompletionToken(moduleReference.tokens, moduleReference.sourceStart, moduleReference.sourceEnd, moduleReference.sourcePositions); + findTargettedModules(CharOperation.toLowerCase(this.completionToken), skipSet); + } + private void setCompletionToken(char[][] tokens, int sourceStart, int sourceEnd, long[] sourcePositions, boolean without) { + this.completionToken = without ? CharOperation.concatWith(tokens, '.') : CharOperation.concatWithAll(tokens, '.'); + if (this.completionToken.length == 0) + this.completionToken = CharOperation.ALL_PREFIX; + setSourceRange(sourceStart, sourceEnd); + long completionPosition = sourcePositions[sourcePositions.length - 1]; + setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); + } + private void setCompletionToken(char[][] tokens, int sourceStart, int sourceEnd, long[] sourcePositions) { + setCompletionToken(tokens, sourceStart, sourceEnd, sourcePositions, true); + } + private void findModules(CompletionOnModuleReference moduleReference, boolean targetted) { + setCompletionToken(moduleReference.tokens, moduleReference.sourceStart, moduleReference.sourceEnd, moduleReference.sourcePositions); + findTargettedModules(moduleReference, new HashSet<>()); // empty skipSet passed + this.nameEnvironment.findModules(CharOperation.toLowerCase(this.completionToken), this, targetted ? this.javaProject : null); + } + private void findPackages(CompletionOnPackageVisibilityReference reference) { + setCompletionToken(reference.tokens, reference.sourceStart, reference.sourceEnd, reference.sourcePositions, false); + findPackagesInCurrentModule(); + } + + private void findPackagesInCurrentModule() { + try { + IPackageFragmentRoot[] moduleRoots = SearchableEnvironment.getOwnedPackageFragmentRoots(this.javaProject); + this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this, moduleRoots); + } catch (JavaModelException e) { + // silent + } + } + private void findPackages(CompletionOnPackageReference packageStatement) { this.completionToken = CharOperation.concatWithAll(packageStatement.tokens, '.'); if (this.completionToken.length == 0) return; - setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd); long completionPosition = packageStatement.sourcePositions[packageStatement.sourcePositions.length - 1]; setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); @@ -10728,15 +11039,15 @@ private void findTypesAndPackages(char[] token, Scope scope, boolean proposeBase hasArrayTypeAsExpectedSuperTypes()) { char[] typeName = sourceType.sourceName(); createTypeProposal( - sourceType, - typeName, - IAccessRule.K_ACCESSIBLE, - typeName, - relevance, - null, - null, - null, - false); + sourceType, + typeName, + IAccessRule.K_ACCESSIBLE, + typeName, + relevance, + null, + null, + null, + false); } if (proposeConstructor) { @@ -11304,6 +11615,7 @@ private void findTypesFromImports(char[] token, Scope scope, boolean proposeType private void findTypesFromStaticImports(char[] token, Scope scope, boolean proposeAllMemberTypes, ObjectVector typesFound) { ImportBinding[] importBindings = scope.compilationUnitScope().imports; + if (importBindings == null) return; for (int i = 0; i < importBindings.length; i++) { ImportBinding importBinding = importBindings[i]; if(importBinding.isValidBinding() && importBinding.isStatic()) { @@ -11543,6 +11855,138 @@ public void acceptName(char[] name) { return null; } + private void findTypeReferences(TypeReference reference, boolean findMembers) { + char[][] tokens = reference.getTypeName(); + + char[] typeName = CharOperation.concatWithAll(tokens, '.'); + + if (typeName.length == 0) { + this.completionToken = new char[] {'*'}; + } else if (reference instanceof CompletionOnUsesQualifiedTypeReference || + reference instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) { + CompletionOnQualifiedTypeReference qReference = (CompletionOnQualifiedTypeReference) reference; + if (qReference.completionIdentifier != null) { + this.completionToken = CharOperation.concatAll(typeName, qReference.completionIdentifier, '.'); + } + } else { + char[] lastToken = tokens[tokens.length - 1]; + this.completionToken = lastToken != null && lastToken.length == 0 ? + CharOperation.concat(typeName, new char[]{'.'}) :lastToken; + } + setSourceRange(reference.sourceStart, reference.sourceEnd); + findTypesAndPackages(this.completionToken, this.unitScope, true, true, new ObjectVector()); + } + + private void findImplementations(ProvidesStatement providesStmt, int stmtIndex, int implIndex) { + TypeReference reference = providesStmt.implementations[implIndex]; + char[][] tokens = reference.getTypeName(); + char[] typeName = CharOperation.concatWithAll(tokens, '.'); + + if (typeName.length == 0) { + this.completionToken = CharOperation.ALL_PREFIX; + } else if (reference instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) { + CompletionOnQualifiedTypeReference qReference = (CompletionOnQualifiedTypeReference) reference; + if (qReference.completionIdentifier != null) { + this.completionToken = CharOperation.concatAll(typeName, qReference.completionIdentifier, '.'); + } + } else { + char[] lastToken = tokens[tokens.length - 1]; + this.completionToken = lastToken != null && lastToken.length == 0 ? + CharOperation.concat(typeName, new char[]{'.'}) :lastToken; + } + setSourceRange(reference.sourceStart, reference.sourceEnd); + findImplementations(this.completionToken, this.unitScope, providesStmt, stmtIndex); + } + + private void findImplementations(char[] token, Scope scope, ProvidesStatement providesStmt, int stmtIndex) { + + TypeReference theInterface = providesStmt.serviceInterface; + + if (token == null) return; + char[][] theInterfaceType = theInterface.getTypeName(); + if (theInterfaceType == null) return; + SearchPattern pattern = null; + NameEnvironmentAnswer answer = this.nameEnvironment.findTypeInModules(theInterfaceType, scope.module()); + if (answer != null ) { + if (answer.isSourceType()) { + IType typeHandle = ((SourceTypeElementInfo) answer.getSourceTypes()[0]).getHandle(); + pattern = SearchPattern.createPattern(typeHandle, IJavaSearchConstants.IMPLEMENTORS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); + } else if (answer.isBinaryType()) { + String typeName = new String(CharOperation.replaceOnCopy(answer.getBinaryType().getName(), '/', '.')); + pattern = SearchPattern.createPattern(typeName, + IJavaSearchConstants.CLASS_AND_INTERFACE, + IJavaSearchConstants.IMPLEMENTORS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); + } + } + if (pattern == null) return; + IJavaSearchScope searchScope = BasicSearchEngine.createJavaSearchScope(new IJavaElement[] {this.javaProject}); + class ImplSearchRequestor extends SearchRequestor { + String prefix; + List filter; + public List types = new ArrayList<>(); + public ImplSearchRequestor(char[] prefixToken, List filter) { + this.prefix = (prefixToken == CharOperation.ALL_PREFIX) ? null : new String(prefixToken); + this.filter = filter; + } + @Override + public void acceptSearchMatch(SearchMatch match) throws CoreException { + checkCancel(); + IJavaElement element = ((IJavaElement) match.getElement()); + if (element.getElementType() == IJavaElement.TYPE) { + IType type = (IType) element; + if (this.prefix != null) { + String fullTypeName = type.getPackageFragment().getElementName(); + if (fullTypeName != null) { + fullTypeName = fullTypeName.concat(".").concat(type.getElementName()); //$NON-NLS-1$ + } else { + fullTypeName = type.getElementName(); + } + if (!fullTypeName.startsWith(this.prefix) || this.filter.contains(fullTypeName)) return; + } + this.types.add(type); + } + } + } + try { + List existingImpl = new ArrayList<>(); + char[][] theInterfaceName = theInterface.getTypeName(); + // filter out existing implementations of the same interfaces + for (int i = 0, l = this.moduleDeclaration.servicesCount; i < l; ++i) { + if (i == stmtIndex) continue; + ProvidesStatement prevProvides = this.moduleDeclaration.services[i]; + if (!CharOperation.equals(theInterfaceName, prevProvides.serviceInterface.getTypeName())) continue; + TypeReference[] prevImpls = prevProvides.implementations; + for (TypeReference prevImpl : prevImpls) { + char[][] typeName = prevImpl.getTypeName(); + if (typeName.equals(CharOperation.NO_CHAR_CHAR)) continue; + existingImpl.add(CharOperation.toString(typeName)); + } + } + // use search infrastructure - faster than using model + ImplSearchRequestor searchRequestor = new ImplSearchRequestor(this.completionToken, existingImpl); + new SearchEngine(this.owner == null ? null : JavaModelManager.getJavaModelManager().getWorkingCopies(this.owner, true/*add primary WCs*/)).search( + pattern, + new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, + searchScope, + searchRequestor, + null + ); + for (IType type : searchRequestor.types) { + String pkg = type.getPackageFragment().getElementName(); + String name = type.getElementName(); + this.acceptType(pkg.toCharArray(), name.toCharArray(), CharOperation.NO_CHAR_CHAR, type.getFlags(), null); + acceptTypes(scope); + } + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { + checkCancel(); + findPackagesInCurrentModule(); + } + } + private char[][] findVariableFromUnresolvedReference(LocalDeclaration variable, BlockScope scope, final char[][] discouragedNames) { final TypeReference type = variable.type; if(type != null && @@ -12234,6 +12678,11 @@ protected boolean hasPossibleAnnotationTarget(TypeBinding typeBinding, Scope sco if(target != 0 && (target & TagBits.AnnotationForPackage) == 0) { return false; } + } else if (this.targetedElement == TagBits.AnnotationForModule) { + long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK; + if(target != 0 && (target & TagBits.AnnotationForModule) == 0) { + return false; + } } else if ((this.targetedElement & (TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0) { if (scope.parent != null && scope.parent.parent != null && @@ -13037,6 +13486,7 @@ protected void reset() { super.reset(false); this.validPackageNames = new SimpleSetOfCharArray(10); this.invalidPackageNames = new SimpleSetOfCharArray(1); + this.knownModules = new HashtableOfObject(10); this.knownPkgs = new HashtableOfObject(10); this.knownTypes = new HashtableOfObject(10); if (this.noCacheNameEnvironment != null) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java index 23beccc90d..f87241b634 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java @@ -90,4 +90,6 @@ public void acceptConstructor( * The default package is represented by an empty array. */ public void acceptPackage(char[] packageName); + + public void acceptModule(char[] moduleName); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java index cd0b4bb129..9bf0875529 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -51,6 +51,20 @@ void acceptType( int start, int end); + /** + * Code assist notification of a module selection. + * + * @param moduleName name of the module + * @param uniqueKey unique key of this module + * @param start Start of the selection + * @param end End of the selection + */ + void acceptModule( + char[] moduleName, + char[] uniqueKey, + int start, + int end); + /** * Code assist notification of a compilation error detected during selection. * @param error CategorizedProblem diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java index b2427c4a83..2cb39bee42 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2015 IBM Corporation and others. + * Copyright (c) 2004, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -36,6 +36,7 @@ import org.eclipse.jdt.internal.core.JavaElement; import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.NameLookup; +import org.eclipse.jdt.internal.core.NamedMember; import org.eclipse.jdt.internal.core.SourceMapper; /** @@ -50,6 +51,7 @@ public class InternalCompletionProposal extends CompletionProposal { protected char[] declarationPackageName; protected char[] declarationTypeName; + protected char[] moduleName; protected char[] packageName; protected char[] typeName; protected char[][] parameterPackageNames; @@ -243,7 +245,7 @@ this.completionEngine.openedBinaryTypes < getOpenedBinaryTypesThreshold()) { IBinaryType info = (IBinaryType) ((BinaryType) type).getElementInfo(); char[] source = mapper.findSource(type, info); if (source != null){ - mapper.mapSource(type, source, info); + mapper.mapSource((NamedMember) type, source, info); } paramNames = mapper.getMethodParameterNames(method); } @@ -377,6 +379,10 @@ private int getOpenedBinaryTypesThreshold() { return JavaModelManager.getJavaModelManager().getOpenableCacheSize() / 10; } + protected char[] getModuleName() { + return this.moduleName; + } + protected char[] getPackageName() { return this.packageName; } @@ -402,6 +408,10 @@ protected void setDeclarationTypeName(char[] declarationTypeName) { this.declarationTypeName = declarationTypeName; } + protected void setModuleName(char[] moduleName) { + this.moduleName = moduleName; + } + protected void setPackageName(char[] packageName) { this.packageName = packageName; } @@ -826,7 +836,7 @@ public char[] getDeclarationKey() { } /** - * Sets the type or package signature of the relevant + * Sets the type or package or module(1.9) signature of the relevant * declaration in the context, or null if none. *

* If not set, defaults to none. @@ -836,7 +846,7 @@ public char[] getDeclarationKey() { * its properties; this method is not intended to be used by other clients. *

* - * @param signature the type or package signature, or + * @param signature the type or package or module(1.9) signature, or * null if none */ public void setDeclarationSignature(char[] signature) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/MissingTypesGuesser.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/MissingTypesGuesser.java index 1d2c010fa3..16dcd1ee01 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/MissingTypesGuesser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/MissingTypesGuesser.java @@ -477,6 +477,10 @@ public void acceptConstructor( AccessRestriction access) { // constructors aren't searched } + @Override + public void acceptModule(char[] moduleName) { + // TODO Auto-generated method stub + } public void acceptPackage(char[] packageName) { // package aren't searched } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java index 97f8a5e458..eb00196136 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java @@ -56,4 +56,5 @@ public interface RelevanceConstants { int R_TARGET = 5; int R_FINAL = 3; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 int R_CONSTRUCTOR = 3; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=373409 + int R_MODULE_DECLARATION = 31; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java index a975ad25ab..d486cea4c8 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,6 +18,7 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jdt.core.IBuffer; +import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IOpenable; @@ -40,6 +41,7 @@ import org.eclipse.jdt.internal.codeassist.impl.Engine; import org.eclipse.jdt.internal.codeassist.select.SelectionJavadocParser; import org.eclipse.jdt.internal.codeassist.select.SelectionNodeFound; +import org.eclipse.jdt.internal.codeassist.select.SelectionOnPackageVisibilityReference; import org.eclipse.jdt.internal.codeassist.select.SelectionOnImportReference; import org.eclipse.jdt.internal.codeassist.select.SelectionOnPackageReference; import org.eclipse.jdt.internal.codeassist.select.SelectionOnQualifiedTypeReference; @@ -55,6 +57,8 @@ import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeParameter; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; @@ -75,15 +79,18 @@ import org.eclipse.jdt.internal.compiler.lookup.MemberTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.parser.Scanner; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; @@ -539,7 +546,8 @@ private void acceptQualifiedTypes() { private boolean checkSelection( char[] source, int selectionStart, - int selectionEnd) { + int selectionEnd, + boolean isModuleInfo) { Scanner scanner = new Scanner( @@ -628,7 +636,7 @@ private boolean checkSelection( } // compute start and end of the last token - scanner.resetTo(nextCharacterPosition, end); + scanner.resetTo(nextCharacterPosition, end, isModuleInfo); isolateLastName: do { try { token = scanner.getNextToken(); @@ -678,7 +686,7 @@ private boolean checkSelection( } } } // there could be some innocuous widening, shouldn't matter. - scanner.resetTo(selectionStart, selectionEnd); + scanner.resetTo(selectionStart, selectionEnd, isModuleInfo); boolean expectingIdentifier = true; do { @@ -940,7 +948,8 @@ public void select( System.out.println("SELECTION - Source :"); //$NON-NLS-1$ System.out.println(source); } - if (!checkSelection(source, selectionSourceStart, selectionSourceEnd)) { + boolean isModuleInfo = CharOperation.endsWith(sourceUnit.getFileName(), TypeConstants.MODULE_INFO_FILE_NAME); + if (!checkSelection(source, selectionSourceStart, selectionSourceEnd, isModuleInfo)) { return; } if (DEBUG) { @@ -1015,14 +1024,21 @@ public void select( } } } - if (parsedUnit.types != null || parsedUnit.isPackageInfo()) { - if(selectDeclaration(parsedUnit)) - return; - this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); - if ((this.unitScope = parsedUnit.scope) != null) { - try { + try { + if (parsedUnit.isModuleInfo() && parsedUnit.moduleDeclaration != null) { + ModuleDeclaration module = parsedUnit.moduleDeclaration; + this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); + module.resolveModuleDirectives(parsedUnit.scope); + module.resolvePackageDirectives(parsedUnit.scope); + module.resolveTypeDirectives(parsedUnit.scope); + acceptPackageVisibilityStatements(module.exports, parsedUnit.scope); + acceptPackageVisibilityStatements(module.opens, parsedUnit.scope); + } else if (parsedUnit.types != null || parsedUnit.isPackageInfo()) { + if(selectDeclaration(parsedUnit)) + return; + this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); + if ((this.unitScope = parsedUnit.scope) != null) { this.lookupEnvironment.completeTypeBindings(parsedUnit, true); - CompilationUnitDeclaration previousUnitBeingCompleted = this.lookupEnvironment.unitBeingCompleted; this.lookupEnvironment.unitBeingCompleted = parsedUnit; parsedUnit.scope.faultInTypes(); @@ -1038,17 +1054,17 @@ public void select( if (node != null) { selectLocalDeclaration(node); } - } catch (SelectionNodeFound e) { - if (e.binding != null) { - if(DEBUG) { - System.out.println("SELECTION - Selection binding:"); //$NON-NLS-1$ - System.out.println(e.binding.toString()); - } - // if null then we found a problem in the selection node - selectFrom(e.binding, parsedUnit, sourceUnit, e.isDeclaration); - } } } + } catch (SelectionNodeFound e) { + if (e.binding != null) { + if(DEBUG) { + System.out.println("SELECTION - Selection binding:"); //$NON-NLS-1$ + System.out.println(e.binding.toString()); + } + // if null then we found a problem in the selection node + selectFrom(e.binding, parsedUnit, sourceUnit, e.isDeclaration); + } } } // only reaches here if no selection could be derived from the parsed tree @@ -1084,6 +1100,16 @@ public void select( } } + private void acceptPackageVisibilityStatements(PackageVisibilityStatement[] pvs, Scope scope) { + if (pvs != null) { + for (PackageVisibilityStatement pv : pvs) { + if (pv.pkgRef instanceof SelectionOnPackageVisibilityReference) { + this.noProposal = false; + this.requestor.acceptPackage(CharOperation.concatWith(((SelectionOnPackageVisibilityReference) pv.pkgRef).tokens, '.')); + } + } + } + } private void selectMemberTypeFromImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref, boolean staticOnly) { int fieldLength = lastToken.length; ReferenceBinding[] memberTypes = ref.memberTypes(); @@ -1349,6 +1375,15 @@ private void selectFrom(Binding binding, CompilationUnitDeclaration parsedUnit, this.acceptedAnswer = true; } else if(binding instanceof BaseTypeBinding) { this.acceptedAnswer = true; + } else if (binding instanceof ModuleBinding) { + this.noProposal = false; + ModuleBinding moduleBinding = (ModuleBinding) binding; + this.requestor.acceptModule( + moduleBinding.moduleName, + moduleBinding.computeUniqueKey(), + this.actualSelectionStart, + this.actualSelectionEnd); + this.acceptedAnswer = true; } } /* @@ -1486,26 +1521,29 @@ public void selectType(char[] typeName, IType context) throws JavaModelException typeDeclaration = new ASTNodeFinder(parsedUnit).findType(context); } } else { // binary type - ClassFile classFile = (ClassFile) context.getClassFile(); - BinaryTypeDescriptor descriptor = BinaryTypeFactory.createDescriptor(classFile); - ClassFileReader reader = null; - try { - reader = BinaryTypeFactory.rawReadType(descriptor, false/*don't fully initialize so as to keep constant pool (used below)*/); - } catch (ClassFormatException e) { - if (JavaCore.getPlugin().isDebugging()) { - e.printStackTrace(System.err); + IClassFile iClassFile = context.getClassFile(); + if (iClassFile instanceof ClassFile) { + ClassFile classFile = (ClassFile) iClassFile; + BinaryTypeDescriptor descriptor = BinaryTypeFactory.createDescriptor(classFile); + ClassFileReader reader = null; + try { + reader = BinaryTypeFactory.rawReadType(descriptor, false/*don't fully initialize so as to keep constant pool (used below)*/); + } catch (ClassFormatException e) { + if (JavaCore.getPlugin().isDebugging()) { + e.printStackTrace(System.err); + } } + if (reader == null) { + throw classFile.newNotPresentException(); + } + CompilationResult result = new CompilationResult(reader.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit); + parsedUnit = new CompilationUnitDeclaration(this.parser.problemReporter(), result, 0); + HashSetOfCharArrayArray typeNames = new HashSetOfCharArrayArray(); + + BinaryTypeConverter converter = new BinaryTypeConverter(this.parser.problemReporter(), result, typeNames); + typeDeclaration = converter.buildTypeDeclaration(context, parsedUnit); + parsedUnit.imports = converter.buildImports(reader); } - if (reader == null) { - throw classFile.newNotPresentException(); - } - CompilationResult result = new CompilationResult(reader.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit); - parsedUnit = new CompilationUnitDeclaration(this.parser.problemReporter(), result, 0); - HashSetOfCharArrayArray typeNames = new HashSetOfCharArrayArray(); - - BinaryTypeConverter converter = new BinaryTypeConverter(this.parser.problemReporter(), result, typeNames); - typeDeclaration = converter.buildTypeDeclaration(context, parsedUnit); - parsedUnit.imports = converter.buildImports(reader); } if (typeDeclaration != null) { @@ -1913,4 +1951,10 @@ private Object visitInheritDocInterfaces(ArrayList visited, ReferenceBinding cur return InheritDocVisitor.CONTINUE; } } + + @Override + public void acceptModule(char[] moduleName) { + // TODO Auto-generated method stub + + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExportReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExportReference.java new file mode 100644 index 0000000000..0f8ff294f2 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExportReference.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.jdt.internal.codeassist.complete; + +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; +import org.eclipse.jdt.internal.compiler.ast.ImportReference; +/* + * Completion node build by the parser in any case it was intending to + * reduce an exports reference containing the cursor location. + * e.g. + * + * module myModule { + * exports packageo[cursor]; + * } + * + * module myModule { + * ---> + * } + * + * The source range is always of length 0. + * The arguments of the allocation expression are all the arguments defined + * before the cursor. + */ + +public class CompletionOnExportReference extends ExportsStatement { + + public CompletionOnExportReference(ImportReference ref) { + super(ref, null); + } + public StringBuffer print(int indent, StringBuffer output) { + + printIndent(indent, output).append("'); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModule2.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModule2.java new file mode 100644 index 0000000000..21f282a289 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModule2.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; + +public class CompletionOnKeywordModule2 extends ModuleReference implements CompletionOnKeyword { + private char[] token; + private char[][] possibleKeywords; + + public CompletionOnKeywordModule2(char[] token, long pos, char[][] possibleKeywords) { + super(new char[][] {token}, new long[] {pos}); // dummy + this.token = token; + this.possibleKeywords = possibleKeywords; + this.sourceStart = (int) (pos>>>32) ; + this.sourceEnd = (int) (pos & 0x00000000FFFFFFFFL); + } + + @Override + public char[] getToken() { + return this.token; + } + + @Override + public char[][] getPossibleKeywords() { + return this.possibleKeywords; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleDeclaration.java new file mode 100644 index 0000000000..3650305f1d --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleDeclaration.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; + +public class CompletionOnKeywordModuleDeclaration extends ModuleDeclaration implements CompletionOnKeyword { + + private char[] token; + private char[][] possibleKeywords; + + public CompletionOnKeywordModuleDeclaration(char[] token, long pos, char[][] possibleKeywords) { + super(null, new char[][]{token}, new long[]{pos}); + this.token = token; + this.possibleKeywords = possibleKeywords; + } + + @Override + public char[] getToken() { + return this.token; + } + + @Override + public char[][] getPossibleKeywords() { + return this.possibleKeywords; + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleInfo.java new file mode 100644 index 0000000000..91d6f4f0e0 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleInfo.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; +import org.eclipse.jdt.internal.compiler.ast.ImportReference; + +/** + * + * This class is independent of its parent class and is in fact a dummy ExportsStatement. Used to hook + * into the existing module declaration type and is used as a placeholder for keyword completion. This can + * be any module keyword completion and not necessarily related to exports statement. + */ +public class CompletionOnKeywordModuleInfo extends ExportsStatement implements CompletionOnKeyword { + private char[] token; + private char[][] possibleKeywords; + + public CompletionOnKeywordModuleInfo(char[] token, long pos, char[][] possibleKeywords) { + super(new ImportReference(new char[][] {token}, new long[] {pos}, false, 0), null); // dummy + this.token = token; + this.possibleKeywords = possibleKeywords; + this.sourceStart = (int) (pos>>>32) ; + this.sourceEnd = (int) (pos & 0x00000000FFFFFFFFL); + } + + @Override + public char[] getToken() { + return this.token; + } + + @Override + public char[][] getPossibleKeywords() { + return this.possibleKeywords; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleDeclaration.java new file mode 100644 index 0000000000..763b861d38 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleDeclaration.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; + +public class CompletionOnModuleDeclaration extends ModuleDeclaration { + + public CompletionOnModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions) { + super(compilationResult, tokens, positions); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleReference.java new file mode 100644 index 0000000000..7ccea8c491 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleReference.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; + +public class CompletionOnModuleReference extends ModuleReference { + + public CompletionOnModuleReference(char[] ident, long pos) { + this(new char[][]{ident}, new long[]{pos}); + } + public CompletionOnModuleReference(char[][] tokens, long[] sourcePositions) { + super(tokens, sourcePositions); + } + + public ModuleBinding resolve(Scope scope) { + super.resolve(scope); +// if (this.binding != null) { +// throw new CompletionNodeFound(this, this.binding, scope); +// } else { + throw new CompletionNodeFound(); + //} + } + public StringBuffer print(int indent, StringBuffer output) { + + printIndent(indent, output).append(" 0) output.append('.'); + output.append(this.tokens[i]); + } + return output.append('>'); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageVisibilityReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageVisibilityReference.java new file mode 100644 index 0000000000..aad83580e3 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageVisibilityReference.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.jdt.internal.codeassist.complete; + +import org.eclipse.jdt.core.compiler.CharOperation; + +/* + * Completion node build by the parser in any case it was intending to + * reduce an exports or an opens reference containing the cursor location. + * e.g. + * + * module myModule { + * exports packageo[cursor]; + * opens packageo[cursor]; + + * } + * + * module myModule { + * ---> + * } + * + * The source range is always of length 0. + * The arguments of the allocation expression are all the arguments defined + * before the cursor. + */ + +public class CompletionOnPackageVisibilityReference extends CompletionOnImportReference { + + String pkgName; + public CompletionOnPackageVisibilityReference(char[][] ident, long[] pos) { + super(ident, pos, 0); + this.pkgName = new String(CharOperation.concatWith(ident, '.')); + } + + public StringBuffer print(int indent, StringBuffer output) { + printIndent(indent, output).append("'); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsQualifiedTypeReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsQualifiedTypeReference.java new file mode 100644 index 0000000000..8564a037d8 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsQualifiedTypeReference.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +public class CompletionOnProvidesImplementationsQualifiedTypeReference extends CompletionOnQualifiedTypeReference { + + public CompletionOnProvidesImplementationsQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, + long[] positions) { + super(previousIdentifiers, completionIdentifier, positions); + } + +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsSingleTypeReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsSingleTypeReference.java new file mode 100644 index 0000000000..420fffecf8 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsSingleTypeReference.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +public class CompletionOnProvidesImplementationsSingleTypeReference extends CompletionOnSingleTypeReference { + public CompletionOnProvidesImplementationsSingleTypeReference(char[] source, long pos) { + super(source, pos); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesQualifiedTypeReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesQualifiedTypeReference.java new file mode 100644 index 0000000000..180c0cac5e --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesQualifiedTypeReference.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +public class CompletionOnProvidesInterfacesQualifiedTypeReference extends CompletionOnQualifiedTypeReference { + + public CompletionOnProvidesInterfacesQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, + long[] positions) { + super(previousIdentifiers, completionIdentifier, positions); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesSingleTypeReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesSingleTypeReference.java new file mode 100644 index 0000000000..1d080993fa --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesSingleTypeReference.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.complete; + +public class CompletionOnProvidesInterfacesSingleTypeReference extends CompletionOnSingleTypeReference { + public CompletionOnProvidesInterfacesSingleTypeReference(char[] source, long pos) { + super(source, pos); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesQualifiedTypeReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesQualifiedTypeReference.java new file mode 100644 index 0000000000..ae5a64ccb5 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesQualifiedTypeReference.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/package org.eclipse.jdt.internal.codeassist.complete; + +public class CompletionOnUsesQualifiedTypeReference extends CompletionOnQualifiedTypeReference { + + public CompletionOnUsesQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, + long[] positions) { + super(previousIdentifiers, completionIdentifier, positions); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesSingleTypeReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesSingleTypeReference.java new file mode 100644 index 0000000000..2cc19b29f2 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesSingleTypeReference.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/package org.eclipse.jdt.internal.codeassist.complete; + +public class CompletionOnUsesSingleTypeReference extends CompletionOnSingleTypeReference { + + public CompletionOnUsesSingleTypeReference(char[] source, long pos) { + super(source, pos); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java index 8b4af64bbd..ebf52c6e76 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java @@ -85,6 +85,14 @@ public class CompletionParser extends AssistParser { // added for https://bugs.eclipse.org/bugs/show_bug.cgi?id=261534 protected static final int K_BETWEEN_INSTANCEOF_AND_RPAREN = COMPLETION_PARSER + 41; protected static final int K_INSIDE_IMPORT_STATEMENT = COMPLETION_PARSER + 43; + protected static final int K_INSIDE_EXPORTS_STATEMENT = COMPLETION_PARSER + 44; + protected static final int K_INSIDE_REQUIRES_STATEMENT = COMPLETION_PARSER + 45; + protected static final int K_INSIDE_USES_STATEMENT = COMPLETION_PARSER + 46; + protected static final int K_INSIDE_PROVIDES_STATEMENT = COMPLETION_PARSER + 47; + protected static final int K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT = COMPLETION_PARSER + 48; + protected static final int K_AFTER_NAME_IN_PROVIDES_STATEMENT = COMPLETION_PARSER + 49; + protected static final int K_AFTER_WITH_IN_PROVIDES_STATEMENT = COMPLETION_PARSER + 50; + protected static final int K_INSIDE_OPENS_STATEMENT = COMPLETION_PARSER + 51; public final static char[] FAKE_TYPE_NAME = new char[]{' '}; @@ -249,16 +257,17 @@ protected void attachOrphanCompletionNode(){ if (this.currentElement instanceof RecoveredUnit){ if (orphan instanceof ImportReference){ this.currentElement.add((ImportReference)orphan, 0); + } else if (orphan instanceof ModuleDeclaration) { + this.currentElement.add((ModuleDeclaration)orphan, 0); } - } - - /* if in context of a type, then persists the identifier into a fake field return type */ - if (this.currentElement instanceof RecoveredType){ + } else if (this.currentElement instanceof RecoveredType){ /* if in context of a type, then persists the identifier into a fake field return type */ RecoveredType recoveredType = (RecoveredType)this.currentElement; /* filter out cases where scanner is still inside type header */ if (recoveredType.foundOpeningBrace) { /* generate a pseudo field with a completion on type reference */ if (orphan instanceof TypeReference){ + if (isInsideModuleInfo()) return; //taken care elsewhere + TypeReference fieldType; int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER); @@ -1455,6 +1464,7 @@ private boolean checkClassLiteralAccess() { private boolean checkKeyword() { if (this.currentElement instanceof RecoveredUnit) { RecoveredUnit unit = (RecoveredUnit) this.currentElement; + if (unit.unitDeclaration.isModuleInfo()) return false; int index = -1; if ((index = this.indexOfAssistIdentifier()) > -1) { int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1; @@ -1517,6 +1527,78 @@ private boolean checkKeyword() { } return false; } + +private enum ModuleKeyword { + FIRST_ALL, + TO, + PROVIDES_WITH, + NOT_A_KEYWORD +} + +private ModuleKeyword getKeyword() { + ModuleKeyword keyword = ModuleKeyword.FIRST_ALL; + if (isInModuleStatements()) { + if (foundToken(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT)) keyword = ModuleKeyword.TO; + else if (foundToken(K_AFTER_NAME_IN_PROVIDES_STATEMENT)) keyword = ModuleKeyword.PROVIDES_WITH; + else keyword = ModuleKeyword.NOT_A_KEYWORD; + } + return keyword; +} +private char[][] getModuleKeywords(ModuleKeyword keyword) { + if (keyword == ModuleKeyword.TO) return new char[][]{Keywords.TO}; + else if (keyword == ModuleKeyword.PROVIDES_WITH) return new char[][]{Keywords.WITH}; + else return new char[][]{Keywords.EXPORTS, Keywords.OPENS, Keywords.REQUIRES, Keywords.PROVIDES, Keywords.USES}; +} +private boolean checkModuleInfoConstructs() { + + if (!isInsideModuleInfo()) return false; + + int index = -1; + if ((index = this.indexOfAssistIdentifier()) <= -1) return false; + + if (this.currentElement instanceof RecoveredModule) { + RecoveredModule module = (RecoveredModule) this.currentElement; + if (checkModuleInfoKeyword(module, index)) return true; + } else { + ModuleKeyword keyword = ModuleKeyword.NOT_A_KEYWORD; + if (isInModuleStatements()) { + if (foundToken(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT)) keyword = ModuleKeyword.TO; + if (foundToken(K_AFTER_NAME_IN_PROVIDES_STATEMENT)) keyword = ModuleKeyword.PROVIDES_WITH; + } + if (keyword == ModuleKeyword.NOT_A_KEYWORD) return false; + + int length = this.identifierLengthStack[this.identifierLengthPtr]; + int ptr = this.identifierPtr - length + index + 1; + + char[] ident = this.identifierStack[ptr]; + long pos = this.identifierPositionStack[ptr]; + char[][] keywords = getModuleKeywords(keyword); + if (this.currentElement instanceof RecoveredPackageVisibilityStatement) { + RecoveredPackageVisibilityStatement rPvs = (RecoveredPackageVisibilityStatement) this.currentElement; + rPvs.add(new CompletionOnKeywordModule2(ident, pos, keywords), 0); + return true; + } else if (this.currentElement instanceof RecoveredProvidesStatement) { + RecoveredProvidesStatement rPs = (RecoveredProvidesStatement) this.currentElement; + rPs.add(new CompletionOnKeyword1(ident, pos, keywords), 0); + return true; + } + } + return false; +} +private boolean checkModuleInfoKeyword(RecoveredModule module, int index) { + ModuleKeyword keyword = getKeyword(); + if (keyword == ModuleKeyword.NOT_A_KEYWORD) return false; + + int length = this.identifierLengthStack[this.identifierLengthPtr]; + int ptr = this.identifierPtr - length + index + 1; + + char[] ident = this.identifierStack[ptr]; + long pos = this.identifierPositionStack[ptr]; + char[][] keywords = getModuleKeywords(keyword); + module.add(new CompletionOnKeywordModuleInfo(ident, pos, keywords), 0); + return true; +} + private boolean checkInstanceofKeyword() { if(isInsideMethod()) { int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER); @@ -2037,6 +2119,7 @@ public void completionIdentifierCheck(){ if (checkMemberValueName()) return; if (checkKeyword()) return; + if (checkModuleInfoConstructs()) return; if (checkRecoveredType()) return; if (checkRecoveredMethod()) return; @@ -2044,7 +2127,8 @@ public void completionIdentifierCheck(){ if (!(isInsideMethod() && !this.diet) && !isIndirectlyInsideFieldInitialization() && !isIndirectlyInsideEnumConstantnitialization() - && !isInsideAttributeValue()) return; + && !isInsideAttributeValue() + && !isInsideModuleInfo()) return; /* In some cases, the completion identifier may not have yet been consumed, @@ -2073,6 +2157,7 @@ This is because the grammar does not allow any (empty) identifier to follow // no need to check further if we are not at the cursor location if (this.indexOfAssistIdentifier() < 0) return; + if (checkModuleInfoConstructs()) return; if (checkClassInstanceCreation()) return; if (checkMemberAccess()) return; if (checkClassLiteralAccess()) return; @@ -3362,6 +3447,22 @@ protected void consumeModifiers() { this.lastModifiersStart = this.intStack[this.intPtr]; this.lastModifiers = this.intStack[this.intPtr-1]; } +protected void consumeModuleHeader() { + super.consumeModuleHeader(); +} +protected void consumeProvidesInterface() { + super.consumeProvidesInterface(); + pushOnElementStack(K_AFTER_NAME_IN_PROVIDES_STATEMENT); +} +protected void consumeProvidesStatement() { + super.consumeProvidesStatement(); + popElement(K_INSIDE_PROVIDES_STATEMENT); +} +protected void consumeWithClause() { + super.consumeWithClause(); + popElement(K_AFTER_WITH_IN_PROVIDES_STATEMENT); +} + protected void consumeReferenceType() { if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name // potential receiver is being poped, so reset potential receiver @@ -3370,12 +3471,25 @@ protected void consumeReferenceType() { } super.consumeReferenceType(); } +protected void consumeRequiresStatement() { + super.consumeRequiresStatement(); + popElement(K_INSIDE_REQUIRES_STATEMENT); +} protected void consumeRestoreDiet() { super.consumeRestoreDiet(); if (isInsideMethod()) { popElement(K_LOCAL_INITIALIZER_DELIMITER); } } +protected void consumeExportsStatement() { + super.consumeExportsStatement(); + popElement(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT); + popElement(K_INSIDE_EXPORTS_STATEMENT); +} +protected void consumeSinglePkgName() { + super.consumeSinglePkgName(); + pushOnElementStack(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT); +} protected void consumeSingleMemberAnnotation(boolean isTypeAnnotation) { if (this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN && (this.topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) & ANNOTATION_NAME_COMPLETION) != 0 ) { @@ -3574,6 +3688,21 @@ protected void consumeToken(int token) { } if (token == TokenNameimport) { pushOnElementStack(K_INSIDE_IMPORT_STATEMENT); + } else if (token == TokenNameexports) { + pushOnElementStack(K_INSIDE_EXPORTS_STATEMENT); + } else if (token == TokenNameopens) { + pushOnElementStack(K_INSIDE_OPENS_STATEMENT); + } else if (token == TokenNameto) { + popElement(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT); + } else if (token == TokenNamerequires) { + pushOnElementStack(K_INSIDE_REQUIRES_STATEMENT); + } else if (token == TokenNameprovides) { + pushOnElementStack(K_INSIDE_PROVIDES_STATEMENT); + } else if (token == TokenNameuses) { + pushOnElementStack(K_INSIDE_USES_STATEMENT); + } else if (token == TokenNamewith) { + popElement(K_AFTER_NAME_IN_PROVIDES_STATEMENT); + pushOnElementStack(K_AFTER_WITH_IN_PROVIDES_STATEMENT); } // if in a method or if in a field initializer @@ -4084,6 +4213,12 @@ protected void consumeOpenFakeBlock() { super.consumeOpenFakeBlock(); pushOnElementStack(K_BLOCK_DELIMITER); } +@Override +protected void consumeOpensStatement() { + super.consumeOpensStatement(); + popElement(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT); + popElement(K_INSIDE_OPENS_STATEMENT); +} protected void consumeRightParen() { super.consumeRightParen(); } @@ -4208,6 +4343,11 @@ protected void consumeUnionTypeAsClassType() { super.consumeUnionTypeAsClassType(); popElement(K_NEXT_TYPEREF_IS_EXCEPTION); } +protected void consumeUsesStatement() { + super.consumeUsesStatement(); + popElement(K_INSIDE_USES_STATEMENT); +} + protected void consumeWildcard() { super.consumeWildcard(); if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource() @@ -4314,9 +4454,34 @@ public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, Co } return methodDeclaration; } +public ImportReference createAssistPackageVisibilityReference(char[][] tokens, long[] positions){ + return new CompletionOnPackageVisibilityReference(tokens, positions); +} public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){ return new CompletionOnImportReference(tokens, positions, mod); } +@Override +public ModuleReference createAssistModuleReference(int index) { + /* retrieve identifiers subset and whole positions, the assist node positions + should include the entire replaced source. */ + int length = this.identifierLengthStack[this.identifierLengthPtr]; + char[][] subset = identifierSubSet(index+1); // include the assistIdentifier + this.identifierLengthPtr--; + this.identifierPtr -= length; + long[] positions = new long[length]; + System.arraycopy( + this.identifierPositionStack, + this.identifierPtr + 1, + positions, + 0, + length); + return new CompletionOnModuleReference(subset, positions); +} +@Override +public ModuleDeclaration createAssistModuleDeclaration(CompilationResult compilationResult, char[][] tokens, + long[] positions) { + return new CompletionOnModuleDeclaration(compilationResult, tokens, positions); +} public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){ return new CompletionOnPackageReference(tokens, positions); } @@ -4327,6 +4492,14 @@ public NameReference createQualifiedAssistNameReference(char[][] previousIdentif positions, isInsideAttributeValue()); } +private TypeReference checkAndCreateModuleQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions) { + if (isInUsesStatement()) return new CompletionOnUsesQualifiedTypeReference(previousIdentifiers, assistName, positions); + if (isInProvidesStatement()) { + if (isAfterWithClause()) return new CompletionOnProvidesImplementationsQualifiedTypeReference(previousIdentifiers, assistName, positions); + return new CompletionOnProvidesInterfacesQualifiedTypeReference(previousIdentifiers, assistName, positions); + } + return new CompletionOnQualifiedTypeReference(previousIdentifiers, assistName, positions); +} public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){ switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) { case K_NEXT_TYPEREF_IS_EXCEPTION : @@ -4350,7 +4523,7 @@ public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentif positions, CompletionOnQualifiedTypeReference.K_INTERFACE); default : - return new CompletionOnQualifiedTypeReference( + return checkAndCreateModuleQualifiedAssistTypeReference( previousIdentifiers, assistName, positions); @@ -4513,6 +4686,14 @@ && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) { } } } +private TypeReference checkAndCreateModuleSingleAssistTypeReference(char[] assistName, long position) { + if (isInUsesStatement()) return new CompletionOnUsesSingleTypeReference(assistName, position); + if (isInProvidesStatement()) { + if (isAfterWithClause()) return new CompletionOnProvidesImplementationsSingleTypeReference(assistName, position); + return new CompletionOnProvidesInterfacesSingleTypeReference(assistName, position); + } + return new CompletionOnSingleTypeReference(assistName,position); +} public TypeReference createSingleAssistTypeReference(char[] assistName, long position) { switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) { case K_NEXT_TYPEREF_IS_EXCEPTION : @@ -4524,7 +4705,7 @@ public TypeReference createSingleAssistTypeReference(char[] assistName, long pos case K_NEXT_TYPEREF_IS_INTERFACE : return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_INTERFACE); default : - return new CompletionOnSingleTypeReference(assistName, position); + return checkAndCreateModuleSingleAssistTypeReference(assistName, position); } } public TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position) { @@ -5082,7 +5263,7 @@ public void resetAfterCompletion() { this.cursorLocation = 0; flushAssistState(); } -public void restoreAssistParser(Object parserState) { +public void restoreAssistParser(Object parserState) { int[] state = (int[]) parserState; CompletionScanner completionScanner = (CompletionScanner)this.scanner; @@ -5284,14 +5465,43 @@ protected boolean isInsideArrayInitializer(){ } return false; } -protected boolean isInImportStatement() { +private boolean foundToken(int token) { int i = this.elementPtr; while (i > -1) { - if (this.elementKindStack[i] == K_INSIDE_IMPORT_STATEMENT) { + if (this.elementKindStack[i] == token) { return true; } i--; } return false; } + +protected boolean isInImportStatement() { + return foundToken(K_INSIDE_IMPORT_STATEMENT); +} +protected boolean isInExportsStatement() { + return foundToken(K_INSIDE_EXPORTS_STATEMENT); +} +protected boolean isInOpensStatement() { + return foundToken(K_INSIDE_OPENS_STATEMENT); +} +protected boolean isInRequiresStatement() { + return foundToken(K_INSIDE_REQUIRES_STATEMENT); +} +protected boolean isInUsesStatement() { + return foundToken(K_INSIDE_USES_STATEMENT); +} +protected boolean isInProvidesStatement() { + return foundToken(K_INSIDE_PROVIDES_STATEMENT); +} +protected boolean isAfterWithClause() { + return foundToken(K_AFTER_WITH_IN_PROVIDES_STATEMENT); +} +protected boolean isInModuleStatements() { + return isInExportsStatement() || + isInOpensStatement() || + isInRequiresStatement() || + isInProvidesStatement() || + isInUsesStatement(); +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java index 754641a959..526c3ba517 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java @@ -18,6 +18,7 @@ import java.util.HashSet; import org.eclipse.jdt.core.compiler.InvalidInputException; +import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; @@ -35,7 +36,10 @@ import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; import org.eclipse.jdt.internal.compiler.ast.NameReference; +import org.eclipse.jdt.internal.compiler.ast.RequiresStatement; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.SuperReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -46,6 +50,7 @@ import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock; import org.eclipse.jdt.internal.compiler.parser.RecoveredElement; +import org.eclipse.jdt.internal.compiler.parser.RecoveredExportsStatement; import org.eclipse.jdt.internal.compiler.parser.RecoveredField; import org.eclipse.jdt.internal.compiler.parser.RecoveredInitializer; import org.eclipse.jdt.internal.compiler.parser.RecoveredLocalVariable; @@ -95,7 +100,8 @@ public abstract class AssistParser extends Parser { protected static final int K_ATTRIBUTE_VALUE_DELIMITER = ASSIST_PARSER + 5; // whether we are inside a annotation attribute valuer protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer protected static final int K_LAMBDA_EXPRESSION_DELIMITER = ASSIST_PARSER + 7; // whether we are inside a lambda expression - + protected static final int K_MODULE_INFO_DELIMITER = ASSIST_PARSER + 8; // whether we are inside a module info declaration + // selector constants protected static final int THIS_CONSTRUCTOR = -1; protected static final int SUPER_CONSTRUCTOR = -2; @@ -103,7 +109,7 @@ public abstract class AssistParser extends Parser { // enum constant constants protected static final int NO_BODY = 0; protected static final int WITH_BODY = 1; - + protected static final int EXPRESSION_BODY = 0; protected static final int BLOCK_BODY = 1; @@ -179,6 +185,7 @@ public RecoveredElement buildInitialRecoveryState(){ flushAssistState(); flushElementStack(); this.snapShot = null; + initModuleInfo(element); return element; } @@ -365,6 +372,22 @@ public RecoveredElement buildInitialRecoveryState(){ return element; } + +private void initModuleInfo(RecoveredElement element) { + if (element instanceof RecoveredUnit) { + RecoveredUnit unit = (RecoveredUnit) element; + if (unit.unitDeclaration.isModuleInfo()) { + ASTNode node = null; + int i = 0; + for (; i <= this.astPtr; i++) { + if ((node = this.astStack[i]) instanceof ModuleDeclaration) { + unit.add((ModuleDeclaration) node, this.bracketDepth); + break; + } + } + } + } +} protected void consumeAnnotationTypeDeclarationHeader() { super.consumeAnnotationTypeDeclarationHeader(); pushOnElementStack(K_TYPE_DELIMITER); @@ -686,6 +709,57 @@ protected void consumeMethodInvocationSuperWithTypeArguments() { this.lastCheckPoint = messageSend.sourceEnd + 1; } } +protected void consumeModuleHeader() { + pushOnElementStack(K_MODULE_INFO_DELIMITER); + // ModuleHeader ::= 'module' Name + /* build an ImportRef build from the last name + stored in the identifier stack. */ + + int index; + + /* no need to take action if not inside assist identifiers */ + if ((index = indexOfAssistIdentifier()) < 0) { + super.consumeModuleHeader(); + return; + } + /* retrieve identifiers subset and whole positions, the assist node positions + should include the entire replaced source. */ + int length = this.identifierLengthStack[this.identifierLengthPtr]; + char[][] subset = identifierSubSet(index+1); // include the assistIdentifier + this.identifierLengthPtr--; + this.identifierPtr -= length; + long[] positions = new long[length]; + System.arraycopy( + this.identifierPositionStack, + this.identifierPtr + 1, + positions, + 0, + length); + ModuleDeclaration typeDecl = createAssistModuleDeclaration(this.compilationUnit.compilationResult, subset, positions); + + this.compilationUnit.moduleDeclaration = typeDecl; + this.assistNode = typeDecl; + this.lastCheckPoint = typeDecl.sourceEnd + 1; + + //compute the declaration source too + typeDecl.declarationSourceStart = this.intStack[this.intPtr--]; + + typeDecl.bodyStart = typeDecl.sourceEnd + 1; + pushOnAstStack(typeDecl); + + this.listLength = 0; // will be updated when reading super-interfaces + // recovery + if (this.currentElement != null){ + this.lastCheckPoint = typeDecl.bodyStart; + this.currentElement = this.currentElement.add(typeDecl, 0); + this.lastIgnoredToken = -1; + } +} + +protected void consumeModuleDeclaration() { + super.consumeModuleDeclaration(); + popElement(K_MODULE_INFO_DELIMITER); +} protected void consumeNestedMethod() { super.consumeNestedMethod(); if(!isInsideMethod()) pushOnElementStack(K_METHOD_DELIMITER); @@ -899,6 +973,104 @@ protected void consumeSingleStaticImportDeclarationName() { this.restartRecovery = true; // used to avoid branching back into the regular automaton } } +protected void consumeSinglePkgName() { + int index; + /* no need to take action if not inside assist identifiers */ + if ((index = indexOfAssistIdentifier()) < 0) { + super.consumeSinglePkgName(); + return; + } + /* retrieve identifiers subset and whole positions, the assist node positions + should include the entire replaced source. */ + int length = this.identifierLengthStack[this.identifierLengthPtr]; + char[][] subset = identifierSubSet(index+1); // include the assistIdentifier + this.identifierLengthPtr--; + this.identifierPtr -= length; + long[] positions = new long[length]; + System.arraycopy( + this.identifierPositionStack, + this.identifierPtr + 1, + positions, + 0, + length); + + /* build specific assist node on import statement */ + ImportReference reference = createAssistPackageVisibilityReference(subset, positions); + this.assistNode = reference; + this.lastCheckPoint = reference.sourceEnd + 1; + + pushOnAstStack(reference); + + if (this.currentToken == TokenNameSEMICOLON) { + reference.declarationSourceEnd = this.scanner.currentPosition - 1; + } else { + reference.declarationSourceEnd = (int) positions[length-1]; + } +} +protected void consumeSingleTargetModuleName() { + int index; + /* no need to take action if not inside assist identifiers */ + if ((index = indexOfAssistIdentifier()) < 0) { + super.consumeSingleTargetModuleName(); + return; + } + + /* build specific assist node on targetted exports statement */ + ModuleReference reference = createAssistModuleReference(index); + this.assistNode = reference; + this.lastCheckPoint = reference.sourceEnd + 1; + pushOnAstStack(reference); + + // recovery - TBD + if (this.currentElement instanceof RecoveredExportsStatement){ + // TODO + this.lastCheckPoint = reference.sourceEnd+1; + this.currentElement = ((RecoveredExportsStatement) this.currentElement).add(reference, 0); + this.lastIgnoredToken = -1; + //this.restartRecovery = true; // used to avoid branching back into the regular automaton + } + +} +protected void consumeSingleRequiresModuleName() { + + int index = indexOfAssistIdentifier(); + /* no need to take action if not inside assist identifiers */ + if (index < 0) { + super.consumeSingleRequiresModuleName(); + return; + } + + /* build specific assist node on requires statement */ + ModuleReference reference = createAssistModuleReference(index); + this.assistNode = reference; + this.lastCheckPoint = reference.sourceEnd + 1; + RequiresStatement req = new RequiresStatement(reference); + if (this.currentToken == TokenNameSEMICOLON){ + req.declarationSourceEnd = this.scanner.currentPosition - 1; + } else { + req.declarationSourceEnd = reference.sourceEnd; + } + req.sourceStart = req.declarationSourceStart; + req.declarationEnd = req.declarationSourceEnd; + req.modifiersSourceStart = this.intStack[this.intPtr--]; + req.modifiers |= this.intStack[this.intPtr--]; + req.declarationSourceStart = this.intStack[this.intPtr--]; + if (req.modifiersSourceStart >= 0) { + req.declarationSourceStart = req.modifiersSourceStart; + } + req.sourceEnd = reference.sourceEnd; + pushOnAstStack(req); + + // recovery TBD + + if (this.currentElement != null){ + this.lastCheckPoint = req.declarationSourceEnd + 1; + this.currentElement = this.currentElement.add(req, 0); + this.lastIgnoredToken = -1; + } + +} + protected void consumeSingleTypeImportDeclarationName() { // SingleTypeImportDeclarationName ::= 'import' Name /* push an ImportRef build from the last name @@ -1012,6 +1184,20 @@ protected void consumeStaticOnly() { super.consumeStaticOnly(); pushOnElementStack(K_METHOD_DELIMITER); } +private void adjustBracket(int token) { + switch (token) { + case TokenNameLPAREN : + case TokenNameLBRACE: + case TokenNameLBRACKET: + this.bracketDepth++; + break; + case TokenNameRBRACE: + case TokenNameRBRACKET: + case TokenNameRPAREN: + this.bracketDepth--; + break; + } +} protected void consumeToken(int token) { super.consumeToken(token); @@ -1022,9 +1208,9 @@ protected void consumeToken(int token) { // register message send selector only if inside a method or if looking at a field initializer // and if the current token is an open parenthesis if (isInsideMethod() || isInsideFieldInitialization() || isInsideAttributeValue() || isInsideEnumConstantnitialization()) { + adjustBracket(token); switch (token) { case TokenNameLPAREN : - this.bracketDepth++; switch (this.previousToken) { case TokenNameIdentifier: this.pushOnElementStack(K_SELECTOR, this.identifierPtr); @@ -1049,21 +1235,10 @@ protected void consumeToken(int token) { popElement(K_LAMBDA_EXPRESSION_DELIMITER); pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, BLOCK_BODY, this.previousObjectInfo); } - this.bracketDepth++; - break; - case TokenNameLBRACKET: - this.bracketDepth++; - break; - case TokenNameRBRACE: - this.bracketDepth--; - break; - case TokenNameRBRACKET: - this.bracketDepth--; - break; - case TokenNameRPAREN: - this.bracketDepth--; break; } + } else if (isInsideModuleInfo()) { + adjustBracket(token); } else { switch (token) { case TokenNameRBRACE : @@ -1132,7 +1307,11 @@ protected void consumeTypeImportOnDemandDeclarationName() { this.restartRecovery = true; // used to avoid branching back into the regular automaton } } + +// TODO : Change to ExportsReference/PackageReference once we have the new compiler ast.node +public abstract ImportReference createAssistPackageVisibilityReference(char[][] tokens, long[] positions); public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod); +public abstract ModuleReference createAssistModuleReference(int index); public abstract ImportReference createAssistPackageReference(char[][] tokens, long[] positions); public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions); public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions); @@ -1140,6 +1319,7 @@ protected void consumeTypeImportOnDemandDeclarationName() { public abstract NameReference createSingleAssistNameReference(char[] assistName, long position); public abstract TypeReference createSingleAssistTypeReference(char[] assistName, long position); public abstract TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position); +public abstract ModuleDeclaration createAssistModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions); /* * Flush parser/scanner state regarding to code assist */ @@ -1535,6 +1715,21 @@ protected boolean isInsideEnumConstantnitialization(){ } return false; } +protected boolean isInsideModuleInfo(){ + int i = this.elementPtr; + while(i > -1) { + switch (this.elementKindStack[i]) { + case K_TYPE_DELIMITER : + case K_METHOD_DELIMITER : + case K_FIELD_INITIALIZER_DELIMITER : + return false; + case K_MODULE_INFO_DELIMITER: + return true; + } + i--; + } + return false; +} protected boolean isInsideMethod(){ int i = this.elementPtr; while(i > -1) { @@ -2087,6 +2282,12 @@ protected int resumeAfterRecovery() { goForBlockStatementsopt(); } else { prepareForHeaders(); + if (this.referenceContext instanceof CompilationUnitDeclaration) { + CompilationUnitDeclaration unit = (CompilationUnitDeclaration) this.referenceContext; + if (unit.isModuleInfo()) { + pushOnElementStack(K_MODULE_INFO_DELIMITER); + } + } goForHeaders(); this.diet = true; // passed this point, will not consider method bodies this.dietInt = 0; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java index 69295990b6..94faf8283a 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -118,18 +118,21 @@ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, Acc } else { result = new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit); } + LookupEnvironment environment = packageBinding.environment; + if (environment == null) + environment = this.lookupEnvironment; CompilationUnitDeclaration unit = SourceTypeConverter.buildCompilationUnit( sourceTypes,//sourceTypes[0] is always toplevel here SourceTypeConverter.FIELD_AND_METHOD // need field and methods | SourceTypeConverter.MEMBER_TYPE, // need member types // no need for field initialization - this.lookupEnvironment.problemReporter, + environment.problemReporter, result); if (unit != null) { - this.lookupEnvironment.buildTypeBindings(unit, accessRestriction); - this.lookupEnvironment.completeTypeBindings(unit, true); + environment.buildTypeBindings(unit, accessRestriction); + environment.completeTypeBindings(unit, true); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java index 79c4c7f592..e905601b49 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java @@ -11,7 +11,7 @@ package org.eclipse.jdt.internal.codeassist.impl; public interface Keywords { - int COUNT = 41; + int COUNT = 49; char[] ABSTRACT = "abstract".toCharArray(); //$NON-NLS-1$ char[] ASSERT = "assert".toCharArray(); //$NON-NLS-1$ @@ -25,20 +25,25 @@ public interface Keywords { char[] ELSE = "else".toCharArray(); //$NON-NLS-1$ char[] ENUM = "enum".toCharArray(); //$NON-NLS-1$ char[] EXTENDS = "extends".toCharArray(); //$NON-NLS-1$ + char[] EXPORTS = "exports".toCharArray(); //$NON-NLS-1$ char[] FINAL = "final".toCharArray(); //$NON-NLS-1$ char[] FINALLY = "finally".toCharArray(); //$NON-NLS-1$ char[] FOR = "for".toCharArray(); //$NON-NLS-1$ char[] IF = "if".toCharArray(); //$NON-NLS-1$ char[] IMPLEMENTS = "implements".toCharArray(); //$NON-NLS-1$ char[] IMPORT = "import".toCharArray(); //$NON-NLS-1$ + char[] MODULE = "module".toCharArray(); //$NON-NLS-1$ char[] INSTANCEOF = "instanceof".toCharArray(); //$NON-NLS-1$ char[] INTERFACE = "interface".toCharArray(); //$NON-NLS-1$ char[] NATIVE = "native".toCharArray(); //$NON-NLS-1$ char[] NEW = "new".toCharArray(); //$NON-NLS-1$ + char[] OPENS= "opens".toCharArray(); //$NON-NLS-1$ char[] PACKAGE = "package".toCharArray(); //$NON-NLS-1$ char[] PRIVATE = "private".toCharArray(); //$NON-NLS-1$ char[] PROTECTED = "protected".toCharArray(); //$NON-NLS-1$ + char[] PROVIDES = "provides".toCharArray(); //$NON-NLS-1$ char[] PUBLIC = "public".toCharArray(); //$NON-NLS-1$ + char[] REQUIRES = "requires".toCharArray(); //$NON-NLS-1$ char[] RETURN = "return".toCharArray(); //$NON-NLS-1$ char[] STATIC = "static".toCharArray(); //$NON-NLS-1$ char[] STRICTFP = "strictfp".toCharArray(); //$NON-NLS-1$ @@ -48,10 +53,13 @@ public interface Keywords { char[] THIS = "this".toCharArray(); //$NON-NLS-1$ char[] THROW = "throw".toCharArray(); //$NON-NLS-1$ char[] THROWS = "throws".toCharArray(); //$NON-NLS-1$ + char[] TO = "to".toCharArray(); //$NON-NLS-1$ char[] TRANSIENT = "transient".toCharArray(); //$NON-NLS-1$ char[] TRY = "try".toCharArray(); //$NON-NLS-1$ + char[] USES = "uses".toCharArray(); //$NON-NLS-1$ char[] VOLATILE = "volatile".toCharArray(); //$NON-NLS-1$ char[] WHILE = "while".toCharArray(); //$NON-NLS-1$ + char[] WITH = "with".toCharArray(); //$NON-NLS-1$ char[] TRUE = "true".toCharArray(); //$NON-NLS-1$ char[] FALSE = "false".toCharArray(); //$NON-NLS-1$ char[] NULL = "null".toCharArray(); //$NON-NLS-1$ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleDeclaration.java new file mode 100644 index 0000000000..24c388d7cf --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleDeclaration.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.select; + +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.SourceModuleBinding; + +public class SelectionOnModuleDeclaration extends ModuleDeclaration { + + public SelectionOnModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions) { + super(compilationResult, tokens, positions); + } + + @Override + public ModuleBinding setBinding(SourceModuleBinding sourceModuleBinding) { + super.setBinding(sourceModuleBinding); + throw new SelectionNodeFound(this.binding); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleReference.java new file mode 100644 index 0000000000..500f7c72d2 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleReference.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.select; + +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; + +public class SelectionOnModuleReference extends ModuleReference { + + public SelectionOnModuleReference(char[][] tokens, long[] sourcePositions) { + super(tokens, sourcePositions); + } + + public ModuleBinding resolve(Scope scope) { + ModuleBinding resolvedBinding = super.resolve(scope); + if (resolvedBinding != null) { + throw new SelectionNodeFound(resolvedBinding); + } else { + throw new SelectionNodeFound(); + } + } + + public StringBuffer print(int tab, StringBuffer output) { + printIndent(tab, output).append(" 0) output.append('.'); + output.append(this.tokens[i]); + } + return output.append('>'); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageVisibilityReference.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageVisibilityReference.java new file mode 100644 index 0000000000..a452b1301f --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageVisibilityReference.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist.select; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ast.ImportReference; + +/* + * Selection node build by the parser in any case it was intending to + * reduce an export reference containing the assist identifier. + * e.g. + * + * module myModule { + * exports packageo[cursor]; + * } + * + * module myModule { + * ---> + * } + * + */ +public class SelectionOnPackageVisibilityReference extends ImportReference { + + public SelectionOnPackageVisibilityReference(char[][] tokens, long[] positions) { + super(tokens, positions, false, 0); + } + + public StringBuffer print(int indent, StringBuffer output) { + + printIndent(indent, output).append("'); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java index 3c511ca730..03e8737abd 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -41,6 +41,8 @@ import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MessageSend; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; import org.eclipse.jdt.internal.compiler.ast.NameReference; import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; @@ -1258,9 +1260,17 @@ protected void consumeTypeImportOnDemandDeclarationName() { protected SelectionParser createSnapShotParser() { return new SelectionParser(this.problemReporter); } +public ImportReference createAssistPackageVisibilityReference(char[][] tokens, long[] positions){ + return new SelectionOnPackageVisibilityReference(tokens, positions); +} public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){ return new SelectionOnImportReference(tokens, positions, mod); } +@Override +public ModuleDeclaration createAssistModuleDeclaration(CompilationResult compilationResult, char[][] tokens, + long[] positions) { + return new SelectionOnModuleDeclaration(compilationResult, tokens, positions); +} public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){ return new SelectionOnPackageReference(tokens, positions); } @@ -1591,4 +1601,17 @@ public String toString() { s = s + "}\n"; //$NON-NLS-1$ return s + super.toString(); } +@Override +public ModuleReference createAssistModuleReference(int index) { + // ignore index, all segments of the module name are part of a single identifier. + /* retrieve identifiers subset and whole positions, the assist node positions + should include the entire replaced source. */ + int length; + char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][]; + this.identifierPtr -= length; + long[] positions = new long[length]; + System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length); + System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length); + return new SelectionOnModuleReference(tokens, positions); +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CategorizedProblem.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CategorizedProblem.java index 513ffdbcf2..843cb75a4b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CategorizedProblem.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CategorizedProblem.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -95,6 +95,11 @@ public abstract class CategorizedProblem implements IProblem { public static final int CAT_NLS = 140; /** Category for optional problems related to access restrictions */ public static final int CAT_RESTRICTION = 150; + /** + * Category for fatal problems relating to modules + * @since 3.14 + */ + public static final int CAT_MODULE = 160; /** * Returns an integer identifying the category of this problem. Categories, like problem IDs are diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java index 23b3817817..7b55aece2b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,6 +14,7 @@ package org.eclipse.jdt.core.compiler; import java.util.Arrays; +import java.util.List; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; @@ -41,6 +42,18 @@ public final class CharOperation { */ public static final String[] NO_STRINGS = new String[0]; + /** + * Constant for all Prefix + * @since 3.14 + */ + public static final char[] ALL_PREFIX = new char[] {'*'}; + + /** + * Constant for comma + * @since 3.14 + */ + public static final char[] COMMA_SEPARATOR = new char[] {','}; + /** * Answers a new array with appending the suffix character at the end of the array. *
@@ -165,6 +178,39 @@ public static final char[] append(char[] target, int index, char[] array, int st return target; } +/** + * Answers a new array with prepending the prefix character at the start of the array. + *
+ *
+ * For example:
+ *
    + *
  1. + *    prefix = 'c'
    + *    array = { 'a', 'b' }
    + *    => result = { 'c' , 'a', 'b' }
    + * 
    + *
  2. + *
  3. + *    prefix = 'c'
    + *    array = null
    + *    => result = { 'c' }
    + * 
  4. + *
+ * + * @param array the array that is concatenated with the prefix character + * @param prefix the prefix character + * @return the new array + * @since 3.14 + */ +public static final char[] prepend(char prefix, char[] array) { + if (array == null) + return new char[] { prefix }; + int length = array.length; + System.arraycopy(array, 0, array = new char[length + 1], 1, length); + array[0] = prefix; + return array; +} + /** * Answers the concatenation of the two arrays. It answers null if the two arrays are null. * If the first array is null, then the second array is returned. @@ -816,6 +862,22 @@ public static String charToString(char[] charArray) { return new String(charArray); } +/** + * Converts the given list of strings to an array of equal size, + * containing the individual strings converted to char[] each. + * + * @param stringList + * @return an array of char[], representing the elements in the input list, or {@code null} if the list was {@code null}. + * @since 3.14 + */ +public static char[][] toCharArrays(List stringList) { + if (stringList == null) + return null; + char[][] result = new char[stringList.size()][]; + for (int i = 0; i < result.length; i++) + result[i] = stringList.get(i).toCharArray(); + return result; +} /** * Answers a new array adding the second array at the end of first array. * It answers null if the first and second are null. @@ -1164,6 +1226,77 @@ public static final char[] concat( return result; } +/** + * Answers the concatenation of the two arrays inserting the separator character between the two arrays. Differs from + * {@link CharOperation#contains(char, char[])} in case second array is a zero length array. + * It answers null if the two arrays are null. + * If the first array is null, then the second array is returned. + * If the second array is null, then the first array is returned. + * if the second array is zero length array, the separator is appended. + *
+ *
+ * For example: + *
    + *
  1. + *    first = null
    + *    second = { 'a' }
    + *    separator = '/'
    + *    => result = { ' a' }
    + * 
    + *
  2. + *
  3. + *    first = { ' a' }
    + *    second = null
    + *    separator = '/'
    + *    => result = { ' a' }
    + * 
    + *
  4. + *
  5. + *    first = { ' a' }
    + *    second = { ' b' }
    + *    separator = '/'
    + *    => result = { ' a' , '/', 'b' }
    + * 
    + *
  6. + *
  7. + *    first = { ' a' }
    + *    second = { '' }
    + *    separator = '.'
    + *    => result = { ' a' , '.', }
    + * 
    + *
  8. + *
+ * + * @param first the first array to concatenate + * @param second the second array to concatenate + * @param separator the character to insert + * @return the concatenation of the two arrays inserting the separator character + * between the two arrays , or null if the two arrays are null. If second array + * is of zero length, the separator is appended to the first array and returned. + * @since 3.14 + */ +public static final char[] concatAll( + char[] first, + char[] second, + char separator) { + if (first == null) + return second; + if (second == null) + return first; + + int length1 = first.length; + if (length1 == 0) + return second; + int length2 = second.length; + + char[] result = new char[length1 + length2 + 1]; + System.arraycopy(first, 0, result, 0, length1); + result[length1] = separator; + if (length2 > 0) + System.arraycopy(second, 0, result, length1 + 1, length2); + return result; +} + /** * Answers the concatenation of the three arrays inserting the sep1 character between the * first two arrays and sep2 between the last two. @@ -1780,6 +1913,21 @@ public static final boolean contains(char[] characters, char[] array) { return false; } +/** + * Does the given array contain a char sequence that is equal to the give sequence? + * @param array + * @param sequence + * @return true if sequence is equal to an element in array + * @since 3.14 + */ +public static boolean containsEqual(char[][] array, char[] sequence) { + for (int i = 0; i < array.length; i++) { + if (equals(array[i], sequence)) + return true; + } + return false; +} + /** * Answers a deep copy of the toCopy array. * diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java index 12f6fe05e1..07d669095b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java @@ -357,15 +357,22 @@ public interface IProblem { int Syntax = 0x40000000; /** @since 3.0 */ int Javadoc = 0x80000000; + /** @since 3.14 */ + int ModuleRelated = 0x00800000; /** * Mask to use in order to filter out the category portion of the problem ID. */ - int IgnoreCategoriesMask = 0xFFFFFF; + int IgnoreCategoriesMask = 0x7FFFFF; - /** + /* * Below are listed all available problem IDs. Note that this list could be augmented in the future, * as new features are added to the Java core implementation. + * + * Problem IDs must be kept unique even when their mask is stripped, since + * the bare integer literal is used for message lookup in + * /org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties. + * Use this regex to find duplicates: (?s)(\+ \d+)\b.*\1\b */ /** @@ -1476,6 +1483,8 @@ public interface IProblem { int InterfaceSuperInvocationNotBelow18 = Internal + Syntax + 667; /** @since 3.13*/ int InterfaceStaticMethodInvocationNotBelow18 = Internal + Syntax + 668; + /** @since 3.13 */ + int FieldMustBeFinal = Internal + 669; /** @@ -1673,6 +1682,8 @@ public interface IProblem { /** @since 3.10 */ int RepeatedAnnotationWithContainerAnnotation = TypeRelated + 899; + /** @since 3.14 */ + int AutoManagedVariableResourceNotBelow9 = Syntax + Internal + 1351; /** * External problems -- These are problems defined by other plugins */ @@ -1871,11 +1882,92 @@ public interface IProblem { /** @since 3.13 */ int CannotInferInvocationType = TypeRelated + 1059; + /** @since 3.13 */ int TypeAnnotationAtQualifiedName = Internal + Syntax + 1060; /** @since 3.13 */ int NullAnnotationAtQualifyingType = Internal + Syntax + 1061; + + /** @since 3.14*/ + int IllegalModifierForInterfaceMethod9 = MethodRelated + 1071; + /** @since 3.14*/ + int IllegalModifierCombinationForPrivateInterfaceMethod9 = MethodRelated + 1070; + /** @since 3.14 */ + int UndefinedModule = ModuleRelated + 1300; + /** @since 3.14 */ + int DuplicateRequires = ModuleRelated + 1301; + /** @since 3.14 */ + int DuplicateExports = ModuleRelated + 1302; + /** @since 3.14 */ + int DuplicateUses = ModuleRelated + 1303; + /** @since 3.14 */ + int DuplicateServices = ModuleRelated + 1304; + /** @since 3.14 */ + int CyclicModuleDependency = ModuleRelated + 1305; + /** @since 3.14 */ + int AbstractServiceImplementation = TypeRelated + 1306; + /** @since 3.14 */ + int ProviderMethodOrConstructorRequiredForServiceImpl = TypeRelated + 1307; + /** @since 3.14 */ + int ServiceImplDefaultConstructorNotPublic = TypeRelated + 1308; + /** @since 3.14 */ + int NestedServiceImpl = TypeRelated + 1309; + /** @since 3.14 */ + int ServiceImplNotDefinedByModule = TypeRelated + 1310; + /** @since 3.14 */ + int PackageDoesNotExistOrIsEmpty = ModuleRelated + 1311; + /** @since 3.14 */ + int NonDenotableTypeArgumentForAnonymousDiamond = TypeRelated + 1312; + /** @since 3.14 */ + int DuplicateOpens = ModuleRelated + 1313; + /** @since 3.14 */ + int DuplicateModuleRef = ModuleRelated + 1314; + /** @since 3.14 */ + int InvalidOpensStatement = ModuleRelated + 1315; + /** @since 3.14 */ + int InvalidServiceIntfType = ModuleRelated + 1316; + /** @since 3.14 */ + int InvalidServiceImplType = ModuleRelated + 1317; + /** @since 3.14 */ + int IllegalModifierForModule = ModuleRelated + 1318; + + /** @since 3.14 */ + int DuplicateResource = Internal + 1251; + + /** @since 3.14 */ + int UsingTerminallyDeprecatedType = TypeRelated + 1400; + /** @since 3.14 */ + int UsingTerminallyDeprecatedMethod = MethodRelated + 1401; + /** @since 3.14 */ + int UsingTerminallyDeprecatedConstructor = MethodRelated + 1402; + /** @since 3.14 */ + int UsingTerminallyDeprecatedField = FieldRelated + 1403; + /** @since 3.14 */ + int OverridingTerminallyDeprecatedMethod = MethodRelated + 1404; + + /** @since 3.14 */ + int NotAccessibleType = TypeRelated + 1450; + /** @since 3.14 */ + int NotAccessibleField = FieldRelated + 1451; + /** @since 3.14 */ + int NotAccessibleMethod = MethodRelated + 1452; + /** @since 3.14 */ + int NotAccessibleConstructor = MethodRelated + 1453; + /** @since 3.14 */ + int NotAccessiblePackage = ImportRelated + 1454; + /** @since 3.14 */ + int ConflictingPackageFromModules = ModuleRelated + 1455; + /** @since 3.14 */ + int ConflictingPackageFromOtherModules = ModuleRelated + 1456; + /** @since 3.14 */ + int NonPublicTypeInAPI = ModuleRelated + 1457; + /** @since 3.14 */ + int NotExportedTypeInAPI = ModuleRelated + 1458; + /** @since 3.14 */ + int MissingRequiresTransitiveForTypeInAPI = ModuleRelated + 1459; + /** @since 3.14 */ + int UnnamedPackageInNamedModule = ModuleRelated + 1460; /** @since 3.13 */ int RedundantNullDefaultAnnotationLocal = Internal + 1062; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java index b77408d7af..a386c19d86 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -584,6 +584,9 @@ public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) { public boolean visit(Clinit clinit, ClassScope scope) { return true; // do nothing by default, keep traversing } + public boolean visit(ModuleDeclaration module, CompilationUnitScope scope) { + return true; + } public boolean visit( CompilationUnitDeclaration compilationUnitDeclaration, CompilationUnitScope scope) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java index 906bac87a0..9ad9dba5be 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -50,6 +50,8 @@ import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression; @@ -57,10 +59,13 @@ import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; +import org.eclipse.jdt.internal.compiler.ast.OpensStatement; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.Receiver; import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression; +import org.eclipse.jdt.internal.compiler.ast.RequiresStatement; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -90,6 +95,7 @@ import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; @@ -296,7 +302,16 @@ public ClassFile(SourceTypeBinding typeBinding) { } else { this.codeStream = new CodeStream(this); } - initByteArrays(); + initByteArrays(this.referenceBinding.methods().length + this.referenceBinding.fields().length); + } + + public ClassFile(ModuleBinding moduleBinding, CompilerOptions options) { + this.constantPool = new ConstantPool(this); + this.targetJDK = options.targetJDK; + this.produceAttributes = ClassFileConstants.ATTR_SOURCE; + this.isNestedType = false; + this.codeStream = new StackMapFrameCodeStream(this); + initByteArrays(0); } /** @@ -440,6 +455,63 @@ public int compare(Object o1, Object o2) { this.header[this.constantPoolOffset++] = (byte) (constantPoolCount >> 8); this.header[this.constantPoolOffset] = (byte) constantPoolCount; } + + /** + * INTERNAL USE-ONLY + * This methods generate all the module attributes for the receiver. + */ + public void addModuleAttributes(ModuleBinding module, Annotation[] annotations, CompilationUnitDeclaration cud) { + int attributesNumber = 0; + // leave two bytes for the number of attributes and store the current offset + int attributeOffset = this.contentsOffset; + this.contentsOffset += 2; + + // source attribute + if ((this.produceAttributes & ClassFileConstants.ATTR_SOURCE) != 0) { + String fullFileName = + new String(cud.getFileName()); + fullFileName = fullFileName.replace('\\', '/'); + int lastIndex = fullFileName.lastIndexOf('/'); + if (lastIndex != -1) { + fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length()); + } + attributesNumber += generateSourceAttribute(fullFileName); + } + // Deprecated attribute + if (module.isDeprecated()) { + // check that there is enough space to write all the bytes for the field info corresponding + // to the @fieldBinding + attributesNumber += generateDeprecatedAttribute(); + } + attributesNumber += generateModuleAttribute(cud.moduleDeclaration); + if (annotations != null) { + long targetMask = TagBits.AnnotationForModule; + attributesNumber += generateRuntimeAnnotations(annotations, targetMask); + } + char[] mainClass = cud.moduleDeclaration.binding.mainClassName; + if (mainClass != null) { + attributesNumber += generateModuleMainClassAttribute(CharOperation.replaceOnCopy(mainClass, '.', '/')); + } + char[][] packageNames = cud.moduleDeclaration.binding.getPackageNamesForClassFile(); + if (packageNames != null) { + attributesNumber += generateModulePackagesAttribute(packageNames); + } + + // update the number of attributes + if (attributeOffset + 2 >= this.contents.length) { + resizeContents(2); + } + this.contents[attributeOffset++] = (byte) (attributesNumber >> 8); + this.contents[attributeOffset] = (byte) attributesNumber; + + // resynchronize all offsets of the classfile + this.header = this.constantPool.poolContent; + this.headerOffset = this.constantPool.currentOffset; + int constantPoolCount = this.constantPool.currentIndex; + this.header[this.constantPoolOffset++] = (byte) (constantPoolCount >> 8); + this.header[this.constantPoolOffset] = (byte) constantPoolCount; + } + /** * INTERNAL USE-ONLY * This methods generate all the default abstract method infos that correpond to @@ -2583,6 +2655,298 @@ private int generateDeprecatedAttribute() { this.contentsOffset = localContentsOffset; return 1; } + private int generateModuleAttribute(ModuleDeclaration module) { + ModuleBinding binding = module.binding; + int localContentsOffset = this.contentsOffset; + if (localContentsOffset + 10 >= this.contents.length) { + resizeContents(10); + } + int moduleAttributeNameIndex = + this.constantPool.literalIndex(AttributeNamesConstants.ModuleName); + this.contents[localContentsOffset++] = (byte) (moduleAttributeNameIndex >> 8); + this.contents[localContentsOffset++] = (byte) moduleAttributeNameIndex; + int attrLengthOffset = localContentsOffset; + localContentsOffset += 4; + int moduleNameIndex = + this.constantPool.literalIndexForModule(binding.moduleName); + this.contents[localContentsOffset++] = (byte) (moduleNameIndex >> 8); + this.contents[localContentsOffset++] = (byte) moduleNameIndex; + int flags = module.modifiers & ~(ClassFileConstants.AccModule); + this.contents[localContentsOffset++] = (byte) (flags >> 8); + this.contents[localContentsOffset++] = (byte) flags; + int module_version = 0; + this.contents[localContentsOffset++] = (byte) (module_version >> 8); + this.contents[localContentsOffset++] = (byte) module_version; + int attrLength = 6; + + // ================= requires section ================= + /** u2 requires_count; + { u2 requires_index; + u2 requires_flags; + } requires[requires_count]; + **/ + int requiresCountOffset = localContentsOffset; + int requiresCount = module.requiresCount; + int requiresSize = 2 + requiresCount * 6; + if (localContentsOffset + requiresSize >= this.contents.length) { + resizeContents(requiresSize); + } + + localContentsOffset += 2; + ModuleBinding javaBaseBinding = null; + for(int i = 0; i < module.requiresCount; i++) { + RequiresStatement req = module.requires[i]; + ModuleBinding reqBinding = req.resolvedBinding; + if (CharOperation.equals(reqBinding.moduleName, TypeConstants.JAVA_BASE)) { + javaBaseBinding = reqBinding; + } + int nameIndex = this.constantPool.literalIndexForModule(reqBinding.moduleName); + this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); + this.contents[localContentsOffset++] = (byte) (nameIndex); + flags = req.modifiers; + this.contents[localContentsOffset++] = (byte) (flags >> 8); + this.contents[localContentsOffset++] = (byte) (flags); + int required_version = 0; + this.contents[localContentsOffset++] = (byte) (required_version >> 8); + this.contents[localContentsOffset++] = (byte) (required_version); + } + if (!CharOperation.equals(binding.moduleName, TypeConstants.JAVA_BASE) && javaBaseBinding == null) { + if (localContentsOffset + 6 >= this.contents.length) { + resizeContents(6); + } + javaBaseBinding = binding.environment.javaBaseModule(); + int javabase_index = this.constantPool.literalIndexForModule(javaBaseBinding.moduleName); + this.contents[localContentsOffset++] = (byte) (javabase_index >> 8); + this.contents[localContentsOffset++] = (byte) (javabase_index); + flags = ClassFileConstants.AccMandated; + this.contents[localContentsOffset++] = (byte) (flags >> 8); + this.contents[localContentsOffset++] = (byte) flags; + int required_version = 0; + this.contents[localContentsOffset++] = (byte) (required_version >> 8); + this.contents[localContentsOffset++] = (byte) (required_version); + requiresCount++; + } + this.contents[requiresCountOffset++] = (byte) (requiresCount >> 8); + this.contents[requiresCountOffset++] = (byte) requiresCount; + attrLength += 2 + 6 * requiresCount; + // ================= end requires section ================= + + // ================= exports section ================= + /** + * u2 exports_count; + * { u2 exports_index; + * u2 exports_flags; + * u2 exports_to_count; + * u2 exports_to_index[exports_to_count]; + * } exports[exports_count]; + */ + int exportsSize = 2 + module.exportsCount * 6; + if (localContentsOffset + exportsSize >= this.contents.length) { + resizeContents(exportsSize); + } + this.contents[localContentsOffset++] = (byte) (module.exportsCount >> 8); + this.contents[localContentsOffset++] = (byte) module.exportsCount; + for (int i = 0; i < module.exportsCount; i++) { + ExportsStatement ref = module.exports[i]; + if (localContentsOffset + 6 >= this.contents.length) { + resizeContents((module.exportsCount - i) * 6); + } + int nameIndex = this.constantPool.literalIndexForPackage(CharOperation.replaceOnCopy(ref.pkgName, '.', '/')); + this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); + this.contents[localContentsOffset++] = (byte) (nameIndex); + // TODO exports_flags - check when they are set + this.contents[localContentsOffset++] = (byte) 0; + this.contents[localContentsOffset++] = (byte) 0; + + int exportsToCount = ref.isQualified() ? ref.targets.length : 0; + this.contents[localContentsOffset++] = (byte) (exportsToCount >> 8); + this.contents[localContentsOffset++] = (byte) (exportsToCount); + if (exportsToCount > 0) { + int targetSize = 2 * exportsToCount; + if (localContentsOffset + targetSize >= this.contents.length) { + resizeContents(targetSize); + } + for(int j = 0; j < exportsToCount; j++) { + nameIndex = this.constantPool.literalIndexForModule(ref.targets[j].moduleName); + this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); + this.contents[localContentsOffset++] = (byte) (nameIndex); + } + attrLength += targetSize; + } + } + attrLength += exportsSize; + // ================= end exports section ================= + + // ================= opens section ================= + /** + * u2 opens_count; + * { u2 opens_index; + * u2 opens_flags; + * u2 opens_to_count; + * u2 opens_to_index[opens_to_count]; + * } exports[exports_count]; + */ + int opensSize = 2 + module.opensCount * 6; + if (localContentsOffset + opensSize >= this.contents.length) { + resizeContents(opensSize); + } + this.contents[localContentsOffset++] = (byte) (module.opensCount >> 8); + this.contents[localContentsOffset++] = (byte) module.opensCount; + for (int i = 0; i < module.opensCount; i++) { + OpensStatement ref = module.opens[i]; + if (localContentsOffset + 6 >= this.contents.length) { + resizeContents((module.opensCount - i) * 6); + } + int nameIndex = this.constantPool.literalIndexForPackage(CharOperation.replaceOnCopy(ref.pkgName, '.', '/')); + this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); + this.contents[localContentsOffset++] = (byte) (nameIndex); + // TODO opens_flags - check when they are set + this.contents[localContentsOffset++] = (byte) 0; + this.contents[localContentsOffset++] = (byte) 0; + + int opensToCount = ref.isQualified() ? ref.targets.length : 0; + this.contents[localContentsOffset++] = (byte) (opensToCount >> 8); + this.contents[localContentsOffset++] = (byte) (opensToCount); + if (opensToCount > 0) { + int targetSize = 2 * opensToCount; + if (localContentsOffset + targetSize >= this.contents.length) { + resizeContents(targetSize); + } + for(int j = 0; j < opensToCount; j++) { + nameIndex = this.constantPool.literalIndexForModule(ref.targets[j].moduleName); + this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); + this.contents[localContentsOffset++] = (byte) (nameIndex); + } + attrLength += targetSize; + } + } + attrLength += opensSize; + // ================= end opens section ================= + + // ================= uses section ================= + /** + * u2 uses_count; + * u2 uses_index[uses_count]; + */ + int usesSize = 2 + 2 * module.usesCount; + if (localContentsOffset + usesSize >= this.contents.length) { + resizeContents(usesSize); + } + this.contents[localContentsOffset++] = (byte) (module.usesCount >> 8); + this.contents[localContentsOffset++] = (byte) module.usesCount; + for(int i = 0; i < module.usesCount; i++) { + int nameIndex = this.constantPool.literalIndexForType(module.uses[i].serviceInterface.resolvedType.constantPoolName()); + this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); + this.contents[localContentsOffset++] = (byte) (nameIndex); + } + attrLength += usesSize; + // ================= end uses section ================= + + // ================= provides section ================= + /** + * u2 provides_count; + * { + * u2 provides_index; + * u2 provides_with_count; + * u2 provides_with_index[provides_with_count]; + * } provides[provides_count]; + */ + int servicesSize = 2 + 4 * module.servicesCount; + if (localContentsOffset + servicesSize >= this.contents.length) { + resizeContents(servicesSize); + } + this.contents[localContentsOffset++] = (byte) (module.servicesCount >> 8); + this.contents[localContentsOffset++] = (byte) module.servicesCount; + for(int i = 0; i < module.servicesCount; i++) { + if (localContentsOffset + 4 >= this.contents.length) { + resizeContents((module.servicesCount - i) * 4); + } + int nameIndex = this.constantPool.literalIndexForType(module.services[i].serviceInterface.resolvedType.constantPoolName()); + this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); + this.contents[localContentsOffset++] = (byte) (nameIndex); + TypeReference[] impls = module.services[i].implementations; + int implLength = impls.length; + this.contents[localContentsOffset++] = (byte) (implLength >> 8); + this.contents[localContentsOffset++] = (byte) implLength; + int targetSize = implLength * 2; + if (localContentsOffset + targetSize >= this.contents.length) { + resizeContents(targetSize); + } + for (int j = 0; j < implLength; j++) { + nameIndex = this.constantPool.literalIndexForType(impls[j].resolvedType.constantPoolName()); + this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); + this.contents[localContentsOffset++] = (byte) (nameIndex); + } + attrLength += targetSize; + } + attrLength += servicesSize; + // ================= end provides section ================= + + this.contents[attrLengthOffset++] = (byte)(attrLength >> 24); + this.contents[attrLengthOffset++] = (byte)(attrLength >> 16); + this.contents[attrLengthOffset++] = (byte)(attrLength >> 8); + this.contents[attrLengthOffset++] = (byte)attrLength; + this.contentsOffset = localContentsOffset; + return 1; + } + + private int generateModuleMainClassAttribute(char[] moduleMainClass) { + int localContentsOffset = this.contentsOffset; + if (localContentsOffset + 8 >= this.contents.length) { + resizeContents(8); + } + int moduleAttributeNameIndex = + this.constantPool.literalIndex(AttributeNamesConstants.ModuleMainClass); + this.contents[localContentsOffset++] = (byte) (moduleAttributeNameIndex >> 8); + this.contents[localContentsOffset++] = (byte) moduleAttributeNameIndex; + int attrLength = 2; + this.contents[localContentsOffset++] = (byte)(attrLength >> 24); + this.contents[localContentsOffset++] = (byte)(attrLength >> 16); + this.contents[localContentsOffset++] = (byte)(attrLength >> 8); + this.contents[localContentsOffset++] = (byte)attrLength; + int moduleNameIndex = this.constantPool.literalIndexForType(moduleMainClass); + this.contents[localContentsOffset++] = (byte) (moduleNameIndex >> 8); + this.contents[localContentsOffset++] = (byte) moduleNameIndex; + this.contentsOffset = localContentsOffset; + return 1; + } + + private int generateModulePackagesAttribute(char[][] packageNames) { + int localContentsOffset = this.contentsOffset; + int maxSize = 6 + 2*packageNames.length; + if (localContentsOffset + maxSize >= this.contents.length) { + resizeContents(maxSize); + } + int moduleAttributeNameIndex = + this.constantPool.literalIndex(AttributeNamesConstants.ModulePackages); + this.contents[localContentsOffset++] = (byte) (moduleAttributeNameIndex >> 8); + this.contents[localContentsOffset++] = (byte) moduleAttributeNameIndex; + + int attrLengthOffset = localContentsOffset; + localContentsOffset+= 4; + int packageCountOffset = localContentsOffset; + localContentsOffset+= 2; + + int packagesCount = 0; + for (char[] packageName : packageNames) { + if (packageName == null || packageName.length == 0) continue; + int packageNameIndex = this.constantPool.literalIndexForPackage(packageName); + this.contents[localContentsOffset++] = (byte) (packageNameIndex >> 8); + this.contents[localContentsOffset++] = (byte) packageNameIndex; + packagesCount++; + } + + this.contents[packageCountOffset++] = (byte)(packagesCount >> 8); + this.contents[packageCountOffset++] = (byte)packagesCount; + int attrLength = 2 + 2 * packagesCount; + this.contents[attrLengthOffset++] = (byte)(attrLength >> 24); + this.contents[attrLengthOffset++] = (byte)(attrLength >> 16); + this.contents[attrLengthOffset++] = (byte)(attrLength >> 8); + this.contents[attrLengthOffset++] = (byte)attrLength; + this.contentsOffset = localContentsOffset; + return 1; + } + private void generateElementValue( Expression defaultValue, TypeBinding memberValuePairReturnType, @@ -4911,13 +5275,12 @@ private final int i4At(byte[] reference, int relativeOffset, + (reference[position] & 0xFF); } - protected void initByteArrays() { - int members = this.referenceBinding.methods().length + this.referenceBinding.fields().length; + protected void initByteArrays(int members) { this.header = new byte[INITIAL_HEADER_SIZE]; this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE]; } - public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boolean createProblemType) { + private void initializeHeader(ClassFile parentClassFile, int accessFlags) { // generate the magic numbers inside the header this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 24); this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 16); @@ -4933,6 +5296,14 @@ public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boole this.constantPoolOffset = this.headerOffset; this.headerOffset += 2; this.constantPool.initialize(this); + this.enclosingClassFile = parentClassFile; + + // now we continue to generate the bytes inside the contents array + this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); + this.contents[this.contentsOffset++] = (byte) accessFlags; + } + + public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boolean createProblemType) { // Modifier manipulations for classfile int accessFlags = aType.getAccessFlags(); @@ -4963,12 +5334,9 @@ public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boole if ((accessFlags & finalAbstract) == finalAbstract) { accessFlags &= ~finalAbstract; } - this.enclosingClassFile = parentClassFile; + initializeHeader(parentClassFile, accessFlags); // innerclasses get their names computed at code gen time - // now we continue to generate the bytes inside the contents array - this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); - this.contents[this.contentsOffset++] = (byte) accessFlags; int classNameIndex = this.constantPool.literalIndexForType(aType); this.contents[this.contentsOffset++] = (byte) (classNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) classNameIndex; @@ -5012,6 +5380,26 @@ public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boole this.codeStream.maxFieldCount = aType.scope.outerMostClassScope().referenceType().maxFieldCount; } + public void initializeForModule(ModuleBinding module) { + initializeHeader(null, ClassFileConstants.AccModule); + int classNameIndex = this.constantPool.literalIndexForType(TypeConstants.MODULE_INFO_NAME); + this.contents[this.contentsOffset++] = (byte) (classNameIndex >> 8); + this.contents[this.contentsOffset++] = (byte) classNameIndex; + this.codeStream.maxFieldCount = 0; + // superclass: + this.contents[this.contentsOffset++] = 0; + this.contents[this.contentsOffset++] = 0; + // superInterfacesCount + this.contents[this.contentsOffset++] = 0; + this.contents[this.contentsOffset++] = 0; + // fieldsCount + this.contents[this.contentsOffset++] = 0; + this.contents[this.contentsOffset++] = 0; + // methodsCount + this.contents[this.contentsOffset++] = 0; + this.contents[this.contentsOffset++] = 0; + } + private void initializeDefaultLocals(StackMapFrame frame, MethodBinding methodBinding, int maxLocals, @@ -5240,17 +5628,23 @@ public int recordBootstrapMethod(FunctionalExpression expression) { return expression.bootstrapMethodNumber = this.bootstrapMethods.size() - 1; } - public void reset(SourceTypeBinding typeBinding) { + public void reset(/*@Nullable*/SourceTypeBinding typeBinding, CompilerOptions options) { // the code stream is reinitialized for each method - final CompilerOptions options = typeBinding.scope.compilerOptions(); - this.referenceBinding = typeBinding; - this.isNestedType = typeBinding.isNestedType(); + if (typeBinding != null) { + this.referenceBinding = typeBinding; + this.isNestedType = typeBinding.isNestedType(); + } else { + this.referenceBinding = null; + this.isNestedType = false; + } this.targetJDK = options.targetJDK; this.produceAttributes = options.produceDebugAttributes; if (this.targetJDK >= ClassFileConstants.JDK1_6) { this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; if (this.targetJDK >= ClassFileConstants.JDK1_8) { this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION; + if (!(this.codeStream instanceof TypeAnnotationCodeStream) && this.referenceBinding != null) + this.codeStream = new TypeAnnotationCodeStream(this); if (options.produceMethodParameters) { this.produceAttributes |= ClassFileConstants.ATTR_METHOD_PARAMETERS; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFilePool.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFilePool.java index 37aeb7181d..61208aa8e5 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFilePool.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFilePool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,6 +12,8 @@ import java.util.Arrays; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; public class ClassFilePool { @@ -37,13 +39,30 @@ public synchronized ClassFile acquire(SourceTypeBinding typeBinding) { return newClassFile; } if (!classFile.isShared) { - classFile.reset(typeBinding); + classFile.reset(typeBinding, typeBinding.scope.compilerOptions()); classFile.isShared = true; return classFile; } } return new ClassFile(typeBinding); } +public synchronized ClassFile acquireForModule(ModuleBinding moduleBinding, CompilerOptions options) { + for (int i = 0; i < POOL_SIZE; i++) { + ClassFile classFile = this.classFiles[i]; + if (classFile == null) { + ClassFile newClassFile = new ClassFile(moduleBinding, options); + this.classFiles[i] = newClassFile; + newClassFile.isShared = true; + return newClassFile; + } + if (!classFile.isShared) { + classFile.reset(null, options); + classFile.isShared = true; + return classFile; + } + } + return new ClassFile(moduleBinding, options); +} public synchronized void release(ClassFile classFile) { classFile.isShared = false; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java index 87de83ff3f..1ebd88d21c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -415,7 +415,7 @@ ReferenceContext getContext(CategorizedProblem problem) { */ public void record(char[] typeName, ClassFile classFile) { SourceTypeBinding sourceType = classFile.referenceBinding; - if (!sourceType.isLocalType() && sourceType.isHierarchyInconsistent()) { + if (sourceType != null && !sourceType.isLocalType() && sourceType.isHierarchyInconsistent()) { this.hasInconsistentToplevelHierarchies = true; } this.compiledTypes.put(typeName, classFile); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java index adb3a08f03..f1fd74bbba 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,6 +19,7 @@ import org.eclipse.jdt.internal.compiler.env.*; import org.eclipse.jdt.internal.compiler.impl.*; import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.parser.*; import org.eclipse.jdt.internal.compiler.problem.*; @@ -308,7 +309,8 @@ public void accept(IBinaryType binaryType, PackageBinding packageBinding, Access // new Exception("TRACE BINARY").printStackTrace(System.out); // System.out.println(); } - this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction); + LookupEnvironment env = packageBinding.environment; + env.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction); } /** @@ -437,6 +439,10 @@ private void compile(ICompilationUnit[] sourceUnits, boolean lastRound) { // build and record parsed units reportProgress(Messages.compilation_beginningToCompile); + if (this.options.complianceLevel >= ClassFileConstants.JDK9) { + // in Java 9 the compiler must never ask the oracle for a module that is contained in the input units: + sortModuleDeclarationsFirst(sourceUnits); + } if (this.annotationProcessorManager == null) { beginToCompile(sourceUnits); } else { @@ -484,6 +490,18 @@ private void compile(ICompilationUnit[] sourceUnits, boolean lastRound) { } } + private void sortModuleDeclarationsFirst(ICompilationUnit[] sourceUnits) { + Arrays.sort(sourceUnits, (u1, u2) -> { + char[] fn1 = u1.getFileName(); + char[] fn2 = u2.getFileName(); + boolean isMod1 = CharOperation.endsWith(fn1, TypeConstants.MODULE_INFO_FILE_NAME) || CharOperation.endsWith(fn1, TypeConstants.MODULE_INFO_CLASS_NAME); + boolean isMod2 = CharOperation.endsWith(fn2, TypeConstants.MODULE_INFO_FILE_NAME) || CharOperation.endsWith(fn2, TypeConstants.MODULE_INFO_CLASS_NAME); + if (isMod1 == isMod2) + return 0; + return isMod1 ? -1 : 1; + }); + } + class APTProblem { CategorizedProblem problem; ReferenceContext context; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java index 856a911c31..738a4b3aea 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java @@ -62,6 +62,7 @@ import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding; @@ -285,6 +286,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { // for import reference public static final int OnDemand = Bit18; public static final int Used = Bit2; + public static final int inModule = Bit19; // for parameterized qualified/single type ref public static final int DidResolve = Bit19; @@ -773,6 +775,15 @@ public static void resolveAnnotations(BlockScope scope, Annotation[] sourceAnnot // deliberately don't set the annotation resolved tagbits, it is not material and also we are working with a dummy static object. annotations = new AnnotationBinding[length]; break; + case Binding.MODULE: + ModuleBinding module = (ModuleBinding)recipient; + if ((module.tagBits & TagBits.AnnotationResolved) != 0) return annotations; + module.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); + if (length > 0) { + annotations = new AnnotationBinding[length]; + module.setAnnotations(annotations, scope); + } + break; default : return annotations; } @@ -1167,28 +1178,38 @@ public static void resolveDeprecatedAnnotations(BlockScope scope, Annotation[] a if (!CharOperation.equals(TypeConstants.JAVA_LANG_DEPRECATED[2], annotationTypeRef.getLastToken())) continue; TypeBinding annotationType = annotations[i].type.resolveType(scope); if(annotationType != null && annotationType.isValidBinding() && annotationType.id == TypeIds.T_JavaLangDeprecated) { + long deprecationTagBits = TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved; + if (scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK9) { + for (MemberValuePair memberValuePair : annotations[i].memberValuePairs()) { + if (CharOperation.equals(memberValuePair.name, TypeConstants.FOR_REMOVAL)) { + if (memberValuePair.value instanceof TrueLiteral) + deprecationTagBits |= TagBits.AnnotationTerminallyDeprecated; + break; + } + } + } switch (kind) { case Binding.PACKAGE : PackageBinding packageBinding = (PackageBinding) recipient; - packageBinding.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); + packageBinding.tagBits |= deprecationTagBits; return; case Binding.TYPE : case Binding.GENERIC_TYPE : case Binding.TYPE_PARAMETER : ReferenceBinding type = (ReferenceBinding) recipient; - type.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); + type.tagBits |= deprecationTagBits; return; case Binding.METHOD : MethodBinding method = (MethodBinding) recipient; - method.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); + method.tagBits |= deprecationTagBits; return; case Binding.FIELD : FieldBinding field = (FieldBinding) recipient; - field.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); + field.tagBits |= deprecationTagBits; return; case Binding.LOCAL : LocalVariableBinding local = (LocalVariableBinding) recipient; - local.tagBits |= (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved); + local.tagBits |= deprecationTagBits; return; default: return; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java index 25abe90547..557086eae3 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -466,6 +466,14 @@ public TypeBinding resolveType(BlockScope scope) { return new PolyTypeBinding(this); } this.resolvedType = this.type.resolvedType = this.binding.declaringClass; + // 15.9.3 - If the compile-time declaration is applicable by variable arity invocation... + if (this.binding.isVarargs()) { + TypeBinding lastArg = this.binding.parameters[this.binding.parameters.length - 1].leafComponentType(); + if (!lastArg.erasure().canBeSeenBy(scope)) { + scope.problemReporter().invalidType(this, new ProblemReferenceBinding(new char[][] {lastArg.readableName()}, (ReferenceBinding)lastArg, ProblemReasons.NotVisible)); + return this.resolvedType = null; + } + } resolvePolyExpressionArguments(this, this.binding, this.argumentTypes, scope); } else { this.binding = findConstructorBinding(scope, this, (ReferenceBinding) this.resolvedType, this.argumentTypes); @@ -591,15 +599,21 @@ public static MethodBinding inferDiamondConstructor(Scope scope, InvocationSite if (constructorTypeArguments.length > 0) System.arraycopy(((ParameterizedGenericMethodBinding)factory).typeArguments, sfmb.typeVariables().length - constructorTypeArguments.length , constructorTypeArguments, 0, constructorTypeArguments.length); + if (allocationType.isInterface()) { + ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) factory.returnType; + return new ParameterizedMethodBinding(parameterizedType, sfmb.getConstructor()); + } return sfmb.applyTypeArgumentsOnConstructor(((ParameterizedTypeBinding)factory.returnType).arguments, constructorTypeArguments, genericFactory.inferredWithUncheckedConversion); } return null; } - public TypeBinding[] inferElidedTypes(final Scope scope) { + return inferElidedTypes((ParameterizedTypeBinding) this.resolvedType, scope); +} +public TypeBinding[] inferElidedTypes(ParameterizedTypeBinding parameterizedType, final Scope scope) { - ReferenceBinding genericType = ((ParameterizedTypeBinding) this.resolvedType).genericType(); - ReferenceBinding enclosingType = this.resolvedType.enclosingType(); + ReferenceBinding genericType = parameterizedType.genericType(); + ReferenceBinding enclosingType = parameterizedType.enclosingType(); ParameterizedTypeBinding allocationType = scope.environment().createParameterizedType(genericType, genericType.typeVariables(), enclosingType); /* Given the allocation type and the arguments to the constructor, see if we can synthesize a generic static factory @@ -643,7 +657,7 @@ public void checkTypeArgumentRedundancy(ParameterizedTypeBinding allocationType, // checking for redundant type parameters must fake a diamond, // so we infer the same results as we would get with a diamond in source code: this.type.bits |= IsDiamond; - inferredTypes = inferElidedTypes(scope); + inferredTypes = inferElidedTypes(allocationType, scope); } finally { // reset effects of inference this.type.bits = previousBits; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java index 5e9034c6f4..515cdcab8b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java @@ -5,7 +5,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for @@ -287,6 +287,8 @@ public static long getTargetElementType(char[] elementName) { case 'M' : if (CharOperation.equals(elementName, TypeConstants.UPPER_METHOD)) return TagBits.AnnotationForMethod; + else if (CharOperation.equals(elementName, TypeConstants.UPPER_MODULE)) + return TagBits.AnnotationForModule; break; case 'P' : if (CharOperation.equals(elementName, TypeConstants.UPPER_PARAMETER)) @@ -364,6 +366,15 @@ private long detectStandardAnnotation(Scope scope, ReferenceBinding annotationTy // marker annotations case TypeIds.T_JavaLangDeprecated : tagBits |= TagBits.AnnotationDeprecated; + if (scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK9) { + for (MemberValuePair memberValuePair : memberValuePairs()) { + if (CharOperation.equals(memberValuePair.name, TypeConstants.FOR_REMOVAL)) { + if (memberValuePair.value instanceof TrueLiteral) + tagBits |= TagBits.AnnotationTerminallyDeprecated; + break; + } + } + } break; case TypeIds.T_JavaLangAnnotationDocumented : tagBits |= TagBits.AnnotationDocumented; @@ -635,6 +646,7 @@ public boolean hasError() { builder.check(TagBits.AnnotationForPackage, TypeConstants.UPPER_PACKAGE); builder.check(TagBits.AnnotationForTypeParameter, TypeConstants.TYPE_PARAMETER_TARGET); builder.check(TagBits.AnnotationForTypeUse, TypeConstants.TYPE_USE_TARGET); + builder.check(TagBits.AnnotationForModule, TypeConstants.UPPER_MODULE); if (builder.hasError()) { repeatableAnnotationType.tagAsHavingDefectiveContainerType(); scope.problemReporter().repeatableAnnotationTypeTargetMismatch(culpritNode, repeatableAnnotationType, containerType, builder.toString()); @@ -1150,6 +1162,12 @@ else if (scope.compilerOptions().sourceLevel <= ClassFileConstants.JDK1_6) { if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) != 0) { return AnnotationTargetAllowed.YES; } + break; + case Binding.MODULE: + if ((metaTagBits & (TagBits.AnnotationForModule)) != 0) { + return AnnotationTargetAllowed.YES; + } + break; } return AnnotationTargetAllowed.NO; } @@ -1167,6 +1185,8 @@ static AnnotationTargetAllowed isAnnotationTargetAllowed(Annotation annotation, long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) { // does not specify any target restriction - all locations supported in Java 7 and before are possible + // TBD - revisit for modules - as per 9.6.4.1, annotation without target is applicable for module declaration + // which is listed as a declaration context, but javac does not allow this if (kind == Binding.TYPE_PARAMETER || kind == Binding.TYPE_USE) { scope.problemReporter().explitAnnotationTargetRequired(annotation); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java index 0c2543025a..b0eb6aad31 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -100,7 +100,7 @@ public StringBuffer print(int tab, StringBuffer output) { public void resolveStatements() { super.resolveStatements(); - if (this.arguments != null) { + if (this.arguments != null || this.receiver != null) { this.scope.problemReporter().annotationMembersCannotHaveParameters(this); } if (this.typeParameters != null) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java index 7d5d671674..9668d111d5 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -107,7 +107,7 @@ class literals exist only for the raw underlying type. // Integer.class --> Class, perform boxing of base types (int.class --> Class) TypeBinding boxedType = null; if (this.targetType.id == T_void) { - boxedType = environment.getResolvedType(JAVA_LANG_VOID, scope); + boxedType = environment.getResolvedJavaBaseType(JAVA_LANG_VOID, scope); } else { boxedType = scope.boxing(this.targetType); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java index 3825b47087..26e30078cc 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -23,6 +23,7 @@ import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.IrritantSet; @@ -30,7 +31,9 @@ import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; import org.eclipse.jdt.internal.compiler.lookup.ImportBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.parser.NLSTag; @@ -56,6 +59,7 @@ public int compare(Object o1, Object o2) { public ImportReference currentPackage; public ImportReference[] imports; public TypeDeclaration[] types; + public ModuleDeclaration moduleDeclaration; public int[][] comments; public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors @@ -119,6 +123,9 @@ public void analyseCode() { this.types[i].analyseCode(this.scope); } } + if (this.moduleDeclaration != null) { + this.moduleDeclaration.analyseCode(this.scope); + } // request inner emulation propagation propagateInnerEmulationForAllLocalTypes(); } catch (AbortCompilationUnit e) { @@ -383,6 +390,9 @@ public void generateCode() { for (int i = 0, count = this.types.length; i < count; i++) this.types[i].generateCode(this.scope); } + if (this.moduleDeclaration != null) { + this.moduleDeclaration.generateCode(); + } } catch (AbortCompilationUnit e) { // ignore } @@ -422,6 +432,10 @@ public boolean isPackageInfo() { return CharOperation.equals(getMainTypeName(), TypeConstants.PACKAGE_INFO_NAME); } +public boolean isModuleInfo() { + return CharOperation.equals(getMainTypeName(), TypeConstants.MODULE_INFO_NAME); +} + public boolean isSuppressed(CategorizedProblem problem) { if (this.suppressWarningsCount == 0) return false; int irritant = ProblemReporter.getIrritant(problem.getID()); @@ -462,8 +476,9 @@ public StringBuffer print(int indent, StringBuffer output) { } currentImport.print(0, output).append(";\n"); //$NON-NLS-1$ } - - if (this.types != null) { + if (this.moduleDeclaration != null) { + this.moduleDeclaration.print(indent, output).append("\n"); //$NON-NLS-1$ + } else if (this.types != null) { for (int i = 0; i < this.types.length; i++) { this.types[i].print(indent, output).append("\n"); //$NON-NLS-1$ } @@ -764,12 +779,28 @@ public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope, boolean this.types[i].traverse(visitor, this.scope); } } + if (this.isModuleInfo() && this.moduleDeclaration != null) { + this.moduleDeclaration.traverse(visitor, this.scope); + } } visitor.endVisit(this, this.scope); } catch (AbortCompilationUnit e) { // ignore } } +public ModuleBinding module(LookupEnvironment environment) { + if (this.moduleDeclaration != null) { + ModuleBinding binding = this.moduleDeclaration.binding; + if (binding != null) + return binding; + } + if (this.compilationResult != null) { + ICompilationUnit compilationUnit = this.compilationResult.compilationUnit; + if (compilationUnit != null) + return compilationUnit.module(environment); + } + return environment.module; +} // GROOVY add //new method so that other compilation unit declarations can built alternative scopes public CompilationUnitScope buildCompilationUnitScope(org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment lookupEnvironment) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExportsStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExportsStatement.java new file mode 100644 index 0000000000..dc2112a20f --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExportsStatement.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +public class ExportsStatement extends PackageVisibilityStatement { + + public ExportsStatement(ImportReference pkgRef) { + this(pkgRef, null); + } + public ExportsStatement(ImportReference pkgRef, ModuleReference[] targets) { + super(pkgRef, targets); + } + + @Override + public StringBuffer print(int indent, StringBuffer output) { + printIndent(indent, output); + output.append("exports "); //$NON-NLS-1$ + super.print(0, output); + output.append(";"); //$NON-NLS-1$ + return output; + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java index 7e74f74b1f..03fbe12b71 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,6 +11,9 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; +import java.util.HashSet; +import java.util.Set; + import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.*; @@ -55,6 +58,21 @@ public char[][] getImportName() { return this.tokens; } + public void checkPackageConflict(CompilationUnitScope scope) { + ModuleBinding module = scope.module(); + PackageBinding visiblePackage = module.getVisiblePackage(this.tokens); + if (visiblePackage instanceof SplitPackageBinding) { + Set declaringMods = new HashSet<>(); + for (PackageBinding incarnation : ((SplitPackageBinding) visiblePackage).incarnations) { + if (incarnation.enclosingModule != module && module.canAccess(incarnation)) + declaringMods.add(incarnation.enclosingModule); + } + if (!declaringMods.isEmpty()) { + scope.problemReporter().conflictingPackagesFromOtherModules(this, declaringMods); + } + } + } + public StringBuffer print(int indent, StringBuffer output) { return print(indent, output, true); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java index 63e2c2ca84..42a68a9222 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java @@ -65,6 +65,7 @@ import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; @@ -481,6 +482,9 @@ public boolean argumentsTypeElided() { private void analyzeExceptions() { ExceptionHandlingFlowContext ehfc; + CompilerOptions compilerOptions = this.scope.compilerOptions(); + boolean oldAnalyseResources = compilerOptions.analyseResourceLeaks; + compilerOptions.analyseResourceLeaks = false; try { this.body.analyseCode(this.scope, ehfc = new ExceptionInferenceFlowContext(null, this, Binding.NO_EXCEPTIONS, null, this.scope, FlowInfo.DEAD_END), @@ -488,6 +492,8 @@ private void analyzeExceptions() { this.thrownExceptions = ehfc.extendedExceptions == null ? Collections.emptySet() : new HashSet(ehfc.extendedExceptions); } catch (Exception e) { // drop silently. + } finally { + compilerOptions.analyseResourceLeaks = oldAnalyseResources; } } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, final FlowInfo flowInfo) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index a1be3fddef..e44943cff5 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -67,6 +67,7 @@ import java.util.HashMap; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; @@ -660,6 +661,7 @@ public TypeBinding resolveType(BlockScope scope) { } this.actualReceiverType = this.receiver.resolveType(scope); if (this.actualReceiverType instanceof InferenceVariable) { + scope.referenceContext().tagAsHavingIgnoredMandatoryErrors(IProblem.UndefinedMethod); return null; // not yet ready for resolving } this.receiverIsType = this.receiver instanceof NameReference && (((NameReference) this.receiver).bits & Binding.TYPE) != 0; @@ -860,8 +862,10 @@ public TypeBinding resolveType(BlockScope scope) { } } else { // static message invoked through receiver? legal but unoptimal (optional warning). - if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || this.receiverIsType)) { - scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding); + if (this.binding.declaringClass.isInterface() && !((isTypeAccess() || this.receiver.isImplicitThis()) && TypeBinding.equalsEquals(this.binding.declaringClass, this.actualReceiverType))) { + scope.problemReporter().nonStaticOrAlienTypeReceiver(this, this.binding); + } else if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || this.receiverIsType)) { + scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding); } if (!this.receiver.isImplicitThis() && TypeBinding.notEquals(this.binding.declaringClass, this.actualReceiverType)) { scope.problemReporter().indirectAccessToStaticMethod(this, this.binding); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java index 55cb793120..94d81392e7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -297,7 +297,8 @@ else if (this.binding == null || this.binding.isStatic() || (this.binding.declar case TypeDeclaration.INTERFACE_DECL : if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8 && (this.modifiers & (ExtraCompilerModifiers.AccSemicolonBody | ClassFileConstants.AccAbstract)) == ExtraCompilerModifiers.AccSemicolonBody) { - if ((this.modifiers & (ClassFileConstants.AccStatic | ExtraCompilerModifiers.AccDefaultMethod)) != 0) { + boolean isPrivateMethod = compilerOptions.sourceLevel >= ClassFileConstants.JDK9 && (this.modifiers & ClassFileConstants.AccPrivate) != 0; + if (isPrivateMethod || ((this.modifiers & (ClassFileConstants.AccStatic | ExtraCompilerModifiers.AccDefaultMethod)) != 0)) { this.scope.problemReporter().methodNeedBody(this); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java new file mode 100644 index 0000000000..c5e8a40367 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java @@ -0,0 +1,382 @@ +/******************************************************************************* + * Copyright (c) 2015, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.ASTVisitor; +import org.eclipse.jdt.internal.compiler.ClassFile; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.BlockScope; +import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; +import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; +import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; +import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; +import org.eclipse.jdt.internal.compiler.lookup.SourceModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.SplitPackageBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.problem.AbortType; +import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; +import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; + +public class ModuleDeclaration extends ASTNode { + + public ExportsStatement[] exports; + public RequiresStatement[] requires; + public UsesStatement[] uses; + public ProvidesStatement[] services; + public OpensStatement[] opens; + public Annotation[] annotations; + public int exportsCount; + public int requiresCount; + public int usesCount; + public int servicesCount; + public int opensCount; + public SourceModuleBinding binding; + public int declarationSourceStart; + public int declarationSourceEnd; + public int bodyStart; + public int bodyEnd; // doesn't include the trailing comment if any. + public int modifiersSourceStart; + public BlockScope scope; + public char[][] tokens; + public char[] moduleName; + public long[] sourcePositions; + public int modifiers = ClassFileConstants.AccDefault; + boolean ignoreFurtherInvestigation; + boolean hasResolvedModuleDirectives; + boolean hasResolvedPackageDirectives; + boolean hasResolvedTypeDirectives; + CompilationResult compilationResult; + + public ModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions) { + this.compilationResult = compilationResult; + this.exportsCount = 0; + this.requiresCount = 0; + this.tokens = tokens; + this.moduleName = CharOperation.concatWith(tokens, '.'); + this.sourcePositions = positions; + this.sourceEnd = (int) (positions[positions.length-1] & 0x00000000FFFFFFFF); + this.sourceStart = (int) (positions[0] >>> 32); + } + + public ModuleBinding setBinding(SourceModuleBinding sourceModuleBinding) { + this.binding = sourceModuleBinding; + return sourceModuleBinding; + } + + public void checkAndSetModifiers() { + int realModifiers = this.modifiers & ExtraCompilerModifiers.AccJustFlag; + int expectedModifiers = ClassFileConstants.ACC_OPEN | ClassFileConstants.ACC_SYNTHETIC; + if ((realModifiers & ~(expectedModifiers)) != 0) { + this.scope.problemReporter().illegalModifierForModule(this); + realModifiers &= expectedModifiers; + } + int effectiveModifiers = ClassFileConstants.AccModule | realModifiers; + this.modifiers = this.binding.modifiers = effectiveModifiers; + } + + public boolean isOpen() { + return (this.modifiers & ClassFileConstants.ACC_OPEN) != 0; + } + + public void createScope(final Scope parentScope) { + this.scope = new MethodScope(parentScope, null, true) { + @Override + public ProblemReporter problemReporter() { + // this method scope has no reference context so we better deletegate to the 'real' cuScope: + return parentScope.problemReporter(); + } + }; + } + + public void generateCode() { + if ((this.bits & ASTNode.HasBeenGenerated) != 0) + return; + this.bits |= ASTNode.HasBeenGenerated; + if (this.ignoreFurtherInvestigation) { + return; + } + try { + // create the result for a compiled type + LookupEnvironment env = this.scope.environment(); + ClassFile classFile = env.classFilePool.acquireForModule(this.binding, env.globalOptions); + classFile.initializeForModule(this.binding); + + // finalize the compiled type result + classFile.addModuleAttributes(this.binding, this.annotations, this.scope.referenceCompilationUnit()); + this.scope.referenceCompilationUnit().compilationResult.record( + this.binding.moduleName, + classFile); + } catch (AbortType e) { + if (this.binding == null) + return; + } + } + + /** Resolve those module directives that relate to modules (requires). */ + public void resolveModuleDirectives(CompilationUnitScope cuScope) { + if (this.binding == null) { + this.ignoreFurtherInvestigation = true; + return; + } + if (this.hasResolvedModuleDirectives) + return; + + this.hasResolvedModuleDirectives = true; + + Set requiredModules = new HashSet(); + Set requiredTransitiveModules = new HashSet(); + for(int i = 0; i < this.requiresCount; i++) { + RequiresStatement ref = this.requires[i]; + if (ref != null && ref.resolve(cuScope) != null) { + if (!requiredModules.add(ref.resolvedBinding)) { + cuScope.problemReporter().duplicateModuleReference(IProblem.DuplicateRequires, ref.module); + } + if (ref.isTransitive()) + requiredTransitiveModules.add(ref.resolvedBinding); + Collection deps = ref.resolvedBinding.dependencyGraphCollector().get(); + if (deps.contains(this.binding)) { + cuScope.problemReporter().cyclicModuleDependency(this.binding, ref.module); + requiredModules.remove(ref.module.binding); + } + } + } + this.binding.setRequires(requiredModules.toArray(new ModuleBinding[requiredModules.size()]), + requiredTransitiveModules.toArray(new ModuleBinding[requiredTransitiveModules.size()])); + } + + /** Resolve those module directives that relate to packages (exports, opens). */ + public void resolvePackageDirectives(CompilationUnitScope cuScope) { + if (this.binding == null) { + this.ignoreFurtherInvestigation = true; + return; + } + if (this.hasResolvedPackageDirectives) + return; + + this.hasResolvedPackageDirectives = true; + + Set exportedPkgs = new HashSet<>(); + for (int i = 0; i < this.exportsCount; i++) { + ExportsStatement ref = this.exports[i]; + if (ref != null && ref.resolve(cuScope)) { + if (!exportedPkgs.add(ref.resolvedPackage)) { + cuScope.problemReporter().invalidPackageReference(IProblem.DuplicateExports, ref); + } + char[][] targets = null; + if (ref.targets != null) { + targets = new char[ref.targets.length][]; + for (int j = 0; j < targets.length; j++) + targets[j] = ref.targets[j].moduleName; + } + this.binding.addResolvedExport(ref.resolvedPackage, targets); + } + } + + HashtableOfObject openedPkgs = new HashtableOfObject(); + for (int i = 0; i < this.opensCount; i++) { + OpensStatement ref = this.opens[i]; + if (isOpen()) { + cuScope.problemReporter().invalidOpensStatement(ref, this); + } else { + if (openedPkgs.containsKey(ref.pkgName)) { + cuScope.problemReporter().invalidPackageReference(IProblem.DuplicateOpens, ref); + } else { + openedPkgs.put(ref.pkgName, ref); + ref.resolve(cuScope); + } + char[][] targets = null; + if (ref.targets != null) { + targets = new char[ref.targets.length][]; + for (int j = 0; j < targets.length; j++) + targets[j] = ref.targets[j].moduleName; + } + this.binding.addResolvedOpens(ref.resolvedPackage, targets); + } + } + } + + /** Resolve those module directives that relate to types (provides / uses). */ + public void resolveTypeDirectives(CompilationUnitScope cuScope) { + if (this.binding == null) { + this.ignoreFurtherInvestigation = true; + return; + } + if (this.hasResolvedTypeDirectives) + return; + + this.hasResolvedTypeDirectives = true; + ASTNode.resolveAnnotations(this.scope, this.annotations, this.binding); + + Set allTypes = new HashSet(); + for(int i = 0; i < this.usesCount; i++) { + TypeBinding serviceBinding = this.uses[i].serviceInterface.resolveType(this.scope); + if (serviceBinding != null && serviceBinding.isValidBinding()) { + if (!(serviceBinding.isClass() || serviceBinding.isInterface() || serviceBinding.isAnnotationType())) { + cuScope.problemReporter().invalidServiceRef(IProblem.InvalidServiceIntfType, this.uses[i].serviceInterface); + } + if (!allTypes.add(this.uses[i].serviceInterface.resolvedType)) { + cuScope.problemReporter().duplicateTypeReference(IProblem.DuplicateUses, this.uses[i].serviceInterface); + } + } + } + this.binding.setUses(allTypes.toArray(new TypeBinding[allTypes.size()])); + + Set interfaces = new HashSet<>(); + for(int i = 0; i < this.servicesCount; i++) { + this.services[i].resolve(this.scope); + TypeBinding infBinding = this.services[i].serviceInterface.resolvedType; + if (infBinding != null && infBinding.isValidBinding()) { + if (!interfaces.add(this.services[i].serviceInterface.resolvedType)) { + cuScope.problemReporter().duplicateTypeReference(IProblem.DuplicateServices, + this.services[i].serviceInterface); + } + this.binding.setImplementations(infBinding, this.services[i].getResolvedImplementations()); + } + } + this.binding.setServices(interfaces.toArray(new TypeBinding[interfaces.size()])); + } + + public void analyseCode(CompilationUnitScope skope) { + analyseModuleGraph(skope); + analyseExportedPackages(skope); + } + + private void analyseExportedPackages(CompilationUnitScope skope) { + if (this.exports != null) { + for (ExportsStatement export : this.exports) { + PackageBinding pb = export.resolvedPackage; + if (pb == null) + continue; + if (pb instanceof SplitPackageBinding) + pb = ((SplitPackageBinding) pb).getIncarnation(this.binding); + if (pb.hasCompilationUnit(true)) + continue; + skope.problemReporter().invalidPackageReference(IProblem.PackageDoesNotExistOrIsEmpty, export); + } + } + } + public void analyseModuleGraph(CompilationUnitScope skope) { + if (this.requires != null) { + // collect transitively: + Map> pack2mods = new HashMap<>(); + for (ModuleBinding requiredModule : this.binding.getAllRequiredModules()) { + for (PackageBinding exportedPackage : requiredModule.getExports()) { + if (this.binding.canAccess(exportedPackage)) { + String packName = String.valueOf(exportedPackage.readableName()); + Set mods = pack2mods.get(packName); + if (mods == null) + pack2mods.put(packName, mods = new HashSet<>()); + mods.add(requiredModule); + } + } + } + // report against the causing requires directives: + for (RequiresStatement requiresStat : this.requires) { + ModuleBinding requiredModule = requiresStat.resolvedBinding; + if (requiredModule != null) { + analyseOneDependency(requiresStat, requiredModule, skope, pack2mods); + if (requiresStat.isTransitive()) { + for (ModuleBinding secondLevelModule : requiredModule.getAllRequiredModules()) + analyseOneDependency(requiresStat, secondLevelModule, skope, pack2mods); + } + } + } + } + } + + private void analyseOneDependency(RequiresStatement requiresStat, ModuleBinding requiredModule, CompilationUnitScope skope, + Map> pack2mods) + { + for (PackageBinding pack : requiredModule.getExports()) { + Set mods = pack2mods.get(String.valueOf(pack.readableName())); + if (mods != null && mods.size() > 1) + skope.problemReporter().conflictingPackagesFromModules(pack, mods, requiresStat.sourceStart, requiresStat.sourceEnd); + } + } + + public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) { + visitor.visit(this, unitScope); + } + + public StringBuffer printHeader(int indent, StringBuffer output) { + if (this.annotations != null) { + for (int i = 0; i < this.annotations.length; i++) { + this.annotations[i].print(indent, output); + if (i != this.annotations.length - 1) + output.append(" "); //$NON-NLS-1$ + } + output.append('\n'); + } + if (isOpen()) { + output.append("open "); //$NON-NLS-1$ + } + output.append("module "); //$NON-NLS-1$ + output.append(CharOperation.charToString(this.moduleName)); + return output; + } + public StringBuffer printBody(int indent, StringBuffer output) { + output.append(" {"); //$NON-NLS-1$ + if (this.requires != null) { + for(int i = 0; i < this.requiresCount; i++) { + output.append('\n'); + printIndent(indent + 1, output); + this.requires[i].print(0, output); + } + } + if (this.exports != null) { + for(int i = 0; i < this.exportsCount; i++) { + output.append('\n'); + this.exports[i].print(indent + 1, output); + } + } + if (this.opens != null) { + for(int i = 0; i < this.opensCount; i++) { + output.append('\n'); + this.opens[i].print(indent + 1, output); + } + } + if (this.uses != null) { + for(int i = 0; i < this.usesCount; i++) { + output.append('\n'); + this.uses[i].print(indent + 1, output); + } + } + if (this.servicesCount != 0) { + for(int i = 0; i < this.servicesCount; i++) { + output.append('\n'); + this.services[i].print(indent + 1, output); + } + } + output.append('\n'); + return printIndent(indent, output).append('}'); + } + + @Override + public StringBuffer print(int indent, StringBuffer output) { + // + printIndent(indent, output); + printHeader(0, output); + return printBody(indent, output); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleReference.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleReference.java new file mode 100644 index 0000000000..a3feb5ba30 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleReference.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; + +public class ModuleReference extends ASTNode { + public char[][] tokens; + public long[] sourcePositions; //each entry is using the code : (start<<32) + end + public char[] moduleName; + public ModuleBinding binding = null; + + public ModuleReference(char[][] tokens, long[] sourcePositions) { + this.tokens = tokens; + this.sourcePositions = sourcePositions; + this.sourceEnd = (int) (sourcePositions[sourcePositions.length - 1] & 0x00000000FFFFFFFF); + this.sourceStart = (int) (sourcePositions[0] >>> 32); + this.moduleName = CharOperation.concatWith(tokens, '.'); + } + + @Override + public StringBuffer print(int indent, StringBuffer output) { + for (int i = 0; i < this.tokens.length; i++) { + if (i > 0) output.append('.'); + output.append(this.tokens[i]); + } + return output; + } + + public ModuleBinding resolve(Scope scope) { + if (scope == null || this.binding != null) + return this.binding; + return this.binding = scope.environment().getModule(this.moduleName); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleStatement.java new file mode 100644 index 0000000000..4279c07164 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleStatement.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +/** + * Just a marker class to represent statements that can occur in a module declaration + * + */ +public abstract class ModuleStatement extends ASTNode { + + public int declarationEnd; + public int declarationSourceStart; + public int declarationSourceEnd; +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java index 4086a9c394..002f1680fb 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java @@ -94,7 +94,7 @@ public void setFieldIndex(int index){ Aborts if constraints are violated. Due to various complexities, this check is not conveniently implementable in resolve/analyze phases. */ -protected void checkEffectiveFinality(LocalVariableBinding localBinding, Scope scope) { +public void checkEffectiveFinality(VariableBinding localBinding, Scope scope) { if ((this.bits & ASTNode.IsCapturedOuterLocal) != 0) { if (!localBinding.isFinal() && !localBinding.isEffectivelyFinal()) { scope.problemReporter().cannotReferToNonEffectivelyFinalOuterLocal(localBinding, this); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java new file mode 100644 index 0000000000..6a7546dd23 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; + +public class OpensStatement extends PackageVisibilityStatement { + + public OpensStatement(ImportReference pkgRef) { + this(pkgRef, null); + } + public OpensStatement(ImportReference pkgRef, ModuleReference[] targets) { + super(pkgRef, targets); + } + protected int computeSeverity(int problemId) { + return ProblemSeverities.Warning; + } + @Override + public StringBuffer print(int indent, StringBuffer output) { + printIndent(indent, output); + output.append("opens "); //$NON-NLS-1$ + super.print(0, output); + output.append(";"); //$NON-NLS-1$ + return output; + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java new file mode 100644 index 0000000000..61aa3499b8 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; +import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; +import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; + +public abstract class PackageVisibilityStatement extends ModuleStatement { + public ImportReference pkgRef; + public ModuleReference[] targets; + public char[] pkgName; + public PackageBinding resolvedPackage; + + public PackageVisibilityStatement(ImportReference pkgRef, ModuleReference[] targets) { + this.pkgRef = pkgRef; + this.pkgName = CharOperation.concatWith(this.pkgRef.tokens, '.'); + this.targets = targets; + } + public boolean isQualified() { + return this.targets != null && this.targets.length > 0; + } + + public ModuleReference[] getTargetedModules() { + return this.targets; + } + + public boolean resolve(Scope scope) { + boolean errorsExist = resolvePackageReference(scope) == null; + if (this.isQualified()) { + HashtableOfObject modules = new HashtableOfObject(this.targets.length); + for (int i = 0; i < this.targets.length; i++) { + ModuleReference ref = this.targets[i]; + if (modules.containsKey(ref.moduleName)) { + scope.problemReporter().duplicateModuleReference(IProblem.DuplicateModuleRef, ref); + errorsExist = true; + } else { + ref.resolve(scope.compilationUnitScope()); + modules.put(ref.moduleName, ref); + } + } + } + return !errorsExist; + } + protected int computeSeverity(int problemId) { + return ProblemSeverities.Error; + } + protected PackageBinding resolvePackageReference(Scope scope) { + if (this.resolvedPackage != null) + return this.resolvedPackage; + ModuleDeclaration exportingModule = scope.compilationUnitScope().referenceContext.moduleDeclaration; + ModuleBinding src = exportingModule.binding; + this.resolvedPackage = src != null ? src.getVisiblePackage(this.pkgRef.tokens) : null; + int problemId = IProblem.PackageDoesNotExistOrIsEmpty; + if (this.resolvedPackage == null) { + // TODO: need a check for empty package as well + scope.problemReporter().invalidPackageReference(problemId, this, computeSeverity(problemId)); + } else { + if (!this.resolvedPackage.isDeclaredIn(src)) { + this.resolvedPackage = null; + // TODO(SHMOD): specific error? + scope.problemReporter().invalidPackageReference(problemId, this, computeSeverity(problemId)); + } + } + + return this.resolvedPackage; + } + + @Override + public StringBuffer print(int indent, StringBuffer output) { + this.pkgRef.print(indent, output); + if (this.isQualified()) { + output.append(" to "); //$NON-NLS-1$ + for (int i = 0; i < this.targets.length; i++) { + if (i > 0) output.append(", "); //$NON-NLS-1$ + this.targets[i].print(0, output); + } + } + return output; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ProvidesStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ProvidesStatement.java new file mode 100644 index 0000000000..16e9a0f40e --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ProvidesStatement.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.lookup.Binding; +import org.eclipse.jdt.internal.compiler.lookup.BlockScope; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; +import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; + +public class ProvidesStatement extends ModuleStatement { + + public TypeReference serviceInterface; + public TypeReference[] implementations; + + public boolean resolve(BlockScope scope) { + ModuleDeclaration module = scope.referenceCompilationUnit().moduleDeclaration; + ModuleBinding src = module.binding; + TypeBinding infBinding = this.serviceInterface.resolveType(scope); + boolean hasErrors = false; + if (infBinding == null || !infBinding.isValidBinding()) { + return false; + } + if (!(infBinding.isClass() || infBinding.isInterface() || infBinding.isAnnotationType())) { + scope.problemReporter().invalidServiceRef(IProblem.InvalidServiceIntfType, this.serviceInterface); + } + ReferenceBinding intf = (ReferenceBinding) this.serviceInterface.resolvedType; + Set impls = new HashSet<>(); + for (int i = 0; i < this.implementations.length; i++) { + ReferenceBinding impl = (ReferenceBinding) this.implementations[i].resolveType(scope); + if (impl == null || !impl.isValidBinding() || !impl.canBeSeenBy(scope)) { + hasErrors = true; + continue; + } + if (!impls.add(impl)) { + scope.problemReporter().duplicateTypeReference(IProblem.DuplicateServices, this.implementations[i]); + continue; + } + int problemId = ProblemReasons.NoError; + ModuleBinding declaringModule = impl.module(); + + if (declaringModule != src) { + problemId = IProblem.ServiceImplNotDefinedByModule; + } else if (!impl.isClass() && !impl.isInterface()) { + problemId = IProblem.InvalidServiceImplType; + } else if (impl.isNestedType() && !impl.isStatic()) { + problemId = IProblem.NestedServiceImpl; + } else if (impl.isAbstract()) { + problemId = IProblem.AbstractServiceImplementation; + } else { + MethodBinding provider = impl.getExactMethod(TypeConstants.PROVIDER, Binding.NO_PARAMETERS, scope.compilationUnitScope()); + if (provider != null && (!provider.isValidBinding() || !(provider.isPublic() && provider.isStatic()))) { + provider = null; + } + TypeBinding implType = impl; + if (provider != null) { + implType = provider.returnType; + if (implType instanceof ReferenceBinding && !implType.canBeSeenBy(scope)) { + ReferenceBinding referenceBinding = (ReferenceBinding) implType; + scope.problemReporter().invalidType(this.implementations[i], new ProblemReferenceBinding( + referenceBinding.compoundName, referenceBinding, ProblemReasons.NotVisible)); + hasErrors = true; + } + } else { + MethodBinding defaultConstructor = impl.getExactConstructor(Binding.NO_PARAMETERS); + if (defaultConstructor == null || !defaultConstructor.isValidBinding()) { + problemId = IProblem.ProviderMethodOrConstructorRequiredForServiceImpl; + } else if (!defaultConstructor.isPublic()) { + problemId = IProblem.ServiceImplDefaultConstructorNotPublic; + } + } + if (implType.findSuperTypeOriginatingFrom(intf) == null) { + scope.problemReporter().typeMismatchError(implType, intf, this.implementations[i], null); + hasErrors = true; + } + } + if (problemId != ProblemReasons.NoError) { + scope.problemReporter().invalidServiceRef(problemId, this.implementations[i]); + hasErrors = true; + } + } + return hasErrors; + } + + public List getResolvedImplementations() { + List resolved = new ArrayList<>(); + if (this.implementations != null) { + for (TypeReference implRef : this.implementations) { + TypeBinding one = implRef.resolvedType; + if (one != null) + resolved.add(one); + } + } + return resolved; + } + + @Override + public StringBuffer print(int indent, StringBuffer output) { + printIndent(indent, output); + output.append("provides "); //$NON-NLS-1$ + this.serviceInterface.print(0, output); + //output.append(" "); //$NON-NLS-1$ + //printIndent(indent + 1, output); + output.append(" with "); //$NON-NLS-1$ + for (int i = 0; i < this.implementations.length; i++) { + this.implementations[i].print(0, output); + if (i < this.implementations.length - 1) + output.append(", "); //$NON-NLS-1$ + } + output.append(";"); //$NON-NLS-1$ + return output; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java index 6a377df6e3..5992b021ed 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -36,6 +36,8 @@ import static org.eclipse.jdt.internal.compiler.ast.ExpressionContext.INVOCATION_CONTEXT; +import java.util.Arrays; + import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; @@ -48,6 +50,7 @@ import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.ImplicitNullAnnotationVerifier; +import org.eclipse.jdt.internal.compiler.lookup.IntersectionTypeBinding18; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; @@ -59,8 +62,10 @@ import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeBindingVisitor; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; @@ -305,7 +310,7 @@ public TypeBinding resolveType(BlockScope scope) { } return result; } - + private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope scope) { // Propagate the type checking to the arguments, and checks if the constructor is defined. // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt @@ -480,8 +485,10 @@ private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope scope } } else { if (isDiamond) { - scope.problemReporter().diamondNotWithAnoymousClasses(this.type); - return null; + if (sourceLevel < ClassFileConstants.JDK9) { + scope.problemReporter().diamondNotWithAnoymousClasses(this.type); + return null; + } } ReferenceBinding superType = (ReferenceBinding) receiverType; if (superType.isTypeVariable()) { @@ -492,61 +499,7 @@ private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope scope scope.problemReporter().cannotInstantiate(this.type, superType); return this.resolvedType = superType; } - // anonymous type scenario - // an anonymous class inherits from java.lang.Object when declared "after" an interface - ReferenceBinding anonymousSuperclass = superType.isInterface() ? scope.getJavaLangObject() : superType; - // insert anonymous type in scope - scope.addAnonymousType(this.anonymousType, superType); - this.anonymousType.resolve(scope); - - // find anonymous super constructor - this.resolvedType = this.anonymousType.binding; // 1.2 change - if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) { - return null; // stop secondary errors - } - MethodBinding inheritedBinding = findConstructorBinding(scope, this, anonymousSuperclass, this.argumentTypes); - - if (!inheritedBinding.isValidBinding()) { - if (inheritedBinding.declaringClass == null) { - inheritedBinding.declaringClass = anonymousSuperclass; - } - if (this.type != null && !this.type.resolvedType.isValidBinding()) { - // problem already got signaled on type reference, do not report secondary problem - return null; - } - scope.problemReporter().invalidConstructor(this, inheritedBinding); - return this.resolvedType; - } - if ((inheritedBinding.tagBits & TagBits.HasMissingType) != 0) { - scope.problemReporter().missingTypeInConstructor(this, inheritedBinding); - } - if (this.enclosingInstance != null) { - ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType(); - if (targetEnclosing == null) { - scope.problemReporter().unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, superType); - return this.resolvedType; - } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) { - scope.problemReporter().typeMismatchError(enclosingInstanceType, targetEnclosing, this.enclosingInstance, null); - return this.resolvedType; - } - this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType); - } - if (this.arguments != null) { - if (checkInvocationArguments(scope, null, anonymousSuperclass, inheritedBinding, this.arguments, this.argumentTypes, this.argsContainCast, this)) { - this.bits |= ASTNode.Unchecked; - } - } - if (this.typeArguments != null && inheritedBinding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { - scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(inheritedBinding, this.genericTypeArguments, this.typeArguments); - } - // Update the anonymous inner class : superclass, interface - LookupEnvironment environment=scope.environment(); - if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) { - ImplicitNullAnnotationVerifier.ensureNullnessIsKnown(inheritedBinding, scope); - } - - this.binding = this.anonymousType.createDefaultConstructorWithBinding(inheritedBinding, (this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null); - return this.resolvedType; + this.resolvedType = receiverType; } } else { if (this.enclosingInstance != null) { @@ -554,8 +507,9 @@ private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope scope this.resolvedType = receiverType = this.type.resolvedType; } } + MethodBinding constructorBinding = null; if (isDiamond) { - this.binding = inferConstructorOfElidedParameterizedType(scope); + this.binding = constructorBinding = inferConstructorOfElidedParameterizedType(scope); if (this.binding == null || !this.binding.isValidBinding()) { scope.problemReporter().cannotInferElidedTypes(this); return this.resolvedType = null; @@ -564,50 +518,143 @@ private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope scope return new PolyTypeBinding(this); } this.resolvedType = this.type.resolvedType = receiverType = this.binding.declaringClass; + if (this.anonymousType != null) { + constructorBinding = getAnonymousConstructorBinding((ReferenceBinding) receiverType, scope); + if (constructorBinding == null) + return null; + this.resolvedType = this.anonymousType.binding; + // Check that inferred type is valid + if (!validate((ParameterizedTypeBinding) receiverType, scope)) { + return this.resolvedType; + } + } else { + // 15.9.3 - If the compile-time declaration is applicable by variable arity invocation... + if (this.binding.isVarargs()) { + TypeBinding lastArg = this.binding.parameters[this.binding.parameters.length - 1].leafComponentType(); + if (!lastArg.erasure().canBeSeenBy(scope)) { + scope.problemReporter().invalidType(this, new ProblemReferenceBinding(new char[][] {lastArg.readableName()}, (ReferenceBinding)lastArg, ProblemReasons.NotVisible)); + return this.resolvedType = null; + } + } + } resolvePolyExpressionArguments(this, this.binding, this.argumentTypes, scope); } else { - this.binding = findConstructorBinding(scope, this, (ReferenceBinding) receiverType, this.argumentTypes); + if (this.anonymousType != null) { + constructorBinding = getAnonymousConstructorBinding((ReferenceBinding) receiverType, scope); + if (constructorBinding == null) + return null; + this.resolvedType = this.anonymousType.binding; + } else { + this.binding = constructorBinding = findConstructorBinding(scope, this, (ReferenceBinding) receiverType, this.argumentTypes); + } } - - if (this.binding.isValidBinding()) { - if (isMethodUseDeprecated(this.binding, scope, true)) { - scope.problemReporter().deprecatedMethod(this.binding, this); + ReferenceBinding receiver = (ReferenceBinding) receiverType; + ReferenceBinding superType = receiver.isInterface() ? scope.getJavaLangObject() : receiver; + if (constructorBinding.isValidBinding()) { + if (isMethodUseDeprecated(constructorBinding, scope, true)) { + scope.problemReporter().deprecatedMethod(constructorBinding, this); } - if (checkInvocationArguments(scope, null, receiverType, this.binding, this.arguments, this.argumentTypes, this.argsContainCast, this)) { + if (checkInvocationArguments(scope, null, superType, constructorBinding, this.arguments, + this.argumentTypes, this.argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } - if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { - scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments); + if (this.typeArguments != null && constructorBinding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { + scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(constructorBinding, + this.genericTypeArguments, this.typeArguments); } } else { - if (this.binding.declaringClass == null) { - this.binding.declaringClass = (ReferenceBinding) receiverType; + if (constructorBinding.declaringClass == null) { + constructorBinding.declaringClass = superType; } if (this.type != null && !this.type.resolvedType.isValidBinding()) { // problem already got signaled on type reference, do not report secondary problem return null; } - scope.problemReporter().invalidConstructor(this, this.binding); - return this.resolvedType = receiverType; + scope.problemReporter().invalidConstructor(this, constructorBinding); + return this.resolvedType; + } + if ((constructorBinding.tagBits & TagBits.HasMissingType) != 0) { + scope.problemReporter().missingTypeInConstructor(this, constructorBinding); } - if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { - scope.problemReporter().missingTypeInConstructor(this, this.binding); + if (this.enclosingInstance != null) { + ReferenceBinding targetEnclosing = constructorBinding.declaringClass.enclosingType(); + if (targetEnclosing == null) { + scope.problemReporter().unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, receiver); + return this.resolvedType; + } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) { + scope.problemReporter().typeMismatchError(enclosingInstanceType, targetEnclosing, this.enclosingInstance, null); + return this.resolvedType; + } + this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType); } - if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments()) { - checkTypeArgumentRedundancy((ParameterizedTypeBinding)receiverType, scope); + if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments() && + (this.anonymousType == null || sourceLevel >= ClassFileConstants.JDK9)) { + checkTypeArgumentRedundancy((ParameterizedTypeBinding) receiverType, scope); } - // The enclosing instance must be compatible with the innermost enclosing type - ReferenceBinding expectedType = this.binding.declaringClass.enclosingType(); - if (TypeBinding.notEquals(expectedType, enclosingInstanceType)) // must call before computeConversion() and typeMismatchError() - scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType); - if (enclosingInstanceType.isCompatibleWith(expectedType) || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) { - this.enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType); + if (this.anonymousType != null) { + // anonymous type scenario + // Update the anonymous inner class : superclass, interface + LookupEnvironment environment=scope.environment(); + if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) { + ImplicitNullAnnotationVerifier.ensureNullnessIsKnown(constructorBinding, scope); + } + this.binding = this.anonymousType.createDefaultConstructorWithBinding(constructorBinding, (this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null); + return this.resolvedType; + } else { return this.resolvedType = receiverType; } - scope.problemReporter().typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance, null); - return this.resolvedType = receiverType; } + private boolean validate(final ParameterizedTypeBinding allocationType, final Scope scope) { + class ValidityInspector extends TypeBindingVisitor { + private boolean noErrors; + + public ValidityInspector() { + this.noErrors = true; + } + + public boolean visit(IntersectionTypeBinding18 intersectionTypeBinding18) { + Arrays.sort(intersectionTypeBinding18.intersectingTypes, (t1, t2) -> t1.id - t2.id); + scope.problemReporter().anonymousDiamondWithNonDenotableTypeArguments(QualifiedAllocationExpression.this.type, allocationType); + return this.noErrors = false; // stop traversal + } + public boolean visit(TypeVariableBinding typeVariable) { + if (typeVariable.isCapture()) { + scope.problemReporter().anonymousDiamondWithNonDenotableTypeArguments(QualifiedAllocationExpression.this.type, allocationType); + return this.noErrors = false; // stop traversal + } + return true; // continue traversal + } + public boolean visit(ReferenceBinding ref) { + if (!ref.canBeSeenBy(scope)) { + scope.problemReporter().invalidType(QualifiedAllocationExpression.this.anonymousType, new ProblemReferenceBinding(ref.compoundName, ref, ProblemReasons.NotVisible)); + return this.noErrors = false; + } + return true; + } + public boolean isValid() { + TypeBindingVisitor.visit(this, allocationType); + return this.noErrors; + } + } + + return new ValidityInspector().isValid(); + } + private MethodBinding getAnonymousConstructorBinding(ReferenceBinding receiverType, BlockScope scope) { + ReferenceBinding superType = receiverType; + // an anonymous class inherits from java.lang.Object when declared "after" an interface + ReferenceBinding anonymousSuperclass = superType.isInterface() ? scope.getJavaLangObject() : superType; + // insert anonymous type in scope + scope.addAnonymousType(this.anonymousType, superType); + this.anonymousType.resolve(scope); + + // find anonymous super constructor + this.resolvedType = this.anonymousType.binding; // 1.2 change + if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) { + return null; // stop secondary errors + } + return findConstructorBinding(scope, this, anonymousSuperclass, this.argumentTypes); + } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { if (this.enclosingInstance != null) diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java index b10f83e47c..d19603ab3b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -111,11 +111,22 @@ protected TypeBinding getTypeBinding(Scope scope) { return (ReferenceBinding) binding; // not found } PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding; + int typeStart = packageBinding == null ? 0 : packageBinding.compoundName.length; + + if (packageBinding != null) { + PackageBinding uniquePackage = packageBinding.getVisibleFor(scope.module()); + if (uniquePackage instanceof SplitPackageBinding) { + SplitPackageBinding splitPackage = (SplitPackageBinding) uniquePackage; + scope.problemReporter().conflictingPackagesFromModules(splitPackage, this.sourceStart, (int)this.sourcePositions[typeStart-1]); + this.resolvedType = new ProblemReferenceBinding(this.tokens, null, ProblemReasons.Ambiguous); + return null; + } + } rejectAnnotationsOnPackageQualifiers(scope, packageBinding); boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; ReferenceBinding qualifiedType = null; - for (int i = packageBinding == null ? 0 : packageBinding.compoundName.length, max = this.tokens.length, last = max-1; i < max; i++) { + for (int i = typeStart, max = this.tokens.length, last = max-1; i < max; i++) { findNextTypeBinding(i, scope, packageBinding); if (!this.resolvedType.isValidBinding()) return this.resolvedType; @@ -162,10 +173,13 @@ protected TypeBinding getTypeBinding(Scope scope) { } void recordResolution(LookupEnvironment env, TypeBinding typeFound) { - if (typeFound != null && typeFound.isValidBinding()) - for (int i = 0; i < env.resolutionListeners.length; i++) { - env.resolutionListeners[i].recordResolution(this, typeFound); + if (typeFound != null && typeFound.isValidBinding()) { + synchronized (env.root) { + for (int i = 0; i < env.root.resolutionListeners.length; i++) { + env.root.resolutionListeners[i].recordResolution(this, typeFound); + } } + } } public char[][] getTypeName(){ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java index ba19ce25e4..2d516bda44 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java @@ -248,9 +248,9 @@ public void generateImplicitLambda(BlockScope currentScope, CodeStream codeStrea // Process the lambda, taking care not to double report diagnostics. Don't expect any from resolve, Any from code generation should surface, but not those from flow analysis. BlockScope lambdaScope = this.receiverVariable != null ? this.receiverVariable.declaringScope : currentScope; - implicitLambda.resolveType(lambdaScope, true); IErrorHandlingPolicy oldPolicy = lambdaScope.problemReporter().switchErrorHandlingPolicy(silentErrorHandlingPolicy); try { + implicitLambda.resolveType(lambdaScope, true); implicitLambda.analyseCode(lambdaScope, new FieldInitsFakingFlowContext(null, this, Binding.NO_EXCEPTIONS, null, lambdaScope, FlowInfo.DEAD_END), UnconditionalFlowInfo.fakeInitializedFlowInfo(lambdaScope.outerMostMethodScope().analysisIndex, lambdaScope.referenceType().maxFieldCount)); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RequiresStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RequiresStatement.java new file mode 100644 index 0000000000..918ff43ada --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RequiresStatement.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; + +public class RequiresStatement extends ModuleStatement { + + public ModuleReference module; + public ModuleBinding resolvedBinding; + public int modifiers = ClassFileConstants.AccDefault; + public int modifiersSourceStart; + + public RequiresStatement(ModuleReference module) { + this.module = module; + } + public boolean isTransitive() { + return (this.modifiers & ClassFileConstants.ACC_TRANSITIVE) != 0; + } + public boolean isStatic() { + return (this.modifiers & ClassFileConstants.ACC_STATIC_PHASE) != 0; + } + @Override + public StringBuffer print(int indent, StringBuffer output) { + output.append("requires "); //$NON-NLS-1$ + if (isTransitive()) + output.append("transitive "); //$NON-NLS-1$ + if (isStatic()) + output.append("static "); //$NON-NLS-1$ + this.module.print(indent, output); + output.append(";"); //$NON-NLS-1$ + return output; + } + public ModuleBinding resolve(Scope scope) { + if (this.resolvedBinding != null) + return this.resolvedBinding; + this.resolvedBinding = this.module.resolve(scope); + if (this.resolvedBinding == null) { + if (scope != null) + scope.problemReporter().invalidModule(this.module); + } + return this.resolvedBinding; + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java index 7282b48e01..a669f27f21 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -47,9 +47,7 @@ public class TryStatement extends SubRoutineStatement { static final char[] SECRET_CAUGHT_THROWABLE_VARIABLE_NAME = " caughtThrowable".toCharArray(); //$NON-NLS-1$; static final char[] SECRET_RETURN_VALUE_NAME = " returnValue".toCharArray(); //$NON-NLS-1$ - private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0]; - public LocalDeclaration[] resources = NO_RESOURCES; - + public Statement[] resources = new Statement[0]; public Block tryBlock; public Block[] catchBlocks; @@ -146,17 +144,29 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl FlowInfo tryInfo = flowInfo.copy(); for (int i = 0; i < resourcesLength; i++) { - final LocalDeclaration resource = this.resources[i]; + final Statement resource = this.resources[i]; tryInfo = resource.analyseCode(currentScope, handlingContext, tryInfo); this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(tryInfo); - LocalVariableBinding resourceBinding = resource.binding; - resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. - if (resourceBinding.closeTracker != null) { - // this was false alarm, we don't need to track the resource - resourceBinding.closeTracker.withdraw(); - resourceBinding.closeTracker = null; + TypeBinding resolvedType = null; + LocalVariableBinding localVariableBinding = null; + if (resource instanceof LocalDeclaration) { + localVariableBinding = ((LocalDeclaration) resource).binding; + resolvedType = localVariableBinding.type; + } else { //expression + if (resource instanceof NameReference && ((NameReference) resource).binding instanceof LocalVariableBinding) { + localVariableBinding = (LocalVariableBinding) ((NameReference) resource).binding; + } + resolvedType = ((Expression) resource).resolvedType; + } + if (localVariableBinding != null) { + localVariableBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. + if (localVariableBinding.closeTracker != null) { + // this was false alarm, we don't need to track the resource + localVariableBinding.closeTracker.withdraw(); + localVariableBinding.closeTracker = null; + } } - MethodBinding closeMethod = findCloseMethod(resource, resourceBinding); + MethodBinding closeMethod = findCloseMethod(resource, resolvedType); if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) { ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions; for (int j = 0, length = thrownExceptions.length; j < length; j++) { @@ -175,7 +185,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl // to avoid polluting the state indices. However, do this after the postTryInitStateIndex is calculated since // it is used to add or remove assigned resources during code gen for (int i = 0; i < resourcesLength; i++) { - tryInfo.resetAssignmentInfo(this.resources[i].binding); + if (this.resources[i] instanceof LocalDeclaration) + tryInfo.resetAssignmentInfo(((LocalDeclaration) this.resources[i]).binding); } } // check unreachable catch blocks @@ -260,17 +271,29 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl FlowInfo tryInfo = flowInfo.copy(); for (int i = 0; i < resourcesLength; i++) { - final LocalDeclaration resource = this.resources[i]; + final Statement resource = this.resources[i]; tryInfo = resource.analyseCode(currentScope, handlingContext, tryInfo); this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(tryInfo); - LocalVariableBinding resourceBinding = resource.binding; - resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. - if (resourceBinding.closeTracker != null) { - // this was false alarm, we don't need to track the resource - resourceBinding.closeTracker.withdraw(); - // keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block + TypeBinding resolvedType = null; + LocalVariableBinding localVariableBinding = null; + if (resource instanceof LocalDeclaration) { + localVariableBinding = ((LocalDeclaration) this.resources[i]).binding; + resolvedType = localVariableBinding.type; + } else { // Expression + if (resource instanceof NameReference && ((NameReference) resource).binding instanceof LocalVariableBinding) { + localVariableBinding = (LocalVariableBinding)((NameReference) resource).binding; + } + resolvedType = ((Expression) resource).resolvedType; + } + if (localVariableBinding != null) { + localVariableBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. + if (localVariableBinding.closeTracker != null) { + // this was false alarm, we don't need to track the resource + localVariableBinding.closeTracker.withdraw(); + // keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block + } } - MethodBinding closeMethod = findCloseMethod(resource, resourceBinding); + MethodBinding closeMethod = findCloseMethod(resource, resolvedType); if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) { ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions; for (int j = 0, length = thrownExceptions.length; j < length; j++) { @@ -289,7 +312,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl // to avoid polluting the state indices. However, do this after the postTryInitStateIndex is calculated since // it is used to add or remove assigned resources during code gen for (int i = 0; i < resourcesLength; i++) { - tryInfo.resetAssignmentInfo(this.resources[i].binding); + if (this.resources[i] instanceof LocalDeclaration) + tryInfo.resetAssignmentInfo(((LocalDeclaration)this.resources[i]).binding); } } // check unreachable catch blocks @@ -346,10 +370,9 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl } } } -private MethodBinding findCloseMethod(final LocalDeclaration resource, LocalVariableBinding resourceBinding) { +private MethodBinding findCloseMethod(final ASTNode resource, TypeBinding type) { MethodBinding closeMethod = null; - TypeBinding type = resourceBinding.type; - if (type != null && type.isValidBinding()) { + if (type != null && type.isValidBinding() && type instanceof ReferenceBinding) { ReferenceBinding binding = (ReferenceBinding) type; closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter if(closeMethod == null) { @@ -396,7 +419,7 @@ private FlowInfo prepareCatchInfo(FlowInfo flowInfo, ExceptionHandlingFlowContex "(uncheckedExceptionTypes notNil and: [uncheckedExceptionTypes at: index]) ifTrue: [catchInits addPotentialInitializationsFrom: tryInits]." */ - if (this.tryBlock.statements == null && this.resources == NO_RESOURCES) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350579 + if (this.tryBlock.statements == null && this.resources == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350579 catchInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD); } return catchInfo; @@ -515,7 +538,18 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) { this.resourceExceptionLabels[i] = new ExceptionLabel(codeStream, null); this.resourceExceptionLabels[i].placeStart(); if (i < resourceCount) { - this.resources[i].generateCode(this.scope, codeStream); // Initialize resources ... + Statement stmt = this.resources[i]; + if (stmt instanceof NameReference) { + NameReference ref = (NameReference) stmt; + ref.bits |= ASTNode.IsCapturedOuterLocal; // TODO: selective flagging if ref.binding is not one of earlier inlined LVBs. + VariableBinding binding = (VariableBinding) ref.binding; // Only LVB expected here. + ref.checkEffectiveFinality(binding, this.scope); + } else if (stmt instanceof FieldReference) { + FieldReference fieldReference = (FieldReference) stmt; + if (!fieldReference.binding.isFinal()) + this.scope.problemReporter().cannotReferToNonFinalField(fieldReference.binding, fieldReference); + } + stmt.generateCode(this.scope, codeStream); // Initialize resources ... } } } @@ -525,7 +559,7 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) { BranchLabel exitLabel = new BranchLabel(codeStream); this.resourceExceptionLabels[i].placeEnd(); // outer handler if any is the one that should catch exceptions out of close() - LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null; + Statement stmt = i > 0 ? this.resources[i - 1] : null; if ((this.bits & ASTNode.IsTryBlockExiting) == 0) { // inline resource closure if (i > 0) { @@ -537,10 +571,7 @@ Our initialization type state is the same as it was at the end of the just concl codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex); } - codeStream.load(localVariable); - codeStream.ifnull(exitLabel); - codeStream.load(localVariable); - codeStream.invokeAutoCloseableClose(localVariable.type); + generateCodeSnippet(stmt, codeStream, exitLabel, false /* record */); codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd); } codeStream.goto_(exitLabel); // skip over the catch block. @@ -582,13 +613,7 @@ Our initialization type state is the same as it was at the end of the just concl if (i > 0) { // inline resource close here rather than bracketing the current catch block with a try region. BranchLabel postCloseLabel = new BranchLabel(codeStream); - int invokeCloseStartPc = codeStream.position; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=343785 - codeStream.load(localVariable); - codeStream.ifnull(postCloseLabel); - codeStream.load(localVariable); - codeStream.invokeAutoCloseableClose(localVariable.type); - codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd); - codeStream.removeVariable(localVariable); + generateCodeSnippet(stmt, codeStream, postCloseLabel, true /* record */, i, codeStream.position); postCloseLabel.place(); } codeStream.load(this.primaryExceptionVariable); @@ -843,6 +868,64 @@ Our initialization type state is the same as it was at the end of the just concl } codeStream.recordPositionsFrom(pc, this.sourceStart); } +private void generateCodeSnippet(Statement statement, CodeStream codeStream, BranchLabel postCloseLabel, boolean record, int... values) { + + int i = -1; + int invokeCloseStartPc = -1; + if (record) { + i = values[0]; + invokeCloseStartPc = values[1]; + } + if (statement instanceof LocalDeclaration) + generateCodeSnippet((LocalDeclaration)statement, codeStream, postCloseLabel, record, i, invokeCloseStartPc); + else if (statement instanceof Reference) + generateCodeSnippet((Reference)statement, codeStream, postCloseLabel, record, i, invokeCloseStartPc); + // else abort +} + +private void generateCodeSnippet(Reference reference, CodeStream codeStream, BranchLabel postCloseLabel, boolean record, int i, int invokeCloseStartPc) { + reference.generateCode(this.scope, codeStream, true); + codeStream.ifnull(postCloseLabel); + reference.generateCode(this.scope, codeStream, true); + codeStream.invokeAutoCloseableClose(reference.resolvedType); + if (!record) return; + codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd); + isDuplicateResourceReference(i); +} +private void generateCodeSnippet(LocalDeclaration localDeclaration, CodeStream codeStream, BranchLabel postCloseLabel, boolean record, int i, int invokeCloseStartPc) { + LocalVariableBinding variableBinding = localDeclaration.binding; + codeStream.load(variableBinding); + codeStream.ifnull(postCloseLabel); + codeStream.load(variableBinding); + codeStream.invokeAutoCloseableClose(variableBinding.type); + if (!record) return; + codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd); + if (!isDuplicateResourceReference(i)) // do not remove duplicate variable now + codeStream.removeVariable(variableBinding); +} + +private boolean isDuplicateResourceReference(int index) { + int len = this.resources.length; + if (index < len && this.resources[index] instanceof Reference) { + Reference ref = (Reference) this.resources[index]; + Binding refBinding = ref instanceof NameReference ? ((NameReference) ref).binding : + ref instanceof FieldReference ? ((FieldReference) ref).binding : null; + if (refBinding == null) return false; + + //TODO: For field accesses in the form of a.b.c and b.c - could there be a non-trivial dup - to check? + for (int i = 0; i < index; i++) { + Statement stmt = this.resources[i]; + Binding b = stmt instanceof LocalDeclaration ? ((LocalDeclaration) stmt).binding : + stmt instanceof NameReference ? ((NameReference) stmt).binding : + stmt instanceof FieldReference ? ((FieldReference) stmt).binding : null; + if (b == refBinding) { + this.scope.problemReporter().duplicateResourceReference(ref); + return true; + } + } + } + return false; +} /** * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding) @@ -854,13 +937,9 @@ public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream for (int i = resourceCount; i > 0; --i) { // Disarm the handlers and take care of resource closure. this.resourceExceptionLabels[i].placeEnd(); - LocalVariableBinding localVariable = this.resources[i-1].binding; BranchLabel exitLabel = new BranchLabel(codeStream); int invokeCloseStartPc = codeStream.position; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=343785 - codeStream.load(localVariable); - codeStream.ifnull(exitLabel); - codeStream.load(localVariable); - codeStream.invokeAutoCloseableClose(localVariable.type); + generateCodeSnippet(this.resources[i - 1], codeStream, exitLabel, false); codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd); exitLabel.place(); } @@ -954,7 +1033,12 @@ public StringBuffer printStatement(int indent, StringBuffer output) { int length = this.resources.length; printIndent(indent, output).append("try" + (length == 0 ? "\n" : " (")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ for (int i = 0; i < length; i++) { - this.resources[i].printAsExpression(0, output); + Statement stmt = this.resources[i]; + if (stmt instanceof LocalDeclaration) { + ((LocalDeclaration) stmt).printAsExpression(0, output); + } else if (stmt instanceof Reference) { + ((Reference) stmt).printExpression(0, output); + } else continue; if (i != length - 1) { output.append(";\n"); //$NON-NLS-1$ printIndent(indent + 2, output); @@ -1002,19 +1086,34 @@ public void resolve(BlockScope upperScope) { } for (int i = 0; i < resourceCount; i++) { this.resources[i].resolve(resourceManagementScope); - LocalVariableBinding localVariableBinding = this.resources[i].binding; - if (localVariableBinding != null && localVariableBinding.isValidBinding()) { - localVariableBinding.modifiers |= ClassFileConstants.AccFinal; - localVariableBinding.tagBits |= TagBits.IsResource; - TypeBinding resourceType = localVariableBinding.type; + if (this.resources[i] instanceof LocalDeclaration) { + LocalDeclaration node = (LocalDeclaration)this.resources[i]; + LocalVariableBinding localVariableBinding = node.binding; + if (localVariableBinding != null && localVariableBinding.isValidBinding()) { + localVariableBinding.modifiers |= ClassFileConstants.AccFinal; + localVariableBinding.tagBits |= TagBits.IsResource; + TypeBinding resourceType = localVariableBinding.type; + if (resourceType instanceof ReferenceBinding) { + if (resourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangAutoCloseable, false /*AutoCloseable is not a class*/) == null && resourceType.isValidBinding()) { + upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, node.type); + localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); + } + } else if (resourceType != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=349862, avoid secondary error in problematic null case + upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, node.type); + localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); + } + } + } else { // expression + Expression node = (Expression) this.resources[i]; + TypeBinding resourceType = node.resolvedType; if (resourceType instanceof ReferenceBinding) { if (resourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangAutoCloseable, false /*AutoCloseable is not a class*/) == null && resourceType.isValidBinding()) { - upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, this.resources[i].type); - localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); + upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, node); + ((Expression) this.resources[i]).resolvedType = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); } } else if (resourceType != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=349862, avoid secondary error in problematic null case - upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, this.resources[i].type); - localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); + upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, node); + ((Expression) this.resources[i]).resolvedType = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource); } } } @@ -1110,9 +1209,9 @@ public void resolve(BlockScope upperScope) { } public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { - LocalDeclaration[] localDeclarations = this.resources; - for (int i = 0, max = localDeclarations.length; i < max; i++) { - localDeclarations[i].traverse(visitor, this.scope); + Statement[] statements = this.resources; + for (int i = 0, max = statements.length; i < max; i++) { + statements[i].traverse(visitor, this.scope); } this.tryBlock.traverse(visitor, this.scope); if (this.catchArguments != null) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UsesStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UsesStatement.java new file mode 100644 index 0000000000..f2d938f79a --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UsesStatement.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.ast; + +public class UsesStatement extends ModuleStatement { + + public TypeReference serviceInterface; + + public UsesStatement(TypeReference serviceInterface) { + this.serviceInterface = serviceInterface; + } + @Override + public StringBuffer print(int indent, StringBuffer output) { + printIndent(indent, output); + output.append("uses "); //$NON-NLS-1$ + this.serviceInterface.print(0, output); + output.append(";"); //$NON-NLS-1$ + return output; + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java index 35380982d0..fd258d4ce5 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java @@ -289,7 +289,6 @@ private int scanAnnotation(int offset, boolean expectRuntimeVisibleAnno, boolean case 22: if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_DEPRECATED)) { this.standardAnnotationTagBits |= TagBits.AnnotationDeprecated; - return currentOffset; } break; case 23: diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java index 1bc40ebd00..895405e003 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -40,6 +40,7 @@ public interface ClassFileConstants { int AccSynthetic = 0x1000; int AccAnnotation = 0x2000; int AccEnum = 0x4000; + int AccModule = 0x8000; /** * From classfile version 52 (compliance 1.8 up), meaning that a formal parameter is mandated @@ -47,6 +48,13 @@ public interface ClassFileConstants { */ int AccMandated = 0x8000; + /** + * Flags in module declaration - since java9 + */ + int ACC_OPEN = 0x0020; + int ACC_TRANSITIVE = 0x0020; + int ACC_STATIC_PHASE = 0x0040; + int ACC_SYNTHETIC = 0x1000; /** * Other VM flags. @@ -73,6 +81,8 @@ public interface ClassFileConstants { int MethodHandleTag = 15; int MethodTypeTag = 16; int InvokeDynamicTag = 18; + int ModuleTag = 19; + int PackageTag = 20; int ConstantMethodRefFixedSize = 5; int ConstantClassFixedSize = 3; @@ -88,6 +98,8 @@ public interface ClassFileConstants { int ConstantMethodHandleFixedSize = 4; int ConstantMethodTypeFixedSize = 3; int ConstantInvokeDynamicFixedSize = 5; + int ConstantModuleFixedSize = 3; + int ConstantPackageFixedSize = 3; // JVMS 4.4.8 int MethodHandleRefKindGetField = 1; @@ -108,7 +120,7 @@ public interface ClassFileConstants { int MAJOR_VERSION_1_6 = 50; int MAJOR_VERSION_1_7 = 51; int MAJOR_VERSION_1_8 = 52; - int MAJOR_VERSION_1_9 = 53; // This might change + int MAJOR_VERSION_9 = 53; int MINOR_VERSION_0 = 0; int MINOR_VERSION_1 = 1; @@ -116,7 +128,7 @@ public interface ClassFileConstants { int MINOR_VERSION_3 = 3; int MINOR_VERSION_4 = 4; - // JDK 1.1 -> 1.9, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0 + // JDK 1.1 -> 9, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0 // 16 unsigned bits for major, then 16 bits for minor long JDK1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_3; // 1.1. is 45.3 long JDK1_2 = ((long)ClassFileConstants.MAJOR_VERSION_1_2 << 16) + ClassFileConstants.MINOR_VERSION_0; @@ -126,7 +138,7 @@ public interface ClassFileConstants { long JDK1_6 = ((long)ClassFileConstants.MAJOR_VERSION_1_6 << 16) + ClassFileConstants.MINOR_VERSION_0; long JDK1_7 = ((long)ClassFileConstants.MAJOR_VERSION_1_7 << 16) + ClassFileConstants.MINOR_VERSION_0; long JDK1_8 = ((long)ClassFileConstants.MAJOR_VERSION_1_8 << 16) + ClassFileConstants.MINOR_VERSION_0; - long JDK1_9 = ((long)ClassFileConstants.MAJOR_VERSION_1_9 << 16) + ClassFileConstants.MINOR_VERSION_0; + long JDK9 = ((long)ClassFileConstants.MAJOR_VERSION_9 << 16) + ClassFileConstants.MINOR_VERSION_0; /* * cldc1.1 is 45.3, but we modify it to be different from JDK1_1. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java index ff1db76851..8f81410b7c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -28,15 +28,18 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair; import org.eclipse.jdt.internal.compiler.env.IBinaryField; import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; +import org.eclipse.jdt.internal.compiler.env.IBinaryModule; import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.Util; public class ClassFileReader extends ClassFileStruct implements IBinaryType { @@ -49,6 +52,8 @@ public class ClassFileReader extends ClassFileStruct implements IBinaryType { private AnnotationInfo[] annotations; private TypeAnnotationInfo[] typeAnnotations; private FieldInfo[] fields; + private IBinaryModule moduleDeclaration; + public char[] moduleName; private int fieldsCount; // initialized in case the .class file is a nested type @@ -117,6 +122,29 @@ public static ClassFileReader read( return read(zip, filename, false); } +public static ClassFileReader readFromJimage( + File jrt, + String filename) + throws ClassFormatException, java.io.IOException { + + return readFromModule(jrt, null, filename); + } +public static ClassFileReader readFromJrt( + File jrt, + IModule module, + String filename) + + throws ClassFormatException, java.io.IOException { + return JRTUtil.getClassfile(jrt, filename, module); + } +public static ClassFileReader readFromModule( + File jrt, + String moduleName, + String filename) + + throws ClassFormatException, java.io.IOException { + return JRTUtil.getClassfile(jrt, filename, moduleName); +} public static ClassFileReader read( java.util.zip.ZipFile zip, String filename, @@ -237,6 +265,14 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit this.constantPoolOffsets[i] = readOffset; readOffset += ClassFileConstants.ConstantInvokeDynamicFixedSize; break; + case ClassFileConstants.ModuleTag: + this.constantPoolOffsets[i] = readOffset; + readOffset += ClassFileConstants.ConstantModuleFixedSize; + break; + case ClassFileConstants.PackageTag: + this.constantPoolOffsets[i] = readOffset; + readOffset += ClassFileConstants.ConstantPackageFixedSize; + break; } } // Read and validate access flags @@ -245,7 +281,9 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit // Read the classname, use exception handlers to catch bad format this.classNameIndex = u2At(readOffset); - this.className = getConstantClassNameAt(this.classNameIndex); + if (this.classNameIndex != 0) { + this.className = getConstantClassNameAt(this.classNameIndex); + } readOffset += 2; // Read the superclass name, can be null for java.lang.Object @@ -393,6 +431,9 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit missingTypeOffset += 2; } } + } else if (CharOperation.equals(attributeName, AttributeNamesConstants.ModuleName)) { + this.moduleDeclaration = ModuleInfo.createModule(this.className, this.reference, this.constantPoolOffsets, readOffset); + this.moduleName = this.moduleDeclaration.name(); } } readOffset += (6 + u4At(readOffset + 2)); @@ -562,6 +603,21 @@ public char[] getEnclosingTypeName() { public IBinaryField[] getFields() { return this.fields; } +/** + * @see IBinaryType#getModule() + */ +public char[] getModule() { + return this.moduleName; +} +/** + * Returns the module declaration that this class file represents. This will be + * null for non module-info class files. + * + * @return the module declaration this represents + */ +public IBinaryModule getModuleDeclaration() { + return this.moduleDeclaration; +} /** * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName() @@ -1318,6 +1374,8 @@ public String toString() { print.println(getClass().getName() + "{"); //$NON-NLS-1$ print.println(" this.className: " + new String(getName())); //$NON-NLS-1$ print.println(" this.superclassName: " + (getSuperclassName() == null ? "null" : new String(getSuperclassName()))); //$NON-NLS-2$ //$NON-NLS-1$ + if (this.moduleName != null) + print.println(" this.moduleName: " + (new String(this.moduleName))); //$NON-NLS-1$ print.println(" access_flags: " + printTypeModifiers(accessFlags()) + "(" + accessFlags() + ")"); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$ print.flush(); return out.toString(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationDecorator.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationDecorator.java index f379a7ecbf..5819d45304 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationDecorator.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationDecorator.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2016 Google, Inc. and others. + * Copyright (c) 2016, 2017 Google, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Stefan Xenos (Google) - initial API and implementation *******************************************************************************/ @@ -161,6 +161,11 @@ public int getModifiers() { return this.inputType.getModifiers(); } + @Override + public char[] getModule() { + return this.inputType.getModule(); + } + /** * Returns the zip file containing external annotations, if any. Returns null if there are no external annotations * or if the basePath refers to a directory. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java new file mode 100644 index 0000000000..d46cc0563e --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java @@ -0,0 +1,389 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.classfmt; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.env.IBinaryModule; +import org.eclipse.jdt.internal.compiler.env.IModule; + +public class ModuleInfo extends ClassFileStruct implements IBinaryModule { + protected int flags; + protected int requiresCount; + protected int exportsCount; + protected int usesCount; + protected int providesCount; + protected int opensCount; + protected char[] name; + protected char[] version; + protected ModuleReferenceInfo[] requires; + protected PackageExportInfo[] exports; + protected PackageExportInfo[] opens; + char[][] uses; + IModule.IService[] provides; + + @Override + public boolean isOpen() { + return (this.flags & ClassFileConstants.ACC_OPEN) != 0; + } + public int requiresCount() { + return this.requiresCount; + } + public int exportsCount() { + return this.exportsCount; + } + public int usesCount() { + return this.usesCount; + } + public int providesCount() { + return this.providesCount; + } + @Override + public char[] name() { + return this.name; + } + public void setName(char[] name) { + this.name = name; + } + @Override + public IModule.IModuleReference[] requires() { + return this.requires; + } + @Override + public IModule.IPackageExport[] exports() { + return this.exports; + } + @Override + public char[][] uses() { + return this.uses; + } + @Override + public IService[] provides() { + return this.provides; + } + @Override + public IModule.IPackageExport[] opens() { + return this.opens; + } + public void addReads(char[] modName) { + Predicate shouldAdd = m -> { + return Stream.of(this.requires).map(ref -> ref.name()).noneMatch(n -> CharOperation.equals(modName, n)); + }; + if (shouldAdd.test(modName)) { + int len = this.requires.length; + this.requires = Arrays.copyOf(this.requires, len); + ModuleReferenceInfo info = this.requires[len] = new ModuleReferenceInfo(); + info.refName = modName; + } + } + public void addExports(IPackageExport[] toAdd) { + Predicate shouldAdd = m -> { + return Stream.of(this.exports).map(ref -> ref.packageName).noneMatch(n -> CharOperation.equals(m, n)); + }; + Collection merged = Stream.concat(Stream.of(this.exports), Stream.of(toAdd) + .filter(e -> shouldAdd.test(e.name())) + .map(e -> { + PackageExportInfo exp = new PackageExportInfo(); + exp.packageName = e.name(); + exp.exportedTo = e.targets(); + return exp; + })) + .collect( + ArrayList::new, + ArrayList::add, + ArrayList::addAll); + this.exports = merged.toArray(new PackageExportInfo[merged.size()]); + } + /** + * @param classFileBytes byte[] + * @param offsets int[] + * @param offset int + */ + protected ModuleInfo (byte classFileBytes[], int offsets[], int offset) { + super(classFileBytes, offsets, offset); + } + + public static ModuleInfo createModule(char[] className, byte classFileBytes[], int offsets[], int offset) { + + int readOffset = offset; +// module.name = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); // returns 'Module' + int moduleOffset = readOffset + 6; + int utf8Offset; + ModuleInfo module = new ModuleInfo(classFileBytes, offsets, 0); + int name_index = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)]; + module.name = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + CharOperation.replace(module.name, '/', '.'); + moduleOffset += 2; + module.flags = module.u2At(moduleOffset); + moduleOffset += 2; + int version_index = module.u2At(moduleOffset); + if (version_index > 0) { + utf8Offset = module.constantPoolOffsets[version_index]; + module.version = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + } + moduleOffset += 2; + + utf8Offset = module.constantPoolOffsets[module.u2At(readOffset)]; + int count = module.u2At(moduleOffset); + module.requiresCount = count; + module.requires = new ModuleReferenceInfo[count]; + moduleOffset += 2; + for (int i = 0; i < count; i++) { + name_index = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)]; + char[] requiresNames = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + module.requires[i] = module.new ModuleReferenceInfo(); + CharOperation.replace(requiresNames, '/', '.'); + module.requires[i].refName = requiresNames; + moduleOffset += 2; + int modifiers = module.u2At(moduleOffset); + module.requires[i].modifiers = modifiers; + module.requires[i].isTransitive = (ClassFileConstants.ACC_TRANSITIVE & modifiers) != 0; // Access modifier + moduleOffset += 2; + version_index = module.u2At(moduleOffset); + if (version_index > 0) { + utf8Offset = module.constantPoolOffsets[version_index]; + module.requires[i].required_version = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + } + moduleOffset += 2; + } + count = module.u2At(moduleOffset); + moduleOffset += 2; + module.exportsCount = count; + module.exports = new PackageExportInfo[count]; + for (int i = 0; i < count; i++) { + name_index = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)]; + char[] exported = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + CharOperation.replace(exported, '/', '.'); + PackageExportInfo pack = module.new PackageExportInfo(); + module.exports[i] = pack; + pack.packageName = exported; + moduleOffset += 2; + pack.modifiers = module.u2At(moduleOffset); + moduleOffset += 2; + int exportedtoCount = module.u2At(moduleOffset); + moduleOffset += 2; + if (exportedtoCount > 0) { + pack.exportedTo = new char[exportedtoCount][]; + pack.exportedToCount = exportedtoCount; + for(int k = 0; k < exportedtoCount; k++) { + name_index = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)]; + char[] exportedToName = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + CharOperation.replace(exportedToName, '/', '.'); + pack.exportedTo[k] = exportedToName; + moduleOffset += 2; + } + } + } + count = module.u2At(moduleOffset); + moduleOffset += 2; + module.opensCount = count; + module.opens = new PackageExportInfo[count]; + for (int i = 0; i < count; i++) { + name_index = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)]; + char[] exported = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + CharOperation.replace(exported, '/', '.'); + PackageExportInfo pack = module.new PackageExportInfo(); + module.opens[i] = pack; + pack.packageName = exported; + moduleOffset += 2; + pack.modifiers = module.u2At(moduleOffset); + moduleOffset += 2; + int exportedtoCount = module.u2At(moduleOffset); + moduleOffset += 2; + if (exportedtoCount > 0) { + pack.exportedTo = new char[exportedtoCount][]; + pack.exportedToCount = exportedtoCount; + for(int k = 0; k < exportedtoCount; k++) { + name_index = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)]; + char[] exportedToName = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + CharOperation.replace(exportedToName, '/', '.'); + pack.exportedTo[k] = exportedToName; + moduleOffset += 2; + } + } + } + count = module.u2At(moduleOffset); + moduleOffset += 2; + module.usesCount = count; + module.uses = new char[count][]; + for (int i = 0; i < count; i++) { + int classIndex = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(classIndex + 1)]; + char[] inf = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + CharOperation.replace(inf, '/', '.'); + module.uses[i] = inf; + moduleOffset += 2; + } + count = module.u2At(moduleOffset); + moduleOffset += 2; + module.providesCount = count; + module.provides = new ServiceInfo[count]; + for (int i = 0; i < count; i++) { + int classIndex = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(classIndex + 1)]; + char[] inf = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + CharOperation.replace(inf, '/', '.'); + ServiceInfo service = module.new ServiceInfo(); + module.provides[i] = service; + service.serviceName = inf; + moduleOffset += 2; + int implCount = module.u2At(moduleOffset); + moduleOffset += 2; + service.with = new char[implCount][]; + if (implCount > 0) { + service.with = new char[implCount][]; + for(int k = 0; k < implCount; k++) { + classIndex = module.constantPoolOffsets[module.u2At(moduleOffset)]; + utf8Offset = module.constantPoolOffsets[module.u2At(classIndex + 1)]; + char[] implName = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); + CharOperation.replace(implName, '/', '.'); + service.with[k] = implName; + moduleOffset += 2; + } + } + } + return module; + } + class ModuleReferenceInfo implements IModule.IModuleReference { + char[] refName; + boolean isTransitive = false; + int modifiers; + char[] required_version; + @Override + public char[] name() { + return this.refName; + } + @Override + public boolean isTransitive() { + return this.isTransitive; + } + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof IModule.IModuleReference)) + return false; + IModule.IModuleReference mod = (IModule.IModuleReference) o; + if (this.modifiers != mod.getModifiers()) + return false; + return CharOperation.equals(this.refName, mod.name(), false); + } + @Override + public int hashCode() { + return this.refName.hashCode(); + } + @Override + public int getModifiers() { + return this.modifiers; + } + } + class PackageExportInfo implements IModule.IPackageExport { + char[] packageName; + char[][] exportedTo; + int exportedToCount; + int modifiers; + @Override + public char[] name() { + return this.packageName; + } + + @Override + public char[][] targets() { + return this.exportedTo; + } + public String toString() { + StringBuffer buffer = new StringBuffer(); + toStringContent(buffer); + return buffer.toString(); + } + protected void toStringContent(StringBuffer buffer) { + buffer.append(this.packageName); + if (this.exportedToCount > 0) { + buffer.append(" to "); //$NON-NLS-1$ + for(int i = 0; i < this.exportedToCount; i++) { + buffer.append(this.exportedTo[i]); + buffer.append(',').append(' '); + } + } + buffer.append(';').append('\n'); + } + } + class ServiceInfo implements IModule.IService { + char[] serviceName; + char[][] with; + @Override + public char[] name() { + return this.serviceName; + } + + @Override + public char[][] with() { + return this.with; + } + } + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof IModule)) + return false; + IModule mod = (IModule) o; + if (!CharOperation.equals(this.name, mod.name())) + return false; + return Arrays.equals(this.requires, mod.requires()); + } + @Override + public int hashCode() { + int result = 17; + int c = this.name.hashCode(); + result = 31 * result + c; + c = Arrays.hashCode(this.requires); + result = 31 * result + c; + return result; + } + public String toString() { + StringBuffer buffer = new StringBuffer(getClass().getName()); + toStringContent(buffer); + return buffer.toString(); + } + protected void toStringContent(StringBuffer buffer) { + buffer.append("\nmodule "); //$NON-NLS-1$ + buffer.append(this.name).append(' '); + buffer.append('{').append('\n'); + if (this.requiresCount > 0) { + for(int i = 0; i < this.requiresCount; i++) { + buffer.append("\trequires "); //$NON-NLS-1$ + if (this.requires[i].isTransitive) { + buffer.append(" public "); //$NON-NLS-1$ + } + buffer.append(this.requires[i].refName); + buffer.append(';').append('\n'); + } + } + if (this.exportsCount > 0) { + buffer.append('\n'); + for(int i = 0; i < this.exportsCount; i++) { + buffer.append("\texports "); //$NON-NLS-1$ + buffer.append(this.exports[i].toString()); + } + } + buffer.append('\n').append('}').toString(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java index a6fa626f83..3987864fcc 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -28,6 +28,9 @@ public interface AttributeNamesConstants { final char[] SignatureName = "Signature".toCharArray(); //$NON-NLS-1$ final char[] LocalVariableTypeTableName = "LocalVariableTypeTable".toCharArray(); //$NON-NLS-1$ final char[] EnclosingMethodName = "EnclosingMethod".toCharArray(); //$NON-NLS-1$ + final char[] ModuleName = "Module".toCharArray(); //$NON-NLS-1$ + final char[] ModuleMainClass = "ModuleMainClass".toCharArray(); //$NON-NLS-1$ + final char[] ModulePackages = "ModulePackages".toCharArray(); //$NON-NLS-1$ final char[] AnnotationDefaultName = "AnnotationDefault".toCharArray(); //$NON-NLS-1$ final char[] RuntimeInvisibleAnnotationsName = "RuntimeInvisibleAnnotations".toCharArray(); //$NON-NLS-1$ final char[] RuntimeVisibleAnnotationsName = "RuntimeVisibleAnnotations".toCharArray(); //$NON-NLS-1$ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java index 9b1c53aee4..61d4f1e448 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for @@ -6537,7 +6537,7 @@ public void reset(ClassFile givenClassFile) { this.targetLevel = givenClassFile.targetJDK; int produceAttributes = givenClassFile.produceAttributes; this.generateAttributes = produceAttributes; - if ((produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { + if ((produceAttributes & ClassFileConstants.ATTR_LINES) != 0 && givenClassFile.referenceBinding != null) { this.lineSeparatorPositions = givenClassFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.getLineSeparatorPositions(); } else { this.lineSeparatorPositions = null; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java index 2cc81544cd..6a207c775c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -51,6 +51,8 @@ public class ConstantPool implements ClassFileConstants, TypeIds { protected CharArrayCache stringCache; protected HashtableOfObject methodsAndFieldsCache; protected CharArrayCache classCache; + protected CharArrayCache moduleCache; + protected CharArrayCache packageCache; protected HashtableOfObject nameAndTypeCacheForFieldsAndMethods; public byte[] poolContent; public int currentIndex = 1; @@ -306,6 +308,8 @@ public ConstantPool(ClassFile classFile) { this.stringCache = new CharArrayCache(STRING_INITIAL_SIZE); this.methodsAndFieldsCache = new HashtableOfObject(METHODS_AND_FIELDS_INITIAL_SIZE); this.classCache = new CharArrayCache(CLASS_INITIAL_SIZE); + this.moduleCache = new CharArrayCache(5); + this.packageCache = new CharArrayCache(5); this.nameAndTypeCacheForFieldsAndMethods = new HashtableOfObject(NAMEANDTYPE_INITIAL_SIZE); this.offsets = new int[5]; initialize(classFile); @@ -671,6 +675,64 @@ public int literalIndex(String stringConstant) { } return index; } + public int literalIndexForModule(final char[] moduleName) { + int index; + if ((index = this.moduleCache.putIfAbsent(moduleName, this.currentIndex)) < 0) { + // The entry doesn't exit yet + this.currentIndex++; + if ((index = -index) > 0xFFFF){ + this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); + } + // Write the tag first + int length = this.offsets.length; + if (length <= index) { + // resize + System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); + } + this.offsets[index] = this.currentOffset; + writeU1(ModuleTag); + // Then the string index + int stringIndexOffset = this.currentOffset; + if (this.currentOffset + 2 >= this.poolContent.length) { + resizePoolContents(2); + } + this.currentOffset+=2; + + final int stringIndex = literalIndex(moduleName); + this.poolContent[stringIndexOffset++] = (byte) (stringIndex >> 8); + this.poolContent[stringIndexOffset] = (byte) stringIndex; + } + return index; + } + public int literalIndexForPackage(final char[] packageName) { + int index; + if ((index = this.packageCache.putIfAbsent(packageName, this.currentIndex)) < 0) { + // The entry doesn't exit yet + this.currentIndex++; + if ((index = -index) > 0xFFFF){ + this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType()); + } + // Write the tag first + int length = this.offsets.length; + if (length <= index) { + // resize + System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length); + } + this.offsets[index] = this.currentOffset; + writeU1(PackageTag); + // Then the string index + int stringIndexOffset = this.currentOffset; + if (this.currentOffset + 2 >= this.poolContent.length) { + resizePoolContents(2); + } + this.currentOffset+=2; + + final int stringIndex = literalIndex(packageName); + this.poolContent[stringIndexOffset++] = (byte) (stringIndex >> 8); + this.poolContent[stringIndexOffset] = (byte) stringIndex; + } + return index; + } public int literalIndexForType(final char[] constantPoolName) { int index; if ((index = this.classCache.putIfAbsent(constantPoolName, this.currentIndex)) < 0) { @@ -1112,6 +1174,8 @@ public void reset() { this.stringCache.clear(); this.methodsAndFieldsCache.clear(); this.classCache.clear(); + this.packageCache.clear(); + this.moduleCache.clear(); this.nameAndTypeCacheForFieldsAndMethods.clear(); this.currentIndex = 1; this.currentOffset = 0; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AutomaticModuleNaming.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AutomaticModuleNaming.java new file mode 100644 index 0000000000..765c0a149e --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AutomaticModuleNaming.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2017 Till Brychcy and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Till Brychcy - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +import java.io.File; +import java.io.IOException; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +public class AutomaticModuleNaming { + + private static final String AUTOMATIC_MODULE_NAME = "Automatic-Module-Name"; //$NON-NLS-1$ + + /** + * Determine the automatic module name of a given jar as specified in {@link + * ModuleFinder.of} + */ + public static char[] determineAutomaticModuleName(final String jarFileName) { + // "If the JAR file has the attribute "Automatic-Module-Name" in its main manifest then its value is the + // module name." + try (JarFile jar = new JarFile(jarFileName)) { + Manifest manifest = jar.getManifest(); + if (manifest != null) { + String automaticModuleName = manifest.getMainAttributes().getValue(AUTOMATIC_MODULE_NAME); + if (automaticModuleName != null) { + return automaticModuleName.toCharArray(); + } + } + } catch (IOException e) { + // ignore + } + // The module name is otherwise derived from the name of the JAR file. + return determineAutomaticModuleNameFromFileName(jarFileName, true, true); + } + + /** + * Determine the automatic module name of a given jar or project as specified in {@link + * ModuleFinder.of} + * @param fileName names either a jar file or a java project in the workspace + * @param isFile true indicates that fileName denotes a file, false must be used for projects + * @param manifest representation of the META-INF/MANIFEST.MF entry within the given source (jar or project), or null + * @return the derived module name or null + */ + public static char[] determineAutomaticModuleName(final String fileName, boolean isFile, Manifest manifest) { + if (manifest != null) { + String automaticModuleName = manifest.getMainAttributes().getValue(AUTOMATIC_MODULE_NAME); + if (automaticModuleName != null) { + return automaticModuleName.toCharArray(); + } + } + return determineAutomaticModuleNameFromFileName(fileName, true, isFile); + } + + /** + * Determine the automatic module name if no "Automatic-Module-Name" was found in the Manifest, as specified in + * {@link ModuleFinder.of} + * + * @param name + * the filename (or directory name) + * @param skipDirectory + * if true, parent directory names are skipped + * @param removeExtension + * if true, the ".jar" extension is removed. + */ + public static char[] determineAutomaticModuleNameFromFileName(String name, boolean skipDirectory, + boolean removeExtension) { + int index; + int start = 0; + int end = name.length(); + if (skipDirectory) { + index = name.lastIndexOf(File.separatorChar); + start = index + 1; + } + + // "The ".jar" suffix is removed" + if (removeExtension) { + if (name.endsWith(".jar") || name.endsWith(".JAR")) { //$NON-NLS-1$//$NON-NLS-2$ + end -= 4; + } + } + + // "If the name matches the regular expression "-(\\d+(\\.|$))" then the module name will be derived from the + // subsequence preceding the hyphen of the first occurrence. [...]" + dashLoop: for (index = start; index < end - 1; index++) { + if (name.charAt(index) == '-' && name.charAt(index + 1) >= '0' && name.charAt(index + 1) <= '9') { + for (int index2 = index + 2; index2 < end; index2++) { + final char c = name.charAt(index2 + 1); + if (c == '.') { + break; + } + if (c < '0' || c > '9') { + continue dashLoop; + } + } + end = index; + break; + } + } + + // "All non-alphanumeric characters ([^A-Za-z0-9]) in the module name are replaced with a dot ("."), all + // repeating dots are replaced with one dot, and all leading and trailing dots are removed." + StringBuilder sb = new StringBuilder(end - start); + boolean needDot = false; + for (int i = start; i < end; i++) { + char c = name.charAt(i); + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { + if (needDot) { + sb.append('.'); + needDot = false; + } + sb.append(c); + } else { + if (sb.length() > 0) { + needDot = true; + } + } + } + return sb.toString().toCharArray(); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryModule.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryModule.java new file mode 100644 index 0000000000..e2f43ff67f --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryModule.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +/** Marker interface for usage of {@link org.eclipse.jdt.internal.compiler.classfmt.ModuleInfo} outside the compiler proper. */ +public interface IBinaryModule extends IModule { + // empty +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java index dfd3ea18df..78188257bb 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -58,6 +58,13 @@ public interface IBinaryType extends IGenericType { */ IBinaryField[] getFields(); +/** + * Answer the module to which this type belongs. + * {@code null} if the type is associated to the unnamed module. + * + * @return the module name or {@code null} + */ +char[] getModule(); /** * Answer the receiver's ClassSignature, which describes the type parameters, * super class, and super interfaces as specified in section "4.7.9.1 Signatures" diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java index bbe34a26c8..e20b09e56b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,8 +10,18 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.env; +import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; + /** * This interface denotes a compilation unit, providing its name and content. + * + *

+ * Note: This internal interface has been implemented illegally by the + * org.apache.jasper.glassfish bundle from Orbit, see + * bug 500211. + * Avoid changing the API or supply default methods to avoid breaking the Eclipse Help system. + *

*/ public interface ICompilationUnit extends IDependent { /** @@ -39,5 +49,26 @@ public interface ICompilationUnit extends IDependent { * Answer if optional problems should be ignored for this compilation unit. * Implementors should return false if there is no preference. */ -boolean ignoreOptionalProblems(); +default boolean ignoreOptionalProblems() { + return false; +} +/** + * Returns the binding of the module that this compilation unit is associated with. + * + * @return the binding representing the module. + */ +default ModuleBinding module(LookupEnvironment environment) { + return environment.getModule(getModuleName()); +} +/** + * Returns the name of the module to which this compilation unit is associated. + * A return value of {@code null} signals the unnamed module. + * @return module name or {@code null} for the unnamed module. + */ +default char[] getModuleName() { + return null; +} +default String getDestinationPath() { + return null; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModule.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModule.java new file mode 100644 index 0000000000..c5168b6357 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModule.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +import java.util.jar.Manifest; + +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; + +public interface IModule { + + public static IModuleReference[] NO_MODULE_REFS = new IModuleReference[0]; + public static IPackageExport[] NO_EXPORTS = new IPackageExport[0]; + public static char[][] NO_USES = new char[0][]; + public static IService[] NO_PROVIDES = new IService[0]; + public static IModule[] NO_MODULES = new IModule[0]; + public static IPackageExport[] NO_OPENS = new IPackageExport[0]; + + public String MODULE_INFO = "module-info"; //$NON-NLS-1$ + public String MODULE_INFO_JAVA = "module-info.java"; //$NON-NLS-1$ + public String MODULE_INFO_CLASS = "module-info.class"; //$NON-NLS-1$ + + public char[] name(); + + public IModuleReference[] requires(); + + public IPackageExport[] exports(); + + public char[][] uses(); + + public IService[] provides(); + + /* + * the opens package statement is very similar to package export statement, hence + * the same internal models are being used here. + */ + public IPackageExport[] opens(); + + public interface IModuleReference { + public char[] name(); + public default boolean isTransitive() { + return (getModifiers() & ClassFileConstants.ACC_TRANSITIVE) != 0; + } + public int getModifiers(); + public default boolean isStatic() { + return (getModifiers() & ClassFileConstants.ACC_STATIC_PHASE) != 0; + } + } + + public interface IPackageExport { + public char[] name(); + public char[][] targets(); + public default boolean isQualified() { + char[][] targets = targets(); + return targets != null && targets.length > 0; + } + } + + public interface IService { + public char[] name(); + char[][] with(); + } + + public default void addReads(char[] modName) { + // do nothing, would throwing an exception be better? + } + + public default void addExports(IPackageExport[] exports) { + // do nothing, would throwing an exception be better? + } + + public default boolean isAutomatic() { + return false; + } + public abstract boolean isOpen(); + + + public static IModule createAutomatic(char[] moduleName) { + final class AutoModule implements IModule { + char[] name; + public AutoModule(char[] name) { + this.name = name; + } + @Override + public char[] name() { + return this.name; + } + + @Override + public IModuleReference[] requires() { + return IModule.NO_MODULE_REFS; + } + + @Override + public IPackageExport[] exports() { + return IModule.NO_EXPORTS; + } + + @Override + public char[][] uses() { + return IModule.NO_USES; + } + + @Override + public IService[] provides() { + return IModule.NO_PROVIDES; + } + + @Override + public IPackageExport[] opens() { + return NO_OPENS; + } + + public boolean isAutomatic() { + return true; + } + public boolean isOpen() { + return false; + } + } + return new AutoModule(moduleName); + } + + public static IModule createAutomatic(String fileName, boolean isFile, Manifest manifest) { + return createAutomatic(AutomaticModuleNaming.determineAutomaticModuleName(fileName, isFile, manifest)); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java new file mode 100644 index 0000000000..95ba3cb721 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +import java.util.function.Predicate; + +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; + +/** + * A module aware name environment + */ +public interface IModuleAwareNameEnvironment extends INameEnvironment { + + /** Strategies for searching types & packages in classpath locations & modules. */ + enum LookupStrategy { + /** Search a specific named module only. */ + Named { + @Override + public boolean matchesWithName(T elem, Predicate isNamed, Predicate nameMatcher) { + assert nameMatcher != null : "name match needs a nameMatcher"; //$NON-NLS-1$ + return isNamed.test(elem) && nameMatcher.test(elem); + } + }, + /** Search all named modules. */ + AnyNamed { + @Override + public boolean matchesWithName(T elem, Predicate isNamed, Predicate nameMatcher) { + return isNamed.test(elem); + } + }, + /** Search all locations, module or otherwise. */ + Any { + @Override + public boolean matchesWithName(T elem, Predicate isNamed, Predicate nameMatcher) { + return true; + } + }, + /** Search only the unnamed module. */ + Unnamed { + @Override + public boolean matchesWithName(T elem, Predicate isNamed, Predicate nameMatcher) { + return !isNamed.test(elem); + } + }; + /** + * Test whether the given element matches this lookup strategy. + * @param elem location being tests + * @param isNamed predicate to determine if 'elem' represents a named module + * @param nameMatcher predicate to test if 'elem' matches the expected module name + * @return true iff the given element matches this lookup strategy. + */ + public abstract boolean matchesWithName(T elem, Predicate isNamed, Predicate nameMatcher); + /** + * Test whether the given element matches this lookup strategy. + * @param elem location being tests + * @param isNamed predicate to determine if 'elem' represents a named module + * @return true iff the given element matches this lookup strategy. + */ + public boolean matches(T elem, Predicate isNamed) { + return matchesWithName(elem, isNamed, t -> true); + } + + /** Get the lookup strategy corresponding to the given module name. */ + public static LookupStrategy get(char[] moduleName) { + if (moduleName == ModuleBinding.ANY) + return Any; + if (moduleName == ModuleBinding.ANY_NAMED) + return AnyNamed; + if (moduleName == ModuleBinding.UNNAMED) + return Unnamed; + return Named; + } + /** If 'moduleName' is none of the special names (ANY, ANY_NAMED, UNNAMED) return the string converted name, else {@code null}. */ + public static String getStringName(char[] moduleName) { + switch (get(moduleName)) { + case Named : return String.valueOf(moduleName); + default: return null; + } + } + } + + default NameEnvironmentAnswer findType(char[][] compoundTypeName) { + return findType(compoundTypeName, ModuleBinding.ANY); + } + default NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { + return findType(typeName, packageName, ModuleBinding.ANY); + } + default boolean isPackage(char[][] parentPackageName, char[] packageName) { + return getModulesDeclaringPackage(parentPackageName, packageName, ModuleBinding.ANY) != null; + } + + NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName); + /** Answer a type identified by the given names. moduleName may be one of the special names from ModuleBinding (ANY, ANY_NAMED, UNNAMED). */ + NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName); + char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName); + + /** + * Answer whether the given package (within the given module) contains any compilation unit. + * @param qualifiedPackageName + * @param checkCUs - if true, check contained Compilation Units for a matching package declaration + * @return true iff the package contains at least one compilation unit. + */ + boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs); + + /** Get the module with the given name, which must denote a named module. */ + IModule getModule(char[] moduleName); + char[][] getAllAutomaticModules(); + + /** + * Ask the name environment to perform any updates (add-exports or add-reads) to the given module. + * @param module the compiler representation of the module to updates + * @param kind selects what kind of updates should be performed + */ + default void applyModuleUpdates(IUpdatableModule module, IUpdatableModule.UpdateKind kind) { /* default: do nothing */ } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java new file mode 100644 index 0000000000..09d6a52bf4 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.compiler.CharOperation; + +/** + * Represents an entry on the module path of a project. Could be a single module or a collection of + * modules (like a jimage or an exploded module directory structure) + * + */ +public interface IModulePathEntry { + + /** + * Get the module that this entry contributes. May be null, for instance when this entry does not + * represent a single module + * + * @return The module that this entry contributes or null + */ + default IModule getModule() { + return null; + } + + /** + * Get the module named name from this entry. May be null + * + * @param name - The name of the module to look up + * + * @return The module named name or null + */ + default IModule getModule(char[] name) { + IModule mod = getModule(); + if (mod != null && CharOperation.equals(name, mod.name())) + return mod; + return null; + } + + /** + * Indicates whether this entry knows the module named name and can answer queries regarding the module + * + * @param name The name of the module + * + * @return True if this entry knows the module, false otherwise + */ + default boolean servesModule(char[] name) { + return getModule(name) != null; + } + + /** + * Answer the relevant modules that declare the given package. + * If moduleName is ModuleBinding.ANY then all packages are relevant, + * if moduleName is ModuleBinding.UNNAMED, then only packages in the unnamed module are relevant, + * otherwise consider only packages in the module identified by moduleName. + */ + char[][] getModulesDeclaringPackage(String qualifiedPackageName, /*@Nullable*/String moduleName); + + /** + * Answer whether the given package has any compilation unit (.java or .class) in the given module. + * For entries representing a single module, the module name should be checked before invoking this method. + * @param qualifiedPackageName '/'-separated package name + * @param moduleName if non-null only CUs attached to the given module should be considered + * @return true iff a .java or .class file could be found in the given module / package. + */ + boolean hasCompilationUnit(String qualifiedPackageName, String moduleName); + + /** + * Specifies whether this entry represents an automatic module. + * + * @return true if this is an automatic module, false otherwise + */ + public default boolean isAutomaticModule() { + return false; + } + + /** Tests whether the current entry represents the given java project. */ + public default boolean equalsProject(IJavaProject project) { + return false; + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleEntry.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleEntry.java new file mode 100644 index 0000000000..ce9796c2a7 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleEntry.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +import java.util.Collection; + +/** + * Represents a module path entry that represents a collection of modules + * like a jimage or an exploded module directory structure + * + */ +public interface IMultiModuleEntry extends IModulePathEntry { + + /** + * Get the module named name that this entry contributes to the module path + */ + + IModule getModule(char[] name); + + /** + * Get the names of all modules served by this entry. + * @param limitModules if non-null, only modules with names in this set and their + * transitive closure will be reported. + */ + Collection getModuleNames(Collection limitModules); + +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java index 9a7a2e0060..f244549d24 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,57 +15,71 @@ * can use to look up types, compilation units, and packages in the * current environment. The name environment is passed to the compiler * on creation. + *

+ * In JLS diction a name environment implements a "host system", with + * these responsibilities: + *

    + *
  • Determine which packages and compilation units are "observable" (JLS 7.3 & 7.4.3)
  • + *
  • Determine to which module a given compilation unit / package is associated (JLS 7.3)
  • + *
+ *

+ *

+ * Note: This internal interface has been implemented illegally by the + * org.apache.jasper.glassfish bundle from Orbit, see + * bug 500211. + * Avoid changing the API or supply default methods to avoid breaking the Eclipse Help system. + *

*/ public interface INameEnvironment { -/** - * Find a type with the given compound name. - * Answer the binary form of the type if it is known to be consistent. - * Otherwise, answer the compilation unit which defines the type - * or null if the type does not exist. - * Types in the default package are specified as {{typeName}}. - * - * It is unknown whether the package containing the type actually exists. - * - * NOTE: This method can be used to find a member type using its - * internal name A$B, but the source file for A is answered if the binary - * file is inconsistent. - */ + /** + * Find a type with the given compound name. + * Answer the binary form of the type if it is known to be consistent. + * Otherwise, answer the compilation unit which defines the type + * or null if the type does not exist. + * Types in the default package are specified as {{typeName}}. + * + * It is unknown whether the package containing the type actually exists. + * + * NOTE: This method can be used to find a member type using its + * internal name A$B, but the source file for A is answered if the binary + * file is inconsistent. + */ -NameEnvironmentAnswer findType(char[][] compoundTypeName); -/** - * Find a type named in the package . - * Answer the binary form of the type if it is known to be consistent. - * Otherwise, answer the compilation unit which defines the type - * or null if the type does not exist. - * The default package is indicated by char[0][]. - * - * It is known that the package containing the type exists. - * - * NOTE: This method can be used to find a member type using its - * internal name A$B, but the source file for A is answered if the binary - * file is inconsistent. - */ + NameEnvironmentAnswer findType(char[][] compoundTypeName); + /** + * Find a type named in the package . + * Answer the binary form of the type if it is known to be consistent. + * Otherwise, answer the compilation unit which defines the type + * or null if the type does not exist. + * The default package is indicated by char[0][]. + * + * It is known that the package containing the type exists. + * + * NOTE: This method can be used to find a member type using its + * internal name A$B, but the source file for A is answered if the binary + * file is inconsistent. + */ -NameEnvironmentAnswer findType(char[] typeName, char[][] packageName); -/** - * Answer whether packageName is the name of a known subpackage inside - * the package parentPackageName. A top level package is found relative to null. - * The default package is always assumed to exist. - * - * For example: - * isPackage({{java}, {awt}}, {event}); - * isPackage(null, {java}); - */ + NameEnvironmentAnswer findType(char[] typeName, char[][] packageName); + /** + * Answer whether packageName is the name of a known subpackage inside + * the package parentPackageName. A top level package is found relative to null. + * The default package is always assumed to exist. + * + * For example: + * isPackage({{java}, {awt}}, {event}); + * isPackage(null, {java}); + */ -boolean isPackage(char[][] parentPackageName, char[] packageName); + boolean isPackage(char[][] parentPackageName, char[] packageName); -/** - * This method cleans the environment. It is responsible for releasing the memory - * and freeing resources. Passed that point, the name environment is no longer usable. - * - * A name environment can have a long life cycle, therefore it is the responsibility of - * the code which created it to decide when it is a good time to clean it up. - */ -void cleanup(); + /** + * This method cleans the environment. It is responsible for releasing the memory + * and freeing resources. Passed that point, the name environment is no longer usable. + * + * A name environment can have a long life cycle, therefore it is the responsibility of + * the code which created it to decide when it is a good time to clean it up. + */ + void cleanup(); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironmentExtension.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironmentExtension.java index 4dc4972d15..88f9d92ff4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironmentExtension.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironmentExtension.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2016 IBM Corporation and others. + * Copyright (c) 2016, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -41,8 +41,13 @@ public interface INameEnvironmentExtension extends INameEnvironment { * @param typeName type to find * @param packageName package of the searched type * @param searchWithSecondaryTypes flag to switch on/off the search for secondary types + * @param moduleName the name of the module to search in, or one of ModuleBinding.ANY, ModuleBinding.UNNAMED * @return {@link NameEnvironmentAnswer} */ - NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes); + NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes, char[] moduleName); + + default NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes) { + return findType(typeName, packageName, searchWithSecondaryTypes, null); + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java new file mode 100644 index 0000000000..1a2d237a37 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray; + +/** + * Interface to a module as needed to implement the updates for {@code --add-reads} + * and {@code --add-exports} command line options (or corresponding classpath attributes). + */ +public interface IUpdatableModule { + + /** + * The compiler first wires modules only, before then wiring packages based on the module graph. + * This enum selects one of these phases when asking the environment to perform its updates. + */ + enum UpdateKind { MODULE, PACKAGE } + + /** Structure for update operations, sorted by {@link UpdateKind}. */ + class UpdatesByKind { + List> moduleUpdates = Collections.emptyList(); + List> packageUpdates = Collections.emptyList(); + public List> getList(UpdateKind kind, boolean create) { + switch (kind) { + case MODULE: + if (this.moduleUpdates == Collections.EMPTY_LIST && create) + this.moduleUpdates = new ArrayList<>(); + return this.moduleUpdates; + case PACKAGE: + if (this.packageUpdates == Collections.EMPTY_LIST && create) + this.packageUpdates = new ArrayList<>(); + return this.packageUpdates; + default: + throw new IllegalArgumentException("Unknown enum value "+kind); //$NON-NLS-1$ + } + } + } + + /** Answer the name of the module to update. */ + char[] name(); + /** Perform an --add-reads update on the module. */ + void addReads(char[] moduleName); + /** Perform an --add-exports update on the module. */ + void addExports(char[] packageName, char[][] targetModules); + /** Define the ModuleMainClass to be recorded in the generated module-info.class. */ + void setMainClassName(char[] mainClassName); + /** Passes names of packages to be recorded in the ModulePackages classfile attribute. */ + void setPackageNames(SimpleSetOfCharArray packageNames); +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ModuleReferenceImpl.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ModuleReferenceImpl.java new file mode 100644 index 0000000000..15ecf02474 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ModuleReferenceImpl.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +import org.eclipse.jdt.core.compiler.CharOperation; + +public class ModuleReferenceImpl implements IModule.IModuleReference { + public char[] name; + public int modifiers; + @Override + public char[] name() { + return this.name; + } + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof IModule.IModuleReference)) + return false; + IModule.IModuleReference mod = (IModule.IModuleReference) o; + if (this.modifiers != mod.getModifiers()) + return false; + return CharOperation.equals(this.name, mod.name()); + } + @Override + public int hashCode() { + return this.name.hashCode(); + } + @Override + public int getModifiers() { + return this.modifiers; + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java index 03b8563526..6d3c33b096 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,31 +10,54 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.env; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; + public class NameEnvironmentAnswer { - // only one of the three can be set + // only one of the four can be set IBinaryType binaryType; ICompilationUnit compilationUnit; ISourceType[] sourceTypes; + ReferenceBinding binding; + AccessRestriction accessRestriction; + char[] moduleName; // set by name environment + public ModuleBinding moduleBinding; // updated by LookupEnvironment String externalAnnotationPath; // should be an absolute file system path public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction) { this.binaryType = binaryType; this.accessRestriction = accessRestriction; + this.moduleName = binaryType.getModule(); } + public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction, char[] module) { + this.binaryType = binaryType; + this.accessRestriction = accessRestriction; + this.moduleName = module; + } public NameEnvironmentAnswer(ICompilationUnit compilationUnit, AccessRestriction accessRestriction) { + this(compilationUnit, accessRestriction, compilationUnit.getModuleName()); + } + public NameEnvironmentAnswer(ICompilationUnit compilationUnit, AccessRestriction accessRestriction, char[] module) { this.compilationUnit = compilationUnit; this.accessRestriction = accessRestriction; + this.moduleName = module; } - public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction, String externalAnnotationPath) { + public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction, String externalAnnotationPath, char[] module) { this.sourceTypes = sourceTypes; this.accessRestriction = accessRestriction; this.externalAnnotationPath = externalAnnotationPath; + this.moduleName = module; } + public NameEnvironmentAnswer(ReferenceBinding binding, ModuleBinding module) { + this.binding = binding; + this.moduleBinding = module; + } + @Override public String toString() { String baseString = ""; //$NON-NLS-1$ @@ -100,6 +123,13 @@ public ISourceType[] getSourceTypes() { return this.sourceTypes; } + /** + * Answer the resolved compiler binding that was late found during askForName(). + */ + public ReferenceBinding getResolvedBinding() { + return this.binding; + } + /** * Answer whether the receiver contains the resolved binary form of the type. */ @@ -121,9 +151,25 @@ public boolean isSourceType() { return this.sourceTypes != null; } + /** + * Answer whether the receiver contains the resolved compiler binding of the type. + */ + public boolean isResolvedBinding() { + return this.binding != null; + } + public boolean ignoreIfBetter() { return this.accessRestriction != null && this.accessRestriction.ignoreIfBetter(); } + + /** + * Name of the module to which the CU in this answer is associated. + * {@code null} when associated to the unnamed module. + * @return module name or {@code null} + */ + public char[] moduleName() { + return this.moduleName; + } /* * Returns whether this answer is better than the other awswer. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/PackageExportImpl.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/PackageExportImpl.java new file mode 100644 index 0000000000..63a8a7f07c --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/PackageExportImpl.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.env; + +public class PackageExportImpl implements IModule.IPackageExport { + public char[] pack; + public char[][] exportedTo; + @Override + public char[] name() { + return this.pack; + } + + @Override + public char[][] targets() { + return this.exportedTo; + } + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(this.pack); + buffer.append(" to "); //$NON-NLS-1$ + if (this.exportedTo != null) { + for (int i = 0; i < this.exportedTo.length; i++) { + if (i > 0) { + buffer.append(", "); //$NON-NLS-1$ + } + char[] cs = this.exportedTo[i]; + buffer.append(cs); + } + } + buffer.append(';'); + return buffer.toString(); + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java index 584e64c856..83de1b7184 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java @@ -58,6 +58,7 @@ public class CompilerOptions { public static final String OPTION_ReportMethodWithConstructorName = "org.eclipse.jdt.core.compiler.problem.methodWithConstructorName"; //$NON-NLS-1$ public static final String OPTION_ReportOverridingPackageDefaultMethod = "org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod"; //$NON-NLS-1$ public static final String OPTION_ReportDeprecation = "org.eclipse.jdt.core.compiler.problem.deprecation"; //$NON-NLS-1$ + public static final String OPTION_ReportTerminalDeprecation = "org.eclipse.jdt.core.compiler.problem.terminalDeprecation"; //$NON-NLS-1$ public static final String OPTION_ReportDeprecationInDeprecatedCode = "org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode"; //$NON-NLS-1$ public static final String OPTION_ReportDeprecationWhenOverridingDeprecatedMethod = "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"; //$NON-NLS-1$ public static final String OPTION_ReportHiddenCatchBlock = "org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock"; //$NON-NLS-1$ @@ -195,6 +196,8 @@ public class CompilerOptions { public static final String OPTION_ReportUnlikelyCollectionMethodArgumentTypeStrict = "org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict"; //$NON-NLS-1$ public static final String OPTION_ReportUnlikelyEqualsArgumentType = "org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType"; //$NON-NLS-1$ + public static final String OPTION_ReportAPILeak = "org.eclipse.jdt.core.compiler.problem.APILeak"; //$NON-NLS-1$ + // GROOVY add // This first one is the MASTER OPTION and if null, rather than ENABLED or DISABLED then the compiler will abort // FIXASC (M3) aborting is just a short term action to enable us to ensure the right paths into the compiler configure it @@ -225,7 +228,7 @@ public class CompilerOptions { public static final String VERSION_1_6 = "1.6"; //$NON-NLS-1$ public static final String VERSION_1_7 = "1.7"; //$NON-NLS-1$ public static final String VERSION_1_8 = "1.8"; //$NON-NLS-1$ - public static final String VERSION_1_9 = "1.9"; //$NON-NLS-1$ + public static final String VERSION_9 = "9"; //$NON-NLS-1$ public static final String ERROR = "error"; //$NON-NLS-1$ public static final String WARNING = "warning"; //$NON-NLS-1$ public static final String INFO = "info"; //$NON-NLS-1$ @@ -332,6 +335,9 @@ public class CompilerOptions { public static final int NonNullTypeVariableFromLegacyInvocation = IrritantSet.GROUP2 | ASTNode.Bit21; public static final int UnlikelyCollectionMethodArgumentType = IrritantSet.GROUP2 | ASTNode.Bit22; public static final int UnlikelyEqualsArgumentType = IrritantSet.GROUP2 | ASTNode.Bit23; + public static final int UsingTerminallyDeprecatedAPI = IrritantSet.GROUP2 | ASTNode.Bit24; + public static final int APILeak = IrritantSet.GROUP2 | ASTNode.Bit25; + // Severity level for handlers /** @@ -538,6 +544,7 @@ public class CompilerOptions { "cast", //$NON-NLS-1$ "dep-ann", //$NON-NLS-1$ "deprecation", //$NON-NLS-1$ + "exports", //$NON-NLS-1$ "fallthrough", //$NON-NLS-1$ "finally", //$NON-NLS-1$ "hiding", //$NON-NLS-1$ @@ -546,6 +553,7 @@ public class CompilerOptions { "nls", //$NON-NLS-1$ "null", //$NON-NLS-1$ "rawtypes", //$NON-NLS-1$ + "removal", //$NON-NLS-1$ "resource", //$NON-NLS-1$ "restriction", //$NON-NLS-1$ "serial", //$NON-NLS-1$ @@ -601,6 +609,9 @@ public static String optionKeyFromIrritant(int irritant) { case UsingDeprecatedAPI : case (InvalidJavadoc | UsingDeprecatedAPI) : return OPTION_ReportDeprecation; + case UsingTerminallyDeprecatedAPI : + case (InvalidJavadoc | UsingTerminallyDeprecatedAPI) : + return OPTION_ReportTerminalDeprecation; case MaskedCatchBlock : return OPTION_ReportHiddenCatchBlock; case UnusedLocalVariable : @@ -755,6 +766,8 @@ public static String optionKeyFromIrritant(int irritant) { return OPTION_ReportUnlikelyCollectionMethodArgumentType; case UnlikelyEqualsArgumentType: return OPTION_ReportUnlikelyEqualsArgumentType; + case APILeak: + return OPTION_ReportAPILeak; } return null; } @@ -793,9 +806,9 @@ public static String versionFromJdkLevel(long jdkLevel) { if (jdkLevel == ClassFileConstants.JDK1_8) return VERSION_1_8; break; - case ClassFileConstants.MAJOR_VERSION_1_9 : - if (jdkLevel == ClassFileConstants.JDK1_9) - return VERSION_1_9; + case ClassFileConstants.MAJOR_VERSION_9 : + if (jdkLevel == ClassFileConstants.JDK9) + return VERSION_9; break; } return Util.EMPTY_STRING; // unknown version @@ -804,28 +817,34 @@ public static String versionFromJdkLevel(long jdkLevel) { public static long versionToJdkLevel(String versionID) { String version = versionID; // verification is optimized for all versions with same length and same "1." prefix - if (version != null && version.length() == 3 && version.charAt(0) == '1' && version.charAt(1) == '.') { - switch (version.charAt(2)) { - case '1': - return ClassFileConstants.JDK1_1; - case '2': - return ClassFileConstants.JDK1_2; - case '3': - return ClassFileConstants.JDK1_3; - case '4': - return ClassFileConstants.JDK1_4; - case '5': - return ClassFileConstants.JDK1_5; - case '6': - return ClassFileConstants.JDK1_6; - case '7': - return ClassFileConstants.JDK1_7; - case '8': - return ClassFileConstants.JDK1_8; - case '9': - return ClassFileConstants.JDK1_9; - default: - return 0; // unknown + if (version != null && version.length() > 0) { + if (version.length() >= 3 && version.charAt(0) == '1' && version.charAt(1) == '.') { + switch (version.charAt(2)) { + case '1': + return ClassFileConstants.JDK1_1; + case '2': + return ClassFileConstants.JDK1_2; + case '3': + return ClassFileConstants.JDK1_3; + case '4': + return ClassFileConstants.JDK1_4; + case '5': + return ClassFileConstants.JDK1_5; + case '6': + return ClassFileConstants.JDK1_6; + case '7': + return ClassFileConstants.JDK1_7; + case '8': + return ClassFileConstants.JDK1_8; + default: + return 0; // unknown + } + } else { + switch (version.charAt(0)) { + case '9': + return ClassFileConstants.JDK9; + // No default - let it go through the remaining checks. + } } } if (VERSION_JSR14.equals(versionID)) { @@ -949,6 +968,7 @@ public static String[] warningOptionNames() { OPTION_ReportNonnullParameterAnnotationDropped, OPTION_ReportUnlikelyCollectionMethodArgumentType, OPTION_ReportUnlikelyEqualsArgumentType, + OPTION_ReportAPILeak, }; return result; } @@ -962,6 +982,9 @@ public static String warningTokenFromIrritant(int irritant) { case (InvalidJavadoc | UsingDeprecatedAPI) : case UsingDeprecatedAPI : return "deprecation"; //$NON-NLS-1$ + case (InvalidJavadoc | UsingTerminallyDeprecatedAPI) : + case UsingTerminallyDeprecatedAPI : + return "removal"; //$NON-NLS-1$ case FinallyBlockNotCompleting : return "finally"; //$NON-NLS-1$ case FieldHiding : @@ -1043,6 +1066,8 @@ public static String warningTokenFromIrritant(int irritant) { case UnlikelyEqualsArgumentType: case UnlikelyCollectionMethodArgumentType: return "unlikely-arg-type"; //$NON-NLS-1$ + case APILeak: + return "exports"; //$NON-NLS-1$ } return null; } @@ -1069,6 +1094,10 @@ public static IrritantSet warningTokenToIrritants(String warningToken) { if ("dep-ann".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.DEP_ANN; break; + case 'e' : + if ("exports".equals(warningToken)) //$NON-NLS-1$ + return IrritantSet.API_LEAK; + break; case 'f' : if ("fallthrough".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.FALLTHROUGH; @@ -1100,6 +1129,8 @@ public static IrritantSet warningTokenToIrritants(String warningToken) { return IrritantSet.RESOURCE; if ("restriction".equals(warningToken)) //$NON-NLS-1$ return IrritantSet.RESTRICTION; + if ("removal".equals(warningToken)) //$NON-NLS-1$ + return IrritantSet.TERMINAL_DEPRECATION; break; case 's' : if ("serial".equals(warningToken)) //$NON-NLS-1$ @@ -1143,6 +1174,7 @@ public Map getMap() { optionsMap.put(OPTION_ReportMethodWithConstructorName, getSeverityString(MethodWithConstructorName)); optionsMap.put(OPTION_ReportOverridingPackageDefaultMethod, getSeverityString(OverriddenPackageDefaultMethod)); optionsMap.put(OPTION_ReportDeprecation, getSeverityString(UsingDeprecatedAPI)); + optionsMap.put(OPTION_ReportTerminalDeprecation, getSeverityString(UsingTerminallyDeprecatedAPI)); optionsMap.put(OPTION_ReportDeprecationInDeprecatedCode, this.reportDeprecationInsideDeprecatedCode ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, this.reportDeprecationWhenOverridingDeprecatedMethod ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportHiddenCatchBlock, getSeverityString(MaskedCatchBlock)); @@ -1273,6 +1305,7 @@ public Map getMap() { optionsMap.put(OPTION_ReportUnlikelyCollectionMethodArgumentType, getSeverityString(UnlikelyCollectionMethodArgumentType)); optionsMap.put(OPTION_ReportUnlikelyCollectionMethodArgumentTypeStrict, this.reportUnlikelyCollectionMethodArgumentTypeStrict ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnlikelyEqualsArgumentType, getSeverityString(UnlikelyEqualsArgumentType)); + optionsMap.put(OPTION_ReportAPILeak, getSeverityString(APILeak)); // GROOVY add // if not supplied here it isn't seen as something that can be set from elsewhere optionsMap.put(OPTIONG_GroovyTransformsToRunOnReconcile, ""); //$NON-NLS-1$ @@ -1711,6 +1744,7 @@ public void set(Map optionsMap) { if ((optionValue = optionsMap.get(OPTION_ReportMethodWithConstructorName)) != null) updateSeverity(MethodWithConstructorName, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportOverridingPackageDefaultMethod)) != null) updateSeverity(OverriddenPackageDefaultMethod, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportDeprecation)) != null) updateSeverity(UsingDeprecatedAPI, optionValue); + if ((optionValue = optionsMap.get(OPTION_ReportTerminalDeprecation)) != null) updateSeverity(UsingTerminallyDeprecatedAPI, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportHiddenCatchBlock)) != null) updateSeverity(MaskedCatchBlock, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedLocal)) != null) updateSeverity(UnusedLocalVariable, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameter)) != null) updateSeverity(UnusedArgument, optionValue); @@ -1793,6 +1827,7 @@ && getSeverity(ExplicitlyClosedAutoCloseable) == ProblemSeverities.Ignore) { } else { this.analyseResourceLeaks = true; } + if ((optionValue = optionsMap.get(OPTION_ReportAPILeak)) != null) updateSeverity(APILeak, optionValue); if ((optionValue = optionsMap.get(OPTION_AnnotationBasedNullAnalysis)) != null) { this.isAnnotationBasedNullAnalysisEnabled = ENABLED.equals(optionValue); } @@ -2078,6 +2113,7 @@ public String toString() { buf.append("\n\t- method with constructor name: ").append(getSeverityString(MethodWithConstructorName)); //$NON-NLS-1$ buf.append("\n\t- overridden package default method: ").append(getSeverityString(OverriddenPackageDefaultMethod)); //$NON-NLS-1$ buf.append("\n\t- deprecation: ").append(getSeverityString(UsingDeprecatedAPI)); //$NON-NLS-1$ + buf.append("\n\t- removal: ").append(getSeverityString(UsingTerminallyDeprecatedAPI)); //$NON-NLS-1$ buf.append("\n\t- masked catch block: ").append(getSeverityString(MaskedCatchBlock)); //$NON-NLS-1$ buf.append("\n\t- unused local variable: ").append(getSeverityString(UnusedLocalVariable)); //$NON-NLS-1$ buf.append("\n\t- unused parameter: ").append(getSeverityString(UnusedArgument)); //$NON-NLS-1$ @@ -2182,6 +2218,7 @@ public String toString() { buf.append("\n\t- unlikely argument type for collection methods: ").append(getSeverityString(UnlikelyCollectionMethodArgumentType)); //$NON-NLS-1$ buf.append("\n\t- unlikely argument type for collection methods, strict check against expected type: ").append(this.reportUnlikelyCollectionMethodArgumentTypeStrict ? ENABLED : DISABLED); //$NON-NLS-1$ buf.append("\n\t- unlikely argument types for equals(): ").append(getSeverityString(UnlikelyEqualsArgumentType)); //$NON-NLS-1$ + buf.append("\n\t- API leak: ").append(getSeverityString(APILeak)); //$NON-NLS-1$ // GROOVY add buf.append("\n\t- build groovy files: ").append((this.buildGroovyFiles == 0) ? "dontknow" : (this.buildGroovyFiles == 1 ? "no" : "yes")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ buf.append("\n\t- build groovy flags: ").append(Integer.toHexString(this.groovyFlags)); //$NON-NLS-1$ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java index 8ba156b86a..aa7d95af73 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java @@ -49,6 +49,7 @@ public class IrritantSet { public static final IrritantSet BOXING = new IrritantSet(CompilerOptions.AutoBoxing); public static final IrritantSet CAST = new IrritantSet(CompilerOptions.UnnecessaryTypeCheck); public static final IrritantSet DEPRECATION = new IrritantSet(CompilerOptions.UsingDeprecatedAPI); + public static final IrritantSet TERMINAL_DEPRECATION = new IrritantSet(CompilerOptions.UsingTerminallyDeprecatedAPI); public static final IrritantSet DEP_ANN = new IrritantSet(CompilerOptions.MissingDeprecatedAnnotation); public static final IrritantSet FALLTHROUGH = new IrritantSet(CompilerOptions.FallthroughCase); public static final IrritantSet FINALLY = new IrritantSet(CompilerOptions.FinallyBlockNotCompleting); @@ -69,6 +70,7 @@ public class IrritantSet { public static final IrritantSet UNQUALIFIED_FIELD_ACCESS = new IrritantSet(CompilerOptions.UnqualifiedFieldAccess); public static final IrritantSet RESOURCE = new IrritantSet(CompilerOptions.UnclosedCloseable); public static final IrritantSet UNLIKELY_ARGUMENT_TYPE = new IrritantSet(CompilerOptions.UnlikelyCollectionMethodArgumentType); + public static final IrritantSet API_LEAK = new IrritantSet(CompilerOptions.APILeak); public static final IrritantSet JAVADOC = new IrritantSet(CompilerOptions.InvalidJavadoc); public static final IrritantSet COMPILER_DEFAULT_ERRORS = new IrritantSet(0); // no optional error by default @@ -125,7 +127,9 @@ public class IrritantSet { |CompilerOptions.NonnullParameterAnnotationDropped |CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables |CompilerOptions.NonNullTypeVariableFromLegacyInvocation - |CompilerOptions.UnlikelyCollectionMethodArgumentType); + |CompilerOptions.UnlikelyCollectionMethodArgumentType + |CompilerOptions.UsingTerminallyDeprecatedAPI + |CompilerOptions.APILeak); // default errors IF AnnotationBasedNullAnalysis is enabled: COMPILER_DEFAULT_ERRORS.set( CompilerOptions.NullSpecViolation diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java index cfd1fa7814..3e9e57564e 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -70,24 +70,24 @@ public static AnnotationBinding[] addStandardAnnotations(AnnotationBinding[] rec if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0) result[index++] = buildRetentionAnnotation(annotationTagBits, env); if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0) - result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_DEPRECATED, env); + result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_DEPRECATED, env.javaBaseModule(), env); if ((annotationTagBits & TagBits.AnnotationDocumented) != 0) - result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED, env); + result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED, env.javaBaseModule(), env); if ((annotationTagBits & TagBits.AnnotationInherited) != 0) - result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_INHERITED, env); + result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_INHERITED, env.javaBaseModule(), env); if ((annotationTagBits & TagBits.AnnotationOverride) != 0) - result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, env); + result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, env.javaBaseModule(), env); if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0) - result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, env); + result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, env.javaBaseModule(), env); if ((annotationTagBits & TagBits.AnnotationPolymorphicSignature) != 0) - result[index++] = buildMarkerAnnotationForMemberType(TypeConstants.JAVA_LANG_INVOKE_METHODHANDLE_$_POLYMORPHICSIGNATURE, env); + result[index++] = buildMarkerAnnotationForMemberType(TypeConstants.JAVA_LANG_INVOKE_METHODHANDLE_$_POLYMORPHICSIGNATURE, env.javaBaseModule(), env); if ((annotationTagBits & TagBits.AnnotationSafeVarargs) != 0) - result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_SAFEVARARGS, env); + result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_SAFEVARARGS, env.javaBaseModule(), env); return result; } -private static AnnotationBinding buildMarkerAnnotationForMemberType(char[][] compoundName, LookupEnvironment env) { - ReferenceBinding type = env.getResolvedType(compoundName, null); +private static AnnotationBinding buildMarkerAnnotationForMemberType(char[][] compoundName, ModuleBinding module, LookupEnvironment env) { + ReferenceBinding type = env.getResolvedType(compoundName, module, null); // since this is a member type name using '$' the return binding is a // problem reference binding with reason ProblemReasons.InternalNameProvided if (!type.isValidBinding()) { @@ -96,14 +96,14 @@ private static AnnotationBinding buildMarkerAnnotationForMemberType(char[][] com return env.createAnnotation(type, Binding.NO_ELEMENT_VALUE_PAIRS); } -private static AnnotationBinding buildMarkerAnnotation(char[][] compoundName, LookupEnvironment env) { - ReferenceBinding type = env.getResolvedType(compoundName, null); +private static AnnotationBinding buildMarkerAnnotation(char[][] compoundName, ModuleBinding module, LookupEnvironment env) { + ReferenceBinding type = env.getResolvedType(compoundName, module, null); return env.createAnnotation(type, Binding.NO_ELEMENT_VALUE_PAIRS); } private static AnnotationBinding buildRetentionAnnotation(long bits, LookupEnvironment env) { ReferenceBinding retentionPolicy = - env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY, + env.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY, null); Object value = null; if ((bits & TagBits.AnnotationRuntimeRetention) == TagBits.AnnotationRuntimeRetention) { @@ -114,14 +114,14 @@ private static AnnotationBinding buildRetentionAnnotation(long bits, LookupEnvir value = retentionPolicy.getField(TypeConstants.UPPER_SOURCE, true); } return env.createAnnotation( - env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTION, null), + env.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTION, null), new ElementValuePair[] { new ElementValuePair(TypeConstants.VALUE, value, null) }); } private static AnnotationBinding buildTargetAnnotation(long bits, LookupEnvironment env) { - ReferenceBinding target = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_TARGET, null); + ReferenceBinding target = env.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ANNOTATION_TARGET, null); if ((bits & TagBits.AnnotationTarget) != 0) return new AnnotationBinding(target, Binding.NO_ELEMENT_VALUE_PAIRS); @@ -146,11 +146,15 @@ private static AnnotationBinding buildTargetAnnotation(long bits, LookupEnvironm arraysize++; if ((bits & TagBits.AnnotationForTypeParameter) != 0) arraysize++; + if ((bits & TagBits.AnnotationForModule) != 0) + arraysize++; Object[] value = new Object[arraysize]; if (arraysize > 0) { ReferenceBinding elementType = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE, null); int index = 0; + if ((bits & TagBits.AnnotationForTypeUse) != 0) + value[index++] = elementType.getField(TypeConstants.TYPE_USE_TARGET, true); if ((bits & TagBits.AnnotationForAnnotationType) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_ANNOTATION_TYPE, true); if ((bits & TagBits.AnnotationForConstructor) != 0) @@ -163,8 +167,6 @@ private static AnnotationBinding buildTargetAnnotation(long bits, LookupEnvironm value[index++] = elementType.getField(TypeConstants.UPPER_PACKAGE, true); if ((bits & TagBits.AnnotationForParameter) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_PARAMETER, true); - if ((bits & TagBits.AnnotationForTypeUse) != 0) - value[index++] = elementType.getField(TypeConstants.TYPE_USE_TARGET, true); if ((bits & TagBits.AnnotationForTypeParameter) != 0) value[index++] = elementType.getField(TypeConstants.TYPE_PARAMETER_TARGET, true); if ((bits & TagBits.AnnotationForType) != 0) diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java new file mode 100644 index 0000000000..f87486fcf1 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.lookup; + +import java.util.HashMap; +import java.util.stream.Stream; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference; +import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport; +import org.eclipse.jdt.internal.compiler.env.IModule.IService; +import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; + +public class BinaryModuleBinding extends ModuleBinding { + + private static class AutomaticModuleBinding extends ModuleBinding { + + public AutomaticModuleBinding(IModule module, LookupEnvironment existingEnvironment) { + super(module.name(), existingEnvironment); + existingEnvironment.root.knownModules.put(this.moduleName, this); + this.isAuto = true; + this.requires = Binding.NO_MODULES; + this.requiresTransitive = Binding.NO_MODULES; + this.exportedPackages = Binding.NO_PACKAGES; + } + public ModuleBinding[] getRequiresTransitive() { + if (this.requiresTransitive == NO_MODULES) { + char[][] autoModules = ((IModuleAwareNameEnvironment)this.environment.nameEnvironment).getAllAutomaticModules(); + this.requiresTransitive = Stream.of(autoModules) + .filter(name -> !CharOperation.equals(name, this.moduleName)) + .map(name -> this.environment.getModule(name)).filter(m -> m != null) + .toArray(ModuleBinding[]::new); + } + return this.requiresTransitive; + } + @Override + public char[] nameForLookup() { + return ANY_NAMED; + } + } + + private IPackageExport[] unresolvedExports; + private IPackageExport[] unresolvedOpens; + private char[][] unresolvedUses; + private IService[] unresolvedProvides; + + /** + * Construct a named module from binary, could be an auto module. + *

+ * Side effects: adds the new module to root.knownModules and resolves its directives. + *

+ */ + public static ModuleBinding create(IModule module, LookupEnvironment existingEnvironment) { + if (module.isAutomatic()) + return new AutomaticModuleBinding(module, existingEnvironment); + return new BinaryModuleBinding(module, existingEnvironment); + } + + private BinaryModuleBinding(IModule module, LookupEnvironment existingEnvironment) { + super(module.name(), existingEnvironment); + existingEnvironment.root.knownModules.put(this.moduleName, this); + cachePartsFrom(module); + } + + void cachePartsFrom(IModule module) { + if (module.isOpen()) + this.modifiers |= ClassFileConstants.ACC_OPEN; + + IModuleReference[] requiresReferences = module.requires(); + this.requires = new ModuleBinding[requiresReferences.length]; + this.requiresTransitive = new ModuleBinding[requiresReferences.length]; + int count = 0; + int transitiveCount = 0; + for (int i = 0; i < requiresReferences.length; i++) { + ModuleBinding requiredModule = this.environment.getModule(requiresReferences[i].name()); + if (requiredModule != null) { + this.requires[count++] = requiredModule; + if (requiresReferences[i].isTransitive()) + this.requiresTransitive[transitiveCount++] = requiredModule; + } + // TODO(SHMOD): handle null case + } + if (count < this.requiresTransitive.length) + System.arraycopy(this.requires, 0, this.requires = new ModuleBinding[count], 0, count); + if (transitiveCount < this.requiresTransitive.length) + System.arraycopy(this.requiresTransitive, 0, this.requiresTransitive = new ModuleBinding[transitiveCount], 0, transitiveCount); + + this.unresolvedExports = module.exports(); + this.unresolvedOpens = module.opens(); + this.unresolvedUses = module.uses(); + this.unresolvedProvides = module.provides(); + } + + @Override + public PackageBinding[] getExports() { + if (this.exportedPackages == null && this.unresolvedExports != null) + resolvePackages(); + return super.getExports(); + } + + @Override + public PackageBinding[] getOpens() { + if (this.openedPackages == null && this.unresolvedOpens != null) + resolvePackages(); + return super.getOpens(); + } + + private void resolvePackages() { + this.exportedPackages = new PackageBinding[this.unresolvedExports.length]; + int count = 0; + for (int i = 0; i < this.unresolvedExports.length; i++) { + IPackageExport export = this.unresolvedExports[i]; + PackageBinding declaredPackage = getVisiblePackage(CharOperation.splitOn('.', export.name())); + if (declaredPackage != null) { + this.exportedPackages[count++] = declaredPackage; + declaredPackage.isExported = Boolean.TRUE; + recordExportRestrictions(declaredPackage, export.targets()); + } else { + // TODO(SHMOD): report incomplete module path? + } + } + if (count < this.exportedPackages.length) + System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PackageBinding[count], 0, count); + + this.openedPackages = new PackageBinding[this.unresolvedOpens.length]; + count = 0; + for (int i = 0; i < this.unresolvedOpens.length; i++) { + IPackageExport opens = this.unresolvedOpens[i]; + PackageBinding declaredPackage = getVisiblePackage(CharOperation.splitOn('.', opens.name())); + if (declaredPackage != null) { + this.openedPackages[count++] = declaredPackage; + recordOpensRestrictions(declaredPackage, opens.targets()); + } else { + // TODO(SHMOD): report incomplete module path? + } + } + if (count < this.openedPackages.length) + System.arraycopy(this.openedPackages, 0, this.openedPackages = new PackageBinding[count], 0, count); + } + + @Override + public TypeBinding[] getUses() { + if (this.uses == null) { + this.uses = new TypeBinding[this.unresolvedUses.length]; + for (int i = 0; i < this.unresolvedUses.length; i++) + this.uses[i] = this.environment.getType(CharOperation.splitOn('.', this.unresolvedUses[i]), this); + } + return super.getUses(); + } + + @Override + public TypeBinding[] getServices() { + if (this.services == null) + resolveServices(); + return super.getServices(); + } + + @Override + public TypeBinding[] getImplementations(TypeBinding binding) { + if (this.implementations == null) + resolveServices(); + return super.getImplementations(binding); + } + private void resolveServices() { + this.services = new TypeBinding[this.unresolvedProvides.length]; + this.implementations = new HashMap<>(); + for (int i = 0; i < this.unresolvedProvides.length; i++) { + this.services[i] = this.environment.getType(CharOperation.splitOn('.', this.unresolvedProvides[i].name()), this); + char[][] implNames = this.unresolvedProvides[i].with(); + TypeBinding[] impls = new TypeBinding[implNames.length]; + for (int j = 0; j < implNames.length; j++) + impls[j] = this.environment.getType(CharOperation.splitOn('.', implNames[j]), this); + this.implementations.put(this.services[i], impls); + } + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index 19ffce4bf8..9a0397042e 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -87,6 +87,7 @@ public class BinaryTypeBinding extends ReferenceBinding { // GROOVY end protected ReferenceBinding[] memberTypes; protected TypeVariableBinding[] typeVariables; + protected ModuleBinding module; private BinaryTypeBinding prototype; // For the link with the principle structure @@ -270,7 +271,6 @@ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, this.environment = environment; this.fPackage = packageBinding; this.fileName = binaryType.getFileName(); - /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, even in a 1.4 project, we must internalize type variables and observe any parameterization of super class and/or super interfaces in order to be able to detect overriding in the presence @@ -309,7 +309,10 @@ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, if (needFieldsAndMethods) cachePartsFrom(binaryType, true); } - +public boolean canBeSeenBy(Scope sco) { + ModuleBinding mod = sco.module(); + return mod.canAccess(this.fPackage) && super.canBeSeenBy(sco); +} /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#availableFields() */ @@ -533,12 +536,14 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) { FieldBinding field = this.fields[i]; if (!field.isDeprecated()) { field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; + field.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated; } } for (int i = 0, max = this.methods.length; i < max; i++) { MethodBinding method = this.methods[i]; if (!method.isDeprecated()) { method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; + method.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated; } } } @@ -669,7 +674,8 @@ private MethodBinding createMethod(IBinaryMethod method, IBinaryType binaryType, methodModifiers &= ~ClassFileConstants.AccVarargs; // vararg methods are not recognized until 1.5 if (isInterface() && (methodModifiers & ClassFileConstants.AccAbstract) == 0) { // see https://bugs.eclipse.org/388954 superseded by https://bugs.eclipse.org/390889 - if ((methodModifiers & ClassFileConstants.AccStatic) == 0) { + if (((methodModifiers & ClassFileConstants.AccStatic) == 0 + && (methodModifiers & ClassFileConstants.AccPrivate) == 0)) { // i.e. even at 1.7- we record AccDefaultMethod when reading a 1.8+ interface to avoid errors caused by default methods added to a library methodModifiers |= ExtraCompilerModifiers.AccDefaultMethod; } @@ -841,14 +847,15 @@ private MethodBinding createMethod(IBinaryMethod method, IBinaryType binaryType, if (this.environment.globalOptions.storeAnnotations) { IBinaryAnnotation[] annotations = method.getAnnotations(); - if (annotations == null || annotations.length == 0) - if (method.isConstructor()) - annotations = walker.toMethodReturn().getAnnotationsAtCursor(this.id, false); // FIXME: When both exist, order could become an issue. + if (method.isConstructor()) { + IBinaryAnnotation[] tAnnotations = walker.toMethodReturn().getAnnotationsAtCursor(this.id, false); + result.setTypeAnnotations(createAnnotations(tAnnotations, this.environment, missingTypeNames)); + } result.setAnnotations( - createAnnotations(annotations, this.environment, missingTypeNames), - paramAnnotations, - isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames, true) : null, - this.environment); + createAnnotations(annotations, this.environment, missingTypeNames), + paramAnnotations, + isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames, true) : null, + this.environment); } if (argumentNames != null) result.parameterNames = argumentNames; @@ -1344,7 +1351,7 @@ private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBi ReferenceBinding type, firstBound = null; short rank = 0; if (wrapper.signature[wrapper.start] == Util.C_COLON) { - type = this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); + type = this.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null); rank++; } else { TypeBinding typeFromTypeSignature = this.environment.getTypeFromTypeSignature(wrapper, existingVariables, this, missingTypeNames, walker.toTypeBound(rank++)); @@ -1352,7 +1359,7 @@ private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBi type = (ReferenceBinding) typeFromTypeSignature; } else { // this should only happen if the signature is corrupted (332423) - type = this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); + type = this.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null); } firstBound = type; } @@ -1840,7 +1847,7 @@ private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBin && ((this.typeBits & (TypeIds.BitAnyNullAnnotation)) == 0)) { // this will scan the annotations in package-info - ReferenceBinding packageInfo = packageBinding.getType(TypeConstants.PACKAGE_INFO_NAME); + ReferenceBinding packageInfo = packageBinding.getType(TypeConstants.PACKAGE_INFO_NAME, packageBinding.enclosingModule); if (packageInfo == null) { packageBinding.defaultNullness = Binding.NO_NULL_DEFAULT; } @@ -1876,7 +1883,7 @@ int getNonNullByDefaultValue(IBinaryAnnotation annotation) { IBinaryElementValuePair[] elementValuePairs = annotation.getElementValuePairs(); if (elementValuePairs == null || elementValuePairs.length == 0 ) { // no argument: apply default default - ReferenceBinding annotationType = this.environment.getType(typeName); + ReferenceBinding annotationType = this.environment.getType(typeName, this.environment.UnNamedModule); // TODO(SHMOD): null annotations from a module? if (annotationType == null) return 0; if (annotationType.isUnresolvedType()) annotationType = ((UnresolvedReferenceBinding) annotationType).resolve(this.environment, false); @@ -2130,4 +2137,9 @@ public FieldBinding[] unResolvedFields() { return this.fields; } +public ModuleBinding module() { + if (!isPrototype()) + return this.prototype.module; + return this.module; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java index 46fc51bccf..cbb24760e6 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java @@ -28,6 +28,7 @@ public abstract class Binding { public static final int METHOD = ASTNode.Bit4; public static final int PACKAGE = ASTNode.Bit5; public static final int IMPORT = ASTNode.Bit6; + public static final int MODULE = ASTNode.Bit7; public static final int ARRAY_TYPE = TYPE | ASTNode.Bit7; public static final int BASE_TYPE = TYPE | ASTNode.Bit8; public static final int PARAMETERIZED_TYPE = TYPE | ASTNode.Bit9; @@ -44,6 +45,8 @@ public abstract class Binding { // In the unlikely event you add a new type binding, remember to update TypeBindingVisitor and Scope.substitute methods. // Shared binding collections + public static final ModuleBinding[] NO_MODULES = new ModuleBinding[0]; + public static final PackageBinding[] NO_PACKAGES = new PackageBinding[0]; public static final TypeBinding[] NO_TYPES = new TypeBinding[0]; public static final ReferenceBinding[] NO_REFERENCE_TYPES = new ReferenceBinding[0]; public static final TypeBinding[] NO_PARAMETERS = new TypeBinding[0]; @@ -111,14 +114,16 @@ public abstract class Binding { public abstract int kind(); /* * Computes a key that uniquely identifies this binding. - * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding, a LocalVariableBinding or a PackageBinding (i.e. an ImportBinding). + * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding, a LocalVariableBinding, a PackageBinding (i.e. an ImportBinding) + * or a ModuleBinding. */ public char[] computeUniqueKey() { return computeUniqueKey(true/*leaf*/); } /* * Computes a key that uniquely identifies this binding. Optionally include access flags. - * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding, a LocalVariableBinding or a PackageBinding (i.e. an ImportBinding) + * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding, a LocalVariableBinding, a PackageBinding (i.e. an ImportBinding) + * or a ModuleBinding. */ public char[] computeUniqueKey(boolean isLeaf) { return null; @@ -154,6 +159,9 @@ public boolean isAnnotationType() { public final boolean isValidBinding() { return problemId() == ProblemReasons.NoError; } + public static boolean isValid(/*@Nullable*/Binding binding) { + return binding != null && binding.isValidBinding(); + } public boolean isVolatile() { return false; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java index 32de2db36c..7549e45919 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java @@ -497,7 +497,7 @@ public Binding getBinding(char[][] compoundName, int mask, InvocationSite invoca PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < length) { unitScope.recordReference(packageBinding.compoundName, compoundName[currentIndex]); - binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); + binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module()); invocationSite.setFieldIndex(currentIndex); if (binding == null) { if (currentIndex == length) { @@ -643,7 +643,7 @@ public final Binding getBinding(char[][] compoundName, InvocationSite invocation foundType : if (binding instanceof PackageBinding) { while (currentIndex < length) { PackageBinding packageBinding = (PackageBinding) binding; - binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); + binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module()); if (binding == null) { if (currentIndex == length) { // must be a type if its the last name, otherwise we have no idea if its a package or type diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java index bf7a147fd9..3ff29b6229 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java @@ -242,6 +242,8 @@ public void initializeBounds(Scope scope, ParameterizedTypeBinding capturedParam if (this.superclass.isSuperclassOf(substitutedVariableSuperclass)) { this.setSuperClass(substitutedVariableSuperclass); } + // TODO: there are cases were we need to compute glb(capturedWildcardBound, substitutedVariableSuperclass) + // but then when glb (perhaps triggered inside setFirstBound()) fails, how to report the error?? } this.setSuperInterfaces(substitutedVariableInterfaces); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java index 02f08de5dd..9579adac11 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java @@ -441,6 +441,7 @@ SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding pack } SourceTypeBinding sourceType = this.referenceContext.binding; + sourceType.module = module(); environment().setAccessRestriction(sourceType, accessRestriction); TypeParameter[] typeParameters = this.referenceContext.typeParameters; @@ -505,7 +506,8 @@ private void checkAndSetModifiers() { return; } if (sourceType.isAnonymousType()) { - modifiers |= ClassFileConstants.AccFinal; + if (compilerOptions().complianceLevel < ClassFileConstants.JDK9) + modifiers |= ClassFileConstants.AccFinal; // set AccEnum flag for anonymous body of enum constants if (this.referenceContext.allocation.type == null) modifiers |= ClassFileConstants.AccEnum; @@ -545,8 +547,10 @@ private void checkAndSetModifiers() { // local member if (enclosingType.isStrictfp()) modifiers |= ClassFileConstants.AccStrictfp; - if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated()) + if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated()) { modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; + sourceType.tagBits |= enclosingType.tagBits & TagBits.AnnotationTerminallyDeprecated; + } break; } scope = scope.parent; @@ -1250,7 +1254,7 @@ private boolean detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBind if (superType.isMemberType()) { ReferenceBinding current = superType.enclosingType(); do { - if (current.isHierarchyBeingActivelyConnected() && TypeBinding.equalsEquals(current, sourceType)) { + if (current.isHierarchyBeingActivelyConnected()) { problemReporter().hierarchyCircularity(sourceType, current, reference); sourceType.tagBits |= TagBits.HierarchyHasProblems; current.tagBits |= TagBits.HierarchyHasProblems; @@ -1312,11 +1316,16 @@ private boolean detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBind org.eclipse.jdt.internal.compiler.ast.TypeReference ref = ((SourceTypeBinding) superType).scope.superTypeReference; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=133071 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=121734 - if (ref != null && ref.resolvedType != null && ((ReferenceBinding) ref.resolvedType).isHierarchyBeingActivelyConnected()) { - problemReporter().hierarchyCircularity(sourceType, superType, reference); - sourceType.tagBits |= TagBits.HierarchyHasProblems; - superType.tagBits |= TagBits.HierarchyHasProblems; - return true; + if (ref != null && ref.resolvedType != null) { + ReferenceBinding s = (ReferenceBinding) ref.resolvedType; + do { + if (s.isHierarchyBeingActivelyConnected()) { + problemReporter().hierarchyCircularity(sourceType, superType, reference); + sourceType.tagBits |= TagBits.HierarchyHasProblems; + superType.tagBits |= TagBits.HierarchyHasProblems; + return true; + } + } while ((s = s.enclosingType()) != null); } if (ref != null && ref.resolvedType == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=319885 Don't cry foul prematurely. @@ -1333,9 +1342,11 @@ private boolean detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBind } } } - if ((superType.tagBits & TagBits.BeginHierarchyCheck) == 0) + if ((superType.tagBits & TagBits.BeginHierarchyCheck) == 0) { // ensure if this is a source superclass that it has already been checked - ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers(); + if (superType.isValidBinding() && !superType.isUnresolvedType()) + ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers(); + } if ((superType.tagBits & TagBits.HierarchyHasProblems) != 0) sourceType.tagBits |= TagBits.HierarchyHasProblems; return false; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java index 13e63c20cc..d4092bc39a 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java @@ -23,6 +23,7 @@ import org.eclipse.jdt.internal.compiler.ast.*; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.AccessRestriction; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.util.*; @@ -67,13 +68,17 @@ public class CompilationUnitScope extends Scope { Map uniqueInferenceVariables = new HashMap<>(); public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment environment) { - super(COMPILATION_UNIT_SCOPE, null); + this(unit, environment.globalOptions); this.environment = environment; +} + +public CompilationUnitScope(CompilationUnitDeclaration unit, CompilerOptions compilerOptions) { + super(COMPILATION_UNIT_SCOPE, null); this.referenceContext = unit; unit.scope = this; this.currentPackageName = unit.currentPackage == null ? CharOperation.NO_CHAR_CHAR : unit.currentPackage.tokens; - if (compilerOptions().produceReferenceInfo) { + if (compilerOptions.produceReferenceInfo) { this.qualifiedReferences = new CompoundNameVector(); this.simpleNameReferences = new SimpleNameVector(); this.rootReferences = new SimpleNameVector(); @@ -86,6 +91,7 @@ public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment e this.referencedTypes = null; this.referencedSuperTypes = null; } + // client still needs to assign #environment } void buildFieldsAndMethods() { for (int i = 0, length = this.topLevelTypes.length; i < length; i++) @@ -106,7 +112,7 @@ void buildTypeBindings(AccessRestriction accessRestriction) { boolean firstIsSynthetic = false; if (this.referenceContext.compilationResult.compilationUnit != null) { char[][] expectedPackageName = this.referenceContext.compilationResult.compilationUnit.getPackageName(); - if (expectedPackageName != null + if (expectedPackageName != null && !this.referenceContext.isModuleInfo() && !CharOperation.equals(this.currentPackageName, expectedPackageName)) { // GROOVY add boolean errorReported = true; @@ -129,6 +135,15 @@ void buildTypeBindings(AccessRestriction accessRestriction) { if (this.currentPackageName == CharOperation.NO_CHAR_CHAR) { // environment default package is never null this.fPackage = this.environment.defaultPackage; + if (this.referenceContext.isModuleInfo()) { // cannot have a package as per grammar + ModuleDeclaration moduleDecl = this.referenceContext.moduleDeclaration; + if (moduleDecl != null) { + moduleDecl.createScope(this); + moduleDecl.checkAndSetModifiers(); + } + } else if (this.environment.module != this.environment.UnNamedModule) { + problemReporter().unnamedPackageInNamedModule(this.environment.module); + } } else { if ((this.fPackage = this.environment.createPackage(this.currentPackageName)) == null) { if (this.referenceContext.currentPackage != null) { @@ -162,8 +177,10 @@ void buildTypeBindings(AccessRestriction accessRestriction) { if (this.environment.isProcessingAnnotations && this.environment.isMissingType(typeDecl.name)) throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the type ReferenceBinding typeBinding = this.fPackage.getType0(typeDecl.name); + if (Binding.isValid(typeBinding) && this.fPackage instanceof SplitPackageBinding && !this.environment.module.canAccess(typeBinding.fPackage)) + typeBinding = null; recordSimpleReference(typeDecl.name); // needed to detect collision cases - if (typeBinding != null && typeBinding.isValidBinding() && !(typeBinding instanceof UnresolvedReferenceBinding)) { + if (Binding.isValid(typeBinding) && !(typeBinding instanceof UnresolvedReferenceBinding)) { // if its an unresolved binding - its fixed up whenever its needed, see UnresolvedReferenceBinding.resolve() if (this.environment.isProcessingAnnotations) throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the type @@ -173,11 +190,6 @@ void buildTypeBindings(AccessRestriction accessRestriction) { problemReporter().duplicateTypes(this.referenceContext, typeDecl); continue nextType; } - if (this.fPackage != this.environment.defaultPackage && this.fPackage.getPackage(typeDecl.name) != null) { - // if a package exists, it must be a valid package - cannot be a NotFound problem package - // this is now a warning since a package does not really 'exist' until it contains a type, see JLS v2, 7.4.3 - problemReporter().typeCollidesWithPackage(this.referenceContext, typeDecl); - } // GROOVY edit /*if ((typeDecl.modifiers & ClassFileConstants.AccPublic) != 0) { @@ -222,6 +234,25 @@ protected ClassScope buildClassScope(Scope parentScope, TypeDeclaration typeDecl } // GROOVY end void checkAndSetImports() { + // TODO(SHMOD): verify: this block moved here from buildTypeBindings. + // package resolving may require all modules to be known + TypeDeclaration[] types = this.referenceContext.types; + if (types != null) { + for (int i = 0; i < types.length; i++) { + TypeDeclaration typeDecl = types[i]; + if (this.fPackage != this.environment.defaultPackage && this.fPackage.getPackage(typeDecl.name, module()) != null) { + // if a package exists, it must be a valid package - cannot be a NotFound problem package + // this is now a warning since a package does not really 'exist' until it contains a type, see JLS v2, 7.4.3 + problemReporter().typeCollidesWithPackage(this.referenceContext, typeDecl); + } + } + } + + if (this.referenceContext.moduleDeclaration != null) { + this.referenceContext.moduleDeclaration.resolveModuleDirectives(this); + this.referenceContext.moduleDeclaration.resolvePackageDirectives(this); + } + if (this.referenceContext.imports == null) { this.imports = getDefaultImports(); return; @@ -447,11 +478,6 @@ void faultInImports() { } } if ((importReference.bits & ASTNode.OnDemand) != 0) { - if (CharOperation.equals(compoundName, this.currentPackageName)) { - problemReporter().unusedImport(importReference); // since skipped, must be reported now - continue nextImport; - } - Binding importBinding = findImport(compoundName, compoundName.length); if (!importBinding.isValidBinding()) { // GROOVY edit @@ -460,6 +486,14 @@ void faultInImports() { // GROOVY end continue nextImport; } + if (importBinding instanceof PackageBinding) { + PackageBinding uniquePackage = ((PackageBinding)importBinding).getVisibleFor(module()); + if (uniquePackage instanceof SplitPackageBinding) { + SplitPackageBinding splitPackage = (SplitPackageBinding) uniquePackage; + problemReporter().conflictingPackagesFromModules(splitPackage, importReference.sourceStart, importReference.sourceEnd); + continue nextImport; + } + } if (importReference.isStatic() && importBinding instanceof PackageBinding) { problemReporter().cannotImportPackage(importReference); continue nextImport; @@ -484,6 +518,24 @@ void faultInImports() { if (importBinding instanceof PackageBinding) { problemReporter().cannotImportPackage(importReference); continue nextImport; + } else if (this.environment.useModuleSystem && importBinding instanceof ReferenceBinding) { + PackageBinding importedPackage = ((ReferenceBinding) importBinding).fPackage; + if (importedPackage != null) { + if (!importedPackage.isValidBinding()) { + problemReporter().importProblem(importReference, importedPackage); + continue nextImport; + } + // re-get to find a possible split package: + importedPackage = (PackageBinding) findImport(importedPackage.compoundName, false, true); + if (importedPackage != null) + importedPackage = importedPackage.getVisibleFor(module()); + if (importedPackage instanceof SplitPackageBinding) { + SplitPackageBinding splitPackage = (SplitPackageBinding) importedPackage; + int sourceEnd = (int) importReference.sourcePositions[splitPackage.compoundName.length-1]; + problemReporter().conflictingPackagesFromModules(splitPackage, importReference.sourceStart, sourceEnd); + continue nextImport; + } + } } // all the code here which checks for valid bindings have been moved to the method // checkAndRecordImportBinding() since bug 361327 @@ -521,6 +573,11 @@ void faultInImports() { } public void faultInTypes() { faultInImports(); + if (this.referenceContext.moduleDeclaration != null) { + this.referenceContext.moduleDeclaration.resolveTypeDirectives(this); + } else if (this.referenceContext.currentPackage != null) { + this.referenceContext.currentPackage.checkPackageConflict(this); + } for (int i = 0, length = this.topLevelTypes.length; i < length; i++) this.topLevelTypes[i].faultInTypesForFieldsAndMethods(); @@ -535,13 +592,16 @@ public Binding findImport(char[][] compoundName, boolean findStaticImports, bool } private Binding findImport(char[][] compoundName, int length) { recordQualifiedReference(compoundName); - + ModuleBinding module = module(); Binding binding = this.environment.getTopLevelPackage(compoundName[0]); int i = 1; foundNothingOrType: if (binding != null) { PackageBinding packageBinding = (PackageBinding) binding; while (i < length) { - binding = packageBinding.getTypeOrPackage(compoundName[i++]); + binding = packageBinding.getTypeOrPackage(compoundName[i++], module); + if (binding instanceof ReferenceBinding && binding.problemId() == ProblemReasons.NotAccessible) { + return this.environment.convertToRawType((TypeBinding) binding, false /*do not force conversion of enclosing types*/); + } if (binding == null || !binding.isValidBinding()) { binding = null; break foundNothingOrType; @@ -551,6 +611,8 @@ private Binding findImport(char[][] compoundName, int length) { packageBinding = (PackageBinding) binding; } + if (packageBinding.isValidBinding() && !module.canAccess(packageBinding)) + return new ProblemPackageBinding(compoundName, ProblemReasons.NotAccessible); return packageBinding; } @@ -594,7 +656,7 @@ protected Binding findSingleImport(char[][] compoundName, int mask, boolean find if (compoundName.length == 1) { // findType records the reference // the name cannot be a package - if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) + if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4 && !this.referenceContext.isModuleInfo()) return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound); ReferenceBinding typeBinding = findType(compoundName[0], this.environment.defaultPackage, this.fPackage); if (typeBinding == null) @@ -612,7 +674,7 @@ private Binding findSingleStaticImport(char[][] compoundName, int mask) { char[] name = compoundName[compoundName.length - 1]; if (binding instanceof PackageBinding) { - Binding temp = ((PackageBinding) binding).getTypeOrPackage(name); + Binding temp = ((PackageBinding) binding).getTypeOrPackage(name, module()); if (temp != null && temp instanceof ReferenceBinding) // must resolve to a member type or field, not a top level type return new ProblemReferenceBinding(compoundName, (ReferenceBinding) temp, ProblemReasons.InvalidTypeForStaticImport); return binding; // cannot be a package, error is caught in sender @@ -665,11 +727,11 @@ private MethodBinding findStaticMethod(ReferenceBinding currentType, char[] sele // GROOVY package->protected protected ImportBinding[] getDefaultImports() { // initialize the default imports if necessary... share the default java.lang.* import - if (this.environment.defaultImports != null) return this.environment.defaultImports; + if (this.environment.root.defaultImports != null) return this.environment.root.defaultImports; Binding importBinding = this.environment.getTopLevelPackage(TypeConstants.JAVA); if (importBinding != null) - importBinding = ((PackageBinding) importBinding).getTypeOrPackage(TypeConstants.JAVA_LANG[1]); + importBinding = ((PackageBinding) importBinding).getTypeOrPackage(TypeConstants.JAVA_LANG[1], module()); if (importBinding == null || !importBinding.isValidBinding()) { // create a proxy for the missing BinaryType @@ -681,7 +743,7 @@ protected ImportBinding[] getDefaultImports() { importBinding = missingObject.fPackage; } - return this.environment.defaultImports = new ImportBinding[] {new ImportBinding(TypeConstants.JAVA_LANG, true, importBinding, null)}; + return this.environment.root.defaultImports = new ImportBinding[] {new ImportBinding(TypeConstants.JAVA_LANG, true, importBinding, null)}; } // NOT Public API public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) { @@ -1005,7 +1067,6 @@ private int checkAndRecordImportBinding( } } else if (resolved.resolvedImport == referenceBinding) { if (importReference.isStatic() != resolved.isStatic()) { - problemReporter().duplicateImport(importReference); recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java index 65fc171f5d..7dafc57aa7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java @@ -67,7 +67,13 @@ public Object reduce(InferenceContext18 inferenceContext) throws InferenceFailur // JLS 18.2.1 if (this.right.isProperType(true)) { - return this.left.isCompatibleWith(this.right, inferenceContext.scope) || this.left.isBoxingCompatibleWith(this.right, inferenceContext.scope) ? TRUE : FALSE; + if (this.left.isCompatibleWith(this.right, inferenceContext.scope) || this.left.isBoxingCompatibleWith(this.right, inferenceContext.scope)) { + if (this.left.resolvedType != null && this.left.resolvedType.needsUncheckedConversion(this.right)) { + inferenceContext.usesUncheckedConversion = true; + } + return TRUE; + } + return FALSE; } if (!canBePolyExpression(this.left)) { TypeBinding exprType = this.left.resolvedType; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java index 22da49c265..d6b884c2db 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for @@ -34,7 +34,7 @@ public IntersectionTypeBinding18(ReferenceBinding[] intersectingTypes, LookupEnv this.intersectingTypes = intersectingTypes; this.length = intersectingTypes.length; if (!intersectingTypes[0].isClass()) { - this.javaLangObject = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); + this.javaLangObject = environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null); this.modifiers |= ClassFileConstants.AccInterface; } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java index 97b7967ce5..88e7725cf4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java @@ -45,6 +45,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ClassFilePool; @@ -57,6 +58,7 @@ import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; +import org.eclipse.jdt.internal.compiler.util.HashtableOfModule; import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; @@ -67,25 +69,37 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants { * Map from typeBinding -> accessRestriction rule */ private Map accessRestrictions; - ImportBinding[] defaultImports; + ImportBinding[] defaultImports; // ROOT_ONLY + /** + * The root environment driving the current compilation. + * Other mutable fields in this class marked as ROOT_ONLY must always be accessed from the root environment. + * It is assumed that external clients only know the root environment, whereas calls internally in the compiler + * have to delegate to root where necessary. + * Immutable fields with "global" semantics are SHARED among environments via aliasing. + */ + public final LookupEnvironment root; + public ModuleBinding UnNamedModule; + public ModuleBinding JavaBaseModule; + public ModuleBinding module; public PackageBinding defaultPackage; + /** All visible toplevel packages, i.e. observable packages associated with modules read by the current module. */ HashtableOfPackage knownPackages; - private int lastCompletedUnitIndex = -1; - private int lastUnitIndex = -1; + private int lastCompletedUnitIndex = -1; // ROOT_ONLY + private int lastUnitIndex = -1; // ROOT_ONLY - TypeSystem typeSystem; + TypeSystem typeSystem; // SHARED - public INameEnvironment nameEnvironment; - public CompilerOptions globalOptions; + public INameEnvironment nameEnvironment; // SHARED + public CompilerOptions globalOptions; // SHARED - public ProblemReporter problemReporter; - public ClassFilePool classFilePool; + public ProblemReporter problemReporter; // SHARED + public ClassFilePool classFilePool; // SHARED // indicate in which step on the compilation we are. // step 1 : build the reference binding // step 2 : conect the hierarchy (connect bindings) // step 3 : build fields and method bindings. - private int stepCompleted; - public ITypeRequestor typeRequestor; + private int stepCompleted; // ROOT_ONLY + public ITypeRequestor typeRequestor; // SHARED private SimpleLookupTable uniqueParameterizedGenericMethodBindings; @@ -93,13 +107,17 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants { private SimpleLookupTable uniquePolymorphicMethodBindings; private SimpleLookupTable uniqueGetClassMethodBinding; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300734 - public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units + boolean useModuleSystem; // true when compliance >= 9 and nameEnvironment is module aware + // key is a string with the module name value is a module binding + public HashtableOfModule knownModules; // SHARED + + public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units -- ROOT_ONLY public Object missingClassFileLocation = null; // only set when resolving certain references, to help locating problems - private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4]; + private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4]; // ROOT_ONLY private MethodVerifier verifier; private ArrayList missingTypes; - Set typesBeingConnected; + Set typesBeingConnected; // SHARED public boolean isProcessingAnnotations = false; public boolean mayTolerateMissingType = false; @@ -112,7 +130,7 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants { Map allNullAnnotations = null; - final List deferredEnumMethods = new ArrayList<>(); // during early initialization we cannot mark Enum-methods as nonnull. + final List deferredEnumMethods; // SHARED: during early initialization we cannot mark Enum-methods as nonnull. /** Global access to the outermost active inference context as the universe for inference variable interning. */ InferenceContext18 currentInferenceContext; @@ -124,9 +142,13 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants { static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound); static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound); + static final ModuleBinding TheNotFoundModule = new ModuleBinding(CharOperation.NO_CHAR); - +/** Construct the root LookupEnvironment, corresponding to the UnNamedModule. */ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) { + this.root = this; + this.UnNamedModule = new ModuleBinding.UnNamedModule(this); + this.module = this.UnNamedModule; this.typeRequestor = typeRequestor; this.globalOptions = globalOptions; this.problemReporter = problemReporter; @@ -140,65 +162,280 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOpt this.accessRestrictions = new HashMap(3); this.classFilePool = ClassFilePool.newInstance(); this.typesBeingConnected = new HashSet<>(); + this.deferredEnumMethods = new ArrayList<>(); this.typeSystem = this.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8 && this.globalOptions.storeAnnotations ? new AnnotatableTypeSystem(this) : new TypeSystem(this); + this.knownModules = new HashtableOfModule(); + this.useModuleSystem = nameEnvironment instanceof IModuleAwareNameEnvironment && globalOptions.complianceLevel >= ClassFileConstants.JDK9; + this.resolutionListeners = new IQualifiedTypeResolutionListener[0]; +} + +/** Construct a specific LookupEnvironment, corresponding to the given module. */ +LookupEnvironment(LookupEnvironment rootEnv, ModuleBinding module) { + this.root = rootEnv; + this.UnNamedModule = rootEnv.UnNamedModule; + this.module = module; + this.typeRequestor = rootEnv.typeRequestor; + this.globalOptions = rootEnv.globalOptions; + this.problemReporter = rootEnv.problemReporter; + this.defaultPackage = new PackageBinding(this); // assume the default package always exists + this.defaultImports = null; + this.nameEnvironment = rootEnv.nameEnvironment; + this.knownPackages = new HashtableOfPackage(); + this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3); + this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3); + this.missingTypes = null; + this.accessRestrictions = new HashMap(3); + this.classFilePool = rootEnv.classFilePool; + this.typesBeingConnected = rootEnv.typesBeingConnected; + this.deferredEnumMethods = rootEnv.deferredEnumMethods; + this.typeSystem = rootEnv.typeSystem; + // knownModules is unused in specific LookupEnvironments + this.useModuleSystem = rootEnv.useModuleSystem; +} + +// NOTE: only for resolving! +public ModuleBinding getModule(char[] name) { + if (this.root != this) + return this.root.getModule(name); + if (name == null || name == ModuleBinding.UNNAMED || CharOperation.equals(name, ModuleBinding.ALL_UNNAMED)) + return this.UnNamedModule; + ModuleBinding moduleBinding = this.knownModules.get(name); + if (moduleBinding == null) { + if (this.useModuleSystem) { + IModule mod = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModule(name); + if (mod != null) { + moduleBinding = BinaryModuleBinding.create(mod, this); + } + } else + return this.UnNamedModule; + } + return moduleBinding; } +@Deprecated +public ReferenceBinding askForType(char[][] compoundName) { + return askForType(compoundName, this.UnNamedModule); +} /** * Ask the name environment for a type which corresponds to the compoundName. * Answer null if the name cannot be found. */ -public ReferenceBinding askForType(char[][] compoundName) { - NameEnvironmentAnswer answer = this.nameEnvironment.findType(compoundName); - if (answer == null) return null; +public ReferenceBinding askForType(char[][] compoundName, /*@NonNull*/ModuleBinding clientModule) { + assert clientModule != null : "lookup needs a module"; //$NON-NLS-1$ + NameEnvironmentAnswer[] answers = null; + if (this.useModuleSystem) { + IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.nameEnvironment; + answers = askForTypeFromModules(clientModule, clientModule.getAllRequiredModules(), + mod -> moduleEnv.findType(compoundName, mod.nameForLookup())); + } else { + NameEnvironmentAnswer answer = this.nameEnvironment.findType(compoundName); + if (answer != null) { + answer.moduleBinding = this.module; + answers = new NameEnvironmentAnswer[] { answer }; + } + } + if (answers == null) + return null; + + ReferenceBinding candidate = null; + for (NameEnvironmentAnswer answer : answers) { + if (answer == null) continue; - if (answer.isBinaryType()) { - // the type was found as a .class file - this.typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName, false /* valid pkg */), answer.getAccessRestriction()); - } else if (answer.isCompilationUnit()) { - // the type was found as a .java file, try to build it then search the cache - this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction()); - } else if (answer.isSourceType()) { - // the type was found as a source model - this.typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName, false /* valid pkg */), answer.getAccessRestriction()); + ModuleBinding answerModule = answer.moduleBinding != null ? answer.moduleBinding : this.UnNamedModule; + + if (answer.isBinaryType()) { + // the type was found as a .class file + PackageBinding pkg = answerModule.environment.computePackageFrom(compoundName, false /* valid pkg */); + this.typeRequestor.accept(answer.getBinaryType(), pkg, answer.getAccessRestriction()); + ReferenceBinding binding = pkg.getType0(compoundName[compoundName.length - 1]); + if (binding instanceof BinaryTypeBinding) { + ((BinaryTypeBinding) binding).module = answerModule; + if (pkg.enclosingModule == null) + pkg.enclosingModule = answerModule; + } + } else if (answer.isCompilationUnit()) { + // the type was found as a .java file, try to build it then search the cache + this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction()); + } else if (answer.isSourceType()) { + // the type was found as a source model + PackageBinding pkg = answerModule.environment.computePackageFrom(compoundName, false /* valid pkg */); + this.typeRequestor.accept(answer.getSourceTypes(), pkg, answer.getAccessRestriction()); + ReferenceBinding binding = pkg.getType0(compoundName[compoundName.length - 1]); + if (binding instanceof SourceTypeBinding) { + ((SourceTypeBinding) binding).module = answerModule; + if (pkg.enclosingModule == null) + pkg.enclosingModule = answerModule; + } + } + candidate = combine(candidate, answerModule.environment.getCachedType(compoundName), clientModule); } - return getCachedType(compoundName); + return candidate; } + /* Ask the oracle for a type named name in the packageBinding. * Answer null if the name cannot be found. */ - -ReferenceBinding askForType(PackageBinding packageBinding, char[] name) { +ReferenceBinding askForType(PackageBinding packageBinding, char[] name, ModuleBinding clientModule) { + assert clientModule != null : "lookup needs a module"; //$NON-NLS-1$ if (packageBinding == null) { packageBinding = this.defaultPackage; } - NameEnvironmentAnswer answer = this.nameEnvironment.findType(name, packageBinding.compoundName); - if (answer == null) + NameEnvironmentAnswer[] answers = null; + if (this.useModuleSystem) { + IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.nameEnvironment; + final PackageBinding pack = packageBinding; + // leverage module information from the (split?) package as to prefer NotAccessible over NotFound: + answers = askForTypeFromModules(null, packageBinding.getDeclaringModules(), + mod -> fromSplitPackageOrOracle(moduleEnv, mod, pack, name)); + } else { + NameEnvironmentAnswer answer = this.nameEnvironment.findType(name, packageBinding.compoundName); + if (answer != null) { + answer.moduleBinding = this.module; + answers = new NameEnvironmentAnswer[] { answer }; + } + } + if (answers == null) return null; - if (answer.isBinaryType()) { - // the type was found as a .class file - this.typeRequestor.accept(answer.getBinaryType(), packageBinding, answer.getAccessRestriction()); - } else if (answer.isCompilationUnit()) { - // the type was found as a .java file, try to build it then search the cache - try { - this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction()); - } catch (AbortCompilation abort) { - if (CharOperation.equals(name, TypeConstants.PACKAGE_INFO_NAME)) - return null; // silently, requestor may not be able to handle compilation units (HierarchyResolver) - throw abort; + ReferenceBinding candidate = null; + for (NameEnvironmentAnswer answer : answers) { + if (answer == null) continue; + ModuleBinding answerModule = answer.moduleBinding != null ? answer.moduleBinding : this.UnNamedModule; + PackageBinding answerPackage = packageBinding; + + if (answerModule != null) { + if (!answerPackage.isDeclaredIn(answerModule)) + continue; // this answer is not reachable via the packageBinding + if (answerPackage instanceof SplitPackageBinding) + answerPackage = ((SplitPackageBinding) answerPackage).getIncarnation(answerModule); } - } else if (answer.isSourceType()) { - // the type was found as a source model - this.typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction()); - ReferenceBinding binding = packageBinding.getType0(name); - String externalAnnotationPath = answer.getExternalAnnotationPath(); - if (externalAnnotationPath != null && this.globalOptions.isAnnotationBasedNullAnalysisEnabled && binding instanceof SourceTypeBinding) { - ExternalAnnotationSuperimposer.apply((SourceTypeBinding) binding, externalAnnotationPath); + if (answer.isResolvedBinding()) { + candidate = combine(candidate, answer.getResolvedBinding(), clientModule); + continue; + } else if (answer.isBinaryType()) { + // the type was found as a .class file + this.typeRequestor.accept(answer.getBinaryType(), answerPackage, answer.getAccessRestriction()); + ReferenceBinding binding = answerPackage.getType0(name); + if (binding instanceof BinaryTypeBinding) { + ((BinaryTypeBinding) binding).module = answerModule; + } + } else if (answer.isCompilationUnit()) { + // the type was found as a .java file, try to build it then search the cache + try { + this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction()); + } catch (AbortCompilation abort) { + if (CharOperation.equals(name, TypeConstants.PACKAGE_INFO_NAME)) + return null; // silently, requestor may not be able to handle compilation units (HierarchyResolver) + throw abort; + } + } else if (answer.isSourceType()) { + // the type was found as a source model + this.typeRequestor.accept(answer.getSourceTypes(), answerPackage, answer.getAccessRestriction()); + ReferenceBinding binding = answerPackage.getType0(name); + if (binding instanceof SourceTypeBinding) { + ((SourceTypeBinding) binding).module = answerModule; + } + String externalAnnotationPath = answer.getExternalAnnotationPath(); + if (externalAnnotationPath != null && this.globalOptions.isAnnotationBasedNullAnalysisEnabled && binding instanceof SourceTypeBinding) { + ExternalAnnotationSuperimposer.apply((SourceTypeBinding) binding, externalAnnotationPath); + } + candidate = combine(candidate, binding, clientModule); + continue; } - return binding; + candidate = combine(candidate, answerPackage.getType0(name), clientModule); + if (candidate != null && candidate.problemId() == ProblemReasons.Ambiguous) + return candidate; // saw enough + } + return candidate; +} +/** Combine up-to two candidate types. If both types are present let accessibility from the given clientModule decide. */ +private ReferenceBinding combine(ReferenceBinding one, ReferenceBinding two, ModuleBinding clientModule) { + if (one == null) return two; + if (two == null) return one; + if (!clientModule.canAccess(one.fPackage)) return two; + if (!clientModule.canAccess(two.fPackage)) return one; + if (one == two) return one; //$IDENTITY-COMPARISON$ + return new ProblemReferenceBinding(one.compoundName, one, ProblemReasons.Ambiguous); // TODO(SHMOD): use a new problem ID +} +/** Collect answers from the oracle concerning the given clientModule (if present) and each of a set of other modules. */ +private NameEnvironmentAnswer[] askForTypeFromModules(ModuleBinding clientModule, ModuleBinding[] otherModules, + Function oracle) +{ + if (clientModule != null && clientModule.nameForLookup().length == 0) { + NameEnvironmentAnswer answer = oracle.apply(clientModule); + if (answer != null) + answer.moduleBinding = this.root.getModuleFromAnswer(answer); + return new NameEnvironmentAnswer[] { answer }; + } else { + boolean found = false; + NameEnvironmentAnswer[] answers = null; + if (clientModule != null) { + answers = new NameEnvironmentAnswer[otherModules.length+1]; + NameEnvironmentAnswer answer = oracle.apply(clientModule); + if (answer != null) { + answer.moduleBinding = clientModule; + answers[answers.length-1] = answer; + found = true; + } + } else { + answers = new NameEnvironmentAnswer[otherModules.length]; + } + for (int i = 0; i < otherModules.length; i++) { + NameEnvironmentAnswer answer = oracle.apply(otherModules[i]); + if (answer != null) { + char[] nameFromAnswer = answer.moduleName(); + if (nameFromAnswer == null || CharOperation.equals(nameFromAnswer, otherModules[i].moduleName)) { + answer.moduleBinding = otherModules[i]; + } else { + answer.moduleBinding = getModule(nameFromAnswer); + } + answers[i] = answer; + found = true; + } + } + return found ? answers : null; } - return packageBinding.getType0(name); +} +/** First check for a known type in a split package and otherwise ask the oracle. */ +private static NameEnvironmentAnswer fromSplitPackageOrOracle(IModuleAwareNameEnvironment moduleEnv, ModuleBinding module, + PackageBinding packageBinding, char[] name) +{ + if (packageBinding instanceof SplitPackageBinding) { + // when asking a split package getType0() we may have answered null in case of ambiguity (not knowing the module context). + // now check if the module-incarnation of the package has the type: + // (needed because the moduleEnv will not answer initial types). + ReferenceBinding binding = ((SplitPackageBinding) packageBinding).getType0ForModule(module, name); + if (binding != null && binding.isValidBinding()) { + if (binding instanceof UnresolvedReferenceBinding) + binding = ((UnresolvedReferenceBinding) binding).resolve(module.environment, false); + return new NameEnvironmentAnswer(binding, module); + } + } + return moduleEnv.findType(name, packageBinding.compoundName, module.nameForLookup()); +} +private ModuleBinding getModuleFromAnswer(NameEnvironmentAnswer answer) { + char[] moduleName = answer.moduleName(); + if (moduleName != null) { + ModuleBinding moduleBinding; + if (!this.useModuleSystem || moduleName == ModuleBinding.UNNAMED) { + moduleBinding = this.UnNamedModule; + } else { + moduleBinding = this.knownModules.get(moduleName); + if (moduleBinding == null && this.nameEnvironment instanceof IModuleAwareNameEnvironment) { + assert answer.isBinaryType(); + IModule iModule = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModule(moduleName); + moduleBinding = BinaryModuleBinding.create(iModule, this); + } + } + return moduleBinding; + } + return null; +} + +public boolean canTypeBeAccessed(SourceTypeBinding binding, Scope scope) { + ModuleBinding client = scope.module(); + return client.canAccess(binding.fPackage); } /* Create the initial type bindings for the compilation unit. @@ -208,15 +445,25 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] name) { * NOTE: This method can be called multiple times as additional source files are needed */ public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) { - // GROOVY edit - //CompilationUnitScope scope = new CompilationUnitScope(unit, this); - CompilationUnitScope scope = unit.buildCompilationUnitScope(this); - // GROOVY end + CompilationUnitScope scope; + ModuleBinding unitModule = null; + if (unit.moduleDeclaration != null) { + char[] moduleName = unit.moduleDeclaration.moduleName; + scope = new CompilationUnitScope(unit, this.globalOptions); + unitModule = unit.moduleDeclaration.setBinding(new SourceModuleBinding(moduleName, scope, this.root)); + } else { + unitModule = unit.module(this); + // GROOVY edit + //scope = new CompilationUnitScope(unit, unitModule != null ? unitModule.environment : this); + scope = unit.buildCompilationUnitScope(unitModule != null ? unitModule.environment : this); + // GROOVY end + } scope.buildTypeBindings(accessRestriction); - int unitsLength = this.units.length; - if (++this.lastUnitIndex >= unitsLength) - System.arraycopy(this.units, 0, this.units = new CompilationUnitDeclaration[2 * unitsLength], 0, unitsLength); - this.units[this.lastUnitIndex] = unit; + LookupEnvironment rootEnv = this.root; + int unitsLength = rootEnv.units.length; + if (++rootEnv.lastUnitIndex >= unitsLength) + System.arraycopy(rootEnv.units, 0, rootEnv.units = new CompilationUnitDeclaration[2 * unitsLength], 0, unitsLength); + rootEnv.units[rootEnv.lastUnitIndex] = unit; } /* Cache the binary type since we know it is needed during this compile. @@ -242,6 +489,10 @@ public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFie } public void completeTypeBindings() { + if (this != this.root) { + this.root.completeTypeBindings(); + return; + } this.stepCompleted = BUILD_TYPE_HIERARCHY; for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) { @@ -281,6 +532,10 @@ public void completeTypeBindings() { * suitable replacement will be substituted (such as Object for a missing superclass) */ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) { + if (this != this.root) { + this.root.completeTypeBindings(parsedUnit); + return; + } if (this.stepCompleted == BUILD_FIELDS_AND_METHODS) { // This can only happen because the original set of units are completely built and // are now being processed, so we want to treat all the additional units as a group @@ -314,13 +569,13 @@ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) { */ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean buildFieldsAndMethods) { if (parsedUnit.scope == null) return; // parsing errors were too severe - - (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); + LookupEnvironment rootEnv = this.root; + (rootEnv.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); parsedUnit.scope.connectTypeHierarchy(); parsedUnit.scope.checkParameterizedTypes(); if (buildFieldsAndMethods) parsedUnit.scope.buildFieldsAndMethods(); - this.unitBeingCompleted = null; + rootEnv.unitBeingCompleted = null; } /* @@ -332,28 +587,29 @@ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean * 3. Create the method bindings */ public void completeTypeBindings(CompilationUnitDeclaration[] parsedUnits, boolean[] buildFieldsAndMethods, int unitCount) { + LookupEnvironment rootEnv = this.root; for (int i = 0; i < unitCount; i++) { CompilationUnitDeclaration parsedUnit = parsedUnits[i]; if (parsedUnit.scope != null) - (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); + (rootEnv.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); } for (int i = 0; i < unitCount; i++) { CompilationUnitDeclaration parsedUnit = parsedUnits[i]; if (parsedUnit.scope != null) - (this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy(); + (rootEnv.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy(); } for (int i = 0; i < unitCount; i++) { CompilationUnitDeclaration parsedUnit = parsedUnits[i]; if (parsedUnit.scope != null) { - (this.unitBeingCompleted = parsedUnit).scope.checkParameterizedTypes(); + (rootEnv.unitBeingCompleted = parsedUnit).scope.checkParameterizedTypes(); if (buildFieldsAndMethods[i]) parsedUnit.scope.buildFieldsAndMethods(); } } - this.unitBeingCompleted = null; + rootEnv.unitBeingCompleted = null; } public TypeBinding computeBoxingType(TypeBinding type) { TypeBinding boxedType; @@ -376,35 +632,35 @@ public TypeBinding computeBoxingType(TypeBinding type) { return TypeBinding.LONG; case TypeIds.T_int : - boxedType = getType(JAVA_LANG_INTEGER); + boxedType = getType(JAVA_LANG_INTEGER, javaBaseModule()); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_INTEGER, null, NotFound); case TypeIds.T_byte : - boxedType = getType(JAVA_LANG_BYTE); + boxedType = getType(JAVA_LANG_BYTE, javaBaseModule()); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_BYTE, null, NotFound); case TypeIds.T_short : - boxedType = getType(JAVA_LANG_SHORT); + boxedType = getType(JAVA_LANG_SHORT, javaBaseModule()); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_SHORT, null, NotFound); case TypeIds.T_char : - boxedType = getType(JAVA_LANG_CHARACTER); + boxedType = getType(JAVA_LANG_CHARACTER, javaBaseModule()); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_CHARACTER, null, NotFound); case TypeIds.T_long : - boxedType = getType(JAVA_LANG_LONG); + boxedType = getType(JAVA_LANG_LONG, javaBaseModule()); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_LONG, null, NotFound); case TypeIds.T_float : - boxedType = getType(JAVA_LANG_FLOAT); + boxedType = getType(JAVA_LANG_FLOAT, javaBaseModule()); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_FLOAT, null, NotFound); case TypeIds.T_double : - boxedType = getType(JAVA_LANG_DOUBLE); + boxedType = getType(JAVA_LANG_DOUBLE, javaBaseModule()); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_DOUBLE, null, NotFound); case TypeIds.T_boolean : - boxedType = getType(JAVA_LANG_BOOLEAN); + boxedType = getType(JAVA_LANG_BOOLEAN, javaBaseModule()); if (boxedType != null) return boxedType; return new ProblemReferenceBinding(JAVA_LANG_BOOLEAN, null, NotFound); // case TypeIds.T_int : @@ -456,27 +712,75 @@ public TypeBinding computeBoxingType(TypeBinding type) { return type; } +public ModuleBinding javaBaseModule() { + if (this.JavaBaseModule != null) + return this.JavaBaseModule; + if (this.root != this) + return this.JavaBaseModule = this.root.javaBaseModule(); + ModuleBinding resolvedModel = null; + if (this.useModuleSystem) + resolvedModel = getModule(TypeConstants.JAVA_BASE); + return this.JavaBaseModule = (resolvedModel != null ? resolvedModel : this.UnNamedModule); // fall back to pre-Jigsaw view +} + private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isMissing) { if (constantPoolName.length == 1) return this.defaultPackage; PackageBinding packageBinding = getPackage0(constantPoolName[0]); if (packageBinding == null || packageBinding == TheNotFoundPackage) { - packageBinding = new PackageBinding(constantPoolName[0], this); + if (this.useModuleSystem) { + if (this.module.isUnnamed()) { + char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModulesDeclaringPackage(null, constantPoolName[0], ModuleBinding.ANY); + if (declaringModules != null) { + for (char[] mod : declaringModules) { + ModuleBinding declaringModule = this.root.getModule(mod); + if (declaringModule != null) + packageBinding = SplitPackageBinding.combine(declaringModule.getTopLevelPackage(constantPoolName[0]), packageBinding, this.module); + } + } + } else { + packageBinding = this.module.getTopLevelPackage(constantPoolName[0]); + } + } + if (packageBinding == null || packageBinding == TheNotFoundPackage) { + packageBinding = new PackageBinding(constantPoolName[0], this, this.module); + } if (isMissing) packageBinding.tagBits |= TagBits.HasMissingType; - this.knownPackages.put(constantPoolName[0], packageBinding); + this.knownPackages.put(constantPoolName[0], packageBinding); // TODO: split? } for (int i = 1, length = constantPoolName.length - 1; i < length; i++) { PackageBinding parent = packageBinding; if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) { - packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this); + if (this.useModuleSystem) { + if (this.module.isUnnamed()) { + char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModulesDeclaringPackage(parent.compoundName, constantPoolName[i], ModuleBinding.ANY); + if (declaringModules != null) { + for (char[] mod : declaringModules) { + ModuleBinding declaringModule = this.root.getModule(mod); + if (declaringModule != null) + packageBinding = SplitPackageBinding.combine(declaringModule.getPackage(parent.compoundName, constantPoolName[i]), packageBinding, this.module); + } + } + } else { + packageBinding = this.module.getVisiblePackage(parent, constantPoolName[i]); + } + } + if (packageBinding == null || packageBinding == TheNotFoundPackage) { + packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this, this.module); + } if (isMissing) { packageBinding.tagBits |= TagBits.HasMissingType; } - parent.addPackage(packageBinding); + packageBinding = parent.addPackage(packageBinding, this.module, true); } } + if (packageBinding instanceof SplitPackageBinding) { + PackageBinding incarnation = ((SplitPackageBinding) packageBinding).getIncarnation(this.module); + if (incarnation != null) + packageBinding = incarnation; + } return packageBinding; } @@ -707,6 +1011,8 @@ public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBin } public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods, AccessRestriction accessRestriction) { + if (this != packageBinding.environment) + return packageBinding.environment.createBinaryTypeFrom(binaryType, packageBinding, needFieldsAndMethods, accessRestriction); BinaryTypeBinding binaryBinding = new BinaryTypeBinding(packageBinding, binaryType, this); // resolve any array bindings which reference the unresolvedType @@ -738,7 +1044,7 @@ public MissingTypeBinding createMissingType(PackageBinding packageBinding, char[ MissingTypeBinding missingType = new MissingTypeBinding(packageBinding, compoundName, this); if (missingType.id != TypeIds.T_JavaLangObject) { // make Object be its superclass - it could in turn be missing as well - ReferenceBinding objectType = getType(TypeConstants.JAVA_LANG_OBJECT); + ReferenceBinding objectType = getType(TypeConstants.JAVA_LANG_OBJECT, javaBaseModule()); if (objectType == null) { objectType = createMissingType(null, TypeConstants.JAVA_LANG_OBJECT); // create a proxy for the missing Object type } @@ -752,15 +1058,19 @@ public MissingTypeBinding createMissingType(PackageBinding packageBinding, char[ } /* -* 1. Connect the type hierarchy for the type bindings created for parsedUnits. -* 2. Create the field bindings -* 3. Create the method bindings -*/ + * 1. Connect the type hierarchy for the type bindings created for parsedUnits. + * 2. Create the field bindings + * 3. Create the method bindings + */ public PackageBinding createPackage(char[][] compoundName) { PackageBinding packageBinding = getPackage0(compoundName[0]); if (packageBinding == null || packageBinding == TheNotFoundPackage) { - packageBinding = new PackageBinding(compoundName[0], this); + packageBinding = new PackageBinding(compoundName[0], this, this.module); this.knownPackages.put(compoundName[0], packageBinding); + if (this.module != null) { + packageBinding = this.module.addPackage(packageBinding, true); + this.knownPackages.put(compoundName[0], packageBinding); // update in case of split package + } } for (int i = 1, length = compoundName.length; i < length; i++) { @@ -784,7 +1094,7 @@ public PackageBinding createPackage(char[][] compoundName) { //When the nameEnvironment is an instance of INameEnvironmentWithProgress, it can get avoided to search for secondaryTypes (see flag). // This is a performance optimization, because it is very expensive to search for secondary types and it isn't necessary to check when creating a package, // because package name can not collide with a secondary type name. - if (((INameEnvironmentExtension)this.nameEnvironment).findType(compoundName[i], parent.compoundName, false) != null) { + if (((INameEnvironmentExtension)this.nameEnvironment).findType(compoundName[i], parent.compoundName, false, this.module.nameForLookup()) != null) { return null; } } else { @@ -792,10 +1102,20 @@ public PackageBinding createPackage(char[][] compoundName) { return null; } } - packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this); - parent.addPackage(packageBinding); + if (parent instanceof SplitPackageBinding) { + // parent.getPackage0() may have been too shy, so drill into the split: + PackageBinding singleParent = ((SplitPackageBinding) parent).getIncarnation(this.module); + if (singleParent != null) + packageBinding = singleParent.getPackage0(compoundName[i]); + } + if (packageBinding == null) { + packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this, this.module); + packageBinding = parent.addPackage(packageBinding, this.module, true); + } } } + if (packageBinding instanceof SplitPackageBinding) + packageBinding = ((SplitPackageBinding) packageBinding).getIncarnation(this.module); return packageBinding; } @@ -891,7 +1211,7 @@ public PolymorphicMethodBinding createPolymorphicMethod(MethodBinding originalPo for (int i = 0; i < parametersLength; i++) { TypeBinding parameterTypeBinding = parameters[i]; if (parameterTypeBinding.id == TypeIds.T_null) { - parametersTypeBinding[i] = getType(JAVA_LANG_VOID); + parametersTypeBinding[i] = getType(JAVA_LANG_VOID, javaBaseModule()); } else { parametersTypeBinding[i] = parameterTypeBinding.erasure(); } @@ -1104,7 +1424,7 @@ public ReferenceBinding getCachedType(char[][] compoundName) { return null; for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) - if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) + if ((packageBinding = packageBinding.getPackage0Any(compoundName[i])) == null || packageBinding == TheNotFoundPackage) return null; return packageBinding.getType0(compoundName[compoundName.length - 1]); } @@ -1187,8 +1507,8 @@ private void initializeUsesNullTypeAnnotation() { this.globalOptions.useNullTypeAnnotations = Boolean.FALSE; if (!this.globalOptions.isAnnotationBasedNullAnalysisEnabled || this.globalOptions.originalSourceLevel < ClassFileConstants.JDK1_8) return; - ReferenceBinding nullable = this.nullableAnnotation != null ? this.nullableAnnotation.getAnnotationType() : getType(this.getNullableAnnotationName()); - ReferenceBinding nonNull = this.nonNullAnnotation != null ? this.nonNullAnnotation.getAnnotationType() : getType(this.getNonNullAnnotationName()); + ReferenceBinding nullable = this.nullableAnnotation != null ? this.nullableAnnotation.getAnnotationType() : getType(this.getNullableAnnotationName(), this.UnNamedModule); //FIXME(SHMOD) module for null annotations?? + ReferenceBinding nonNull = this.nonNullAnnotation != null ? this.nonNullAnnotation.getAnnotationType() : getType(this.getNonNullAnnotationName(), this.UnNamedModule); if (nullable == null && nonNull == null) return; if (nullable == null || nonNull == null) @@ -1218,17 +1538,25 @@ PackageBinding getPackage0(char[] name) { * Fail with a classpath error if the type cannot be found. */ public ReferenceBinding getResolvedType(char[][] compoundName, Scope scope) { - ReferenceBinding type = getType(compoundName); + return getResolvedType(compoundName, scope == null ? this.UnNamedModule : scope.module(), scope); +} +public ReferenceBinding getResolvedType(char[][] compoundName, ModuleBinding moduleBinding, Scope scope) { + if (this.module != moduleBinding) + return moduleBinding.environment.getResolvedType(compoundName, moduleBinding, scope); + ReferenceBinding type = getType(compoundName, moduleBinding); if (type != null) return type; // create a proxy for the missing BinaryType // report the missing class file first this.problemReporter.isClassPathCorrect( compoundName, - scope == null ? this.unitBeingCompleted : scope.referenceCompilationUnit(), + scope == null ? this.root.unitBeingCompleted : scope.referenceCompilationUnit(), this.missingClassFileLocation); return createMissingType(null, compoundName); } +public ReferenceBinding getResolvedJavaBaseType(char[][] compoundName, Scope scope) { + return getResolvedType(compoundName, javaBaseModule(), scope); +} /* Answer the top level package named name. * Ask the oracle for the package if its not in the cache. @@ -1241,9 +1569,17 @@ PackageBinding getTopLevelPackage(char[] name) { return null; return packageBinding; } - - if (this.nameEnvironment.isPackage(null, name)) { - this.knownPackages.put(name, packageBinding = new PackageBinding(name, this)); + if (this.useModuleSystem) { + if (this.module != null) + packageBinding = this.module.getTopLevelPackage(name); + } else { + if (this.nameEnvironment.isPackage(null, name)) { + this.knownPackages.put(name, packageBinding = new PackageBinding(name, this, this.module)); + } + } + if (packageBinding != null) { + if (packageBinding == TheNotFoundPackage) + return null; return packageBinding; } @@ -1251,11 +1587,14 @@ PackageBinding getTopLevelPackage(char[] name) { return null; } +public ReferenceBinding getType(char[][] compoundName) { + return getType(compoundName, this.UnNamedModule); +} /* Answer the type corresponding to the compoundName. * Ask the name environment for the type if its not in the cache. * Answer null if the type cannot be found. */ -public ReferenceBinding getType(char[][] compoundName) { +public ReferenceBinding getType(char[][] compoundName, ModuleBinding mod) { ReferenceBinding referenceBinding; if (compoundName.length == 1) { @@ -1263,7 +1602,7 @@ public ReferenceBinding getType(char[][] compoundName) { PackageBinding packageBinding = getPackage0(compoundName[0]); if (packageBinding != null && packageBinding != TheNotFoundPackage) return null; // collides with a known package... should not call this method in such a case - referenceBinding = askForType(this.defaultPackage, compoundName[0]); + referenceBinding = askForType(this.defaultPackage, compoundName[0], mod); } } else { PackageBinding packageBinding = getPackage0(compoundName[0]); @@ -1280,9 +1619,9 @@ public ReferenceBinding getType(char[][] compoundName) { } if (packageBinding == null) - referenceBinding = askForType(compoundName); + referenceBinding = askForType(compoundName, mod); else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null) - referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1]); + referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1], mod); } if (referenceBinding == null || referenceBinding == TheNotFoundType) @@ -1290,8 +1629,8 @@ else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.l referenceBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(referenceBinding, this, false /* no raw conversion for now */); // compoundName refers to a nested type incorrectly (for example, package1.A$B) - if (referenceBinding.isNestedType()) - return new ProblemReferenceBinding(compoundName, referenceBinding, InternalNameProvided); +// if (referenceBinding.isNestedType()) +// return new ProblemReferenceBinding(compoundName, referenceBinding, InternalNameProvided); return referenceBinding; } @@ -1320,11 +1659,17 @@ private ReferenceBinding getTypeFromCompoundName(char[][] compoundName, boolean ReferenceBinding binding = getCachedType(compoundName); if (binding == null) { PackageBinding packageBinding = computePackageFrom(compoundName, false /* valid pkg */); - binding = new UnresolvedReferenceBinding(compoundName, packageBinding); - if (wasMissingType) { - binding.tagBits |= TagBits.HasMissingType; // record it was bound to a missing type + if(this.useModuleSystem) { + // the package might not have been seen in getCachedType, so retry + binding = packageBinding.getType0(compoundName[compoundName.length - 1]); + } + if(binding == null) { + binding = new UnresolvedReferenceBinding(compoundName, packageBinding); + if (wasMissingType) { + binding.tagBits |= TagBits.HasMissingType; // record it was bound to a missing type + } + packageBinding.addType(binding); } - packageBinding.addType(binding); } else if (binding == TheNotFoundType) { // report the missing class file first if (!wasMissingType) { @@ -1332,7 +1677,7 @@ private ReferenceBinding getTypeFromCompoundName(char[][] compoundName, boolean * misconfiguration now that did not also exist in some equivalent form while producing the class files which encode * these missing types. So no need to bark again. Note that wasMissingType == true signals a type referenced in a .class * file which could not be found when the binary was produced. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=364450 */ - this.problemReporter.isClassPathCorrect(compoundName, this.unitBeingCompleted, this.missingClassFileLocation); + this.problemReporter.isClassPathCorrect(compoundName, this.root.unitBeingCompleted, this.missingClassFileLocation); } // create a proxy for the missing BinaryType binding = createMissingType(null, compoundName); @@ -1677,15 +2022,9 @@ boolean isMissingType(char[] typeName) { return false; } -/* Ask the oracle if a package exists named name in the package named compoundName. -*/ -boolean isPackage(char[][] compoundName, char[] name) { - if (compoundName == null || compoundName.length == 0) - return this.nameEnvironment.isPackage(null, name); - return this.nameEnvironment.isPackage(compoundName, name); -} // The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready. public MethodVerifier methodVerifier() { + // TODO(SHMOD): I'm not sure if the verifier would need to be created with a specific LE? if (this.verifier == null) this.verifier = newMethodVerifier(); return this.verifier; @@ -1706,6 +2045,15 @@ public void releaseClassFiles(org.eclipse.jdt.internal.compiler.ClassFile[] clas } public void reset() { + if (this.root != this) { + this.root.reset(); + return; + } + this.knownModules = new HashtableOfModule(); + this.UnNamedModule = new ModuleBinding.UnNamedModule(this); + this.module = this.UnNamedModule; + this.JavaBaseModule = null; + this.defaultPackage = new PackageBinding(this); // assume the default package always exists this.defaultImports = null; this.knownPackages = new HashtableOfPackage(); @@ -1746,17 +2094,19 @@ void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding re this.typeSystem.updateCaches(unresolvedType, resolvedType); } -public IQualifiedTypeResolutionListener[] resolutionListeners = new IQualifiedTypeResolutionListener[0]; +public IQualifiedTypeResolutionListener[] resolutionListeners; // ROOT_ONLY public void addResolutionListener(IQualifiedTypeResolutionListener resolutionListener) { - int length = this.resolutionListeners.length; - for (int i = 0; i < length; i++){ - if (this.resolutionListeners[i].equals(resolutionListener)) - return; - } - System.arraycopy(this.resolutionListeners, 0, - this.resolutionListeners = new IQualifiedTypeResolutionListener[length + 1], 0, length); - this.resolutionListeners[length] = resolutionListener; + synchronized (this.root) { + int length = this.root.resolutionListeners.length; + for (int i = 0; i < length; i++){ + if (this.root.resolutionListeners[i].equals(resolutionListener)) + return; + } + System.arraycopy(this.root.resolutionListeners, 0, + this.root.resolutionListeners = new IQualifiedTypeResolutionListener[length + 1], 0, length); + this.root.resolutionListeners[length] = resolutionListener; + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java index 357672d2b4..4f9ecaa664 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -74,6 +74,7 @@ public void initializeDeprecatedAnnotationTagBits() { } if (enclosing.isViewedAsDeprecated()) { this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; + this.tagBits |= (enclosing.tagBits & TagBits.AnnotationTerminallyDeprecated); } } } @@ -85,4 +86,7 @@ public String toString() { return "Member type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$ } } +public ModuleBinding module() { + return this.enclosingType.module(); +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java index 4636fdd8fe..c94251bd77 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java @@ -283,7 +283,7 @@ public final boolean canBeSeenBy(PackageBinding invocationPackage) { public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { SourceTypeBinding invocationType = scope.enclosingSourceType(); - if (this.declaringClass.isInterface() && isStatic()) { + if (this.declaringClass.isInterface() && isStatic() && !isPrivate()) { // Static interface methods can be explicitly invoked only through the type reference of the declaring interface or implicitly in the interface itself or via static import. if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) return false; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java index 985e414e98..28421ccfba 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -21,6 +21,7 @@ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ast.*; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; @@ -165,6 +166,7 @@ private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) { /** * Spec : 8.4.3 & 9.4 + * TODO: Add the spec section number for private interface methods from jls 9 */ private void checkAndSetModifiersForMethod(MethodBinding methodBinding) { int modifiers = methodBinding.modifiers; @@ -174,17 +176,16 @@ private void checkAndSetModifiersForMethod(MethodBinding methodBinding) { // after this point, tests on the 16 bits reserved. int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; - + long sourceLevel = compilerOptions().sourceLevel; // set the requested modifiers for a method in an interface/annotation if (declaringClass.isInterface()) { int expectedModifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract; boolean isDefaultMethod = (modifiers & ExtraCompilerModifiers.AccDefaultMethod) != 0; // no need to check validity, is done by the parser boolean reportIllegalModifierCombination = false; - boolean isJDK18orGreater = false; - if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8 && !declaringClass.isAnnotationType()) { + if (sourceLevel >= ClassFileConstants.JDK1_8 && !declaringClass.isAnnotationType()) { expectedModifiers |= ClassFileConstants.AccStrictfp | ExtraCompilerModifiers.AccDefaultMethod | ClassFileConstants.AccStatic; - isJDK18orGreater = true; + expectedModifiers |= sourceLevel >= ClassFileConstants.JDK9 ? ClassFileConstants.AccPrivate : 0; if (!methodBinding.isAbstract()) { reportIllegalModifierCombination = isDefaultMethod && methodBinding.isStatic(); } else { @@ -195,6 +196,14 @@ private void checkAndSetModifiersForMethod(MethodBinding methodBinding) { } if (reportIllegalModifierCombination) { problemReporter().illegalModifierCombinationForInterfaceMethod((AbstractMethodDeclaration) this.referenceContext); + } + if (sourceLevel >= ClassFileConstants.JDK9 && (methodBinding.modifiers & ClassFileConstants.AccPrivate) != 0) { + int remaining = realModifiers & ~expectedModifiers; + if (remaining == 0) { // check for the combination of allowed modifiers with private + remaining = realModifiers & ~(ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccStrictfp); + if (isDefaultMethod || remaining != 0) + problemReporter().illegalModifierCombinationForPrivateInterfaceMethod((AbstractMethodDeclaration) this.referenceContext); + } } // Kludge - The AccDefaultMethod bit is outside the lower 16 bits and got removed earlier. Putting it back. if (isDefaultMethod) { @@ -205,10 +214,22 @@ private void checkAndSetModifiersForMethod(MethodBinding methodBinding) { if ((declaringClass.modifiers & ClassFileConstants.AccAnnotation) != 0) problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) this.referenceContext); else - problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) this.referenceContext, isJDK18orGreater); + problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) this.referenceContext, sourceLevel); methodBinding.modifiers &= (expectedModifiers | ~ExtraCompilerModifiers.AccJustFlag); } return; + } else if (declaringClass.isAnonymousType() && sourceLevel >= ClassFileConstants.JDK9) { + // If the class instance creation expression elides the supertype's type arguments using '<>', + // then for all non-private methods declared in the class body, it is as if the method declaration + // is annotated with @Override - https://bugs.openjdk.java.net/browse/JDK-8073593 + LocalTypeBinding local = (LocalTypeBinding) declaringClass; + TypeReference ref = local.scope.referenceContext.allocation.type; + if (ref != null && (ref.bits & ASTNode.IsDiamond) != 0) { + // + if ((realModifiers & (ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic )) == 0) { + methodBinding.tagBits |= TagBits.AnnotationOverride; + } + } } // check for abnormal modifiers @@ -343,6 +364,7 @@ MethodBinding createMethod(AbstractMethodDeclaration method) { // is necessary to ensure error reporting this.referenceContext = method; method.scope = this; + long sourceLevel = compilerOptions().sourceLevel; SourceTypeBinding declaringClass = referenceType().binding; int modifiers = method.modifiers | ExtraCompilerModifiers.AccUnresolved; if (method.isConstructor()) { @@ -352,7 +374,9 @@ MethodBinding createMethod(AbstractMethodDeclaration method) { checkAndSetModifiersForConstructor(method.binding); } else { if (declaringClass.isInterface()) {// interface or annotation type - if (method.isDefaultMethod() || method.isStatic()) { + if (sourceLevel >= ClassFileConstants.JDK9 && ((method.modifiers & ClassFileConstants.AccPrivate) != 0)) { // private method + // do nothing + } else if (method.isDefaultMethod() || method.isStatic()) { modifiers |= ClassFileConstants.AccPublic; // default method is not abstract } else { modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract; @@ -366,7 +390,6 @@ MethodBinding createMethod(AbstractMethodDeclaration method) { Argument[] argTypes = method.arguments; int argLength = argTypes == null ? 0 : argTypes.length; - long sourceLevel = compilerOptions().sourceLevel; if (argLength > 0) { Argument argument = argTypes[--argLength]; if (argument.isVarArgs() && sourceLevel >= ClassFileConstants.JDK1_5) @@ -601,4 +624,65 @@ public Binding checkRedundantDefaultNullness(int nullBits, int sourceStart) { } return this.parent.checkRedundantDefaultNullness(nullBits, sourceStart); } +public boolean shouldCheckAPILeaks(ReferenceBinding declaringClass, boolean memberIsPublic) { + if (environment().useModuleSystem) + return memberIsPublic && declaringClass.isPublic() && declaringClass.fPackage.isExported(); + return false; +} +public void detectAPILeaks(ASTNode typeNode, TypeBinding type) { + if (environment().useModuleSystem) { + // NB: using an ASTVisitor yields more precise locations than a TypeBindingVisitor would + ASTVisitor visitor = new ASTVisitor() { + @Override + public boolean visit(SingleTypeReference typeReference, BlockScope scope) { + if (typeReference.resolvedType instanceof ReferenceBinding) + checkType((ReferenceBinding) typeReference.resolvedType, typeReference.sourceStart, typeReference.sourceEnd); + return true; + } + @Override + public boolean visit(QualifiedTypeReference typeReference, BlockScope scope) { + if (typeReference.resolvedType instanceof ReferenceBinding) + checkType((ReferenceBinding) typeReference.resolvedType, typeReference.sourceStart, typeReference.sourceEnd); + return true; + } + @Override + public boolean visit(ArrayTypeReference typeReference, BlockScope scope) { + TypeBinding leafComponentType = typeReference.resolvedType.leafComponentType(); + if (leafComponentType instanceof ReferenceBinding) + checkType((ReferenceBinding) leafComponentType, typeReference.sourceStart, typeReference.originalSourceEnd); + return true; + } + private void checkType(ReferenceBinding referenceBinding, int sourceStart, int sourceEnd) { + if (!referenceBinding.isValidBinding()) + return; + ModuleBinding otherModule = referenceBinding.module(); + if (otherModule == otherModule.environment.javaBaseModule()) + return; // always accessible + if (!isFullyPublic(referenceBinding)) { + problemReporter().nonPublicTypeInAPI(referenceBinding, sourceStart, sourceEnd); + } else if (!referenceBinding.fPackage.isExported()) { + problemReporter().notExportedTypeInAPI(referenceBinding, sourceStart, sourceEnd); + } else if (isUnrelatedModule(referenceBinding.fPackage)) { + problemReporter().missingRequiresTransitiveForTypeInAPI(referenceBinding, sourceStart, sourceEnd); + } + } + private boolean isFullyPublic(ReferenceBinding referenceBinding) { + if (!referenceBinding.isPublic()) + return false; + if (referenceBinding instanceof NestedTypeBinding) + return isFullyPublic(((NestedTypeBinding) referenceBinding).enclosingType); + return true; + } + private boolean isUnrelatedModule(PackageBinding fPackage) { + ModuleBinding otherModule = fPackage.enclosingModule; + ModuleBinding thisModule = module(); + if (thisModule != otherModule) { + return !thisModule.isTransitivelyRequired(otherModule); + } + return false; + } + }; + typeNode.traverse(visitor, this); + } +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java index 70100580e9..ea78dcb2ee 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -634,7 +634,7 @@ void computeInheritedMethods(ReferenceBinding superclass, ReferenceBinding[] sup MethodBinding[] methods = superType.unResolvedMethods(); nextMethod : for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public MethodBinding inheritedMethod = methods[m]; - if (inheritedMethod.isStatic()) continue nextMethod; + if (inheritedMethod.isStatic() || inheritedMethod.isPrivate()) continue nextMethod; MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector); if (existingMethods == null) { existingMethods = new MethodBinding[] {inheritedMethod}; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java new file mode 100644 index 0000000000..eec6305ca5 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java @@ -0,0 +1,820 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.lookup; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule; +import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage; +import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray; + +/** + * This class serves a dual purpose + *

+ * First, it canonically represents modules in the world of bindings. + *

+ *

+ * Secondly, it adds a graph layer on top of {@link LookupEnvironment}: + * ModuleBindins are linked through "read" edges as per JPMS (see java.lang.module.Configuration). + * Additionally, each ModuleBinding holds its own instance of LookupEnviroment, + * capturing all packages and types that are visible to the current module. + * As a subset of all visible types, the ModuleBinding knows the set of + * packages locally declared in this module. + *

+ */ +public class ModuleBinding extends Binding implements IUpdatableModule { + + /** Name of the unnamed module. */ + public static final char[] UNNAMED = "".toCharArray(); //$NON-NLS-1$ + /** Name to represent unnamed modules in --add-exports & --add-reads options. */ + public static final char[] ALL_UNNAMED = "ALL-UNNAMED".toCharArray(); //$NON-NLS-1$ + /** Module name for package/type lookup that doesn't care about modules. */ + public static final char[] ANY = "".toCharArray(); //$NON-NLS-1$ + /** Module name for package/type lookup that should look into all named modules. */ + public static final char[] ANY_NAMED = "".toCharArray(); //$NON-NLS-1$ + + public static class UnNamedModule extends ModuleBinding { + + private static final char[] UNNAMED_READABLE_NAME = "".toCharArray(); //$NON-NLS-1$ + + @SuppressWarnings("synthetic-access") + UnNamedModule(LookupEnvironment env) { + super(env); + } + public ModuleBinding[] getAllRequiredModules() { + return Binding.NO_MODULES; + } + public boolean canAccess(PackageBinding pkg) { + ModuleBinding mod = pkg.enclosingModule; + if (mod != null && mod != this) + return mod.isPackageExportedTo(pkg, this); + return true; + } + @Override + public boolean isPackageExportedTo(PackageBinding pkg, ModuleBinding client) { + // per JLS 7.7.5 an unnamed module exports all its packages + return pkg.isDeclaredIn(this) && pkg.hasCompilationUnit(false); + } + @Override + public boolean isUnnamed() { + return true; + } + @Override + public char[] nameForLookup() { + return ANY; + } + @Override + public char[] readableName() { + return UNNAMED_READABLE_NAME; + } + @Override + public String toString() { + return "The Unnamed Module"; //$NON-NLS-1$ + } + } + public char[] moduleName; + protected ModuleBinding[] requires; + protected ModuleBinding[] requiresTransitive; + protected PackageBinding[] exportedPackages; + private Map exportRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position + protected PackageBinding[] openedPackages; + private Map openRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position + protected TypeBinding[] uses; + protected TypeBinding[] services; + public Map implementations; + public char[] mainClassName; + private SimpleSetOfCharArray packageNames; + public int modifiers; + public LookupEnvironment environment; + public int tagBits; + ModuleBinding[] requiredModules = null; + boolean isAuto = false; + private boolean[] isComplete = new boolean[UpdateKind.values().length]; + private Set transitiveRequires; + private boolean isPackageLookupActive = false; // to prevent cyclic lookup caused by synthetic reads edges on behalf of auto-modules. + + /** + * Packages declared in this module (indexed by qualified name). + * We consider a package as declared in a module, + * if a compilation unit associated with the module + * declares the package or a subpackage thereof. + */ + public HashtableOfPackage declaredPackages; + + /** Constructor for the unnamed module. */ + private ModuleBinding(LookupEnvironment env) { + this.moduleName = ModuleBinding.UNNAMED; + this.environment = env; + this.requires = Binding.NO_MODULES; + this.requiresTransitive = Binding.NO_MODULES; + this.exportedPackages = Binding.NO_PACKAGES; + this.openedPackages = Binding.NO_PACKAGES; + this.declaredPackages = new HashtableOfPackage(0); + Arrays.fill(this.isComplete, true); + } + /* For error binding and sub class SourceModuleBinding. */ + ModuleBinding(char[] moduleName) { + this.moduleName = moduleName; + this.requires = Binding.NO_MODULES; + this.requiresTransitive = Binding.NO_MODULES; + this.exportedPackages = Binding.NO_PACKAGES; + this.openedPackages = Binding.NO_PACKAGES; + this.uses = Binding.NO_TYPES; + this.services = Binding.NO_TYPES; + this.declaredPackages = new HashtableOfPackage(5); + } + + /* For sub class BinaryModuleBinding */ + protected ModuleBinding(char[] moduleName, LookupEnvironment existingEnvironment) { + this.moduleName = moduleName; + this.requires = Binding.NO_MODULES; + this.requiresTransitive = Binding.NO_MODULES; + this.environment = new LookupEnvironment(existingEnvironment.root, this); + this.declaredPackages = new HashtableOfPackage(5); + } + + public PackageBinding[] getExports() { + completeIfNeeded(UpdateKind.PACKAGE); + return this.exportedPackages; + } + public String[] getExportRestrictions(PackageBinding pack) { + completeIfNeeded(UpdateKind.PACKAGE); + if (this.exportRestrictions != null) { + SimpleSetOfCharArray set = this.exportRestrictions.get(pack); + if (set != null) { + char[][] names = new char[set.elementSize][]; + set.asArray(names); + return CharOperation.charArrayToStringArray(names); + } + } + return CharOperation.NO_STRINGS; + } + public PackageBinding[] getOpens() { + completeIfNeeded(UpdateKind.PACKAGE); + return this.openedPackages; + } + public String[] getOpenRestrictions(PackageBinding pack) { + completeIfNeeded(UpdateKind.PACKAGE); + if (this.openRestrictions != null) { + SimpleSetOfCharArray set = this.openRestrictions.get(pack); + if (set != null) { + char[][] names = new char[set.elementSize][]; + set.asArray(names); + return CharOperation.charArrayToStringArray(names); + } + } + return CharOperation.NO_STRINGS; + } + public TypeBinding[] getImplementations(TypeBinding binding) { + if (this.implementations != null) { + return this.implementations.get(binding); + } + return null; + } + public ModuleBinding[] getRequires() { + completeIfNeeded(UpdateKind.MODULE); + return this.requires; + } + public ModuleBinding[] getRequiresTransitive() { + completeIfNeeded(UpdateKind.MODULE); + return this.requiresTransitive; + } + + public TypeBinding[] getUses() { + return this.uses; + } + + public TypeBinding[] getServices() { + return this.services; + } + + private void completeIfNeeded(IUpdatableModule.UpdateKind kind) { + if (!this.isComplete[kind.ordinal()]) { + this.isComplete[kind.ordinal()] = true; + if (this.environment.nameEnvironment instanceof IModuleAwareNameEnvironment) { + ((IModuleAwareNameEnvironment) this.environment.nameEnvironment).applyModuleUpdates(this, kind); + } + } + } + + // --- Implement IUpdatableModule: --- + + @Override + public void addReads(char[] requiredModuleName) { + ModuleBinding requiredModule = this.environment.getModule(requiredModuleName); + if (requiredModule != null) { + int len = this.requires.length; + if (len == 0) { + this.requires = new ModuleBinding[] { requiredModule }; + } else { + System.arraycopy(this.requires, 0, this.requires = new ModuleBinding[len+1], 0, len); + this.requires[len] = requiredModule; + } + } else { + // TODO(SHMOD) report error + } + // update known packages: + HashtableOfPackage knownPackages = this.environment.knownPackages; + for (int i = 0; i < knownPackages.valueTable.length; i++) { + PackageBinding packageBinding = knownPackages.valueTable[i]; + if (packageBinding == null) continue; + PackageBinding newBinding = requiredModule.getVisiblePackage(packageBinding.compoundName); + newBinding = SplitPackageBinding.combine(newBinding, packageBinding, this); + if (packageBinding != newBinding) { + knownPackages.valueTable[i] = newBinding; + if (this.declaredPackages.containsKey(newBinding.readableName())) + this.declaredPackages.put(newBinding.readableName(), newBinding); + } + } + } + @Override + public void addExports(char[] packageName, char[][] targetModules) { + PackageBinding declaredPackage = getVisiblePackage(CharOperation.splitOn('.', packageName)); + if (declaredPackage != null && declaredPackage.isValidBinding()) + addResolvedExport(declaredPackage, targetModules); + } + + @Override + public void setMainClassName(char[] mainClassName) { + this.mainClassName = mainClassName; + } + + @Override + public void setPackageNames(SimpleSetOfCharArray packageNames) { + this.packageNames = packageNames; + } + + // for code gen: + /** @return array of names, which may contain nulls. */ + public char[][] getPackageNamesForClassFile() { + if (this.packageNames == null) + return null; + for (PackageBinding packageBinding : this.exportedPackages) + this.packageNames.add(packageBinding.readableName()); + for (PackageBinding packageBinding : this.openedPackages) + this.packageNames.add(packageBinding.readableName()); + if (this.implementations != null) + for (TypeBinding[] types : this.implementations.values()) + for (TypeBinding typeBinding : types) + this.packageNames.add(((ReferenceBinding)typeBinding).fPackage.readableName()); + return this.packageNames.values; + } + + // --- + + public void addResolvedExport(PackageBinding declaredPackage, char[][] targetModules) { + int len = this.exportedPackages.length; + if (declaredPackage == null || !declaredPackage.isValidBinding()) { + // FIXME(SHMOD) use a problem binding? See https://bugs.eclipse.org/518794#c13 + return; + } + if (len == 0) { + this.exportedPackages = new PackageBinding[] { declaredPackage }; + } else { + System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PackageBinding[len+1], 0, len); + this.exportedPackages[len] = declaredPackage; + } + declaredPackage.isExported = Boolean.TRUE; + recordExportRestrictions(declaredPackage, targetModules); + } + + public void addResolvedOpens(PackageBinding declaredPackage, char[][] targetModules) { + int len = this.openedPackages.length; + if (declaredPackage == null || !declaredPackage.isValidBinding()) { + // FIXME(SHMOD) use a problem binding? See https://bugs.eclipse.org/518794#c13 + return; + } + if (len == 0) { + this.openedPackages = new PackageBinding[] { declaredPackage }; + } else { + System.arraycopy(this.openedPackages, 0, this.openedPackages = new PackageBinding[len+1], 0, len); + this.openedPackages[len] = declaredPackage; + } + recordOpensRestrictions(declaredPackage, targetModules); + } + + protected void recordExportRestrictions(PackageBinding exportedPackage, char[][] targetModules) { + if (targetModules != null && targetModules.length > 0) { + SimpleSetOfCharArray targetModuleSet = new SimpleSetOfCharArray(targetModules.length); + for (int i = 0; i < targetModules.length; i++) { + targetModuleSet.add(targetModules[i]); + } + if (this.exportRestrictions == null) + this.exportRestrictions = new HashMap<>(); + this.exportRestrictions.put(exportedPackage, targetModuleSet); + } + } + + protected void recordOpensRestrictions(PackageBinding openedPackage, char[][] targetModules) { + if (targetModules != null && targetModules.length > 0) { + SimpleSetOfCharArray targetModuleSet = new SimpleSetOfCharArray(targetModules.length); + for (int i = 0; i < targetModules.length; i++) { + targetModuleSet.add(targetModules[i]); + } + if (this.openRestrictions == null) + this.openRestrictions = new HashMap<>(); + this.openRestrictions.put(openedPackage, targetModuleSet); + } + } + + Stream getRequiredModules(boolean transitiveOnly) { + return Stream.of(transitiveOnly ? this.getRequiresTransitive() : this.getRequires()); + } + private void collectAllDependencies(Set deps) { + getRequiredModules(false).forEach(m -> { + if (deps.add(m)) { + m.collectAllDependencies(deps); + } + }); + } + private void collectTransitiveDependencies(Set deps) { + getRequiredModules(true).forEach(m -> { + if (deps.add(m)) { + m.collectTransitiveDependencies(deps); + } + }); + } + + // All modules required by this module, either directly or indirectly + public Supplier> dependencyGraphCollector() { + return () -> getRequiredModules(false) + .collect(HashSet::new, + (set, mod) -> { + set.add(mod); + mod.collectAllDependencies(set); + }, + HashSet::addAll); + } + // All direct and transitive dependencies of this module + public Supplier> dependencyCollector() { + return () -> getRequiredModules(false) + .collect(HashSet::new, + (set, mod) -> { + set.add(mod); + mod.collectTransitiveDependencies(set); + }, + HashSet::addAll); + } + + /** + * Get all the modules required by this module + * All required modules include modules explicitly specified as required in the module declaration + * as well as implicit dependencies - those specified as ' requires transitive ' by one of the + * dependencies + * + * @return + * An array of all required modules + */ + public ModuleBinding[] getAllRequiredModules() { + if (this.requiredModules != null) + return this.requiredModules; + + Collection allRequires = dependencyCollector().get(); + if (allRequires.contains(this)) { + // TODO(SHMOD): report (when? where?) + return NO_MODULES; // avoid entering unbounded recursion due to cyclic requires + } + ModuleBinding javaBase = this.environment.javaBaseModule(); + // add java.base? + if (!CharOperation.equals(this.moduleName, TypeConstants.JAVA_BASE) // ... not if this *is* java.base + && javaBase != null // ... nor when java.base is absent + && javaBase != this.environment.UnNamedModule) // ..... or faked by the unnamed module + { + allRequires.add(javaBase); + } + return this.requiredModules = allRequires.size() > 0 ? allRequires.toArray(new ModuleBinding[allRequires.size()]) : Binding.NO_MODULES; + } + + /** Answer the name of this module. The unnamed module is identified by {@link #UNNAMED}. */ + public char[] name() { + return this.moduleName; + } + + /** + * Answer the name of this module as it should be used for package or type lookup. + * Unnamed and automatic modules answer {@link #ANY} or {@link #ANY_NAMED} resp., + * to signal that lookup should search in all accessible (named) modules. + */ + public char[] nameForLookup() { + return this.moduleName; + } + + /** + * Check if the specified package is owned by the current module and exported to the client module. + * True if the package appears in the list of exported packages and when the export is targeted, + * the module appears in the targets of the exports statement. + * @param pkg - the package whose visibility is to be checked + * @param client - the module that wishes to use the package + * @return true if the package is visible to the client module, false otherwise + */ + public boolean isPackageExportedTo(PackageBinding pkg, ModuleBinding client) { + // TODO(SHMOD): cache the result? + PackageBinding resolved = null; + if (pkg instanceof SplitPackageBinding) { + resolved = ((SplitPackageBinding) pkg).getIncarnation(this); + } else if (pkg.enclosingModule == this) { + resolved = pkg; + } + if (resolved != null) { + if (this.isAuto) { // all packages are exported by an automatic module + return pkg.enclosingModule == this; // no transitive export + } + PackageBinding[] initializedExports = getExports(); + for (int i = 0; i < initializedExports.length; i++) { + PackageBinding export = initializedExports[i]; + if (export.subsumes(resolved)) { + if (this.exportRestrictions != null) { + SimpleSetOfCharArray restrictions = this.exportRestrictions.get(export); + if (restrictions != null) { + if (client.isUnnamed()) + return restrictions.includes(ALL_UNNAMED); + else + return restrictions.includes(client.name()); + } + } + return true; + } + } + } + return false; + } + + /** + * Return a package binding if there exists a package named name in this module's context and it can be seen by this module. + * A package can be seen by this module if it is declared in this module or any other module read by this module + * (JLS 7.4.3 for packages based on JLS 7.3 for compilation units). + * Package exports are not considered for visibility check (only when checking "uniquely visible" (JLS 7.4.3)). + *

+ * The returned package may be a {@link SplitPackageBinding}, if more than one package of the given name is visible. + *

+ *

+ * When asked via the unnamed module or an automatic module all other named modules are considered visible. + *

+ */ + public PackageBinding getTopLevelPackage(char[] name) { + // check caches: + PackageBinding binding = this.declaredPackages.get(name); + if (binding != null) + return binding; + binding = this.environment.getPackage0(name); + if (binding != null) + return binding; + binding = getVisiblePackage(null, name); + // remember: + if (binding != null) { + this.environment.knownPackages.put(name, binding); + binding = addPackage(binding, false); + } else { + this.environment.knownPackages.put(name, LookupEnvironment.TheNotFoundPackage); + } + return binding; + } + + PackageBinding getDeclaredPackage(char[][] parentName, char[] name) { + // check caches: + char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name); + char[] fullFlatName = CharOperation.concatWith(subPkgCompoundName, '.'); + PackageBinding pkg = this.declaredPackages.get(fullFlatName); + if (pkg != null) + return pkg; + PackageBinding parent = parentName.length == 0 ? null : getVisiblePackage(parentName); + PackageBinding binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this); + // remember + this.declaredPackages.put(fullFlatName, binding); + return binding; + } + // Given parent is visible in this module, see if there is sub package named name visible in this module + PackageBinding getVisiblePackage(PackageBinding parent, char[] name) { + // check caches: + char[][] parentName = parent == null ? CharOperation.NO_CHAR_CHAR : parent.compoundName; + char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name); + char[] fullFlatName = CharOperation.concatWith(subPkgCompoundName, '.'); + PackageBinding pkg = this.declaredPackages.get(fullFlatName); + if (pkg != null) + return pkg; + if (parent != null) + pkg = parent.getPackage0(name); + else + pkg = this.environment.getPackage0(name); + if (pkg != null) { + if (pkg == LookupEnvironment.TheNotFoundPackage) + return null; + else + return addPackage(pkg, false); + } + + PackageBinding binding = null; + if (this.environment.useModuleSystem) { + IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment; + char[][] declaringModuleNames = moduleEnv.getModulesDeclaringPackage(parentName, name, nameForLookup()); + if (declaringModuleNames != null) { + if (!this.isUnnamed() && CharOperation.containsEqual(declaringModuleNames, this.moduleName)) { + // declared here, not yet known, so create it now: + binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this); + } else { + // visible but foreign (when current is unnamed or auto): + for (char[] declaringModuleName : declaringModuleNames) { + ModuleBinding declaringModule = this.environment.root.getModule(declaringModuleName); + if (declaringModule != null && !declaringModule.isPackageLookupActive) + binding = SplitPackageBinding.combine(declaringModule.getDeclaredPackage(parentName, name), binding, this); + } + } + } + } else { + if (this.environment.nameEnvironment.isPackage(parentName, name)) + binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this); + } + + // enrich with split-siblings from visible modules: + if (!isUnnamed()) { + binding = combineWithPackagesFromRequired(binding, subPkgCompoundName); + } + if (binding == null || !binding.isValidBinding()) + return null; + // remember + if (parentName.length == 0) + binding.environment.knownPackages.put(name, binding); + else + binding = parent.addPackage(binding, this, false); + return addPackage(binding, false); + } + + /** + * Answer the package of the given qualified name and visible in this module, + * or {@code null} if no such package exists. + * Accessibility (based on package exports) is not checked. + *

+ * May answer a {@link SplitPackageBinding}. + *

+ */ + public PackageBinding getVisiblePackage(char[][] qualifiedPackageName) { + if (qualifiedPackageName == null || qualifiedPackageName.length == 0) { + return this.environment.defaultPackage; + } + + PackageBinding parent = getTopLevelPackage(qualifiedPackageName[0]); + if (parent == null || parent == LookupEnvironment.TheNotFoundPackage) + return null; + + // check each sub package + for (int i = 1; i < qualifiedPackageName.length; i++) { + PackageBinding binding = getVisiblePackage(parent, qualifiedPackageName[i]); + if (binding == null || binding == LookupEnvironment.TheNotFoundPackage) { + return null; + } + parent = binding; + } + return parent; + } + + /** + * Answer a package, that is a member named packageName of the parent package + * named parentPackageName. + * Considers all packages that are visible to the current module, + * i.e., we consider locally declared packages and packages in all modules + * read by the current module. + * Accessibility (via package exports) is not checked. + */ + public PackageBinding getPackage(char[][] parentPackageName, char[] packageName) { + // Returns a package binding if there exists such a package in the context of this module and it is observable + // A package is observable if it is declared in this module or it is exported by some required module + if (parentPackageName == null || parentPackageName.length == 0) { + return getVisiblePackage(null, packageName); + } + PackageBinding binding = null; + PackageBinding parent = getVisiblePackage(parentPackageName); + if (parent != null && parent != LookupEnvironment.TheNotFoundPackage) { + binding = getVisiblePackage(parent, packageName); + } + if (binding != null) + return addPackage(binding, false); + return null; + } + + /** + * Check if the given package is declared in this module, + * and if so, remember this fact for later. + * The package can be a {@code SplitPackageBinding} in which case + * only one of its incarnations needs to be declared in this module. + * @param packageBinding the package to add + * @param checkForSplit if true then we should try to construct a split package from + * same named packages in required modules. + * @return the given package, possibly enriched to a {@link SplitPackageBinding} + */ + PackageBinding addPackage(PackageBinding packageBinding, boolean checkForSplit) { + if (packageBinding.isDeclaredIn(this)) { + char[] packageName = packageBinding.readableName(); + if (checkForSplit && this.environment.useModuleSystem) { + if (isUnnamed()) { + IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment; + char[][] declaringModuleNames = moduleEnv.getModulesDeclaringPackage(null, packageName, ANY); + if (declaringModuleNames != null) { + for (int i = 0; i < declaringModuleNames.length; i++) { + ModuleBinding otherModule = this.environment.getModule(declaringModuleNames[i]); + if (otherModule != null && !otherModule.isPackageLookupActive) + packageBinding = SplitPackageBinding.combine(otherModule.getVisiblePackage(packageBinding.compoundName), packageBinding, this); + } + } + } else { + packageBinding = combineWithPackagesFromRequired(packageBinding, packageBinding.compoundName); + } + } + this.declaredPackages.put(packageName, packageBinding); + } + return packageBinding; + } + + private PackageBinding combineWithPackagesFromRequired(PackageBinding currentBinding, char[][] compoundName) { + boolean save = this.isPackageLookupActive; + this.isPackageLookupActive = true; + try { + for (ModuleBinding moduleBinding : getAllRequiredModules()) + if (!moduleBinding.isPackageLookupActive) + currentBinding = SplitPackageBinding.combine(moduleBinding.getVisiblePackage(compoundName), currentBinding, this); + return currentBinding; + } finally { + this.isPackageLookupActive = save; + } + } + + /** + * Check if the given package is accessible by this module. True when the package is declared in + * this module or exported by some required module to this module. + * See {@link #isPackageExportedTo(PackageBinding, ModuleBinding)} + * + * @param pkg + * + * @return True, if the package is accessible by this module, false otherwise + */ + public boolean canAccess(PackageBinding pkg) { + if (pkg.isDeclaredIn(this)) + return true; + for (ModuleBinding requiredModule : getAllRequiredModules()) { + // If pkg is a SplitPackageBinding, we actually ask the intersection of all required modules + // and modules declaring the package, if any of them exports the package to this module. + // The intersection is computed when inside isPackageExportedTo we ask for pkg's incarnation in requiredModule. + if (requiredModule.isPackageExportedTo(pkg, ModuleBinding.this)) + return true; + // TODO(SHMOD): store export status in the PackageBinding? + } + return false; + } + @Override + public char[] computeUniqueKey(boolean isLeaf) { + return CharOperation.prepend('"', this.moduleName); + } + + @Override + public int kind() { + // + return Binding.MODULE; + } + + @Override + public char[] readableName() { + return this.moduleName; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(30); + if (isOpen()) + buffer.append("open "); //$NON-NLS-1$ + buffer.append("module " + new String(readableName())); //$NON-NLS-1$ + if (this.requires.length > 0) { + buffer.append("\n/* requires */\n"); //$NON-NLS-1$ + for (int i = 0; i < this.requires.length; i++) { + buffer.append("\n\t"); //$NON-NLS-1$ + if (this.requiresTransitive != null) { + for (ModuleBinding reqTrans : this.requiresTransitive) { + if (reqTrans == this.requires[i]) { + buffer.append("transitive "); //$NON-NLS-1$ + break; + } + } + } + buffer.append(this.requires[i].moduleName); + } + } else { + buffer.append("\nNo Requires"); //$NON-NLS-1$ + } + if (this.exportedPackages != null && this.exportedPackages.length > 0) { + buffer.append("\n/* exports */\n"); //$NON-NLS-1$ + for (int i = 0; i < this.exportedPackages.length; i++) { + PackageBinding export = this.exportedPackages[i]; + buffer.append("\n\t"); //$NON-NLS-1$ + if (export == null) { + buffer.append(""); //$NON-NLS-1$ + continue; + } + buffer.append(export.readableName()); + SimpleSetOfCharArray restrictions = this.exportRestrictions != null ? this.exportRestrictions.get(export) : null; + if (restrictions != null) { + buffer.append(" to "); //$NON-NLS-1$ + String sep = ""; //$NON-NLS-1$ + char[][] allNames = new char[restrictions.elementSize][]; + restrictions.asArray(allNames); + for (char[] targetModule : allNames) { + buffer.append(sep); + buffer.append(targetModule); + sep = ", "; //$NON-NLS-1$ + } + } + } + } else { + buffer.append("\nNo Exports"); //$NON-NLS-1$ + } + if (this.openedPackages != null && this.openedPackages.length > 0) { + buffer.append("\n/* exports */\n"); //$NON-NLS-1$ + for (int i = 0; i < this.openedPackages.length; i++) { + PackageBinding opens = this.openedPackages[i]; + buffer.append("\n\t"); //$NON-NLS-1$ + if (opens == null) { + buffer.append(""); //$NON-NLS-1$ + continue; + } + buffer.append(opens.readableName()); + SimpleSetOfCharArray restrictions = this.openRestrictions != null ? this.openRestrictions.get(opens) : null; + if (restrictions != null) { + buffer.append(" to "); //$NON-NLS-1$ + String sep = ""; //$NON-NLS-1$ + char[][] allNames = new char[restrictions.elementSize][]; + restrictions.asArray(allNames); + for (char[] targetModule : allNames) { + buffer.append(sep); + buffer.append(targetModule); + sep = ", "; //$NON-NLS-1$ + } + } + } + } else { + buffer.append("\nNo Opens"); //$NON-NLS-1$ + } + if (this.uses != null && this.uses.length > 0) { + buffer.append("\n/* uses /*\n"); //$NON-NLS-1$ + for (int i = 0; i < this.uses.length; i++) { + buffer.append("\n\t"); //$NON-NLS-1$ + buffer.append(this.uses[i].debugName()); + } + } else { + buffer.append("\nNo Uses"); //$NON-NLS-1$ + } + if (this.services != null && this.services.length > 0) { + buffer.append("\n/* Services */\n"); //$NON-NLS-1$ + for (int i = 0; i < this.services.length; i++) { + buffer.append("\n\t"); //$NON-NLS-1$ + buffer.append("provides "); //$NON-NLS-1$ + buffer.append(this.services[i].debugName()); + buffer.append(" with "); //$NON-NLS-1$ + if (this.implementations != null && this.implementations.containsKey(this.services[i])) { + String sep = ""; //$NON-NLS-1$ + for (TypeBinding impl : this.implementations.get(this.services[i])) { + buffer.append(sep).append(impl.debugName()); + sep = ", "; //$NON-NLS-1$ + } + } else { + buffer.append(""); //$NON-NLS-1$ + } + } + } else { + buffer.append("\nNo Services"); //$NON-NLS-1$ + } + return buffer.toString(); + } + public boolean isUnnamed() { + return false; + } + public boolean isOpen() { + return (this.modifiers & ClassFileConstants.ACC_OPEN) != 0; + } + public boolean isDeprecated() { + // TODO(SHMOD) implement deprecation for modules + return false; + } + public boolean isTransitivelyRequired(ModuleBinding otherModule) { + if (this.transitiveRequires == null) { + Set transitiveDeps = new HashSet<>(); + collectTransitiveDependencies(transitiveDeps); + this.transitiveRequires = transitiveDeps; + } + return this.transitiveRequires.contains(otherModule); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java index 78325ab451..332324b917 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,7 +14,10 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; +import java.util.ArrayList; + import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage; import org.eclipse.jdt.internal.compiler.util.HashtableOfType; @@ -23,36 +26,53 @@ public class PackageBinding extends Binding implements TypeConstants { public char[][] compoundName; PackageBinding parent; + ArrayList wrappingSplitPackageBindings; public LookupEnvironment environment; - HashtableOfType knownTypes; + /** Types in this map are either uniquely visible in the current module or ProblemReferenceBindings. */ + public HashtableOfType knownTypes; + /** All visible member packages, i.e. observable packages associated with modules read by the current module. */ HashtableOfPackage knownPackages; // code representing the default that has been defined for this package (using @NonNullByDefault) // one of Binding.{NO_NULL_DEFAULT,NULL_UNSPECIFIED_BY_DEFAULT,NONNULL_BY_DEFAULT} protected int defaultNullness = NO_NULL_DEFAULT; + public ModuleBinding enclosingModule; + + /** Is this package exported from its module? NB: to query this property use {@link #isExported()} to ensure initialization. */ + Boolean isExported; + protected PackageBinding() { // for creating problem package } -public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment) { - this(new char[][] {topLevelPackageName}, null, environment); +public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment, ModuleBinding enclosingModule) { + this(new char[][] {topLevelPackageName}, null, environment, enclosingModule); } -/* Create the default package. +/* Create a normal package. */ -public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) { +public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment, ModuleBinding enclosingModule) { this.compoundName = compoundName; this.parent = parent; this.environment = environment; this.knownTypes = null; // initialized if used... class counts can be very large 300-600 this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3 + if (compoundName != CharOperation.NO_CHAR_CHAR) checkIfNullAnnotationPackage(); + + if (enclosingModule != null) + this.enclosingModule = enclosingModule; + else if (parent != null) + this.enclosingModule = parent.enclosingModule; // stop-gap for any remaining calls that don't provide an enclosingModule (they should) + + if (this.enclosingModule == null) + throw new IllegalStateException("Package should have an enclosing module"); //$NON-NLS-1$ } public PackageBinding(LookupEnvironment environment) { - this(CharOperation.NO_CHAR_CHAR, null, environment); + this(CharOperation.NO_CHAR_CHAR, null, environment, environment.module); } -private void addNotFoundPackage(char[] simpleName) { +protected void addNotFoundPackage(char[] simpleName) { this.knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage); } private void addNotFoundType(char[] simpleName) { @@ -60,9 +80,15 @@ private void addNotFoundType(char[] simpleName) { this.knownTypes = new HashtableOfType(25); this.knownTypes.put(simpleName, LookupEnvironment.TheNotFoundType); } -void addPackage(PackageBinding element) { +/** + * Remembers a sub-package. + * For a split parent package this will include enriching with siblings, if checkForSplitSiblings is true + * in which case the enriched (split) binding will be returned. + */ +PackageBinding addPackage(PackageBinding element, ModuleBinding module, boolean checkForSplitSiblings) { if ((element.tagBits & TagBits.HasMissingType) == 0) clearMissingTagBit(); this.knownPackages.put(element.compoundName[element.compoundName.length - 1], element); + return element; } void addType(ReferenceBinding element) { if ((element.tagBits & TagBits.HasMissingType) == 0) clearMissingTagBit(); @@ -76,6 +102,22 @@ void addType(ReferenceBinding element) { if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) if (element.isAnnotationType() || element instanceof UnresolvedReferenceBinding) // unresolved types don't yet have the modifiers set checkIfNullAnnotationType(element); + + if (!element.isUnresolvedType() && this.wrappingSplitPackageBindings != null) { + for (SplitPackageBinding splitPackageBinding : this.wrappingSplitPackageBindings) { + if (splitPackageBinding.knownTypes != null) { + ReferenceBinding prior = splitPackageBinding.knownTypes.get(name); + if (prior != null && prior.isUnresolvedType() && !element.isUnresolvedType()) { + ((UnresolvedReferenceBinding) prior).setResolvedType(element, this.environment); + splitPackageBinding.knownTypes.put(name, null); // forces re-checking for conflicts + } + } + } + } +} + +ModuleBinding[] getDeclaringModules() { + return new ModuleBinding[] { this.enclosingModule }; } void clearMissingTagBit() { @@ -91,21 +133,16 @@ void clearMissingTagBit() { public char[] computeUniqueKey(boolean isLeaf) { return CharOperation.concatWith(this.compoundName, '/'); } -private PackageBinding findPackage(char[] name) { - if (!this.environment.isPackage(this.compoundName, name)) - return null; - - char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name); - PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, this.environment); - addPackage(subPackageBinding); - return subPackageBinding; +protected PackageBinding findPackage(char[] name, ModuleBinding module) { + // delegate to the module to consider the module graph: + return module.getPackage(this.compoundName, name); } /* Answer the subpackage named name; ask the oracle for the package if its not in the cache. * Answer null if it could not be resolved. * * NOTE: This should only be used when we know there is NOT a type with the same name. */ -PackageBinding getPackage(char[] name) { +PackageBinding getPackage(char[] name, ModuleBinding mod) { PackageBinding binding = getPackage0(name); if (binding != null) { if (binding == LookupEnvironment.TheNotFoundPackage) @@ -113,24 +150,32 @@ PackageBinding getPackage(char[] name) { else return binding; } - if ((binding = findPackage(name)) != null) + if ((binding = findPackage(name, mod)) != null) return binding; // not found so remember a problem package binding in the cache for future lookups addNotFoundPackage(name); return null; } -/* Answer the subpackage named name if it exists in the cache. +/** Answer the subpackage named name if it exists in the cache. * Answer theNotFoundPackage if it could not be resolved the first time * it was looked up, otherwise answer null. -* +*

+* NOTE: The returned package binding is guaranteed to be complete wrt. SplitPackageBinding, +* or, if no complete binding is yet available, we shyly answer null. +*

* NOTE: Senders must convert theNotFoundPackage into a real problem -* package if its to returned. +* package if its to returned.

*/ - PackageBinding getPackage0(char[] name) { return this.knownPackages.get(name); } +/** Variant (see {@link #getPackage0(char[])}), that may even answer an incompletely + * combined package (in the case of SplitPackageBinding). + */ +PackageBinding getPackage0Any(char[] name) { + return this.knownPackages.get(name); +} /* Answer the type named name; ask the oracle for the type if its not in the cache. * Answer a NotVisible problem type if the type is not visible from the invocationPackage. * Answer null if it could not be resolved. @@ -139,10 +184,10 @@ PackageBinding getPackage0(char[] name) { * package with the same name. */ -ReferenceBinding getType(char[] name) { +ReferenceBinding getType(char[] name, ModuleBinding mod) { ReferenceBinding referenceBinding = getType0(name); if (referenceBinding == null) { - if ((referenceBinding = this.environment.askForType(this, name)) == null) { + if ((referenceBinding = this.environment.askForType(this, name, mod)) == null) { // not found so remember a problem type binding in the cache for future lookups addNotFoundType(name); return null; @@ -155,6 +200,9 @@ ReferenceBinding getType(char[] name) { referenceBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(referenceBinding, this.environment, false /* no raw conversion for now */); if (referenceBinding.isNestedType()) return new ProblemReferenceBinding(new char[][]{ name }, referenceBinding, ProblemReasons.InternalNameProvided); + if (!mod.canAccess(this)) + return new ProblemReferenceBinding(referenceBinding.compoundName, referenceBinding, ProblemReasons.NotAccessible); + // at this point we have only checked accessibility of the package, accessibility of the type will be checked by callers return referenceBinding; } /* Answer the type named name if it exists in the cache. @@ -180,13 +228,20 @@ ReferenceBinding getType0(char[] name) { * THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES. */ -public Binding getTypeOrPackage(char[] name) { +public Binding getTypeOrPackage(char[] name, ModuleBinding mod) { + ReferenceBinding problemBinding = null; ReferenceBinding referenceBinding = getType0(name); + lookForType0: if (referenceBinding != null && referenceBinding != LookupEnvironment.TheNotFoundType) { referenceBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(referenceBinding, this.environment, false /* no raw conversion for now */); if (referenceBinding.isNestedType()) { return new ProblemReferenceBinding(new char[][]{name}, referenceBinding, ProblemReasons.InternalNameProvided); } + boolean isSameModule = (this instanceof SplitPackageBinding) ? referenceBinding.module() == mod : this.enclosingModule == mod; + if (!isSameModule && referenceBinding.isValidBinding() && !mod.canAccess(referenceBinding.fPackage)) { + problemBinding = new ProblemReferenceBinding(referenceBinding.compoundName, referenceBinding, ProblemReasons.NotAccessible); + break lookForType0; + } if ((referenceBinding.tagBits & TagBits.HasMissingType) == 0) { return referenceBinding; } @@ -197,12 +252,18 @@ public Binding getTypeOrPackage(char[] name) { if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage) { return packageBinding; } - if (referenceBinding == null) { // have not looked for it before - if ((referenceBinding = this.environment.askForType(this, name)) != null) { + lookForType: + if (referenceBinding == null && problemBinding == null) { // have not looked for it before + if ((referenceBinding = this.environment.askForType(this, name, mod)) != null) { if (referenceBinding.isNestedType()) { return new ProblemReferenceBinding(new char[][]{name}, referenceBinding, ProblemReasons.InternalNameProvided); } - return referenceBinding; + if (referenceBinding.isValidBinding() && !mod.canAccess(referenceBinding.fPackage)) { + problemBinding = new ProblemReferenceBinding(referenceBinding.compoundName, referenceBinding, ProblemReasons.NotAccessible); + break lookForType; + } else { + return referenceBinding; + } } // Since name could not be found, add a problem binding @@ -211,22 +272,24 @@ public Binding getTypeOrPackage(char[] name) { } if (packageBinding == null) { // have not looked for it before - if ((packageBinding = findPackage(name)) != null) { + if ((packageBinding = findPackage(name, mod)) != null) { return packageBinding; } if (referenceBinding != null && referenceBinding != LookupEnvironment.TheNotFoundType) { + if (problemBinding != null) + return problemBinding; return referenceBinding; // found cached missing type - check if package conflict } addNotFoundPackage(name); } - return null; + return problemBinding; } public final boolean isViewedAsDeprecated() { if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) { this.tagBits |= TagBits.DeprecatedAnnotationResolved; if (this.compoundName != CharOperation.NO_CHAR_CHAR) { - ReferenceBinding packageInfo = this.getType(TypeConstants.PACKAGE_INFO_NAME); + ReferenceBinding packageInfo = this.getType(TypeConstants.PACKAGE_INFO_NAME, this.enclosingModule); if (packageInfo != null) { packageInfo.initializeDeprecatedAnnotationTagBits(); this.tagBits |= packageInfo.tagBits & TagBits.AllStandardAnnotationsMask; @@ -260,7 +323,6 @@ void checkIfNullAnnotationPackage() { env.nonnullByDefaultAnnotationPackage = this; } } - private boolean isPackageOfQualifiedTypeName(char[][] packageName, char[][] typeName) { int length; if (typeName == null || (length = packageName.length) != typeName.length -1) @@ -309,4 +371,53 @@ public String toString() { } return str; } +public boolean isDeclaredIn(ModuleBinding moduleBinding) { + return this.enclosingModule == moduleBinding; +} +public boolean subsumes(PackageBinding binding) { + return binding == this; +} +/** + * Is this package exported from its module? + * Does not consider export restrictions. + */ +public boolean isExported() { + if (this.isExported == null) { + this.enclosingModule.getExports(); // ensure resolved and completed + if (this.isExported == null) + this.isExported = Boolean.FALSE; + } + return this.isExported == Boolean.TRUE; +} +/** + * If this package is uniquely visible to 'module' return a plain PackageBinding. + * In case of a conflict between a local package and foreign package + * the plain local package is returned, because this conflict will more + * appropriately be reported against the package declaration, not its references. + * In case of multiple accessible foreign packages a SplitPackageBinding is returned + * to indicate a conflict. + */ +public PackageBinding getVisibleFor(ModuleBinding module) { + return this; +} +public boolean hasCompilationUnit(boolean checkCUs) { + if (this.knownTypes != null) { + for (ReferenceBinding knownType : this.knownTypes.valueTable) { + if (knownType != null && knownType != LookupEnvironment.TheNotFoundType) + return true; + } + } + if (this.environment.useModuleSystem) { + IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment; + return moduleEnv.hasCompilationUnit(this.compoundName, this.enclosingModule.nameForLookup(), checkCUs); + } + return false; +} + +public void addWrappingSplitPackageBinding(SplitPackageBinding splitPackageBinding) { + if (this.wrappingSplitPackageBindings == null) { + this.wrappingSplitPackageBindings = new ArrayList<>(); + } + this.wrappingSplitPackageBindings.add(splitPackageBinding); +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java index c266a8eed3..81600aca59 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for @@ -102,7 +102,7 @@ public TypeBinding substitute(TypeVariableBinding typeVariable) { } switch (substitutedSuperclass.kind()) { case Binding.ARRAY_TYPE : - substitutedVariable.setSuperClass(parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null)); + substitutedVariable.setSuperClass(parameterizedDeclaringClass.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null)); substitutedVariable.setSuperInterfaces(substitutedInterfaces); break; default: @@ -240,7 +240,7 @@ public TypeBinding substitute(TypeVariableBinding typeVariable) { } switch (substitutedSuperclass.kind()) { case Binding.ARRAY_TYPE : - substitutedVariable.setSuperClass(environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null)); + substitutedVariable.setSuperClass(environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null)); substitutedVariable.setSuperInterfaces(substitutedInterfaces); break; default: diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java index 1a04f46fd3..82438670c0 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java @@ -115,6 +115,7 @@ public void boundCheck(Scope scope, TypeReference[] argumentReferences) { boolean hasErrors = false; TypeVariableBinding[] typeVariables = this.type.typeVariables(); if (this.arguments != null && typeVariables != null) { // arguments may be null in error cases + // per JLS 4.5 we should capture 'this' for (int i = 0, length = typeVariables.length; i < length; i++) { BoundCheckStatus checkStatus = typeVariables[i].boundCheck(this, this.arguments[i], scope, argumentReferences[i]); hasErrors |= checkStatus != BoundCheckStatus.OK; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyParameterizedGenericMethodBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyParameterizedGenericMethodBinding.java index 29ed92bdc3..6e9e41596c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyParameterizedGenericMethodBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyParameterizedGenericMethodBinding.java @@ -1,33 +1,33 @@ -/******************************************************************************* - * Copyright (c) 2014, 2015 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.compiler.lookup; - -public class PolyParameterizedGenericMethodBinding extends ParameterizedGenericMethodBinding { // confused citizen. - - private ParameterizedGenericMethodBinding wrappedBinding; - public PolyParameterizedGenericMethodBinding(ParameterizedGenericMethodBinding applicableMethod) { - super(applicableMethod.originalMethod, applicableMethod.typeArguments, applicableMethod.environment, false, false); - this.wrappedBinding = applicableMethod; - } - - public boolean equals(Object other) { - if (other instanceof PolyParameterizedGenericMethodBinding) { - PolyParameterizedGenericMethodBinding ppgmb = (PolyParameterizedGenericMethodBinding)other; - return this.wrappedBinding.equals(ppgmb.wrappedBinding); - } - return false; - } - - @Override - public int hashCode() { - return this.wrappedBinding.hashCode(); - } -} +/******************************************************************************* + * Copyright (c) 2014, 2015 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.lookup; + +public class PolyParameterizedGenericMethodBinding extends ParameterizedGenericMethodBinding { // confused citizen. + + private ParameterizedGenericMethodBinding wrappedBinding; + public PolyParameterizedGenericMethodBinding(ParameterizedGenericMethodBinding applicableMethod) { + super(applicableMethod.originalMethod, applicableMethod.typeArguments, applicableMethod.environment, applicableMethod.inferredWithUncheckedConversion, false); + this.wrappedBinding = applicableMethod; + } + + public boolean equals(Object other) { + if (other instanceof PolyParameterizedGenericMethodBinding) { + PolyParameterizedGenericMethodBinding ppgmb = (PolyParameterizedGenericMethodBinding)other; + return this.wrappedBinding.equals(ppgmb.wrappedBinding); + } + return false; + } + + @Override + public int hashCode() { + return this.wrappedBinding.hashCode(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java index b8116a0899..20d949c286 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -47,4 +47,5 @@ public interface ProblemReasons { final int InferredApplicableMethodInapplicable = 27; // 18.5.1 ignores arguments not pertinent to applicability. When these are taken into consideration method could fail applicability final int NoProperEnclosingInstance = 28; final int InterfaceMethodInvocationNotBelow18 = 29; + final int NotAccessible = 30; // JLS 6.6.1 - module aspects } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java index cae1204293..e62bfd0f10 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java @@ -1612,8 +1612,13 @@ public final boolean isUsed() { * Answer true if the receiver is deprecated (or any of its enclosing types) */ public final boolean isViewedAsDeprecated() { - return (this.modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0 - || getPackage().isViewedAsDeprecated(); + if ((this.modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0) + return true; + if (getPackage().isViewedAsDeprecated()) { + this.tagBits |= (getPackage().tagBits & TagBits.AnnotationTerminallyDeprecated); + return true; + } + return false; } public ReferenceBinding[] memberTypes() { @@ -1981,7 +1986,7 @@ protected int applyCloseableInterfaceWhitelists() { LookupEnvironment environment = scope.environment(); for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++) { final MethodBinding method = methods[i]; - if (method == null || method.isStatic() || method.redeclaresPublicObjectMethod(scope)) + if (method == null || method.isStatic() || method.redeclaresPublicObjectMethod(scope) || method.isPrivate()) continue; if (!method.isValidBinding()) throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$ @@ -2204,6 +2209,11 @@ else if (current.isSubtypeOf(mostSpecific)) } return true; } +public ModuleBinding module() { + if (this.fPackage != null) + return this.fPackage.enclosingModule; + return null; +} // GROOVY add //more thought required - is this in the right place? public MethodBinding[] getAnyExtraMethods(char[] selector, TypeBinding[] argumentTypes) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java index 52e0d3e235..2134088bdd 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -344,6 +344,9 @@ public static ReferenceBinding[] greaterLowerBound(ReferenceBinding[] types) { if (i == j) continue; ReferenceBinding jType = result[j]; if (jType == null) continue; + if (isMalformedPair(iType, jType, null)) { + return null; + } if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed if (result == types) { // defensive copy System.arraycopy(result, 0, result = new ReferenceBinding[length], 0, length); @@ -379,6 +382,9 @@ public static TypeBinding[] greaterLowerBound(TypeBinding[] types, /*@Nullable*/ if (i == j) continue; TypeBinding jType = result[j]; if (jType == null) continue; + if (isMalformedPair(iType, jType, scope)) { + return null; + } if (iType.isCompatibleWith(jType, scope)) { // if Vi <: Vj, Vj is removed if (result == types) { // defensive copy System.arraycopy(result, 0, result = new TypeBinding[length], 0, length); @@ -439,6 +445,24 @@ public static TypeBinding[] greaterLowerBound(TypeBinding[] types, /*@Nullable*/ return trimmedResult; } + static boolean isMalformedPair(TypeBinding t1, TypeBinding t2, Scope scope) { + // not spec-ed in JLS, but per email communication (2017-09-13) it should be + switch (t1.kind()) { + case Binding.TYPE: + case Binding.GENERIC_TYPE: + case Binding.PARAMETERIZED_TYPE: + case Binding.RAW_TYPE: + if (t1.isClass()) { + if (t2.getClass() == TypeVariableBinding.class) { + TypeBinding bound = ((TypeVariableBinding) t2).firstBound; + if (bound == null || !bound.erasure().isCompatibleWith(t1.erasure())) { // use of erasure is heuristic-based + return true; // malformed, because substitution could create a contradiction. + } + } + } + } + return false; + } /** * Returns an array of types, where original types got substituted given a substitution. * Only allocate an array if anything is different. @@ -692,7 +716,9 @@ public final CompilationUnitScope compilationUnitScope() { } while (scope != null); return (CompilationUnitScope) lastScope; } - + public final ModuleBinding module() { + return environment().module; + } public boolean isLambdaScope() { return false; } @@ -1234,19 +1260,6 @@ public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding e if (memberType.canBeSeenBy(getCurrentPackage())) { return memberType; } - // maybe some type in the compilation unit is extending some class in some package - // and the selection is for some protected inner class of that superclass - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=235658 - if (this instanceof CompilationUnitScope) { - TypeDeclaration[] types = ((CompilationUnitScope)this).referenceContext.types; - if (types != null) { - for (int i = 0, max = types.length; i < max; i++) { - if (memberType.canBeSeenBy(enclosingType, types[i].binding)) { - return memberType; - } - } - } - } } else if (memberType.canBeSeenBy(enclosingType, enclosingReceiverType)) { return memberType; } @@ -1812,7 +1825,7 @@ public MethodBinding findMethod0(ReferenceBinding receiverType, char[] selector, if (interfaceMethod != null) return interfaceMethod; MethodBinding candidate = candidates[0]; int reason = ProblemReasons.NotVisible; - if (candidate.isStatic() && candidate.declaringClass.isInterface()) { + if (candidate.isStatic() && candidate.declaringClass.isInterface() && !candidate.isPrivate()) { if (soureLevel18) reason = ProblemReasons.NonStaticOrAlienTypeReceiver; else @@ -1968,7 +1981,7 @@ public ReferenceBinding findType( PackageBinding invocationPackage) { compilationUnitScope().recordReference(declarationPackage.compoundName, typeName); - ReferenceBinding typeBinding = declarationPackage.getType(typeName); + ReferenceBinding typeBinding = declarationPackage.getType(typeName, module()); if (typeBinding == null) return null; @@ -2767,90 +2780,90 @@ public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTy public final ReferenceBinding getJavaIoSerializable() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_IO_SERIALIZABLE); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_IO_SERIALIZABLE, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_IO_SERIALIZABLE, this); } public final ReferenceBinding getJavaLangAnnotationAnnotation() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION, this); } public final ReferenceBinding getJavaLangAssertionError() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ASSERTIONERROR); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ASSERTIONERROR, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ASSERTIONERROR, this); } public final ReferenceBinding getJavaLangClass() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLASS); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_CLASS, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_CLASS, this); } public final ReferenceBinding getJavaLangCloneable() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLONEABLE); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_CLONEABLE, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_CLONEABLE, this); } public final ReferenceBinding getJavaLangEnum() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ENUM); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ENUM, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ENUM, this); } public final ReferenceBinding getJavaLangInvokeLambdaMetafactory() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY, this); } public final ReferenceBinding getJavaLangInvokeSerializedLambda() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_INVOKE_SERIALIZEDLAMBDA); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_INVOKE_SERIALIZEDLAMBDA, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_INVOKE_SERIALIZEDLAMBDA, this); } public final ReferenceBinding getJavaLangInvokeMethodHandlesLookup() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_INVOKE_METHODHANDLES); - ReferenceBinding outerType = unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_INVOKE_METHODHANDLES, this); + ReferenceBinding outerType = unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_INVOKE_METHODHANDLES, this); return findDirectMemberType("Lookup".toCharArray(), outerType); //$NON-NLS-1$ } public final ReferenceBinding getJavaLangIterable() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ITERABLE); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ITERABLE, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ITERABLE, this); } public final ReferenceBinding getJavaLangObject() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_OBJECT); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, this); } public final ReferenceBinding getJavaLangString() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_STRING); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_STRING, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_STRING, this); } public final ReferenceBinding getJavaLangThrowable() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_THROWABLE); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_THROWABLE, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_THROWABLE, this); } public final ReferenceBinding getJavaLangIllegalArgumentException() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ILLEGALARGUMENTEXCEPTION); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ILLEGALARGUMENTEXCEPTION, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ILLEGALARGUMENTEXCEPTION, this); } public final ReferenceBinding getJavaUtilIterator() { CompilationUnitScope unitScope = compilationUnitScope(); unitScope.recordQualifiedReference(TypeConstants.JAVA_UTIL_ITERATOR); - return unitScope.environment.getResolvedType(TypeConstants.JAVA_UTIL_ITERATOR, this); + return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_UTIL_ITERATOR, this); } /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType. @@ -2937,11 +2950,11 @@ public final Binding getPackage(char[][] compoundName) { int currentIndex = 1, length = compoundName.length; PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < length) { - binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); + binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module()); if (binding == null) { return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } - if (!binding.isValidBinding()) + if (!binding.isValidBinding() && binding.problemId() != ProblemReasons.Ambiguous) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null, @@ -2972,7 +2985,7 @@ public final Binding getOnlyPackage(char[][] compoundName) { int currentIndex = 1, length = compoundName.length; PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < length) { - binding = packageBinding.getPackage(compoundName[currentIndex++]); + binding = packageBinding.getPackage(compoundName[currentIndex++], module()); if (binding == null) { return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } @@ -3008,7 +3021,7 @@ public final TypeBinding getType(char[] name, PackageBinding packageBinding) { if (packageBinding == null) return getType(name); - Binding binding = packageBinding.getTypeOrPackage(name); + Binding binding = packageBinding.getTypeOrPackage(name, module()); if (binding == null) { return new ProblemReferenceBinding( CharOperation.arrayConcat(packageBinding.compoundName, name), @@ -3064,7 +3077,7 @@ public final TypeBinding getType(char[][] compoundName, int typeNameLength) { if (binding instanceof PackageBinding) { PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < typeNameLength) { - binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility + binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module()); // does not check visibility if (binding == null) { char[][] qName = CharOperation.subarray(compoundName, 0, currentIndex); return new ProblemReferenceBinding( @@ -3288,7 +3301,7 @@ final Binding getTypeOrPackage(char[] name, int mask, boolean needResolve) { // check if the name is in the current package, skip it if its a sub-package PackageBinding currentPackage = unitScope.fPackage; unitScope.recordReference(currentPackage.compoundName, name); - Binding binding = currentPackage.getTypeOrPackage(name); + Binding binding = currentPackage.getTypeOrPackage(name, module()); if (binding instanceof ReferenceBinding) { ReferenceBinding referenceType = (ReferenceBinding) binding; if ((referenceType.tagBits & TagBits.HasMissingType) == 0) { @@ -3310,11 +3323,12 @@ final Binding getTypeOrPackage(char[] name, int mask, boolean needResolve) { if (resolvedImport instanceof PackageBinding) { temp = findType(name, (PackageBinding) resolvedImport, currentPackage); } else if (someImport.isStatic()) { - temp = findMemberType(name, (ReferenceBinding) resolvedImport); // static imports are allowed to see inherited member types + // Imports are always resolved in the CU Scope (bug 520874) + temp = compilationUnitScope().findMemberType(name, (ReferenceBinding) resolvedImport); // static imports are allowed to see inherited member types if (temp != null && !temp.isStatic()) temp = null; } else { - temp = findDirectMemberType(name, (ReferenceBinding) resolvedImport); + temp = compilationUnitScope().findDirectMemberType(name, (ReferenceBinding) resolvedImport); } if (TypeBinding.notEquals(temp, type) && temp != null) { if (temp.isValidBinding()) { @@ -3432,7 +3446,7 @@ public final Binding getTypeOrPackage(char[][] compoundName) { PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < nameLength) { - binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); + binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module()); if (binding == null) return new ProblemReferenceBinding( CharOperation.subarray(compoundName, 0, currentIndex), @@ -4990,8 +5004,10 @@ public MethodBinding getStaticFactory (ParameterizedTypeBinding allocationType, break; currentType = currentType.enclosingType(); } + boolean isInterface = allocationType.isInterface(); + ReferenceBinding typeToSearch = isInterface ? getJavaLangObject() : allocationType; - MethodBinding[] methods = allocationType.getMethods(TypeConstants.INIT, argumentTypes.length); + MethodBinding[] methods = typeToSearch.getMethods(TypeConstants.INIT, argumentTypes.length); MethodBinding [] staticFactories = new MethodBinding[methods.length]; int sfi = 0; for (int i = 0, length = methods.length; i < length; i++) { @@ -5009,8 +5025,8 @@ public MethodBinding getStaticFactory (ParameterizedTypeBinding allocationType, int methodTypeVariablesArity = methodTypeVariables.length; final int factoryArity = classTypeVariablesArity + methodTypeVariablesArity; final LookupEnvironment environment = environment(); - - MethodBinding staticFactory = new SyntheticFactoryMethodBinding(method.original(), environment, originalEnclosingType); + MethodBinding targetMethod = isInterface ? new MethodBinding(method.original(), genericType) : method.original(); + MethodBinding staticFactory = new SyntheticFactoryMethodBinding(targetMethod, environment, originalEnclosingType); staticFactory.typeVariables = new TypeVariableBinding[factoryArity]; final SimpleLookupTable map = new SimpleLookupTable(factoryArity); @@ -5065,12 +5081,12 @@ public TypeBinding substitute(TypeVariableBinding typeVariable) { } switch (substitutedSuperclass.kind()) { case Binding.ARRAY_TYPE : - substitutedVariable.setSuperClass(environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null)); + substitutedVariable.setSuperClass(environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null)); substitutedVariable.setSuperInterfaces(substitutedInterfaces); break; default: if (substitutedSuperclass.isInterface()) { - substitutedVariable.setSuperClass(environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null)); + substitutedVariable.setSuperClass(environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null)); int interfaceCount = substitutedInterfaces.length; System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount); substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass; @@ -5087,7 +5103,7 @@ public TypeBinding substitute(TypeVariableBinding typeVariable) { if (staticFactory.thrownExceptions == null) { staticFactory.thrownExceptions = Binding.NO_EXCEPTIONS; } - staticFactories[sfi++] = new ParameterizedMethodBinding((ParameterizedTypeBinding) environment.convertToParameterizedType(staticFactory.declaringClass), + staticFactories[sfi++] = new ParameterizedMethodBinding((ParameterizedTypeBinding) environment.convertToParameterizedType(isInterface ? allocationType : staticFactory.declaringClass), staticFactory); } if (sfi == 0) diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java new file mode 100644 index 0000000000..6074fe80dd --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.lookup; + +import java.util.Collection; +import java.util.HashMap; +import java.util.function.IntFunction; +import java.util.stream.Stream; + +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; + +public class SourceModuleBinding extends ModuleBinding { + + final public CompilationUnitScope scope; // TODO(SHMOD): consider cleanup at end of compile + private SimpleLookupTable storedAnnotations = null; + + /** + * Construct a named module from source. + *

Side effects: adds the new module to root.knownModules, + * creates a new LookupEnvironment and links that into the scope.

+ */ + public SourceModuleBinding(char[] moduleName, CompilationUnitScope scope, LookupEnvironment rootEnv) { + super(moduleName); + rootEnv.knownModules.put(moduleName, this); + this.environment = new LookupEnvironment(rootEnv, this); + this.scope = scope; + scope.environment = this.environment; + } + + public void setRequires(ModuleBinding[] requires, ModuleBinding[] requiresTransitive) { + // TODO(SHMOD): it's a bit awkward that we may get called after applyModuleUpdates() has already worked. + ModuleBinding javaBase = this.environment.javaBaseModule(); + if (javaBase.isUnnamed()) // happens when no java.base can be found in the name environment. + javaBase = null; + this.requires = merge(this.requires, requires, javaBase, ModuleBinding[]::new); + this.requiresTransitive = merge(this.requiresTransitive, requiresTransitive, null, ModuleBinding[]::new); + } + + public void setUses(TypeBinding[] uses) { + this.uses = merge(this.uses, uses, null, TypeBinding[]::new); + } + + public void setServices(TypeBinding[] services) { + this.services = merge(this.services, services, null, TypeBinding[]::new); + } + + public void setImplementations(TypeBinding infBinding, Collection resolvedImplementations) { + if (this.implementations == null) + this.implementations = new HashMap<>(); + this.implementations.put(infBinding, resolvedImplementations.toArray(new TypeBinding[resolvedImplementations.size()])); + } + + private T[] merge(T[] one, T[] two, T extra, IntFunction supplier) { + if (one.length == 0 && extra == null) { + if (two.length > 0) + return two; + return one; + } + int len0 = extra == null ? 0 : 1; + int len1 = one.length; + int len2 = two.length; + T[] result = supplier.apply(len0+len1+len2); + if (extra != null) + result[0] = extra; + System.arraycopy(one, 0, result, len0, len1); + System.arraycopy(two, 0, result, len0+len1, len2); + return result; + } + + @Override + Stream getRequiredModules(boolean transitiveOnly) { + if (this.requires == NO_MODULES) { + this.scope.referenceContext.moduleDeclaration.resolveModuleDirectives(this.scope); + } + return super.getRequiredModules(transitiveOnly); + } + + @Override + public ModuleBinding[] getAllRequiredModules() { + if (this.scope != null) + this.scope.referenceContext.moduleDeclaration.resolveModuleDirectives(this.scope); + return super.getAllRequiredModules(); + } + public long getAnnotationTagBits() { + //TODO: This code is untested as we don't yet get a scope in ModuleBinding + if ((this.tagBits & TagBits.AnnotationResolved) == 0 && this.scope != null) { + ModuleDeclaration module = this.scope.referenceContext.moduleDeclaration; + ASTNode.resolveAnnotations(module.scope, module.annotations, this); + if ((this.tagBits & TagBits.AnnotationDeprecated) != 0) { + this.modifiers |= ClassFileConstants.AccDeprecated; + this.tagBits |= TagBits.DeprecatedAnnotationResolved; + } + this.tagBits |= TagBits.AnnotationResolved; + } + return this.tagBits; + } + public AnnotationBinding[] getAnnotations() { + return retrieveAnnotations(this); + } + public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) { + SimpleLookupTable store = storedAnnotations(forceInitialization); + return store == null ? null : (AnnotationHolder) store.get(binding); + } + + AnnotationBinding[] retrieveAnnotations(Binding binding) { + AnnotationHolder holder = retrieveAnnotationHolder(binding, true); + return holder == null ? Binding.NO_ANNOTATIONS : holder.getAnnotations(); + } + + public void setAnnotations(AnnotationBinding[] annotations) { + storeAnnotations(this, annotations); + } + void storeAnnotationHolder(Binding binding, AnnotationHolder holder) { + if (holder == null) { + SimpleLookupTable store = storedAnnotations(false); + if (store != null) + store.removeKey(binding); + } else { + SimpleLookupTable store = storedAnnotations(true); + if (store != null) + store.put(binding, holder); + } + } + + void storeAnnotations(Binding binding, AnnotationBinding[] annotations) { + AnnotationHolder holder = null; + if (annotations == null || annotations.length == 0) { + SimpleLookupTable store = storedAnnotations(false); + if (store != null) + holder = (AnnotationHolder) store.get(binding); + if (holder == null) return; // nothing to delete + } else { + SimpleLookupTable store = storedAnnotations(true); + if (store == null) return; // not supported + holder = (AnnotationHolder) store.get(binding); + if (holder == null) + holder = new AnnotationHolder(); + } + storeAnnotationHolder(binding, holder.setAnnotations(annotations)); + } + + SimpleLookupTable storedAnnotations(boolean forceInitialize) { + if (forceInitialize && this.storedAnnotations == null && this.scope != null) { // scope null when no annotation cached, and type got processed fully (159631) + this.scope.referenceCompilationUnit().compilationResult.hasAnnotations = true; + final CompilerOptions globalOptions = this.scope.environment().globalOptions; + if (!globalOptions.storeAnnotations) + return null; // not supported during this compile + this.storedAnnotations = new SimpleLookupTable(3); + } + return this.storedAnnotations; + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java index 3d4cced82f..21f4ae77c1 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java @@ -88,7 +88,7 @@ public class SourceTypeBinding extends ReferenceBinding { public ClassScope scope; protected SourceTypeBinding prototype; LookupEnvironment environment; - + public ModuleBinding module; // Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods // if a new category is added, also increment MAX_SYNTHETICS private final static int METHOD_EMUL = 0; @@ -884,8 +884,10 @@ private void checkAnnotationsInType() { // check @Deprecated annotation getAnnotationTagBits(); // marks as deprecated by side effect ReferenceBinding enclosingType = enclosingType(); - if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !isDeprecated()) + if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !isDeprecated()) { this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; + this.tagBits |= (enclosingType.tagBits & TagBits.AnnotationTerminallyDeprecated); + } for (int i = 0, length = this.memberTypes.length; i < length; i++) ((SourceTypeBinding) this.memberTypes[i]).checkAnnotationsInType(); @@ -1462,7 +1464,13 @@ public boolean isRepeatableAnnotationType() { public boolean isTaggedRepeatable() { // tagged but not necessarily repeatable. see isRepeatableAnnotationType. return (this.tagBits & TagBits.AnnotationRepeatable) != 0; } - +public boolean canBeSeenBy(Scope sco) { + SourceTypeBinding invocationType = sco.enclosingSourceType(); + if (TypeBinding.equalsEquals(invocationType, this)) + return true; + return ((this.environment.canTypeBeAccessed(this, sco)) && + super.canBeSeenBy(sco)); +} public ReferenceBinding[] memberTypes() { if (!isPrototype()) { if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0) @@ -1741,8 +1749,10 @@ public FieldBinding resolveTypeFor(FieldBinding field) { if ((field.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0) field.modifiers |= ClassFileConstants.AccDeprecated; } - if (isViewedAsDeprecated() && !field.isDeprecated()) + if (isViewedAsDeprecated() && !field.isDeprecated()) { field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; + field.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated; + } if (hasRestrictedAccess()) field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; FieldDeclaration[] fieldDecls = this.scope.referenceContext.fields; @@ -1801,7 +1811,7 @@ public FieldBinding resolveTypeFor(FieldBinding field) { // enum constants neither have a type declaration nor can they be null field.tagBits |= TagBits.AnnotationNonNull; } else { - if (hasNonNullDefaultFor(DefaultLocationField, this.environment.usesNullTypeAnnotations(), fieldDecl.sourceStart)) { + if (hasNonNullDefaultFor(DefaultLocationField, this.environment.usesNullTypeAnnotations(), fieldDecl.sourceStart)) { field.fillInDefaultNonNullness(fieldDecl, initializationScope); } // validate null annotation: @@ -1809,6 +1819,8 @@ public FieldBinding resolveTypeFor(FieldBinding field) { field.tagBits &= ~TagBits.AnnotationNullMASK; } } + if (initializationScope.shouldCheckAPILeaks(this, field.isPublic()) && fieldDecl.type != null) // fieldDecl.type is null for enum constants + initializationScope.detectAPILeaks(fieldDecl.type, fieldType); } finally { initializationScope.initializedField = previousField; } @@ -1847,8 +1859,10 @@ private MethodBinding resolveTypesWithSuspendedTempErrorHandlingPolicy(MethodBin if ((method.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0) method.modifiers |= ClassFileConstants.AccDeprecated; } - if (isViewedAsDeprecated() && !method.isDeprecated()) + if (isViewedAsDeprecated() && !method.isDeprecated()) { method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; + method.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated; + } if (hasRestrictedAccess()) method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; @@ -1920,6 +1934,7 @@ private MethodBinding resolveTypesWithSuspendedTempErrorHandlingPolicy(MethodBin } final boolean reportUnavoidableGenericTypeProblems = this.scope.compilerOptions().reportUnavoidableGenericTypeProblems; boolean foundArgProblem = false; + boolean checkAPIleak = methodDecl.scope.shouldCheckAPILeaks(this, method.isPublic()); Argument[] arguments = methodDecl.arguments; if (arguments != null) { int size = arguments.length; @@ -1957,6 +1972,8 @@ private MethodBinding resolveTypesWithSuspendedTempErrorHandlingPolicy(MethodBin if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) method.modifiers |= ExtraCompilerModifiers.AccGenericSignature; newParameters[i] = parameterType; + if (checkAPIleak) + methodDecl.scope.detectAPILeaks(arg.type, parameterType); arg.binding = new LocalVariableBinding(arg, parameterType, arg.modifiers, methodDecl.scope); } } @@ -1971,7 +1988,8 @@ private MethodBinding resolveTypesWithSuspendedTempErrorHandlingPolicy(MethodBin if ((method.tagBits & TagBits.AnnotationSafeVarargs) != 0) { if (!method.isVarargs()) { methodDecl.scope.problemReporter().safeVarargsOnFixedArityMethod(method); - } else if (!method.isStatic() && !method.isFinal() && !method.isConstructor()) { + } else if (!method.isStatic() && !method.isFinal() && !method.isConstructor() + && !(sourceLevel >= ClassFileConstants.JDK9 && method.isPrivate())) { methodDecl.scope.problemReporter().safeVarargsOnNonFinalInstanceMethod(method); } } else if (method.parameters != null && method.parameters.length > 0 && method.isVarargs()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=337795 @@ -2023,6 +2041,8 @@ private MethodBinding resolveTypesWithSuspendedTempErrorHandlingPolicy(MethodBin method.modifiers |= ExtraCompilerModifiers.AccGenericSignature; else if (leafType == TypeBinding.VOID && methodDecl.annotations != null) rejectTypeAnnotatedVoidMethod(methodDecl); + if (checkAPIleak) + methodDecl.scope.detectAPILeaks(returnType, methodType); } } } else { @@ -2128,7 +2148,7 @@ public void evaluateNullAnnotations() { if (!isPackageInfo) { boolean isInNullnessAnnotationPackage = this.scope.environment().isNullnessAnnotationPackage(pkg); if (pkg.defaultNullness == NO_NULL_DEFAULT && !isInDefaultPkg && !isInNullnessAnnotationPackage && !(this instanceof NestedTypeBinding)) { - ReferenceBinding packageInfo = pkg.getType(TypeConstants.PACKAGE_INFO_NAME); + ReferenceBinding packageInfo = pkg.getType(TypeConstants.PACKAGE_INFO_NAME, this.module); if (packageInfo == null) { // no pkgInfo - complain this.scope.problemReporter().missingNonNullByDefaultAnnotation(this.scope.referenceContext); @@ -2206,9 +2226,9 @@ public void evaluateNullAnnotations() { } private void maybeMarkTypeParametersNonNull() { - if (this.typeVariables != null && this.typeVariables.length > 0) { + if (this.typeVariables != null && this.typeVariables.length > 0) { // when creating type variables we didn't yet have the defaultNullness, fill it in now: - if (this.scope == null || !this.scope.hasDefaultNullnessFor(DefaultLocationTypeParameter, this.sourceStart())) + if (this.scope == null || !this.scope.hasDefaultNullnessFor(DefaultLocationTypeParameter, this.sourceStart())) return; AnnotationBinding[] annots = new AnnotationBinding[]{ this.environment.getNonNullAnnotation() }; for (int i = 0; i < this.typeVariables.length; i++) { @@ -2262,8 +2282,8 @@ protected boolean checkRedundantNullnessDefaultOne(ASTNode location, Annotation[ return true; } -@Override -boolean hasNonNullDefaultFor(int location, boolean useTypeAnnotations, int sourceStart) { +@Override +boolean hasNonNullDefaultFor(int location, boolean useTypeAnnotations, int sourceStart) { if (!isPrototype()) throw new IllegalStateException(); @@ -2275,7 +2295,7 @@ boolean hasNonNullDefaultFor(int location, boolean useTypeAnnotations, int sourc Scope skope = this.scope.referenceContext.initializerScope; // for @NNBD on a field if (skope == null) skope = this.scope; - return skope.hasDefaultNullnessFor(location, sourceStart); + return skope.hasDefaultNullnessFor(location, sourceStart); } // find the applicable default inside->out: @@ -2686,4 +2706,9 @@ public void tagIndirectlyAccessibleMembers() { if (this.superclass instanceof SourceTypeBinding) // should always be true because private super type can only be accessed in same CU ((SourceTypeBinding) this.superclass).tagIndirectlyAccessibleMembers(); } +public ModuleBinding module() { + if (!isPrototype()) + return this.prototype.module; + return this.module; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java new file mode 100644 index 0000000000..a38169db59 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java @@ -0,0 +1,293 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.lookup; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.jdt.core.compiler.CharOperation; + +public class SplitPackageBinding extends PackageBinding { + Set declaringModules; + public Set incarnations; + + /** + * Combine two potential package bindings, answering either the better of those if the other has a problem, + * or combine both into a split package. + * @param binding one candidate + * @param previous a previous candidate + * @param primaryModule when constructing a new SplitPackageBinding this primary module will define the + * focus when later an UnresolvedReferenceBinding is resolved relative to this SplitPackageBinding. + * @return one of: null, a regular PackageBinding or a SplitPackageBinding. + */ + public static PackageBinding combine(PackageBinding binding, PackageBinding previous, ModuleBinding primaryModule) { + // if a candidate has problems, pick the "better" candidate: + int prevRank = rank(previous); + int curRank = rank(binding); + if (prevRank < curRank) + return binding; + if (prevRank > curRank) + return previous; + if (previous == null) + return null; + // both are valid + if (previous.subsumes(binding)) + return previous; + if (binding.subsumes(previous)) + return binding; + SplitPackageBinding split = new SplitPackageBinding(previous, primaryModule); + split.add(binding); + return split; + } + private static int rank(PackageBinding candidate) { + if (candidate == null) + return 0; + if (candidate == LookupEnvironment.TheNotFoundPackage) + return 1; + if (!candidate.isValidBinding()) + return 2; + return 3; + } + + public SplitPackageBinding(PackageBinding initialBinding, ModuleBinding primaryModule) { + super(initialBinding.compoundName, initialBinding.parent, primaryModule.environment, primaryModule); + this.declaringModules = new HashSet<>(); + this.incarnations = new HashSet<>(); + add(initialBinding); + } + public void add(PackageBinding packageBinding) { + if (packageBinding instanceof SplitPackageBinding) { + SplitPackageBinding split = (SplitPackageBinding) packageBinding; + this.declaringModules.addAll(split.declaringModules); + for(PackageBinding incarnation: split.incarnations) { + if(this.incarnations.add(incarnation)) { + incarnation.addWrappingSplitPackageBinding(this); + } + } + } else { + this.declaringModules.add(packageBinding.enclosingModule); + if(this.incarnations.add(packageBinding)) { + packageBinding.addWrappingSplitPackageBinding(this); + } + } + } + PackageBinding addPackage(PackageBinding element, ModuleBinding module) { + return addPackage(element, module, true); + } + @Override + PackageBinding addPackage(PackageBinding element, ModuleBinding module, boolean enrichWithSplitSiblings) { + char[] simpleName = element.compoundName[element.compoundName.length-1]; + // enrich + if (enrichWithSplitSiblings) + element = combineWithSiblings(element, simpleName, module); + + PackageBinding visible = this.knownPackages.get(simpleName); + visible = SplitPackageBinding.combine(element, visible, this.enclosingModule); + this.knownPackages.put(simpleName, visible); + PackageBinding incarnation = getIncarnation(element.enclosingModule); + if (incarnation != null) + incarnation.addPackage(element, module, enrichWithSplitSiblings); + return element; + } + + PackageBinding combineWithSiblings(PackageBinding childPackage, char[] name, ModuleBinding module) { + ModuleBinding primaryModule = childPackage != null ? childPackage.enclosingModule : this.enclosingModule; + // see if other incarnations contribute to the child package, too: + for (PackageBinding incarnation : this.incarnations) { + ModuleBinding moduleBinding = incarnation.enclosingModule; + if (moduleBinding == module) + continue; + PackageBinding next = moduleBinding.getVisiblePackage(incarnation, name); // TODO(SHMOD): reduce split-package work during this invocation? + childPackage = combine(next, childPackage, primaryModule); + } + return childPackage; + } + + @Override + ModuleBinding[] getDeclaringModules() { + return this.declaringModules.toArray(new ModuleBinding[this.declaringModules.size()]); + } + + @Override + PackageBinding getPackage0(char[] name) { + PackageBinding knownPackage = super.getPackage0(name); + if (knownPackage != null) + return knownPackage; + + PackageBinding candidate = null; + for (PackageBinding incarnation : this.incarnations) { + PackageBinding package0 = incarnation.getPackage0(name); + if (package0 == null) + return null; // if any incarnation lacks cached info, a full findPackage will be necessary + candidate = combine(package0, candidate, this.enclosingModule); + } + if (candidate != null) + this.knownPackages.put(name, candidate); + + return candidate; + } + + @Override + PackageBinding getPackage0Any(char[] name) { + PackageBinding knownPackage = super.getPackage0(name); + if (knownPackage != null) + return knownPackage; + + PackageBinding candidate = null; + for (PackageBinding incarnation : this.incarnations) { + PackageBinding package0 = incarnation.getPackage0(name); + if (package0 == null) + continue; + candidate = combine(package0, candidate, this.enclosingModule); + } + // don't cache the result, maybe incomplete + return candidate; + } + + @Override + protected PackageBinding findPackage(char[] name, ModuleBinding module) { + Set candidates = new HashSet<>(); + for (ModuleBinding candidateModule : this.declaringModules) { + PackageBinding candidate = super.findPackage(name, candidateModule); + if (candidate != null + && candidate != LookupEnvironment.TheNotFoundPackage + && ((candidate.tagBits & TagBits.HasMissingType) == 0)) + { + candidates.add(candidate); + } + } + int count = candidates.size(); + PackageBinding result = null; + if (count == 1) { + result = candidates.iterator().next(); + } else if (count > 1) { + Iterator iterator = candidates.iterator(); + SplitPackageBinding split = new SplitPackageBinding(iterator.next(), this.enclosingModule); + while (iterator.hasNext()) + split.add(iterator.next()); + result = split; + } + if (result == null) + addNotFoundPackage(name); + else + addPackage(result, module); + return result; + } + + public PackageBinding getIncarnation(ModuleBinding requestedModule) { + for (PackageBinding incarnation : this.incarnations) { + if (incarnation.enclosingModule == requestedModule) + return incarnation; + } + return null; + } + + @Override + public boolean subsumes(PackageBinding binding) { + if (!CharOperation.equals(this.compoundName, binding.compoundName)) + return false; + if (binding instanceof SplitPackageBinding) + return this.declaringModules.containsAll(((SplitPackageBinding) binding).declaringModules); + else + return this.declaringModules.contains(binding.enclosingModule); + } + + @Override + ReferenceBinding getType0(char[] name) { + ReferenceBinding knownType = super.getType0(name); + if (knownType != null) + return knownType; + + ReferenceBinding candidate = null; + for (PackageBinding incarnation : this.incarnations) { + ReferenceBinding next = incarnation.getType0(name); + if (next != null) { + if (next.isValidBinding()) { + if (candidate != null) + return null; // unable to disambiguate without a module context + candidate = next; + } + } + } + if (candidate != null) { + addType(candidate); + } + + return candidate; + } + + /** Similar to getType0() but now we have a module and can ask the specific incarnation! */ + ReferenceBinding getType0ForModule(ModuleBinding module, char[] name) { + if (this.declaringModules.contains(module)) + return getIncarnation(module).getType0(name); + return null; + } + + @Override + ReferenceBinding getType(char[] name, ModuleBinding mod) { + ReferenceBinding candidate = null; + boolean accessible = false; + for (PackageBinding incarnation : this.incarnations) { + ReferenceBinding type = incarnation.getType(name, mod); + if (type != null) { + if (candidate == null || !accessible) { + candidate = type; + accessible = mod.canAccess(incarnation); + } else if (mod.canAccess(incarnation)) { + return new ProblemReferenceBinding(type.compoundName, candidate, ProblemReasons.Ambiguous); // TODO(SHMOD) add module information + } + } + } + if (candidate != null && !accessible) + return new ProblemReferenceBinding(candidate.compoundName, candidate, ProblemReasons.NotAccessible); // TODO(SHMOD) more info + // at this point we have only checked unique accessibility of the package, accessibility of the type will be checked by callers + return candidate; + } + + @Override + public boolean isDeclaredIn(ModuleBinding moduleBinding) { + return this.declaringModules.contains(moduleBinding); + } + + @Override + public PackageBinding getVisibleFor(ModuleBinding clientModule) { + int visibleCount = 0; + PackageBinding unique = null; + for (PackageBinding incarnation : this.incarnations) { + if (incarnation.hasCompilationUnit(false)) { + if (incarnation.enclosingModule == clientModule) { + return incarnation; // prefer local package over foreign + } else { + if (clientModule.canAccess(incarnation)) { + if (++visibleCount > 1) + return this; + unique = incarnation; + } + } + } + } + return unique; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(super.toString()); + buf.append(" (from "); //$NON-NLS-1$ + String sep = ""; //$NON-NLS-1$ + for (ModuleBinding mod : this.declaringModules) { + buf.append(sep).append(mod.readableName()); + sep = ", "; //$NON-NLS-1$ + } + buf.append(")"); //$NON-NLS-1$ + return buf.toString(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java index 6a7b43bac0..62aa631d2d 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -515,8 +515,12 @@ public void initializeMethodAccessor(MethodBinding accessedMethod, boolean isSup this.targetMethod = accessedMethod; if (isSuperAccess && receiverType.isInterface() && !accessedMethod.isStatic()) this.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccSynthetic; - else - this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; + else { + if (receiverType.isInterface()) // default is not allowed. TODO: do we need a target level check here? + this.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; + else + this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; + } this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); SourceTypeBinding declaringSourceType = (SourceTypeBinding) receiverType; SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java index 5f76fed040..7c4bf523c5 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for @@ -120,11 +120,12 @@ public interface TagBits { long AnnotationForPackage = ASTNode.Bit44L; long AnnotationForTypeUse = ASTNode.Bit54L; long AnnotationForTypeParameter = ASTNode.Bit55L; + long AnnotationForModule = ASTNode.Bit62L; long SE7AnnotationTargetMASK = AnnotationForType | AnnotationForField | AnnotationForMethod | AnnotationForParameter | AnnotationForConstructor | AnnotationForLocalVariable | AnnotationForAnnotationType | AnnotationForPackage; long AnnotationTargetMASK = SE7AnnotationTargetMASK | AnnotationTarget - | AnnotationForTypeUse | AnnotationForTypeParameter; + | AnnotationForTypeUse | AnnotationForTypeParameter | AnnotationForModule; // 2-bits for retention (should check (tagBits & RetentionMask) == RuntimeRetention long AnnotationSourceRetention = ASTNode.Bit45L; long AnnotationClassRetention = ASTNode.Bit46L; @@ -153,11 +154,14 @@ public interface TagBits { /** From Java 8 */ long AnnotationRepeatable = ASTNode.Bit61L; // Only for annotation types and since these cannot have constructors, we can overload HasNonPrivateConstructor. + /** From Java 9 */ + long AnnotationTerminallyDeprecated = ASTNode.Bit63L; long AllStandardAnnotationsMask = AnnotationTargetMASK | AnnotationRetentionMASK | AnnotationDeprecated + | AnnotationTerminallyDeprecated | AnnotationDocumented | AnnotationInherited | AnnotationOverride diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java index 5f5360a6df..99a3b89b77 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for @@ -102,8 +102,9 @@ public interface TypeConstants { char[] ANONYMOUS_METHOD = "lambda$".toCharArray(); //$NON-NLS-1$ char[] DESERIALIZE_LAMBDA = "$deserializeLambda$".toCharArray(); //$NON-NLS-1$ char[] LAMBDA_TYPE = "".toCharArray(); //$NON-NLS-1$ - - // jsr308 + char[] UPPER_MODULE = "MODULE".toCharArray(); //$NON-NLS-1$ + + // jsr308 char[] TYPE_USE_TARGET = "TYPE_USE".toCharArray(); //$NON-NLS-1$ char[] TYPE_PARAMETER_TARGET = "TYPE_PARAMETER".toCharArray(); //$NON-NLS-1$ @@ -165,6 +166,7 @@ public interface TypeConstants { char[][] JAVA_UTIL_OBJECTS = {JAVA, UTIL, "Objects".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_UTIL_LIST = {JAVA, UTIL, "List".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_DEPRECATED = {JAVA, LANG, "Deprecated".toCharArray()}; //$NON-NLS-1$ + char[] FOR_REMOVAL = "forRemoval".toCharArray(); //$NON-NLS-1$ char[][] JAVA_LANG_ANNOTATION_DOCUMENTED = {JAVA, LANG, ANNOTATION, "Documented".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_ANNOTATION_INHERITED = {JAVA, LANG, ANNOTATION, "Inherited".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_ANNOTATION_REPEATABLE = {JAVA, LANG, ANNOTATION, "Repeatable".toCharArray()}; //$NON-NLS-1$ @@ -319,7 +321,8 @@ public CloseMethodRecord(char[][] typeName, char[] selector, int num) { // ... methods: char[] IS_TRUE = "isTrue".toCharArray(); //$NON-NLS-1$ char[] NOT_NULL = "notNull".toCharArray(); //$NON-NLS-1$ - + char[] PROVIDER = "provider".toCharArray(); //$NON-NLS-1$ + char[][] COM_GOOGLE_COMMON_BASE_PRECONDITIONS = new char[][] { COM, GOOGLE, "common".toCharArray(), "base".toCharArray(), "Preconditions".toCharArray() }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // ... methods: @@ -464,4 +467,13 @@ public BoundCheckStatus betterOf(BoundCheckStatus other) { // synthetic package-info name public static final char[] PACKAGE_INFO_NAME = "package-info".toCharArray(); //$NON-NLS-1$ + public static final char[] MODULE_INFO_NAME = "module-info".toCharArray(); //$NON-NLS-1$ + public static final String MODULE_INFO_NAME_STRING = "module-info"; //$NON-NLS-1$ + public static final char[] MODULE_INFO_FILE_NAME = "module-info.java".toCharArray(); //$NON-NLS-1$ + public static final char[] MODULE_INFO_CLASS_NAME = "module-info.class".toCharArray(); //$NON-NLS-1$ + public static final String MODULE_INFO_FILE_NAME_STRING = "module-info.java"; //$NON-NLS-1$ + public static final String MODULE_INFO_CLASS_NAME_STRING = "module-info.class"; //$NON-NLS-1$ + // java.base module name + char[] JAVA_BASE = "java.base".toCharArray(); //$NON-NLS-1$ + String META_INF_MANIFEST_MF = "META-INF/MANIFEST.MF"; //$NON-NLS-1$ } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java index f0dd9b277d..1195ff7240 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java @@ -176,6 +176,16 @@ private TypeConstants.BoundCheckStatus internalBoundCheck(Substitution substitut // non-object real superclass should have produced a valid 'match' above return BoundCheckStatus.MISMATCH; } + // not fully spec-ed in JLS, but based on email communication (2017-09-13): + // (a) bound check should apply capture + // (b) capture applies glb + // (c) and then the glb should be checked for well-formedness (see Scope.isMalformedPair() - this part missing in JLS). + // Since we don't do (a), nor (b) for this case, we just directly proceed to (b) here. + // For (a) see ParameterizedTypeBinding.boundCheck() - comment added as of this commit + // for (b) see CaptureBinding.initializeBounds() - comment added as of this commit + if (Scope.greaterLowerBound(new TypeBinding[] {substitutedSuperType, wildcardBound}, scope, this.environment) == null) { + return BoundCheckStatus.MISMATCH; + } } } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java index 8b7df824da..b80272adf3 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contributions for @@ -99,18 +99,21 @@ ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericTo char[] typeName = this.compoundName[this.compoundName.length - 1]; targetType = this.fPackage.getType0(typeName); if (targetType == this) { //$IDENTITY-COMPARISON$ - targetType = environment.askForType(this.compoundName); + if (this.fPackage instanceof SplitPackageBinding) // leverage SplitPackageBinding to avoid duplicate creation of BinaryTypeBinding + targetType = environment.askForType(this.fPackage, typeName, this.fPackage.enclosingModule); + else + targetType = environment.askForType(this.compoundName, this.fPackage.enclosingModule); } if ((targetType == null || targetType == this) && CharOperation.contains('.', typeName)) { //$IDENTITY-COMPARISON$ // bug 491354: this complements the NameLookup#seekTypes(..), which performs the same adaptation - targetType = environment.askForType(this.fPackage, CharOperation.replaceOnCopy(typeName, '.', '$')); + targetType = environment.askForType(this.fPackage, CharOperation.replaceOnCopy(typeName, '.', '$'), this.fPackage.enclosingModule); } if (targetType == null || targetType == this) { // could not resolve any better, error was already reported against it //$IDENTITY-COMPARISON$ // report the missing class file first - only if not resolving a previously missing type if ((this.tagBits & TagBits.HasMissingType) == 0 && !environment.mayTolerateMissingType) { environment.problemReporter.isClassPathCorrect( this.compoundName, - environment.unitBeingCompleted, + environment.root.unitBeingCompleted, environment.missingClassFileLocation); } // create a proxy for the missing BinaryType diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java index 5a852d8fa8..fe4005290c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2005, 2016 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for @@ -917,7 +917,7 @@ public ReferenceBinding superclass() { } this.superclass = superType instanceof ReferenceBinding && !superType.isInterface() ? (ReferenceBinding) superType - : this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); + : this.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null); } return this.superclass; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java index ed0b252c65..035e1f6dd4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java @@ -18,4 +18,10 @@ public interface ConflictedParser { we treat the type annotation as a declarative annotation. */ boolean atConflictScenario(int token); + /* + * Return true if the parser is parsing a module declaration. In Java 9, module, requires, exports, + * to, uses, provides, and with are restricted keywords (i.e. they are keywords solely where they + * appear as terminals in ModuleDeclaration, and are identifiers everywhere else) + */ + boolean isParsingModuleDeclaration(); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java index b1fde15f58..ef628fae02 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -148,6 +148,8 @@ public interface JavadocTagConstants { // since 1.7 {}, // since 1.8 + {}, + // since 9 {} }; public static final char[][][] INLINE_TAGS = { @@ -168,6 +170,8 @@ public interface JavadocTagConstants { // since 1.7 {}, // since 1.8 + {}, + // since 9 {} }; public final static int INLINE_TAGS_LENGTH = INLINE_TAGS.length; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java index 1cf35c9b9f..f8417465d4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java @@ -44,98 +44,7 @@ import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.CompilationResult; -import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression; -import org.eclipse.jdt.internal.compiler.ast.ASTNode; -import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; -import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; -import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; -import org.eclipse.jdt.internal.compiler.ast.Annotation; -import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration; -import org.eclipse.jdt.internal.compiler.ast.Argument; -import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression; -import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; -import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.ArrayReference; -import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference; -import org.eclipse.jdt.internal.compiler.ast.AssertStatement; -import org.eclipse.jdt.internal.compiler.ast.Assignment; -import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; -import org.eclipse.jdt.internal.compiler.ast.Block; -import org.eclipse.jdt.internal.compiler.ast.BreakStatement; -import org.eclipse.jdt.internal.compiler.ast.CaseStatement; -import org.eclipse.jdt.internal.compiler.ast.CastExpression; -import org.eclipse.jdt.internal.compiler.ast.CharLiteral; -import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; -import org.eclipse.jdt.internal.compiler.ast.CombinedBinaryExpression; -import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; -import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment; -import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; -import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; -import org.eclipse.jdt.internal.compiler.ast.ContinueStatement; -import org.eclipse.jdt.internal.compiler.ast.DoStatement; -import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral; -import org.eclipse.jdt.internal.compiler.ast.EmptyStatement; -import org.eclipse.jdt.internal.compiler.ast.EqualExpression; -import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; -import org.eclipse.jdt.internal.compiler.ast.Expression; -import org.eclipse.jdt.internal.compiler.ast.FalseLiteral; -import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; -import org.eclipse.jdt.internal.compiler.ast.FieldReference; -import org.eclipse.jdt.internal.compiler.ast.FloatLiteral; -import org.eclipse.jdt.internal.compiler.ast.ForStatement; -import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; -import org.eclipse.jdt.internal.compiler.ast.IfStatement; -import org.eclipse.jdt.internal.compiler.ast.ImportReference; -import org.eclipse.jdt.internal.compiler.ast.Initializer; -import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression; -import org.eclipse.jdt.internal.compiler.ast.IntLiteral; -import org.eclipse.jdt.internal.compiler.ast.IntersectionCastTypeReference; -import org.eclipse.jdt.internal.compiler.ast.Javadoc; -import org.eclipse.jdt.internal.compiler.ast.LabeledStatement; -import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; -import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; -import org.eclipse.jdt.internal.compiler.ast.LongLiteral; -import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; -import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; -import org.eclipse.jdt.internal.compiler.ast.MessageSend; -import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; -import org.eclipse.jdt.internal.compiler.ast.NameReference; -import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; -import org.eclipse.jdt.internal.compiler.ast.NullLiteral; -import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression; -import org.eclipse.jdt.internal.compiler.ast.OperatorIds; -import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; -import org.eclipse.jdt.internal.compiler.ast.PostfixExpression; -import org.eclipse.jdt.internal.compiler.ast.PrefixExpression; -import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; -import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; -import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference; -import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; -import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.Receiver; -import org.eclipse.jdt.internal.compiler.ast.Reference; -import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression; -import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; -import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; -import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; -import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; -import org.eclipse.jdt.internal.compiler.ast.Statement; -import org.eclipse.jdt.internal.compiler.ast.StringLiteral; -import org.eclipse.jdt.internal.compiler.ast.SuperReference; -import org.eclipse.jdt.internal.compiler.ast.SwitchStatement; -import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement; -import org.eclipse.jdt.internal.compiler.ast.ThisReference; -import org.eclipse.jdt.internal.compiler.ast.ThrowStatement; -import org.eclipse.jdt.internal.compiler.ast.TrueLiteral; -import org.eclipse.jdt.internal.compiler.ast.TryStatement; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; -import org.eclipse.jdt.internal.compiler.ast.TypeParameter; -import org.eclipse.jdt.internal.compiler.ast.TypeReference; -import org.eclipse.jdt.internal.compiler.ast.UnaryExpression; -import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; -import org.eclipse.jdt.internal.compiler.ast.WhileStatement; -import org.eclipse.jdt.internal.compiler.ast.Wildcard; +import org.eclipse.jdt.internal.compiler.ast.*; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; @@ -1021,6 +930,7 @@ public static int tAction(int state, int sym) { protected int valueLambdaNestDepth = -1; private int stateStackLengthStack[] = new int[0]; protected boolean parsingJava8Plus; +protected boolean parsingJava9Plus; protected int unstackedAct = ERROR_ACTION; private boolean haltOnSyntaxError = false; private boolean tolerateDefaultClassMethods = false; @@ -1038,6 +948,7 @@ public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) { this.optimizeStringLiterals = optimizeStringLiterals; initializeScanner(); this.parsingJava8Plus = this.options.sourceLevel >= ClassFileConstants.JDK1_8; + this.parsingJava9Plus = this.options.sourceLevel >= ClassFileConstants.JDK9; this.astLengthStack = new int[50]; this.expressionLengthStack = new int[30]; this.typeAnnotationLengthStack = new int[30]; @@ -4787,7 +4698,8 @@ protected void consumeInterfaceMethodDeclaration(boolean hasSemicolonBody) { boolean isDefault = (md.modifiers & ExtraCompilerModifiers.AccDefaultMethod) != 0; boolean isStatic = (md.modifiers & ClassFileConstants.AccStatic) != 0; - boolean bodyAllowed = isDefault || isStatic; + boolean isPrivate = (md.modifiers & ClassFileConstants.AccPrivate) != 0; + boolean bodyAllowed = (this.parsingJava9Plus && isPrivate) || isDefault || isStatic; if (this.parsingJava8Plus) { if (bodyAllowed && hasSemicolonBody) { md.modifiers |= ExtraCompilerModifiers.AccSemicolonBody; // avoid complaints regarding undocumented empty body @@ -5601,6 +5513,466 @@ protected void consumePackageComment() { resetModifiers(); } } +protected void consumeInternalCompilationUnitWithModuleDeclaration() { + this.compilationUnit.moduleDeclaration = (ModuleDeclaration)this.astStack[this.astPtr--]; + this.astLengthStack[this.astLengthPtr--] = 0; +} +protected void consumeRequiresStatement() { + RequiresStatement req = (RequiresStatement) this.astStack[this.astPtr]; + req.declarationEnd = req.declarationSourceEnd = this.endStatementPosition; + // recovery + if (this.currentElement instanceof RecoveredModule) { + this.lastCheckPoint = req.declarationSourceEnd + 1; + this.currentElement = this.currentElement.add(req, 0); + this.lastIgnoredToken = -1; + this.restartRecovery = true; // used to avoid branching back into the regular automaton + } +} +protected void consumeSingleRequiresModuleName() { + ModuleReference impt; + int length; + char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][]; + this.identifierPtr -= length; + long[] positions = new long[length]; + System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length); + System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length); + RequiresStatement req = new RequiresStatement(impt = new ModuleReference(tokens, positions)); + if (this.currentToken == TokenNameSEMICOLON){ + req.declarationSourceEnd = impt.sourceEnd + 1; + } else { + req.declarationSourceEnd = impt.sourceEnd; + } + req.declarationEnd = req.declarationSourceEnd; + req.modifiersSourceStart = this.intStack[this.intPtr--]; + req.modifiers |= this.intStack[this.intPtr--]; + req.sourceStart = req.declarationSourceStart = this.intStack[this.intPtr--]; + req.sourceEnd = impt.sourceEnd; + pushOnAstStack(req); + // recovery + if (this.currentElement instanceof RecoveredModule){ + this.lastCheckPoint = req.declarationSourceEnd; + } +} +protected void consumeExportsStatement() { + ExportsStatement expt = (ExportsStatement) this.astStack[this.astPtr]; + expt.declarationSourceEnd = this.endStatementPosition; + expt.declarationEnd = expt.declarationSourceEnd; + // recovery + if (this.currentElement instanceof RecoveredPackageVisibilityStatement) { + this.lastCheckPoint = expt.declarationSourceEnd + 1; + this.currentElement = this.currentElement.parent; + this.lastIgnoredToken = -1; + this.restartRecovery = true; + // used to avoid branching back into the regular automaton + } +} +protected void consumeExportsHeader() { + ImportReference impt = (ImportReference) this.astStack[this.astPtr]; + impt.bits |= ASTNode.inModule; + ExportsStatement expt = new ExportsStatement(impt); + expt.declarationSourceStart = this.intStack[this.intPtr--]; + expt.sourceStart = expt.declarationSourceStart; + expt.sourceEnd = impt.sourceEnd; + if (this.currentToken == TokenNameSEMICOLON){ + expt.declarationSourceEnd = this.scanner.currentPosition - 1; + } else { + expt.declarationSourceEnd = expt.sourceEnd; + } + expt.declarationEnd = expt.declarationSourceEnd; + this.astStack[this.astPtr] = expt; // replace with ExportsStatement + // recovery + if (this.currentElement instanceof RecoveredModule) { + this.lastCheckPoint = expt.declarationSourceEnd + 1; + this.currentElement = this.currentElement.add(expt, 0); + } +} +protected void consumeOpensHeader() { + ImportReference impt = (ImportReference) this.astStack[this.astPtr]; + impt.bits |= ASTNode.inModule; + OpensStatement stmt = new OpensStatement(impt); + stmt.declarationSourceStart = this.intStack[this.intPtr--]; + stmt.sourceStart = stmt.declarationSourceStart; + stmt.sourceEnd = impt.sourceEnd; + if (this.currentToken == TokenNameSEMICOLON){ + stmt.declarationSourceEnd = this.scanner.currentPosition - 1; + } else { + stmt.declarationSourceEnd = stmt.sourceEnd; + } + stmt.declarationEnd = stmt.declarationSourceEnd; + this.astStack[this.astPtr] = stmt; // replace with OpensStatement + // recovery + if (this.currentElement instanceof RecoveredModule) { + this.lastCheckPoint = stmt.declarationSourceEnd + 1; + this.lastCheckPoint = stmt.declarationSourceEnd + 1; + this.currentElement = this.currentElement.add(stmt, 0); + } +} +protected void consumeOpensStatement() { + OpensStatement expt = (OpensStatement) this.astStack[this.astPtr]; + expt.declarationSourceEnd = this.endStatementPosition; + expt.declarationEnd = expt.declarationSourceEnd; + // recovery + if (this.currentElement instanceof RecoveredPackageVisibilityStatement) { + this.lastCheckPoint = expt.declarationSourceEnd + 1; + this.currentElement = this.currentElement.parent; + this.lastIgnoredToken = -1; + this.restartRecovery = true; + // used to avoid branching back into the regular automaton + } +} +protected void consumeSingleTargetModuleName() { + ModuleReference reference; + int length; + char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][]; + this.identifierPtr -= length; + long[] positions = new long[length]; + System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length); + System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length); + pushOnAstStack(reference = new ModuleReference(tokens, positions)); + + // recovery + if (this.currentElement != null) { + this.lastCheckPoint = reference.sourceEnd + 1; + } + +} +protected void consumeTargetModuleList() { + int length = this.astLengthStack[this.astLengthPtr--]; + this.astPtr -= length; + PackageVisibilityStatement node = (PackageVisibilityStatement) this.astStack[this.astPtr]; + if (length > 0) { + System.arraycopy( + this.astStack, + this.astPtr + 1, + node.targets = new ModuleReference[length], + 0, + length); + node.sourceEnd = node.targets[length - 1].sourceEnd; + if (this.currentToken == TokenNameSEMICOLON){ + node.declarationSourceEnd = node.sourceEnd + 1; + } else { + node.declarationSourceEnd = node.sourceEnd; + } + } + + this.listLength = 0; // reset after having read target modules list + // recovery TBD + if (this.currentElement != null) { // is recovering + this.lastCheckPoint = node.sourceEnd; + } +} +protected void consumeTargetModuleNameList() { + this.listLength++; + optimizedConcatNodeLists(); +} +protected void consumeSinglePkgName() { + ImportReference impt; + int length; + char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][]; + this.identifierPtr -= length; + long[] positions = new long[length]; + System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length); + System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length); + pushOnAstStack(impt = new ImportReference(tokens, positions, false, ClassFileConstants.AccDefault)); + + // recovery + if (this.currentElement instanceof RecoveredModule){ + this.lastCheckPoint = impt.sourceEnd + 1; + } +} +protected void consumeUsesStatement() { + UsesStatement stmt = (UsesStatement) this.astStack[this.astPtr]; + stmt.declarationEnd = stmt.declarationSourceEnd = this.endStatementPosition; + // recovery + if (this.currentElement instanceof RecoveredModule){ + this.lastCheckPoint = stmt.declarationSourceEnd; + this.lastIgnoredToken = -1; + this.restartRecovery = true; + } +} +protected void consumeUsesHeader() { + pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]); + pushOnGenericsLengthStack(0); + TypeReference siName = getTypeReference(0); + if (siName.annotations != null) { + for (int j = 0; j < siName.annotations.length; j++) { + Annotation[] qualifierAnnot = siName.annotations[j]; + if (qualifierAnnot != null && qualifierAnnot.length > 0) { + problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]); + siName.annotations[j] = null; + } + } + } + UsesStatement stmt = new UsesStatement(siName); + if (this.currentToken == TokenNameSEMICOLON){ + stmt.declarationSourceEnd = siName.sourceEnd + 1; + } else { + stmt.declarationSourceEnd = siName.sourceEnd; + } + stmt.declarationEnd = stmt.declarationSourceEnd; + stmt.sourceStart = stmt.declarationSourceStart = this.intStack[this.intPtr--]; + stmt.sourceEnd = siName.sourceEnd; + pushOnAstStack(stmt); + // recovery + if (this.currentElement instanceof RecoveredModule){ + this.lastCheckPoint = stmt.sourceEnd + 1; + this.currentElement = this.currentElement.add(stmt, 0); + } +} +protected void consumeProvidesInterface() { + pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]); + pushOnGenericsLengthStack(0); + TypeReference siName = getTypeReference(0); + if (siName.annotations != null) { + for (int j = 0; j < siName.annotations.length; j++) { + Annotation[] qualifierAnnot = siName.annotations[j]; + if (qualifierAnnot != null && qualifierAnnot.length > 0) { + problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]); + siName.annotations[j] = null; + } + } + } + ProvidesStatement ref = new ProvidesStatement(); + ref.serviceInterface = siName; + pushOnAstStack(ref); + ref.declarationSourceStart = this.intStack[this.intPtr--]; + ref.sourceStart = ref.declarationSourceStart; + ref.sourceEnd = siName.sourceEnd; + ref.declarationSourceEnd = ref.sourceEnd; + // recovery + if (this.currentElement instanceof RecoveredModule) { + this.lastCheckPoint = siName.sourceEnd + 1; + this.currentElement = this.currentElement.add(ref, 0); + this.lastIgnoredToken = -1; + } +} +protected void consumeSingleServiceImplName() { + pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]); + pushOnGenericsLengthStack(0); + TypeReference siName = getTypeReference(0); + if (siName.annotations != null) { + for (int j = 0; j < siName.annotations.length; j++) { + Annotation[] qualifierAnnot = siName.annotations[j]; + if (qualifierAnnot != null && qualifierAnnot.length > 0) { + problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]); + siName.annotations[j] = null; + } + } + } + pushOnAstStack(siName); + // recovery + if (this.currentElement instanceof RecoveredModule) { + this.lastCheckPoint = siName.sourceEnd + 1; + } + +} +protected void consumeServiceImplNameList() { + this.listLength++; + optimizedConcatNodeLists(); +} +protected void consumeProvidesStatement() { + ProvidesStatement ref = (ProvidesStatement) this.astStack[this.astPtr]; + ref.declarationEnd = ref.declarationSourceEnd = this.endStatementPosition; + //recovery + if (this.currentElement instanceof RecoveredProvidesStatement) { + this.lastIgnoredToken = -1; + this.currentElement = this.currentElement.parent; + this.restartRecovery = true; // used to avoid branching back into the regular automaton + } +} +protected void consumeWithClause() { + int length = this.astLengthStack[this.astLengthPtr--]; + this.astPtr -= length; + + ProvidesStatement service = (ProvidesStatement) this.astStack[this.astPtr]; + System.arraycopy( + this.astStack, + this.astPtr + 1, + service.implementations = new TypeReference[length], + 0, + length); + + service.sourceEnd = service.implementations[length - 1].sourceEnd; + + if (this.currentToken == TokenNameSEMICOLON){ + service.declarationSourceEnd = service.sourceEnd + 1; + } else { + service.declarationSourceEnd = service.sourceEnd; + } + this.listLength = 0; // reset after having read super-interfaces + // recovery + if (this.currentElement instanceof RecoveredProvidesStatement) { // is recovering + this.lastCheckPoint = service.declarationSourceEnd; + } +} +protected void consumeEmptyModuleStatementsOpt() { + pushOnAstLengthStack(0); +} +protected void consumeModuleStatements() { + concatNodeLists(); +} +protected void consumeModuleModifiers() { + checkComment(); // might update modifiers with AccDeprecated + // Merge with other modifiers + this.intStack[this.intPtr -1] |= this.modifiers; + resetModifiers(); + // Account for the possible presence of annotations as well + this.expressionLengthStack[this.expressionLengthPtr - 1] += this.expressionLengthStack[this.expressionLengthPtr--]; +} +protected void consumeModuleHeader() { + // ModuleHeader ::= 'module' Name + + int length; + char[][] tokens = + new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][]; + this.identifierPtr -= length; + long[] positions = new long[length]; + System.arraycopy(this.identifierStack, ++this.identifierPtr, tokens, 0, length); + System.arraycopy( + this.identifierPositionStack, + this.identifierPtr--, + positions, + 0, + length); + + ModuleDeclaration typeDecl = new ModuleDeclaration(this.compilationUnit.compilationResult, tokens, positions); + //compute the declaration source too + typeDecl.declarationSourceStart = this.intStack[this.intPtr--]; + typeDecl.bodyStart = typeDecl.sourceEnd + 1; + typeDecl.modifiersSourceStart = this.intStack[this.intPtr--]; + typeDecl.modifiers = this.intStack[this.intPtr--]; + if (typeDecl.modifiersSourceStart >= 0) { + typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart; + } +// int otherModifiersStart = this.intStack[this.intPtr--]; +// int otherModifiers = this.intStack[this.intPtr--]; +// if (otherModifiersStart >= 0) { +// typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart = otherModifiersStart; +// } + // Merge with other modifiers +// typeDecl.modifiers |= otherModifiers; + if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { + System.arraycopy( + this.expressionStack, + (this.expressionPtr -= length) + 1, + typeDecl.annotations = new Annotation[length], + 0, + length); + } + pushOnAstStack(typeDecl); + + this.listLength = 0; + // recovery + if (this.currentElement != null){ + this.lastCheckPoint = typeDecl.bodyStart; + this.currentElement = this.currentElement.add(typeDecl, 0); + this.lastIgnoredToken = -1; + } + // javadoc +// typeDecl.javadoc = this.javadoc; +// this.javadoc = null; +} +protected void consumeModuleDeclaration() { + // ModuleDeclaration ::= ModuleHeader ModuleBody + int length = this.astLengthStack[this.astLengthPtr--]; + int[] flag = new int[length + 1]; //plus one -- see + int size1 = 0, size2 = 0, size3 = 0, size4 = 0, size5 = 0; + if (length != 0) { + //there are length declarations + //dispatch according to the type of the declarations + for (int i = length - 1; i >= 0; i--) { + ASTNode astNode = this.astStack[this.astPtr--]; + if (astNode instanceof RequiresStatement) { + flag[i] = 1; + size1++; + } else if (astNode instanceof ExportsStatement) { + flag[i] = 2; + size2++; + } else if (astNode instanceof UsesStatement) { + //field + flag[i] = 3; + size3++; + } else if (astNode instanceof ProvidesStatement){ + flag[i] = 4; + size4++; + } else if (astNode instanceof OpensStatement) { + flag[i] = 5; + size5++; + } + } + } + ModuleDeclaration modul = (ModuleDeclaration) this.astStack[this.astPtr]; + modul.requiresCount = size1; + modul.exportsCount = size2; + modul.usesCount = size3; + modul.servicesCount = size4; + modul.opensCount = size5; + modul.requires = new RequiresStatement[size1]; + modul.exports = new ExportsStatement[size2]; + modul.uses = new UsesStatement[size3]; + modul.services = new ProvidesStatement[size4]; + modul.opens = new OpensStatement[size5]; + //arrays fill up + size1 = size2 = size3 = size4 = size5 = 0; + int flagI = flag[0], start = 0; + int length2; + for (int end = 0; end <= length; end++) // the plus one allows to + { + if (flagI != flag[end]) //treat the last element as a ended flag..... + { //array copy + switch (flagI) { + case 1 : + size1 += (length2 = end - start); + System.arraycopy( + this.astStack, + this.astPtr + start + 1, + modul.requires, + size1 - length2, + length2); + break; + case 2 : + size2 += (length2 = end - start); + System.arraycopy( + this.astStack, + this.astPtr + start + 1, + modul.exports, + size2 - length2, + length2); + break; + case 3 : + size3 += (length2 = end - start); + System.arraycopy( + this.astStack, + this.astPtr + start + 1, + modul.uses, + size3 - length2, + length2); + break; + case 4 : + size4 += (length2 = end - start); + System.arraycopy( + this.astStack, + this.astPtr + start + 1, + modul.services, + size4 - length2, + length2); + break; + case 5 : + size5 += (length2 = end - start); + System.arraycopy( + this.astStack, + this.astPtr + start + 1, + modul.opens, + size5 - length2, + length2); + break; + } + flagI = flag[start = end]; + } + } + modul.bodyEnd = this.endStatementPosition; + modul.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); +} protected void consumePackageDeclaration() { // PackageDeclaration ::= 'package' Name ';' /* build an ImportRef build from the last name @@ -5763,9 +6135,6 @@ protected void rejectIllegalLeadingTypeAnnotations(TypeReference typeReference) } } private void rejectIllegalTypeAnnotations(TypeReference typeReference) { - rejectIllegalTypeAnnotations(typeReference, false); -} -private void rejectIllegalTypeAnnotations(TypeReference typeReference, boolean tolerateAnnotationsOnDimensions) { // Reject misplaced annotations on type reference; Used when grammar is permissive enough to allow them in the first place. Annotation [][] annotations = typeReference.annotations; Annotation[] misplacedAnnotations; @@ -5776,23 +6145,15 @@ private void rejectIllegalTypeAnnotations(TypeReference typeReference, boolean t } } annotations = typeReference.getAnnotationsOnDimensions(true); - boolean tolerated = false; for (int i = 0, length = annotations == null ? 0 : annotations.length; i < length; i++) { misplacedAnnotations = annotations[i]; if (misplacedAnnotations != null) { - if (tolerateAnnotationsOnDimensions) { - problemReporter().toleratedMisplacedTypeAnnotations(misplacedAnnotations[0], misplacedAnnotations[misplacedAnnotations.length - 1]); - tolerated = true; - } - else problemReporter().misplacedTypeAnnotations(misplacedAnnotations[0], misplacedAnnotations[misplacedAnnotations.length - 1]); } } - if (!tolerated) { - typeReference.annotations = null; - typeReference.setAnnotationsOnDimensions(null); - typeReference.bits &= ~ASTNode.HasTypeAnnotations; - } +typeReference.annotations = null; +typeReference.setAnnotationsOnDimensions(null); +typeReference.bits &= ~ASTNode.HasTypeAnnotations; } protected void consumeQualifiedSuperReceiver() { // QualifiedSuperReceiver ::= Name '.' 'super' @@ -5828,7 +6189,7 @@ protected void consumePrimaryNoNewArrayPrimitiveArrayType() { ClassLiteralAccess cla; pushOnExpressionStack( cla = new ClassLiteralAccess(this.intStack[this.intPtr--], getTypeReference(this.intStack[this.intPtr--]))); - rejectIllegalTypeAnnotations(cla.type, true /* tolerate annotations on dimensions for bug compatibility for now */); + rejectIllegalTypeAnnotations(cla.type); } protected void consumePrimaryNoNewArrayPrimitiveType() { // PrimaryNoNewArray ::= PrimitiveType '.' 'class' @@ -5971,6 +6332,19 @@ protected void consumeReferenceType2() { protected void consumeReferenceType3() { pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--])); } +protected void consumeResourceAsLocalVariable() { + // Resource ::= Name + NameReference ref = getUnspecifiedReference(true); + //ref.bits |= ASTNode.IsCapturedOuterLocal; + pushOnAstStack(ref); + } +protected void consumeResourceAsFieldAccess() { + // Resource ::= FieldAccess + FieldReference ref = (FieldReference) this.expressionStack[this.expressionPtr--]; + //NameReference ref = getUnspecifiedReference(true); + //ref.bits |= ASTNode.IsCapturedOuterLocal; + pushOnAstStack(ref); + } protected void consumeResourceAsLocalVariableDeclaration() { // Resource ::= Type PushModifiers VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization // Resource ::= Modifiers Type PushRealModifiers VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization @@ -5981,9 +6355,12 @@ protected void consumeResourceSpecification() { } protected void consumeResourceOptionalTrailingSemiColon(boolean punctuated) { // TrailingSemiColon ::= ';' - LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr]; + Statement statement = (Statement) this.astStack[this.astPtr]; + if (punctuated) { - localDeclaration.declarationSourceEnd = this.endStatementPosition; + if (statement instanceof LocalDeclaration) { + ((LocalDeclaration) statement).declarationSourceEnd = this.endStatementPosition; + } } } protected void consumeRestoreDiet() { @@ -6172,1806 +6549,1922 @@ protected void consumeRule(int act) { consumeEmptyInternalCompilationUnit(); break; - case 97 : if (DEBUG) { System.out.println("ReduceImports ::="); } //$NON-NLS-1$ + case 97 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ImportDeclarations..."); } //$NON-NLS-1$ + consumeInternalCompilationUnitWithModuleDeclaration(); + break; + + case 98 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ModuleDeclaration"); } //$NON-NLS-1$ + consumeInternalCompilationUnitWithModuleDeclaration(); + break; + + case 99 : if (DEBUG) { System.out.println("ModuleDeclaration ::= ModuleHeader ModuleBody"); } //$NON-NLS-1$ + consumeModuleDeclaration(); + break; + + case 100 : if (DEBUG) { System.out.println("ModuleHeader ::= Modifiersopt ModuleModifieropt module"); } //$NON-NLS-1$ + consumeModuleHeader(); + break; + + case 102 : if (DEBUG) { System.out.println("ModuleModifieropt ::= ModuleModifier"); } //$NON-NLS-1$ + consumeModuleModifiers(); + break; + + case 105 : if (DEBUG) { System.out.println("ModuleStatementsOpt ::="); } //$NON-NLS-1$ + consumeEmptyModuleStatementsOpt(); + break; + + case 108 : if (DEBUG) { System.out.println("ModuleStatements ::= ModuleStatements ModuleStatement"); } //$NON-NLS-1$ + consumeModuleStatements(); + break; + + case 114 : if (DEBUG) { System.out.println("RequiresStatement ::= SingleRequiresModuleName SEMICOLON"); } //$NON-NLS-1$ + consumeRequiresStatement(); + break; + + case 115 : if (DEBUG) { System.out.println("SingleRequiresModuleName ::= requires..."); } //$NON-NLS-1$ + consumeSingleRequiresModuleName(); + break; + + case 116 : if (DEBUG) { System.out.println("RequiresModifiersopt ::= RequiresModifiers"); } //$NON-NLS-1$ + consumeModifiers(); + break; + + case 117 : if (DEBUG) { System.out.println("RequiresModifiersopt ::="); } //$NON-NLS-1$ + consumeDefaultModifiers(); + break; + + case 119 : if (DEBUG) { System.out.println("RequiresModifiers ::= RequiresModifiers RequiresModifier"); } //$NON-NLS-1$ + consumeModifiers2(); + break; + + case 122 : if (DEBUG) { System.out.println("ExportsStatement ::= ExportsHeader TargetModuleListopt"); } //$NON-NLS-1$ + consumeExportsStatement(); + break; + + case 123 : if (DEBUG) { System.out.println("ExportsHeader ::= exports SinglePkgName"); } //$NON-NLS-1$ + consumeExportsHeader(); + break; + + case 125 : if (DEBUG) { System.out.println("TargetModuleListopt ::= to TargetModuleNameList"); } //$NON-NLS-1$ + consumeTargetModuleList(); + break; + + case 126 : if (DEBUG) { System.out.println("TargetModuleName ::= UnannotatableName"); } //$NON-NLS-1$ + consumeSingleTargetModuleName(); + break; + + case 128 : if (DEBUG) { System.out.println("TargetModuleNameList ::= TargetModuleNameList COMMA..."); } //$NON-NLS-1$ + consumeTargetModuleNameList(); + break; + + case 129 : if (DEBUG) { System.out.println("SinglePkgName ::= UnannotatableName"); } //$NON-NLS-1$ + consumeSinglePkgName(); + break; + + case 130 : if (DEBUG) { System.out.println("OpensStatement ::= OpensHeader TargetModuleListopt..."); } //$NON-NLS-1$ + consumeOpensStatement(); + break; + + case 131 : if (DEBUG) { System.out.println("OpensHeader ::= opens SinglePkgName"); } //$NON-NLS-1$ + consumeOpensHeader(); + break; + + case 132 : if (DEBUG) { System.out.println("UsesStatement ::= UsesHeader SEMICOLON"); } //$NON-NLS-1$ + consumeUsesStatement(); + break; + + case 133 : if (DEBUG) { System.out.println("UsesHeader ::= uses Name"); } //$NON-NLS-1$ + consumeUsesHeader(); + break; + + case 134 : if (DEBUG) { System.out.println("ProvidesStatement ::= ProvidesInterface WithClause..."); } //$NON-NLS-1$ + consumeProvidesStatement(); + break; + + case 135 : if (DEBUG) { System.out.println("ProvidesInterface ::= provides Name"); } //$NON-NLS-1$ + consumeProvidesInterface(); + break; + + case 136 : if (DEBUG) { System.out.println("ServiceImplName ::= Name"); } //$NON-NLS-1$ + consumeSingleServiceImplName(); + break; + + case 138 : if (DEBUG) { System.out.println("ServiceImplNameList ::= ServiceImplNameList COMMA..."); } //$NON-NLS-1$ + consumeServiceImplNameList(); + break; + + case 139 : if (DEBUG) { System.out.println("WithClause ::= with ServiceImplNameList"); } //$NON-NLS-1$ + consumeWithClause(); + break; + + case 140 : if (DEBUG) { System.out.println("ReduceImports ::="); } //$NON-NLS-1$ consumeReduceImports(); break; - case 98 : if (DEBUG) { System.out.println("EnterCompilationUnit ::="); } //$NON-NLS-1$ + case 141 : if (DEBUG) { System.out.println("EnterCompilationUnit ::="); } //$NON-NLS-1$ consumeEnterCompilationUnit(); break; - case 114 : if (DEBUG) { System.out.println("CatchHeader ::= catch LPAREN CatchFormalParameter RPAREN"); } //$NON-NLS-1$ + case 163 : if (DEBUG) { System.out.println("CatchHeader ::= catch LPAREN CatchFormalParameter RPAREN"); } //$NON-NLS-1$ consumeCatchHeader(); break; - case 116 : if (DEBUG) { System.out.println("ImportDeclarations ::= ImportDeclarations..."); } //$NON-NLS-1$ + case 165 : if (DEBUG) { System.out.println("ImportDeclarations ::= ImportDeclarations..."); } //$NON-NLS-1$ consumeImportDeclarations(); break; - case 118 : if (DEBUG) { System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); } //$NON-NLS-1$ + case 167 : if (DEBUG) { System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); } //$NON-NLS-1$ consumeTypeDeclarations(); break; - case 119 : if (DEBUG) { System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); } //$NON-NLS-1$ + case 168 : if (DEBUG) { System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); } //$NON-NLS-1$ consumePackageDeclaration(); break; - case 120 : if (DEBUG) { System.out.println("PackageDeclarationName ::= Modifiers package..."); } //$NON-NLS-1$ + case 169 : if (DEBUG) { System.out.println("PackageDeclarationName ::= Modifiers package..."); } //$NON-NLS-1$ consumePackageDeclarationNameWithModifiers(); break; - case 121 : if (DEBUG) { System.out.println("PackageDeclarationName ::= PackageComment package Name"); } //$NON-NLS-1$ + case 170 : if (DEBUG) { System.out.println("PackageDeclarationName ::= PackageComment package Name"); } //$NON-NLS-1$ consumePackageDeclarationName(); break; - case 122 : if (DEBUG) { System.out.println("PackageComment ::="); } //$NON-NLS-1$ + case 171 : if (DEBUG) { System.out.println("PackageComment ::="); } //$NON-NLS-1$ consumePackageComment(); break; - case 127 : if (DEBUG) { System.out.println("SingleTypeImportDeclaration ::=..."); } //$NON-NLS-1$ + case 176 : if (DEBUG) { System.out.println("SingleTypeImportDeclaration ::=..."); } //$NON-NLS-1$ consumeImportDeclaration(); break; - case 128 : if (DEBUG) { System.out.println("SingleTypeImportDeclarationName ::= import Name..."); } //$NON-NLS-1$ + case 177 : if (DEBUG) { System.out.println("SingleTypeImportDeclarationName ::= import Name..."); } //$NON-NLS-1$ consumeSingleTypeImportDeclarationName(); break; - case 129 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclaration ::=..."); } //$NON-NLS-1$ + case 178 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclaration ::=..."); } //$NON-NLS-1$ consumeImportDeclaration(); break; - case 130 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT..."); } //$NON-NLS-1$ + case 179 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT..."); } //$NON-NLS-1$ consumeTypeImportOnDemandDeclarationName(); break; - case 133 : if (DEBUG) { System.out.println("TypeDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ + case 182 : if (DEBUG) { System.out.println("TypeDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ consumeEmptyTypeDeclaration(); break; - case 137 : if (DEBUG) { System.out.println("Modifiers ::= Modifiers Modifier"); } //$NON-NLS-1$ + case 186 : if (DEBUG) { System.out.println("Modifiers ::= Modifiers Modifier"); } //$NON-NLS-1$ consumeModifiers2(); break; - case 149 : if (DEBUG) { System.out.println("Modifier ::= Annotation"); } //$NON-NLS-1$ + case 198 : if (DEBUG) { System.out.println("Modifier ::= Annotation"); } //$NON-NLS-1$ consumeAnnotationAsModifier(); break; - case 150 : if (DEBUG) { System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); } //$NON-NLS-1$ + case 199 : if (DEBUG) { System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); } //$NON-NLS-1$ consumeClassDeclaration(); break; - case 151 : if (DEBUG) { System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt..."); } //$NON-NLS-1$ + case 200 : if (DEBUG) { System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt..."); } //$NON-NLS-1$ consumeClassHeader(); break; - case 152 : if (DEBUG) { System.out.println("ClassHeaderName ::= ClassHeaderName1 TypeParameters"); } //$NON-NLS-1$ + case 201 : if (DEBUG) { System.out.println("ClassHeaderName ::= ClassHeaderName1 TypeParameters"); } //$NON-NLS-1$ consumeTypeHeaderNameWithTypeParameters(); break; - case 154 : if (DEBUG) { System.out.println("ClassHeaderName1 ::= Modifiersopt class Identifier"); } //$NON-NLS-1$ + case 203 : if (DEBUG) { System.out.println("ClassHeaderName1 ::= Modifiersopt class Identifier"); } //$NON-NLS-1$ consumeClassHeaderName1(); break; - case 155 : if (DEBUG) { System.out.println("ClassHeaderExtends ::= extends ClassType"); } //$NON-NLS-1$ + case 204 : if (DEBUG) { System.out.println("ClassHeaderExtends ::= extends ClassType"); } //$NON-NLS-1$ consumeClassHeaderExtends(); break; - case 156 : if (DEBUG) { System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); } //$NON-NLS-1$ + case 205 : if (DEBUG) { System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); } //$NON-NLS-1$ consumeClassHeaderImplements(); break; - case 158 : if (DEBUG) { System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA..."); } //$NON-NLS-1$ + case 207 : if (DEBUG) { System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA..."); } //$NON-NLS-1$ consumeInterfaceTypeList(); break; - case 159 : if (DEBUG) { System.out.println("InterfaceType ::= ClassOrInterfaceType"); } //$NON-NLS-1$ + case 208 : if (DEBUG) { System.out.println("InterfaceType ::= ClassOrInterfaceType"); } //$NON-NLS-1$ consumeInterfaceType(); break; - case 162 : if (DEBUG) { System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations..."); } //$NON-NLS-1$ + case 211 : if (DEBUG) { System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations..."); } //$NON-NLS-1$ consumeClassBodyDeclarations(); break; - case 166 : if (DEBUG) { System.out.println("ClassBodyDeclaration ::= Diet NestedMethod..."); } //$NON-NLS-1$ + case 215 : if (DEBUG) { System.out.println("ClassBodyDeclaration ::= Diet NestedMethod..."); } //$NON-NLS-1$ consumeClassBodyDeclaration(); break; - case 167 : if (DEBUG) { System.out.println("Diet ::="); } //$NON-NLS-1$ + case 216 : if (DEBUG) { System.out.println("Diet ::="); } //$NON-NLS-1$ consumeDiet(); break; - case 168 : if (DEBUG) { System.out.println("Initializer ::= Diet NestedMethod CreateInitializer..."); } //$NON-NLS-1$ + case 217 : if (DEBUG) { System.out.println("Initializer ::= Diet NestedMethod CreateInitializer..."); } //$NON-NLS-1$ consumeClassBodyDeclaration(); break; - case 169 : if (DEBUG) { System.out.println("CreateInitializer ::="); } //$NON-NLS-1$ + case 218 : if (DEBUG) { System.out.println("CreateInitializer ::="); } //$NON-NLS-1$ consumeCreateInitializer(); break; - case 176 : if (DEBUG) { System.out.println("ClassMemberDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ + case 225 : if (DEBUG) { System.out.println("ClassMemberDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ consumeEmptyTypeDeclaration(); break; - case 179 : if (DEBUG) { System.out.println("FieldDeclaration ::= Modifiersopt Type..."); } //$NON-NLS-1$ + case 228 : if (DEBUG) { System.out.println("FieldDeclaration ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeFieldDeclaration(); break; - case 181 : if (DEBUG) { System.out.println("VariableDeclarators ::= VariableDeclarators COMMA..."); } //$NON-NLS-1$ + case 230 : if (DEBUG) { System.out.println("VariableDeclarators ::= VariableDeclarators COMMA..."); } //$NON-NLS-1$ consumeVariableDeclarators(); break; - case 184 : if (DEBUG) { System.out.println("EnterVariable ::="); } //$NON-NLS-1$ + case 233 : if (DEBUG) { System.out.println("EnterVariable ::="); } //$NON-NLS-1$ consumeEnterVariable(); break; - case 185 : if (DEBUG) { System.out.println("ExitVariableWithInitialization ::="); } //$NON-NLS-1$ + case 234 : if (DEBUG) { System.out.println("ExitVariableWithInitialization ::="); } //$NON-NLS-1$ consumeExitVariableWithInitialization(); break; - case 186 : if (DEBUG) { System.out.println("ExitVariableWithoutInitialization ::="); } //$NON-NLS-1$ + case 235 : if (DEBUG) { System.out.println("ExitVariableWithoutInitialization ::="); } //$NON-NLS-1$ consumeExitVariableWithoutInitialization(); break; - case 187 : if (DEBUG) { System.out.println("ForceNoDiet ::="); } //$NON-NLS-1$ + case 236 : if (DEBUG) { System.out.println("ForceNoDiet ::="); } //$NON-NLS-1$ consumeForceNoDiet(); break; - case 188 : if (DEBUG) { System.out.println("RestoreDiet ::="); } //$NON-NLS-1$ + case 237 : if (DEBUG) { System.out.println("RestoreDiet ::="); } //$NON-NLS-1$ consumeRestoreDiet(); break; - case 193 : if (DEBUG) { System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); } //$NON-NLS-1$ + case 242 : if (DEBUG) { System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); } //$NON-NLS-1$ // set to true to consume a method with a body consumeMethodDeclaration(true, false); break; - case 194 : if (DEBUG) { System.out.println("MethodDeclaration ::= DefaultMethodHeader MethodBody"); } //$NON-NLS-1$ + case 243 : if (DEBUG) { System.out.println("MethodDeclaration ::= DefaultMethodHeader MethodBody"); } //$NON-NLS-1$ // set to true to consume a method with a body consumeMethodDeclaration(true, true); break; - case 195 : if (DEBUG) { System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); } //$NON-NLS-1$ + case 244 : if (DEBUG) { System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); } //$NON-NLS-1$ // set to false to consume a method without body consumeMethodDeclaration(false, false); break; - case 196 : if (DEBUG) { System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt"); } //$NON-NLS-1$ + case 245 : if (DEBUG) { System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt"); } //$NON-NLS-1$ consumeMethodHeader(); break; - case 197 : if (DEBUG) { System.out.println("DefaultMethodHeader ::= DefaultMethodHeaderName..."); } //$NON-NLS-1$ + case 246 : if (DEBUG) { System.out.println("DefaultMethodHeader ::= DefaultMethodHeaderName..."); } //$NON-NLS-1$ consumeMethodHeader(); break; - case 198 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt TypeParameters Type..."); } //$NON-NLS-1$ + case 247 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt TypeParameters Type..."); } //$NON-NLS-1$ consumeMethodHeaderNameWithTypeParameters(false); break; - case 199 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN"); } //$NON-NLS-1$ + case 248 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN"); } //$NON-NLS-1$ consumeMethodHeaderName(false); break; - case 200 : if (DEBUG) { System.out.println("DefaultMethodHeaderName ::= ModifiersWithDefault..."); } //$NON-NLS-1$ + case 249 : if (DEBUG) { System.out.println("DefaultMethodHeaderName ::= ModifiersWithDefault..."); } //$NON-NLS-1$ consumeMethodHeaderNameWithTypeParameters(false); break; - case 201 : if (DEBUG) { System.out.println("DefaultMethodHeaderName ::= ModifiersWithDefault Type..."); } //$NON-NLS-1$ + case 250 : if (DEBUG) { System.out.println("DefaultMethodHeaderName ::= ModifiersWithDefault Type..."); } //$NON-NLS-1$ consumeMethodHeaderName(false); break; - case 202 : if (DEBUG) { System.out.println("ModifiersWithDefault ::= Modifiersopt default..."); } //$NON-NLS-1$ + case 251 : if (DEBUG) { System.out.println("ModifiersWithDefault ::= Modifiersopt default..."); } //$NON-NLS-1$ consumePushCombineModifiers(); break; - case 203 : if (DEBUG) { System.out.println("MethodHeaderRightParen ::= RPAREN"); } //$NON-NLS-1$ + case 252 : if (DEBUG) { System.out.println("MethodHeaderRightParen ::= RPAREN"); } //$NON-NLS-1$ consumeMethodHeaderRightParen(); break; - case 204 : if (DEBUG) { System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); } //$NON-NLS-1$ + case 253 : if (DEBUG) { System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); } //$NON-NLS-1$ consumeMethodHeaderExtendedDims(); break; - case 205 : if (DEBUG) { System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); } //$NON-NLS-1$ + case 254 : if (DEBUG) { System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); } //$NON-NLS-1$ consumeMethodHeaderThrowsClause(); break; - case 206 : if (DEBUG) { System.out.println("ConstructorHeader ::= ConstructorHeaderName..."); } //$NON-NLS-1$ + case 255 : if (DEBUG) { System.out.println("ConstructorHeader ::= ConstructorHeaderName..."); } //$NON-NLS-1$ consumeConstructorHeader(); break; - case 207 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt TypeParameters..."); } //$NON-NLS-1$ + case 256 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt TypeParameters..."); } //$NON-NLS-1$ consumeConstructorHeaderNameWithTypeParameters(); break; - case 208 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); } //$NON-NLS-1$ + case 257 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); } //$NON-NLS-1$ consumeConstructorHeaderName(); break; - case 210 : if (DEBUG) { System.out.println("FormalParameterList ::= FormalParameterList COMMA..."); } //$NON-NLS-1$ + case 259 : if (DEBUG) { System.out.println("FormalParameterList ::= FormalParameterList COMMA..."); } //$NON-NLS-1$ consumeFormalParameterList(); break; - case 211 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); } //$NON-NLS-1$ + case 260 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeFormalParameter(false); break; - case 212 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); } //$NON-NLS-1$ + case 261 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeFormalParameter(true); break; - case 213 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type AT308DOTDOTDOT..."); } //$NON-NLS-1$ + case 262 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type AT308DOTDOTDOT..."); } //$NON-NLS-1$ consumeFormalParameter(true); break; - case 214 : if (DEBUG) { System.out.println("CatchFormalParameter ::= Modifiersopt CatchType..."); } //$NON-NLS-1$ + case 263 : if (DEBUG) { System.out.println("CatchFormalParameter ::= Modifiersopt CatchType..."); } //$NON-NLS-1$ consumeCatchFormalParameter(); break; - case 215 : if (DEBUG) { System.out.println("CatchType ::= UnionType"); } //$NON-NLS-1$ + case 264 : if (DEBUG) { System.out.println("CatchType ::= UnionType"); } //$NON-NLS-1$ consumeCatchType(); break; - case 216 : if (DEBUG) { System.out.println("UnionType ::= Type"); } //$NON-NLS-1$ + case 265 : if (DEBUG) { System.out.println("UnionType ::= Type"); } //$NON-NLS-1$ consumeUnionTypeAsClassType(); break; - case 217 : if (DEBUG) { System.out.println("UnionType ::= UnionType OR Type"); } //$NON-NLS-1$ + case 266 : if (DEBUG) { System.out.println("UnionType ::= UnionType OR Type"); } //$NON-NLS-1$ consumeUnionType(); break; - case 219 : if (DEBUG) { System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); } //$NON-NLS-1$ + case 268 : if (DEBUG) { System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); } //$NON-NLS-1$ consumeClassTypeList(); break; - case 220 : if (DEBUG) { System.out.println("ClassTypeElt ::= ClassType"); } //$NON-NLS-1$ + case 269 : if (DEBUG) { System.out.println("ClassTypeElt ::= ClassType"); } //$NON-NLS-1$ consumeClassTypeElt(); break; - case 221 : if (DEBUG) { System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt..."); } //$NON-NLS-1$ + case 270 : if (DEBUG) { System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt..."); } //$NON-NLS-1$ consumeMethodBody(); break; - case 222 : if (DEBUG) { System.out.println("NestedMethod ::="); } //$NON-NLS-1$ + case 271 : if (DEBUG) { System.out.println("NestedMethod ::="); } //$NON-NLS-1$ consumeNestedMethod(); break; - case 223 : if (DEBUG) { System.out.println("StaticInitializer ::= StaticOnly Block"); } //$NON-NLS-1$ + case 272 : if (DEBUG) { System.out.println("StaticInitializer ::= StaticOnly Block"); } //$NON-NLS-1$ consumeStaticInitializer(); break; - case 224 : if (DEBUG) { System.out.println("StaticOnly ::= static"); } //$NON-NLS-1$ + case 273 : if (DEBUG) { System.out.println("StaticOnly ::= static"); } //$NON-NLS-1$ consumeStaticOnly(); break; - case 225 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody"); } //$NON-NLS-1$ + case 274 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody"); } //$NON-NLS-1$ consumeConstructorDeclaration() ; break; - case 226 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); } //$NON-NLS-1$ + case 275 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); } //$NON-NLS-1$ consumeInvalidConstructorDeclaration() ; break; - case 227 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= this LPAREN..."); } //$NON-NLS-1$ + case 276 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= this LPAREN..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(0, THIS_CALL); break; - case 228 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments this"); } //$NON-NLS-1$ + case 277 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments this"); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(0,THIS_CALL); break; - case 229 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= super LPAREN..."); } //$NON-NLS-1$ + case 278 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= super LPAREN..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(0,SUPER_CALL); break; - case 230 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments..."); } //$NON-NLS-1$ + case 279 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(0,SUPER_CALL); break; - case 231 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT super..."); } //$NON-NLS-1$ + case 280 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT super..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(1, SUPER_CALL); break; - case 232 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); } //$NON-NLS-1$ + case 281 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(1, SUPER_CALL); break; - case 233 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN"); } //$NON-NLS-1$ + case 282 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN"); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(2, SUPER_CALL); break; - case 234 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); } //$NON-NLS-1$ + case 283 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(2, SUPER_CALL); break; - case 235 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT this..."); } //$NON-NLS-1$ + case 284 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT this..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(1, THIS_CALL); break; - case 236 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); } //$NON-NLS-1$ + case 285 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(1, THIS_CALL); break; - case 237 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN"); } //$NON-NLS-1$ + case 286 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN"); } //$NON-NLS-1$ consumeExplicitConstructorInvocation(2, THIS_CALL); break; - case 238 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); } //$NON-NLS-1$ + case 287 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); } //$NON-NLS-1$ consumeExplicitConstructorInvocationWithTypeArguments(2, THIS_CALL); break; - case 239 : if (DEBUG) { System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); } //$NON-NLS-1$ + case 288 : if (DEBUG) { System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); } //$NON-NLS-1$ consumeInterfaceDeclaration(); break; - case 240 : if (DEBUG) { System.out.println("InterfaceHeader ::= InterfaceHeaderName..."); } //$NON-NLS-1$ + case 289 : if (DEBUG) { System.out.println("InterfaceHeader ::= InterfaceHeaderName..."); } //$NON-NLS-1$ consumeInterfaceHeader(); break; - case 241 : if (DEBUG) { System.out.println("InterfaceHeaderName ::= InterfaceHeaderName1..."); } //$NON-NLS-1$ + case 290 : if (DEBUG) { System.out.println("InterfaceHeaderName ::= InterfaceHeaderName1..."); } //$NON-NLS-1$ consumeTypeHeaderNameWithTypeParameters(); break; - case 243 : if (DEBUG) { System.out.println("InterfaceHeaderName1 ::= Modifiersopt interface..."); } //$NON-NLS-1$ + case 292 : if (DEBUG) { System.out.println("InterfaceHeaderName1 ::= Modifiersopt interface..."); } //$NON-NLS-1$ consumeInterfaceHeaderName1(); break; - case 244 : if (DEBUG) { System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); } //$NON-NLS-1$ + case 293 : if (DEBUG) { System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); } //$NON-NLS-1$ consumeInterfaceHeaderExtends(); break; - case 247 : if (DEBUG) { System.out.println("InterfaceMemberDeclarations ::=..."); } //$NON-NLS-1$ + case 296 : if (DEBUG) { System.out.println("InterfaceMemberDeclarations ::=..."); } //$NON-NLS-1$ consumeInterfaceMemberDeclarations(); break; - case 248 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ + case 297 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); } //$NON-NLS-1$ consumeEmptyTypeDeclaration(); break; - case 250 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= DefaultMethodHeader..."); } //$NON-NLS-1$ + case 299 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= DefaultMethodHeader..."); } //$NON-NLS-1$ consumeInterfaceMethodDeclaration(false); break; - case 251 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= MethodHeader MethodBody"); } //$NON-NLS-1$ + case 300 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= MethodHeader MethodBody"); } //$NON-NLS-1$ consumeInterfaceMethodDeclaration(false); break; - case 252 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= DefaultMethodHeader..."); } //$NON-NLS-1$ + case 301 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= DefaultMethodHeader..."); } //$NON-NLS-1$ consumeInterfaceMethodDeclaration(true); break; - case 253 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); } //$NON-NLS-1$ + case 302 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); } //$NON-NLS-1$ consumeInvalidConstructorDeclaration(true); break; - case 254 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); } //$NON-NLS-1$ + case 303 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); } //$NON-NLS-1$ consumeInvalidConstructorDeclaration(false); break; - case 265 : if (DEBUG) { System.out.println("PushLeftBrace ::="); } //$NON-NLS-1$ + case 314 : if (DEBUG) { System.out.println("PushLeftBrace ::="); } //$NON-NLS-1$ consumePushLeftBrace(); break; - case 266 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace ,opt RBRACE"); } //$NON-NLS-1$ + case 315 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace ,opt RBRACE"); } //$NON-NLS-1$ consumeEmptyArrayInitializer(); break; - case 267 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$ + case 316 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$ consumeArrayInitializer(); break; - case 268 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$ + case 317 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$ consumeArrayInitializer(); break; - case 270 : if (DEBUG) { System.out.println("VariableInitializers ::= VariableInitializers COMMA..."); } //$NON-NLS-1$ + case 319 : if (DEBUG) { System.out.println("VariableInitializers ::= VariableInitializers COMMA..."); } //$NON-NLS-1$ consumeVariableInitializers(); break; - case 271 : if (DEBUG) { System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); } //$NON-NLS-1$ + case 320 : if (DEBUG) { System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); } //$NON-NLS-1$ consumeBlock(); break; - case 272 : if (DEBUG) { System.out.println("OpenBlock ::="); } //$NON-NLS-1$ + case 321 : if (DEBUG) { System.out.println("OpenBlock ::="); } //$NON-NLS-1$ consumeOpenBlock() ; break; - case 273 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatement"); } //$NON-NLS-1$ + case 322 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatement"); } //$NON-NLS-1$ consumeBlockStatement() ; break; - case 274 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatements BlockStatement"); } //$NON-NLS-1$ + case 323 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatements BlockStatement"); } //$NON-NLS-1$ consumeBlockStatements() ; break; - case 281 : if (DEBUG) { System.out.println("BlockStatement ::= InterfaceDeclaration"); } //$NON-NLS-1$ + case 330 : if (DEBUG) { System.out.println("BlockStatement ::= InterfaceDeclaration"); } //$NON-NLS-1$ consumeInvalidInterfaceDeclaration(); break; - case 282 : if (DEBUG) { System.out.println("BlockStatement ::= AnnotationTypeDeclaration"); } //$NON-NLS-1$ + case 331 : if (DEBUG) { System.out.println("BlockStatement ::= AnnotationTypeDeclaration"); } //$NON-NLS-1$ consumeInvalidAnnotationTypeDeclaration(); break; - case 283 : if (DEBUG) { System.out.println("BlockStatement ::= EnumDeclaration"); } //$NON-NLS-1$ + case 332 : if (DEBUG) { System.out.println("BlockStatement ::= EnumDeclaration"); } //$NON-NLS-1$ consumeInvalidEnumDeclaration(); break; - case 284 : if (DEBUG) { System.out.println("LocalVariableDeclarationStatement ::=..."); } //$NON-NLS-1$ + case 333 : if (DEBUG) { System.out.println("LocalVariableDeclarationStatement ::=..."); } //$NON-NLS-1$ consumeLocalVariableDeclarationStatement(); break; - case 285 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Type PushModifiers..."); } //$NON-NLS-1$ + case 334 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Type PushModifiers..."); } //$NON-NLS-1$ consumeLocalVariableDeclaration(); break; - case 286 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Modifiers Type..."); } //$NON-NLS-1$ + case 335 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Modifiers Type..."); } //$NON-NLS-1$ consumeLocalVariableDeclaration(); break; - case 287 : if (DEBUG) { System.out.println("PushModifiers ::="); } //$NON-NLS-1$ + case 336 : if (DEBUG) { System.out.println("PushModifiers ::="); } //$NON-NLS-1$ consumePushModifiers(); break; - case 288 : if (DEBUG) { System.out.println("PushModifiersForHeader ::="); } //$NON-NLS-1$ + case 337 : if (DEBUG) { System.out.println("PushModifiersForHeader ::="); } //$NON-NLS-1$ consumePushModifiersForHeader(); break; - case 289 : if (DEBUG) { System.out.println("PushRealModifiers ::="); } //$NON-NLS-1$ + case 338 : if (DEBUG) { System.out.println("PushRealModifiers ::="); } //$NON-NLS-1$ consumePushRealModifiers(); break; - case 316 : if (DEBUG) { System.out.println("EmptyStatement ::= SEMICOLON"); } //$NON-NLS-1$ + case 365 : if (DEBUG) { System.out.println("EmptyStatement ::= SEMICOLON"); } //$NON-NLS-1$ consumeEmptyStatement(); break; - case 317 : if (DEBUG) { System.out.println("LabeledStatement ::= Label COLON Statement"); } //$NON-NLS-1$ + case 366 : if (DEBUG) { System.out.println("LabeledStatement ::= Label COLON Statement"); } //$NON-NLS-1$ consumeStatementLabel() ; break; - case 318 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Label COLON..."); } //$NON-NLS-1$ + case 367 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Label COLON..."); } //$NON-NLS-1$ consumeStatementLabel() ; break; - case 319 : if (DEBUG) { System.out.println("Label ::= Identifier"); } //$NON-NLS-1$ + case 368 : if (DEBUG) { System.out.println("Label ::= Identifier"); } //$NON-NLS-1$ consumeLabel() ; break; - case 320 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); } //$NON-NLS-1$ + case 369 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); } //$NON-NLS-1$ consumeExpressionStatement(); break; - case 329 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); } //$NON-NLS-1$ + case 378 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); } //$NON-NLS-1$ consumeStatementIfNoElse(); break; - case 330 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); } //$NON-NLS-1$ + case 379 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); } //$NON-NLS-1$ consumeStatementIfWithElse(); break; - case 331 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); } //$NON-NLS-1$ + case 380 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); } //$NON-NLS-1$ consumeStatementIfWithElse(); break; - case 332 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); } //$NON-NLS-1$ + case 381 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); } //$NON-NLS-1$ consumeStatementSwitch() ; break; - case 333 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); } //$NON-NLS-1$ + case 382 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); } //$NON-NLS-1$ consumeEmptySwitchBlock() ; break; - case 336 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); } //$NON-NLS-1$ + case 385 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); } //$NON-NLS-1$ consumeSwitchBlock() ; break; - case 338 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); } //$NON-NLS-1$ + case 387 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); } //$NON-NLS-1$ consumeSwitchBlockStatements() ; break; - case 339 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); } //$NON-NLS-1$ + case 388 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); } //$NON-NLS-1$ consumeSwitchBlockStatement() ; break; - case 341 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); } //$NON-NLS-1$ + case 390 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); } //$NON-NLS-1$ consumeSwitchLabels() ; break; - case 342 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); } //$NON-NLS-1$ + case 391 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); } //$NON-NLS-1$ consumeCaseLabel(); break; - case 343 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); } //$NON-NLS-1$ + case 392 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); } //$NON-NLS-1$ consumeDefaultLabel(); break; - case 344 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); } //$NON-NLS-1$ + case 393 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); } //$NON-NLS-1$ consumeStatementWhile() ; break; - case 345 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); } //$NON-NLS-1$ + case 394 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); } //$NON-NLS-1$ consumeStatementWhile() ; break; - case 346 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); } //$NON-NLS-1$ + case 395 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); } //$NON-NLS-1$ consumeStatementDo() ; break; - case 347 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); } //$NON-NLS-1$ + case 396 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); } //$NON-NLS-1$ consumeStatementFor() ; break; - case 348 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); } //$NON-NLS-1$ + case 397 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); } //$NON-NLS-1$ consumeStatementFor() ; break; - case 349 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); } //$NON-NLS-1$ + case 398 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); } //$NON-NLS-1$ consumeForInit() ; break; - case 353 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); } //$NON-NLS-1$ + case 402 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); } //$NON-NLS-1$ consumeStatementExpressionList() ; break; - case 354 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); } //$NON-NLS-1$ + case 403 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); } //$NON-NLS-1$ consumeSimpleAssertStatement() ; break; - case 355 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); } //$NON-NLS-1$ + case 404 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); } //$NON-NLS-1$ consumeAssertStatement() ; break; - case 356 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); } //$NON-NLS-1$ + case 405 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); } //$NON-NLS-1$ consumeStatementBreak() ; break; - case 357 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); } //$NON-NLS-1$ + case 406 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); } //$NON-NLS-1$ consumeStatementBreakWithLabel() ; break; - case 358 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); } //$NON-NLS-1$ + case 407 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); } //$NON-NLS-1$ consumeStatementContinue() ; break; - case 359 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); } //$NON-NLS-1$ + case 408 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); } //$NON-NLS-1$ consumeStatementContinueWithLabel() ; break; - case 360 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); } //$NON-NLS-1$ + case 409 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); } //$NON-NLS-1$ consumeStatementReturn() ; break; - case 361 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); } //$NON-NLS-1$ + case 410 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); } //$NON-NLS-1$ consumeStatementThrow(); break; - case 362 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); } //$NON-NLS-1$ + case 411 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); } //$NON-NLS-1$ consumeStatementSynchronized(); break; - case 363 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); } //$NON-NLS-1$ + case 412 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); } //$NON-NLS-1$ consumeOnlySynchronized(); break; - case 364 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); } //$NON-NLS-1$ + case 413 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); } //$NON-NLS-1$ consumeStatementTry(false, false); break; - case 365 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); } //$NON-NLS-1$ + case 414 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); } //$NON-NLS-1$ consumeStatementTry(true, false); break; - case 366 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); } //$NON-NLS-1$ + case 415 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); } //$NON-NLS-1$ consumeStatementTry(false, true); break; - case 367 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); } //$NON-NLS-1$ + case 416 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); } //$NON-NLS-1$ consumeStatementTry(true, true); break; - case 368 : if (DEBUG) { System.out.println("ResourceSpecification ::= LPAREN Resources ;opt RPAREN"); } //$NON-NLS-1$ + case 417 : if (DEBUG) { System.out.println("ResourceSpecification ::= LPAREN Resources ;opt RPAREN"); } //$NON-NLS-1$ consumeResourceSpecification(); break; - case 369 : if (DEBUG) { System.out.println(";opt ::="); } //$NON-NLS-1$ + case 418 : if (DEBUG) { System.out.println(";opt ::="); } //$NON-NLS-1$ consumeResourceOptionalTrailingSemiColon(false); break; - case 370 : if (DEBUG) { System.out.println(";opt ::= SEMICOLON"); } //$NON-NLS-1$ + case 419 : if (DEBUG) { System.out.println(";opt ::= SEMICOLON"); } //$NON-NLS-1$ consumeResourceOptionalTrailingSemiColon(true); break; - case 371 : if (DEBUG) { System.out.println("Resources ::= Resource"); } //$NON-NLS-1$ + case 420 : if (DEBUG) { System.out.println("Resources ::= Resource"); } //$NON-NLS-1$ consumeSingleResource(); break; - case 372 : if (DEBUG) { System.out.println("Resources ::= Resources TrailingSemiColon Resource"); } //$NON-NLS-1$ + case 421 : if (DEBUG) { System.out.println("Resources ::= Resources TrailingSemiColon Resource"); } //$NON-NLS-1$ consumeMultipleResources(); break; - case 373 : if (DEBUG) { System.out.println("TrailingSemiColon ::= SEMICOLON"); } //$NON-NLS-1$ + case 422 : if (DEBUG) { System.out.println("TrailingSemiColon ::= SEMICOLON"); } //$NON-NLS-1$ consumeResourceOptionalTrailingSemiColon(true); break; - case 374 : if (DEBUG) { System.out.println("Resource ::= Type PushModifiers VariableDeclaratorId..."); } //$NON-NLS-1$ + case 423 : if (DEBUG) { System.out.println("Resource ::= Type PushModifiers VariableDeclaratorId..."); } //$NON-NLS-1$ consumeResourceAsLocalVariableDeclaration(); break; - case 375 : if (DEBUG) { System.out.println("Resource ::= Modifiers Type PushRealModifiers..."); } //$NON-NLS-1$ + case 424 : if (DEBUG) { System.out.println("Resource ::= Modifiers Type PushRealModifiers..."); } //$NON-NLS-1$ consumeResourceAsLocalVariableDeclaration(); break; - case 377 : if (DEBUG) { System.out.println("ExitTryBlock ::="); } //$NON-NLS-1$ + case 425 : if (DEBUG) { System.out.println("Resource ::= Name"); } //$NON-NLS-1$ + consumeResourceAsLocalVariable(); + break; + + case 426 : if (DEBUG) { System.out.println("Resource ::= FieldAccess"); } //$NON-NLS-1$ + consumeResourceAsFieldAccess(); + break; + + case 428 : if (DEBUG) { System.out.println("ExitTryBlock ::="); } //$NON-NLS-1$ consumeExitTryBlock(); break; - case 379 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); } //$NON-NLS-1$ + case 430 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); } //$NON-NLS-1$ consumeCatches(); break; - case 380 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN CatchFormalParameter RPAREN"); } //$NON-NLS-1$ + case 431 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN CatchFormalParameter RPAREN"); } //$NON-NLS-1$ consumeStatementCatch() ; break; - case 382 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); } //$NON-NLS-1$ + case 433 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); } //$NON-NLS-1$ consumeLeftParen(); break; - case 383 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); } //$NON-NLS-1$ + case 434 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); } //$NON-NLS-1$ consumeRightParen(); break; - case 388 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); } //$NON-NLS-1$ + case 439 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); } //$NON-NLS-1$ consumePrimaryNoNewArrayThis(); break; - case 389 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); } //$NON-NLS-1$ + case 440 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); } //$NON-NLS-1$ consumePrimaryNoNewArray(); break; - case 390 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); } //$NON-NLS-1$ + case 441 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); } //$NON-NLS-1$ consumePrimaryNoNewArrayWithName(); break; - case 393 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); } //$NON-NLS-1$ + case 444 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); } //$NON-NLS-1$ consumePrimaryNoNewArrayNameThis(); break; - case 394 : if (DEBUG) { System.out.println("QualifiedSuperReceiver ::= Name DOT super"); } //$NON-NLS-1$ + case 445 : if (DEBUG) { System.out.println("QualifiedSuperReceiver ::= Name DOT super"); } //$NON-NLS-1$ consumeQualifiedSuperReceiver(); break; - case 395 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); } //$NON-NLS-1$ + case 446 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); } //$NON-NLS-1$ consumePrimaryNoNewArrayName(); break; - case 396 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); } //$NON-NLS-1$ + case 447 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); } //$NON-NLS-1$ consumePrimaryNoNewArrayArrayType(); break; - case 397 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); } //$NON-NLS-1$ + case 448 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); } //$NON-NLS-1$ consumePrimaryNoNewArrayPrimitiveArrayType(); break; - case 398 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); } //$NON-NLS-1$ + case 449 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); } //$NON-NLS-1$ consumePrimaryNoNewArrayPrimitiveType(); break; - case 404 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); } //$NON-NLS-1$ + case 455 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); } //$NON-NLS-1$ consumeReferenceExpressionTypeArgumentsAndTrunk(false); break; - case 405 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); } //$NON-NLS-1$ + case 456 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); } //$NON-NLS-1$ consumeReferenceExpressionTypeArgumentsAndTrunk(true); break; - case 406 : if (DEBUG) { System.out.println("ReferenceExpression ::= PrimitiveType Dims COLON_COLON"); } //$NON-NLS-1$ + case 457 : if (DEBUG) { System.out.println("ReferenceExpression ::= PrimitiveType Dims COLON_COLON"); } //$NON-NLS-1$ consumeReferenceExpressionTypeForm(true); break; - case 407 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name Dimsopt COLON_COLON..."); } //$NON-NLS-1$ + case 458 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name Dimsopt COLON_COLON..."); } //$NON-NLS-1$ consumeReferenceExpressionTypeForm(false); break; - case 408 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name BeginTypeArguments..."); } //$NON-NLS-1$ + case 459 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name BeginTypeArguments..."); } //$NON-NLS-1$ consumeReferenceExpressionGenericTypeForm(); break; - case 409 : if (DEBUG) { System.out.println("ReferenceExpression ::= Primary COLON_COLON..."); } //$NON-NLS-1$ + case 460 : if (DEBUG) { System.out.println("ReferenceExpression ::= Primary COLON_COLON..."); } //$NON-NLS-1$ consumeReferenceExpressionPrimaryForm(); break; - case 410 : if (DEBUG) { System.out.println("ReferenceExpression ::= QualifiedSuperReceiver..."); } //$NON-NLS-1$ + case 461 : if (DEBUG) { System.out.println("ReferenceExpression ::= QualifiedSuperReceiver..."); } //$NON-NLS-1$ consumeReferenceExpressionPrimaryForm(); break; - case 411 : if (DEBUG) { System.out.println("ReferenceExpression ::= super COLON_COLON..."); } //$NON-NLS-1$ + case 462 : if (DEBUG) { System.out.println("ReferenceExpression ::= super COLON_COLON..."); } //$NON-NLS-1$ consumeReferenceExpressionSuperForm(); break; - case 412 : if (DEBUG) { System.out.println("NonWildTypeArgumentsopt ::="); } //$NON-NLS-1$ + case 463 : if (DEBUG) { System.out.println("NonWildTypeArgumentsopt ::="); } //$NON-NLS-1$ consumeEmptyTypeArguments(); break; - case 414 : if (DEBUG) { System.out.println("IdentifierOrNew ::= Identifier"); } //$NON-NLS-1$ + case 465 : if (DEBUG) { System.out.println("IdentifierOrNew ::= Identifier"); } //$NON-NLS-1$ consumeIdentifierOrNew(false); break; - case 415 : if (DEBUG) { System.out.println("IdentifierOrNew ::= new"); } //$NON-NLS-1$ + case 466 : if (DEBUG) { System.out.println("IdentifierOrNew ::= new"); } //$NON-NLS-1$ consumeIdentifierOrNew(true); break; - case 416 : if (DEBUG) { System.out.println("LambdaExpression ::= LambdaParameters ARROW LambdaBody"); } //$NON-NLS-1$ + case 467 : if (DEBUG) { System.out.println("LambdaExpression ::= LambdaParameters ARROW LambdaBody"); } //$NON-NLS-1$ consumeLambdaExpression(); break; - case 417 : if (DEBUG) { System.out.println("NestedLambda ::="); } //$NON-NLS-1$ + case 468 : if (DEBUG) { System.out.println("NestedLambda ::="); } //$NON-NLS-1$ consumeNestedLambda(); break; - case 418 : if (DEBUG) { System.out.println("LambdaParameters ::= Identifier NestedLambda"); } //$NON-NLS-1$ + case 469 : if (DEBUG) { System.out.println("LambdaParameters ::= Identifier NestedLambda"); } //$NON-NLS-1$ consumeTypeElidedLambdaParameter(false); break; - case 424 : if (DEBUG) { System.out.println("TypeElidedFormalParameterList ::=..."); } //$NON-NLS-1$ + case 475 : if (DEBUG) { System.out.println("TypeElidedFormalParameterList ::=..."); } //$NON-NLS-1$ consumeFormalParameterList(); break; - case 425 : if (DEBUG) { System.out.println("TypeElidedFormalParameter ::= Modifiersopt Identifier"); } //$NON-NLS-1$ + case 476 : if (DEBUG) { System.out.println("TypeElidedFormalParameter ::= Modifiersopt Identifier"); } //$NON-NLS-1$ consumeTypeElidedLambdaParameter(true); break; - case 428 : if (DEBUG) { System.out.println("ElidedLeftBraceAndReturn ::="); } //$NON-NLS-1$ + case 479 : if (DEBUG) { System.out.println("ElidedLeftBraceAndReturn ::="); } //$NON-NLS-1$ consumeElidedLeftBraceAndReturn(); break; - case 429 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); } //$NON-NLS-1$ + case 480 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); } //$NON-NLS-1$ consumeAllocationHeader(); break; - case 430 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); } //$NON-NLS-1$ + case 481 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionWithTypeArguments(); break; - case 431 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType..."); } //$NON-NLS-1$ + case 482 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpression(); break; - case 432 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); } //$NON-NLS-1$ + case 483 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ; break; - case 433 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); } //$NON-NLS-1$ + case 484 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionQualified() ; break; - case 434 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); } //$NON-NLS-1$ + case 485 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionQualified() ; break; - case 435 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); } //$NON-NLS-1$ + case 486 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ; break; - case 436 : if (DEBUG) { System.out.println("EnterInstanceCreationArgumentList ::="); } //$NON-NLS-1$ + case 487 : if (DEBUG) { System.out.println("EnterInstanceCreationArgumentList ::="); } //$NON-NLS-1$ consumeEnterInstanceCreationArgumentList(); break; - case 437 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT new"); } //$NON-NLS-1$ + case 488 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT new"); } //$NON-NLS-1$ consumeClassInstanceCreationExpressionName() ; break; - case 438 : if (DEBUG) { System.out.println("UnqualifiedClassBodyopt ::="); } //$NON-NLS-1$ + case 489 : if (DEBUG) { System.out.println("UnqualifiedClassBodyopt ::="); } //$NON-NLS-1$ consumeClassBodyopt(); break; - case 440 : if (DEBUG) { System.out.println("UnqualifiedEnterAnonymousClassBody ::="); } //$NON-NLS-1$ + case 491 : if (DEBUG) { System.out.println("UnqualifiedEnterAnonymousClassBody ::="); } //$NON-NLS-1$ consumeEnterAnonymousClassBody(false); break; - case 441 : if (DEBUG) { System.out.println("QualifiedClassBodyopt ::="); } //$NON-NLS-1$ + case 492 : if (DEBUG) { System.out.println("QualifiedClassBodyopt ::="); } //$NON-NLS-1$ consumeClassBodyopt(); break; - case 443 : if (DEBUG) { System.out.println("QualifiedEnterAnonymousClassBody ::="); } //$NON-NLS-1$ + case 494 : if (DEBUG) { System.out.println("QualifiedEnterAnonymousClassBody ::="); } //$NON-NLS-1$ consumeEnterAnonymousClassBody(true); break; - case 445 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); } //$NON-NLS-1$ + case 496 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); } //$NON-NLS-1$ consumeArgumentList(); break; - case 446 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); } //$NON-NLS-1$ + case 497 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); } //$NON-NLS-1$ consumeArrayCreationHeader(); break; - case 447 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); } //$NON-NLS-1$ + case 498 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); } //$NON-NLS-1$ consumeArrayCreationHeader(); break; - case 448 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); } //$NON-NLS-1$ + case 499 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); } //$NON-NLS-1$ consumeArrayCreationExpressionWithoutInitializer(); break; - case 449 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); } //$NON-NLS-1$ + case 500 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); } //$NON-NLS-1$ consumeArrayCreationExpressionWithInitializer(); break; - case 450 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); } //$NON-NLS-1$ + case 501 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); } //$NON-NLS-1$ consumeArrayCreationExpressionWithoutInitializer(); break; - case 451 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); } //$NON-NLS-1$ + case 502 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); } //$NON-NLS-1$ consumeArrayCreationExpressionWithInitializer(); break; - case 453 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); } //$NON-NLS-1$ + case 504 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); } //$NON-NLS-1$ consumeDimWithOrWithOutExprs(); break; - case 455 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= TypeAnnotationsopt LBRACKET..."); } //$NON-NLS-1$ + case 506 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= TypeAnnotationsopt LBRACKET..."); } //$NON-NLS-1$ consumeDimWithOrWithOutExpr(); break; - case 456 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); } //$NON-NLS-1$ + case 507 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); } //$NON-NLS-1$ consumeDims(); break; - case 459 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); } //$NON-NLS-1$ + case 510 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); } //$NON-NLS-1$ consumeOneDimLoop(false); break; - case 460 : if (DEBUG) { System.out.println("OneDimLoop ::= TypeAnnotations LBRACKET RBRACKET"); } //$NON-NLS-1$ + case 511 : if (DEBUG) { System.out.println("OneDimLoop ::= TypeAnnotations LBRACKET RBRACKET"); } //$NON-NLS-1$ consumeOneDimLoop(true); break; - case 461 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); } //$NON-NLS-1$ + case 512 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); } //$NON-NLS-1$ consumeFieldAccess(false); break; - case 462 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); } //$NON-NLS-1$ + case 513 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); } //$NON-NLS-1$ consumeFieldAccess(true); break; - case 463 : if (DEBUG) { System.out.println("FieldAccess ::= QualifiedSuperReceiver DOT Identifier"); } //$NON-NLS-1$ + case 514 : if (DEBUG) { System.out.println("FieldAccess ::= QualifiedSuperReceiver DOT Identifier"); } //$NON-NLS-1$ consumeFieldAccess(false); break; - case 464 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); } //$NON-NLS-1$ + case 515 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); } //$NON-NLS-1$ consumeMethodInvocationName(); break; - case 465 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); } //$NON-NLS-1$ + case 516 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); } //$NON-NLS-1$ consumeMethodInvocationNameWithTypeArguments(); break; - case 466 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); } //$NON-NLS-1$ + case 517 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); } //$NON-NLS-1$ consumeMethodInvocationPrimaryWithTypeArguments(); break; - case 467 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); } //$NON-NLS-1$ + case 518 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); } //$NON-NLS-1$ consumeMethodInvocationPrimary(); break; - case 468 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); } //$NON-NLS-1$ + case 519 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); } //$NON-NLS-1$ consumeMethodInvocationPrimary(); break; - case 469 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); } //$NON-NLS-1$ + case 520 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); } //$NON-NLS-1$ consumeMethodInvocationPrimaryWithTypeArguments(); break; - case 470 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); } //$NON-NLS-1$ + case 521 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); } //$NON-NLS-1$ consumeMethodInvocationSuperWithTypeArguments(); break; - case 471 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); } //$NON-NLS-1$ + case 522 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); } //$NON-NLS-1$ consumeMethodInvocationSuper(); break; - case 472 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); } //$NON-NLS-1$ + case 523 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); } //$NON-NLS-1$ consumeArrayAccess(true); break; - case 473 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); } //$NON-NLS-1$ + case 524 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); } //$NON-NLS-1$ consumeArrayAccess(false); break; - case 474 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); } //$NON-NLS-1$ + case 525 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); } //$NON-NLS-1$ consumeArrayAccess(false); break; - case 476 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); } //$NON-NLS-1$ + case 527 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); } //$NON-NLS-1$ consumePostfixExpression(); break; - case 479 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); } //$NON-NLS-1$ + case 530 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.PLUS,true); break; - case 480 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); } //$NON-NLS-1$ + case 531 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.MINUS,true); break; - case 481 : if (DEBUG) { System.out.println("PushPosition ::="); } //$NON-NLS-1$ + case 532 : if (DEBUG) { System.out.println("PushPosition ::="); } //$NON-NLS-1$ consumePushPosition(); break; - case 484 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); } //$NON-NLS-1$ + case 535 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.PLUS); break; - case 485 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); } //$NON-NLS-1$ + case 536 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.MINUS); break; - case 487 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); } //$NON-NLS-1$ + case 538 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.PLUS,false); break; - case 488 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); } //$NON-NLS-1$ + case 539 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.MINUS,false); break; - case 490 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); } //$NON-NLS-1$ + case 541 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.TWIDDLE); break; - case 491 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); } //$NON-NLS-1$ + case 542 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.NOT); break; - case 493 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); } //$NON-NLS-1$ + case 544 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); } //$NON-NLS-1$ consumeCastExpressionWithPrimitiveType(); break; - case 494 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); } //$NON-NLS-1$ + case 545 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); } //$NON-NLS-1$ consumeCastExpressionWithGenericsArray(); break; - case 495 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); } //$NON-NLS-1$ + case 546 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); } //$NON-NLS-1$ consumeCastExpressionWithQualifiedGenericsArray(); break; - case 496 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); } //$NON-NLS-1$ + case 547 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); } //$NON-NLS-1$ consumeCastExpressionLL1(); break; - case 497 : if (DEBUG) { System.out.println("CastExpression ::= BeginIntersectionCast PushLPAREN..."); } //$NON-NLS-1$ + case 548 : if (DEBUG) { System.out.println("CastExpression ::= BeginIntersectionCast PushLPAREN..."); } //$NON-NLS-1$ consumeCastExpressionLL1WithBounds(); break; - case 498 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims..."); } //$NON-NLS-1$ + case 549 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims..."); } //$NON-NLS-1$ consumeCastExpressionWithNameArray(); break; - case 499 : if (DEBUG) { System.out.println("AdditionalBoundsListOpt ::="); } //$NON-NLS-1$ + case 550 : if (DEBUG) { System.out.println("AdditionalBoundsListOpt ::="); } //$NON-NLS-1$ consumeZeroAdditionalBounds(); break; - case 503 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); } //$NON-NLS-1$ + case 554 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); } //$NON-NLS-1$ consumeOnlyTypeArgumentsForCastExpression(); break; - case 504 : if (DEBUG) { System.out.println("InsideCastExpression ::="); } //$NON-NLS-1$ + case 555 : if (DEBUG) { System.out.println("InsideCastExpression ::="); } //$NON-NLS-1$ consumeInsideCastExpression(); break; - case 505 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); } //$NON-NLS-1$ + case 556 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); } //$NON-NLS-1$ consumeInsideCastExpressionLL1(); break; - case 506 : if (DEBUG) { System.out.println("InsideCastExpressionLL1WithBounds ::="); } //$NON-NLS-1$ + case 557 : if (DEBUG) { System.out.println("InsideCastExpressionLL1WithBounds ::="); } //$NON-NLS-1$ consumeInsideCastExpressionLL1WithBounds (); break; - case 507 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); } //$NON-NLS-1$ + case 558 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); } //$NON-NLS-1$ consumeInsideCastExpressionWithQualifiedGenerics(); break; - case 509 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ + case 560 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.MULTIPLY); break; - case 510 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ + case 561 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.DIVIDE); break; - case 511 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ + case 562 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.REMAINDER); break; - case 513 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); } //$NON-NLS-1$ + case 564 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.PLUS); break; - case 514 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); } //$NON-NLS-1$ + case 565 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.MINUS); break; - case 516 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); } //$NON-NLS-1$ + case 567 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LEFT_SHIFT); break; - case 517 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); } //$NON-NLS-1$ + case 568 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.RIGHT_SHIFT); break; - case 518 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$ + case 569 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT); break; - case 520 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); } //$NON-NLS-1$ + case 571 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LESS); break; - case 521 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); } //$NON-NLS-1$ + case 572 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.GREATER); break; - case 522 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); } //$NON-NLS-1$ + case 573 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LESS_EQUAL); break; - case 523 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); } //$NON-NLS-1$ + case 574 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.GREATER_EQUAL); break; - case 525 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); } //$NON-NLS-1$ + case 576 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); } //$NON-NLS-1$ consumeInstanceOfExpression(); break; - case 527 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); } //$NON-NLS-1$ + case 578 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); } //$NON-NLS-1$ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL); break; - case 528 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); } //$NON-NLS-1$ + case 579 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); } //$NON-NLS-1$ consumeEqualityExpression(OperatorIds.NOT_EQUAL); break; - case 530 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); } //$NON-NLS-1$ + case 581 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.AND); break; - case 532 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); } //$NON-NLS-1$ + case 583 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.XOR); break; - case 534 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); } //$NON-NLS-1$ + case 585 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.OR); break; - case 536 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); } //$NON-NLS-1$ + case 587 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.AND_AND); break; - case 538 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); } //$NON-NLS-1$ + case 589 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.OR_OR); break; - case 540 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); } //$NON-NLS-1$ + case 591 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); } //$NON-NLS-1$ consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ; break; - case 543 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); } //$NON-NLS-1$ + case 594 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); } //$NON-NLS-1$ consumeAssignment(); break; - case 545 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); } //$NON-NLS-1$ + case 596 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); } //$NON-NLS-1$ ignoreExpressionAssignment(); break; - case 546 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); } //$NON-NLS-1$ + case 597 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(EQUAL); break; - case 547 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); } //$NON-NLS-1$ + case 598 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(MULTIPLY); break; - case 548 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); } //$NON-NLS-1$ + case 599 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(DIVIDE); break; - case 549 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); } //$NON-NLS-1$ + case 600 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(REMAINDER); break; - case 550 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); } //$NON-NLS-1$ + case 601 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(PLUS); break; - case 551 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); } //$NON-NLS-1$ + case 602 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(MINUS); break; - case 552 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); } //$NON-NLS-1$ + case 603 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(LEFT_SHIFT); break; - case 553 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); } //$NON-NLS-1$ + case 604 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(RIGHT_SHIFT); break; - case 554 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); } //$NON-NLS-1$ + case 605 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT); break; - case 555 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); } //$NON-NLS-1$ + case 606 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(AND); break; - case 556 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); } //$NON-NLS-1$ + case 607 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(XOR); break; - case 557 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); } //$NON-NLS-1$ + case 608 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); } //$NON-NLS-1$ consumeAssignmentOperator(OR); break; - case 558 : if (DEBUG) { System.out.println("Expression ::= AssignmentExpression"); } //$NON-NLS-1$ + case 609 : if (DEBUG) { System.out.println("Expression ::= AssignmentExpression"); } //$NON-NLS-1$ consumeExpression(); break; - case 561 : if (DEBUG) { System.out.println("Expressionopt ::="); } //$NON-NLS-1$ + case 612 : if (DEBUG) { System.out.println("Expressionopt ::="); } //$NON-NLS-1$ consumeEmptyExpression(); break; - case 566 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); } //$NON-NLS-1$ + case 617 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); } //$NON-NLS-1$ consumeEmptyClassBodyDeclarationsopt(); break; - case 567 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ + case 618 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ consumeClassBodyDeclarationsopt(); break; - case 568 : if (DEBUG) { System.out.println("Modifiersopt ::="); } //$NON-NLS-1$ + case 619 : if (DEBUG) { System.out.println("Modifiersopt ::="); } //$NON-NLS-1$ consumeDefaultModifiers(); break; - case 569 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); } //$NON-NLS-1$ + case 620 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); } //$NON-NLS-1$ consumeModifiers(); break; - case 570 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); } //$NON-NLS-1$ + case 621 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); } //$NON-NLS-1$ consumeEmptyBlockStatementsopt(); break; - case 572 : if (DEBUG) { System.out.println("Dimsopt ::="); } //$NON-NLS-1$ + case 623 : if (DEBUG) { System.out.println("Dimsopt ::="); } //$NON-NLS-1$ consumeEmptyDimsopt(); break; - case 574 : if (DEBUG) { System.out.println("ArgumentListopt ::="); } //$NON-NLS-1$ + case 625 : if (DEBUG) { System.out.println("ArgumentListopt ::="); } //$NON-NLS-1$ consumeEmptyArgumentListopt(); break; - case 578 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); } //$NON-NLS-1$ + case 629 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); } //$NON-NLS-1$ consumeFormalParameterListopt(); break; - case 582 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); } //$NON-NLS-1$ + case 633 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); } //$NON-NLS-1$ consumeEmptyInterfaceMemberDeclarationsopt(); break; - case 583 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ + case 634 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ consumeInterfaceMemberDeclarationsopt(); break; - case 584 : if (DEBUG) { System.out.println("NestedType ::="); } //$NON-NLS-1$ + case 635 : if (DEBUG) { System.out.println("NestedType ::="); } //$NON-NLS-1$ consumeNestedType(); break; - case 585 : if (DEBUG) { System.out.println("ForInitopt ::="); } //$NON-NLS-1$ + case 636 : if (DEBUG) { System.out.println("ForInitopt ::="); } //$NON-NLS-1$ consumeEmptyForInitopt(); break; - case 587 : if (DEBUG) { System.out.println("ForUpdateopt ::="); } //$NON-NLS-1$ + case 638 : if (DEBUG) { System.out.println("ForUpdateopt ::="); } //$NON-NLS-1$ consumeEmptyForUpdateopt(); break; - case 591 : if (DEBUG) { System.out.println("Catchesopt ::="); } //$NON-NLS-1$ + case 642 : if (DEBUG) { System.out.println("Catchesopt ::="); } //$NON-NLS-1$ consumeEmptyCatchesopt(); break; - case 593 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); } //$NON-NLS-1$ + case 644 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); } //$NON-NLS-1$ consumeEnumDeclaration(); break; - case 594 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); } //$NON-NLS-1$ + case 645 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); } //$NON-NLS-1$ consumeEnumHeader(); break; - case 595 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); } //$NON-NLS-1$ + case 646 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); } //$NON-NLS-1$ consumeEnumHeaderName(); break; - case 596 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier..."); } //$NON-NLS-1$ + case 647 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier..."); } //$NON-NLS-1$ consumeEnumHeaderNameWithTypeParameters(); break; - case 597 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); } //$NON-NLS-1$ + case 648 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); } //$NON-NLS-1$ consumeEnumBodyNoConstants(); break; - case 598 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); } //$NON-NLS-1$ + case 649 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); } //$NON-NLS-1$ consumeEnumBodyNoConstants(); break; - case 599 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); } //$NON-NLS-1$ + case 650 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); } //$NON-NLS-1$ consumeEnumBodyWithConstants(); break; - case 600 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); } //$NON-NLS-1$ + case 651 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); } //$NON-NLS-1$ consumeEnumBodyWithConstants(); break; - case 602 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); } //$NON-NLS-1$ + case 653 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); } //$NON-NLS-1$ consumeEnumConstants(); break; - case 603 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); } //$NON-NLS-1$ + case 654 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); } //$NON-NLS-1$ consumeEnumConstantHeaderName(); break; - case 604 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); } //$NON-NLS-1$ + case 655 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); } //$NON-NLS-1$ consumeEnumConstantHeader(); break; - case 605 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); } //$NON-NLS-1$ + case 656 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); } //$NON-NLS-1$ consumeEnumConstantWithClassBody(); break; - case 606 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); } //$NON-NLS-1$ + case 657 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); } //$NON-NLS-1$ consumeEnumConstantNoClassBody(); break; - case 607 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); } //$NON-NLS-1$ + case 658 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); } //$NON-NLS-1$ consumeArguments(); break; - case 608 : if (DEBUG) { System.out.println("Argumentsopt ::="); } //$NON-NLS-1$ + case 659 : if (DEBUG) { System.out.println("Argumentsopt ::="); } //$NON-NLS-1$ consumeEmptyArguments(); break; - case 610 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); } //$NON-NLS-1$ + case 661 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); } //$NON-NLS-1$ consumeEnumDeclarations(); break; - case 611 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); } //$NON-NLS-1$ + case 662 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); } //$NON-NLS-1$ consumeEmptyEnumDeclarations(); break; - case 613 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); } //$NON-NLS-1$ + case 664 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); } //$NON-NLS-1$ consumeEnhancedForStatement(); break; - case 614 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); } //$NON-NLS-1$ + case 665 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); } //$NON-NLS-1$ consumeEnhancedForStatement(); break; - case 615 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); } //$NON-NLS-1$ + case 666 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); } //$NON-NLS-1$ consumeEnhancedForStatementHeaderInit(false); break; - case 616 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); } //$NON-NLS-1$ + case 667 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); } //$NON-NLS-1$ consumeEnhancedForStatementHeaderInit(true); break; - case 617 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); } //$NON-NLS-1$ + case 668 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); } //$NON-NLS-1$ consumeEnhancedForStatementHeader(); break; - case 618 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); } //$NON-NLS-1$ + case 669 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); } //$NON-NLS-1$ consumeImportDeclaration(); break; - case 619 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); } //$NON-NLS-1$ + case 670 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); } //$NON-NLS-1$ consumeSingleStaticImportDeclarationName(); break; - case 620 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); } //$NON-NLS-1$ + case 671 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); } //$NON-NLS-1$ consumeImportDeclaration(); break; - case 621 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); } //$NON-NLS-1$ + case 672 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); } //$NON-NLS-1$ consumeStaticImportOnDemandDeclarationName(); break; - case 622 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); } //$NON-NLS-1$ + case 673 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); } //$NON-NLS-1$ consumeTypeArguments(); break; - case 623 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); } //$NON-NLS-1$ + case 674 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); } //$NON-NLS-1$ consumeOnlyTypeArguments(); break; - case 625 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ + case 676 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ consumeTypeArgumentList1(); break; - case 627 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); } //$NON-NLS-1$ + case 678 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); } //$NON-NLS-1$ consumeTypeArgumentList(); break; - case 628 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); } //$NON-NLS-1$ + case 679 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); } //$NON-NLS-1$ consumeTypeArgument(); break; - case 632 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); } //$NON-NLS-1$ + case 683 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); } //$NON-NLS-1$ consumeReferenceType1(); break; - case 633 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); } //$NON-NLS-1$ + case 684 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); } //$NON-NLS-1$ consumeTypeArgumentReferenceType1(); break; - case 635 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ + case 686 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ consumeTypeArgumentList2(); break; - case 638 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); } //$NON-NLS-1$ + case 689 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); } //$NON-NLS-1$ consumeReferenceType2(); break; - case 639 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); } //$NON-NLS-1$ + case 690 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); } //$NON-NLS-1$ consumeTypeArgumentReferenceType2(); break; - case 641 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ + case 692 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$ consumeTypeArgumentList3(); break; - case 644 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$ + case 695 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$ consumeReferenceType3(); break; - case 645 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION"); } //$NON-NLS-1$ + case 696 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION"); } //$NON-NLS-1$ consumeWildcard(); break; - case 646 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION WildcardBounds"); } //$NON-NLS-1$ + case 697 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION WildcardBounds"); } //$NON-NLS-1$ consumeWildcardWithBounds(); break; - case 647 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); } //$NON-NLS-1$ + case 698 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); } //$NON-NLS-1$ consumeWildcardBoundsExtends(); break; - case 648 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); } //$NON-NLS-1$ + case 699 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); } //$NON-NLS-1$ consumeWildcardBoundsSuper(); break; - case 649 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION GREATER"); } //$NON-NLS-1$ + case 700 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION GREATER"); } //$NON-NLS-1$ consumeWildcard1(); break; - case 650 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION..."); } //$NON-NLS-1$ + case 701 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION..."); } //$NON-NLS-1$ consumeWildcard1WithBounds(); break; - case 651 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); } //$NON-NLS-1$ + case 702 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); } //$NON-NLS-1$ consumeWildcardBounds1Extends(); break; - case 652 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); } //$NON-NLS-1$ + case 703 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); } //$NON-NLS-1$ consumeWildcardBounds1Super(); break; - case 653 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION RIGHT_SHIFT"); } //$NON-NLS-1$ + case 704 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION RIGHT_SHIFT"); } //$NON-NLS-1$ consumeWildcard2(); break; - case 654 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION..."); } //$NON-NLS-1$ + case 705 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION..."); } //$NON-NLS-1$ consumeWildcard2WithBounds(); break; - case 655 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); } //$NON-NLS-1$ + case 706 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); } //$NON-NLS-1$ consumeWildcardBounds2Extends(); break; - case 656 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); } //$NON-NLS-1$ + case 707 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); } //$NON-NLS-1$ consumeWildcardBounds2Super(); break; - case 657 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); } //$NON-NLS-1$ + case 708 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); } //$NON-NLS-1$ consumeWildcard3(); break; - case 658 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); } //$NON-NLS-1$ + case 709 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); } //$NON-NLS-1$ consumeWildcard3WithBounds(); break; - case 659 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); } //$NON-NLS-1$ + case 710 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); } //$NON-NLS-1$ consumeWildcardBounds3Extends(); break; - case 660 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); } //$NON-NLS-1$ + case 711 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); } //$NON-NLS-1$ consumeWildcardBounds3Super(); break; - case 661 : if (DEBUG) { System.out.println("TypeParameterHeader ::= TypeAnnotationsopt Identifier"); } //$NON-NLS-1$ + case 712 : if (DEBUG) { System.out.println("TypeParameterHeader ::= TypeAnnotationsopt Identifier"); } //$NON-NLS-1$ consumeTypeParameterHeader(); break; - case 662 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); } //$NON-NLS-1$ + case 713 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); } //$NON-NLS-1$ consumeTypeParameters(); break; - case 664 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); } //$NON-NLS-1$ + case 715 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); } //$NON-NLS-1$ consumeTypeParameterList(); break; - case 666 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ + case 717 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ consumeTypeParameterWithExtends(); break; - case 667 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ + case 718 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ consumeTypeParameterWithExtendsAndBounds(); break; - case 669 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); } //$NON-NLS-1$ + case 720 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); } //$NON-NLS-1$ consumeAdditionalBoundList(); break; - case 670 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); } //$NON-NLS-1$ + case 721 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); } //$NON-NLS-1$ consumeAdditionalBound(); break; - case 672 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); } //$NON-NLS-1$ + case 723 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); } //$NON-NLS-1$ consumeTypeParameterList1(); break; - case 673 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); } //$NON-NLS-1$ + case 724 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); } //$NON-NLS-1$ consumeTypeParameter1(); break; - case 674 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ + case 725 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ consumeTypeParameter1WithExtends(); break; - case 675 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ + case 726 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); } //$NON-NLS-1$ consumeTypeParameter1WithExtendsAndBounds(); break; - case 677 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); } //$NON-NLS-1$ + case 728 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); } //$NON-NLS-1$ consumeAdditionalBoundList1(); break; - case 678 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); } //$NON-NLS-1$ + case 729 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); } //$NON-NLS-1$ consumeAdditionalBound1(); break; - case 684 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); } //$NON-NLS-1$ + case 735 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.PLUS); break; - case 685 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); } //$NON-NLS-1$ + case 736 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.MINUS); break; - case 688 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); } //$NON-NLS-1$ + case 739 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.TWIDDLE); break; - case 689 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); } //$NON-NLS-1$ + case 740 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); } //$NON-NLS-1$ consumeUnaryExpression(OperatorIds.NOT); break; - case 692 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ + case 743 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.MULTIPLY); break; - case 693 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); } //$NON-NLS-1$ + case 744 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.MULTIPLY); break; - case 694 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ + case 745 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.DIVIDE); break; - case 695 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); } //$NON-NLS-1$ + case 746 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.DIVIDE); break; - case 696 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ + case 747 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.REMAINDER); break; - case 697 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); } //$NON-NLS-1$ + case 748 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.REMAINDER); break; - case 699 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); } //$NON-NLS-1$ + case 750 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.PLUS); break; - case 700 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); } //$NON-NLS-1$ + case 751 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.PLUS); break; - case 701 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); } //$NON-NLS-1$ + case 752 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.MINUS); break; - case 702 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); } //$NON-NLS-1$ + case 753 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.MINUS); break; - case 704 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ + case 755 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LEFT_SHIFT); break; - case 705 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); } //$NON-NLS-1$ + case 756 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.LEFT_SHIFT); break; - case 706 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ + case 757 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.RIGHT_SHIFT); break; - case 707 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); } //$NON-NLS-1$ + case 758 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.RIGHT_SHIFT); break; - case 708 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ + case 759 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT); break; - case 709 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT..."); } //$NON-NLS-1$ + case 760 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.UNSIGNED_RIGHT_SHIFT); break; - case 711 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); } //$NON-NLS-1$ + case 762 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LESS); break; - case 712 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); } //$NON-NLS-1$ + case 763 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.LESS); break; - case 713 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); } //$NON-NLS-1$ + case 764 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.GREATER); break; - case 714 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); } //$NON-NLS-1$ + case 765 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.GREATER); break; - case 715 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); } //$NON-NLS-1$ + case 766 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.LESS_EQUAL); break; - case 716 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); } //$NON-NLS-1$ + case 767 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.LESS_EQUAL); break; - case 717 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); } //$NON-NLS-1$ + case 768 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.GREATER_EQUAL); break; - case 718 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); } //$NON-NLS-1$ + case 769 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.GREATER_EQUAL); break; - case 720 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name instanceof..."); } //$NON-NLS-1$ + case 771 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name instanceof..."); } //$NON-NLS-1$ consumeInstanceOfExpressionWithName(); break; - case 721 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); } //$NON-NLS-1$ + case 772 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); } //$NON-NLS-1$ consumeInstanceOfExpression(); break; - case 723 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); } //$NON-NLS-1$ + case 774 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); } //$NON-NLS-1$ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL); break; - case 724 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); } //$NON-NLS-1$ + case 775 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); } //$NON-NLS-1$ consumeEqualityExpressionWithName(OperatorIds.EQUAL_EQUAL); break; - case 725 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); } //$NON-NLS-1$ + case 776 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); } //$NON-NLS-1$ consumeEqualityExpression(OperatorIds.NOT_EQUAL); break; - case 726 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); } //$NON-NLS-1$ + case 777 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); } //$NON-NLS-1$ consumeEqualityExpressionWithName(OperatorIds.NOT_EQUAL); break; - case 728 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); } //$NON-NLS-1$ + case 779 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.AND); break; - case 729 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); } //$NON-NLS-1$ + case 780 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.AND); break; - case 731 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); } //$NON-NLS-1$ + case 782 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.XOR); break; - case 732 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR AndExpression"); } //$NON-NLS-1$ + case 783 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR AndExpression"); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.XOR); break; - case 734 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); } //$NON-NLS-1$ + case 785 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.OR); break; - case 735 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); } //$NON-NLS-1$ + case 786 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.OR); break; - case 737 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); } //$NON-NLS-1$ + case 788 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.AND_AND); break; - case 738 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); } //$NON-NLS-1$ + case 789 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.AND_AND); break; - case 740 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); } //$NON-NLS-1$ + case 791 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); } //$NON-NLS-1$ consumeBinaryExpression(OperatorIds.OR_OR); break; - case 741 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); } //$NON-NLS-1$ + case 792 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); } //$NON-NLS-1$ consumeBinaryExpressionWithName(OperatorIds.OR_OR); break; - case 743 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); } //$NON-NLS-1$ + case 794 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); } //$NON-NLS-1$ consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ; break; - case 744 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); } //$NON-NLS-1$ + case 795 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); } //$NON-NLS-1$ consumeConditionalExpressionWithName(OperatorIds.QUESTIONCOLON) ; break; - case 748 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); } //$NON-NLS-1$ + case 799 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeaderName() ; break; - case 749 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); } //$NON-NLS-1$ + case 800 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ; break; - case 750 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); } //$NON-NLS-1$ + case 801 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ; break; - case 751 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); } //$NON-NLS-1$ + case 802 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeaderName() ; break; - case 752 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); } //$NON-NLS-1$ + case 803 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclarationHeader() ; break; - case 753 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); } //$NON-NLS-1$ + case 804 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); } //$NON-NLS-1$ consumeAnnotationTypeDeclaration() ; break; - case 755 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); } //$NON-NLS-1$ + case 806 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); } //$NON-NLS-1$ consumeEmptyAnnotationTypeMemberDeclarationsopt() ; break; - case 756 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ + case 807 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$ consumeAnnotationTypeMemberDeclarationsopt() ; break; - case 758 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); } //$NON-NLS-1$ + case 809 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); } //$NON-NLS-1$ consumeAnnotationTypeMemberDeclarations() ; break; - case 759 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); } //$NON-NLS-1$ + case 810 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); } //$NON-NLS-1$ consumeMethodHeaderNameWithTypeParameters(true); break; - case 760 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); } //$NON-NLS-1$ + case 811 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeMethodHeaderName(true); break; - case 761 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); } //$NON-NLS-1$ + case 812 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); } //$NON-NLS-1$ consumeEmptyMethodHeaderDefaultValue() ; break; - case 762 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); } //$NON-NLS-1$ + case 813 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); } //$NON-NLS-1$ consumeMethodHeaderDefaultValue(); break; - case 763 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); } //$NON-NLS-1$ + case 814 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); } //$NON-NLS-1$ consumeMethodHeader(); break; - case 764 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); } //$NON-NLS-1$ + case 815 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); } //$NON-NLS-1$ consumeAnnotationTypeMemberDeclaration() ; break; - case 772 : if (DEBUG) { System.out.println("AnnotationName ::= AT UnannotatableName"); } //$NON-NLS-1$ + case 823 : if (DEBUG) { System.out.println("AnnotationName ::= AT UnannotatableName"); } //$NON-NLS-1$ consumeAnnotationName() ; break; - case 773 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); } //$NON-NLS-1$ + case 824 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); } //$NON-NLS-1$ consumeNormalAnnotation(false) ; break; - case 774 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); } //$NON-NLS-1$ + case 825 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); } //$NON-NLS-1$ consumeEmptyMemberValuePairsopt() ; break; - case 777 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); } //$NON-NLS-1$ + case 828 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); } //$NON-NLS-1$ consumeMemberValuePairs() ; break; - case 778 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue..."); } //$NON-NLS-1$ + case 829 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue..."); } //$NON-NLS-1$ consumeMemberValuePair() ; break; - case 779 : if (DEBUG) { System.out.println("EnterMemberValue ::="); } //$NON-NLS-1$ + case 830 : if (DEBUG) { System.out.println("EnterMemberValue ::="); } //$NON-NLS-1$ consumeEnterMemberValue() ; break; - case 780 : if (DEBUG) { System.out.println("ExitMemberValue ::="); } //$NON-NLS-1$ + case 831 : if (DEBUG) { System.out.println("ExitMemberValue ::="); } //$NON-NLS-1$ consumeExitMemberValue() ; break; - case 782 : if (DEBUG) { System.out.println("MemberValue ::= Name"); } //$NON-NLS-1$ + case 833 : if (DEBUG) { System.out.println("MemberValue ::= Name"); } //$NON-NLS-1$ consumeMemberValueAsName() ; break; - case 785 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ + case 836 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ consumeMemberValueArrayInitializer() ; break; - case 786 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ + case 837 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ consumeMemberValueArrayInitializer() ; break; - case 787 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ + case 838 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ consumeEmptyMemberValueArrayInitializer() ; break; - case 788 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ + case 839 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); } //$NON-NLS-1$ consumeEmptyMemberValueArrayInitializer() ; break; - case 789 : if (DEBUG) { System.out.println("EnterMemberValueArrayInitializer ::="); } //$NON-NLS-1$ + case 840 : if (DEBUG) { System.out.println("EnterMemberValueArrayInitializer ::="); } //$NON-NLS-1$ consumeEnterMemberValueArrayInitializer() ; break; - case 791 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); } //$NON-NLS-1$ + case 842 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); } //$NON-NLS-1$ consumeMemberValues() ; break; - case 792 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); } //$NON-NLS-1$ + case 843 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); } //$NON-NLS-1$ consumeMarkerAnnotation(false) ; break; - case 793 : if (DEBUG) { System.out.println("SingleMemberAnnotationMemberValue ::= MemberValue"); } //$NON-NLS-1$ + case 844 : if (DEBUG) { System.out.println("SingleMemberAnnotationMemberValue ::= MemberValue"); } //$NON-NLS-1$ consumeSingleMemberAnnotationMemberValue() ; break; - case 794 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); } //$NON-NLS-1$ + case 845 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); } //$NON-NLS-1$ consumeSingleMemberAnnotation(false) ; break; - case 795 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); } //$NON-NLS-1$ + case 846 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); } //$NON-NLS-1$ consumeRecoveryMethodHeaderNameWithTypeParameters(); break; - case 796 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); } //$NON-NLS-1$ + case 847 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); } //$NON-NLS-1$ consumeRecoveryMethodHeaderName(); break; - case 797 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault..."); } //$NON-NLS-1$ + case 848 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault..."); } //$NON-NLS-1$ consumeRecoveryMethodHeaderNameWithTypeParameters(); break; - case 798 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault Type"); } //$NON-NLS-1$ + case 849 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault Type"); } //$NON-NLS-1$ consumeRecoveryMethodHeaderName(); break; - case 799 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); } //$NON-NLS-1$ + case 850 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); } //$NON-NLS-1$ consumeMethodHeader(); break; - case 800 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); } //$NON-NLS-1$ + case 851 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); } //$NON-NLS-1$ consumeMethodHeader(); break; @@ -8754,16 +9247,26 @@ protected void consumeStatementTry(boolean withFinally, boolean hasResources) { if (hasResources) { // get the resources length = this.astLengthStack[this.astLengthPtr--]; - LocalDeclaration[] resources = new LocalDeclaration[length]; + Statement[] stmts = new Statement[length]; System.arraycopy( - this.astStack, - (this.astPtr -= length) + 1, - resources, - 0, - length); - tryStmt.resources = resources; + this.astStack, + (this.astPtr -= length) + 1, + stmts, + 0, + length); + + tryStmt.resources = stmts; + if (this.options.sourceLevel < ClassFileConstants.JDK1_7) { - problemReporter().autoManagedResourcesNotBelow17(resources); + problemReporter().autoManagedResourcesNotBelow17(stmts); + } + if (this.options.sourceLevel < ClassFileConstants.JDK9) { + for (int i = 0, l = stmts.length; i < l; ++i) { + Statement stmt = stmts[i]; + if (stmt instanceof FieldReference || stmt instanceof NameReference) { + problemReporter().autoManagedVariableResourcesNotBelow9((Expression) stmt); + } + } } } //positions @@ -8953,6 +9456,10 @@ protected void consumeToken(int type) { checkAndSetModifiers(ClassFileConstants.AccNative); pushOnExpressionStackLengthStack(0); break; + case TokenNameopen : + checkAndSetModifiers(ClassFileConstants.ACC_OPEN); + pushOnExpressionStackLengthStack(0); + break; case TokenNameprivate : checkAndSetModifiers(ClassFileConstants.AccPrivate); pushOnExpressionStackLengthStack(0); @@ -8969,12 +9476,19 @@ protected void consumeToken(int type) { checkAndSetModifiers(ClassFileConstants.AccTransient); pushOnExpressionStackLengthStack(0); break; + case TokenNametransitive : + checkAndSetModifiers(ClassFileConstants.ACC_TRANSITIVE); + pushOnExpressionStackLengthStack(0); + break; case TokenNamevolatile : checkAndSetModifiers(ClassFileConstants.AccVolatile); pushOnExpressionStackLengthStack(0); break; case TokenNamestatic : - checkAndSetModifiers(ClassFileConstants.AccStatic); + if (isParsingModuleDeclaration()) + checkAndSetModifiers(ClassFileConstants.ACC_STATIC_PHASE); + else + checkAndSetModifiers(ClassFileConstants.AccStatic); pushOnExpressionStackLengthStack(0); break; case TokenNamesynchronized : @@ -9123,6 +9637,12 @@ protected void consumeToken(int type) { case TokenNamecontinue : case TokenNamereturn : case TokenNamecase : + case TokenNamemodule: + case TokenNamerequires: + case TokenNameexports: + case TokenNameopens: + case TokenNameuses: + case TokenNameprovides: pushOnIntStack(this.scanner.startPosition); break; case TokenNamenew : @@ -10512,6 +11032,7 @@ public void goForHeaders(){ this.firstToken = TokenNameUNSIGNED_RIGHT_SHIFT; } this.scanner.recordLineSeparator = true; // recovery goals must record line separators + this.scanner.scanContext = null; } public void goForImportDeclaration(){ //tells the scanner to go for import declaration parsing @@ -10538,10 +11059,13 @@ public void goForMethodBody(){ this.scanner.recordLineSeparator = false; } public void goForPackageDeclaration() { + goForPackageDeclaration(true); +} +public void goForPackageDeclaration(boolean recordLineSeparators) { //tells the scanner to go for package declaration parsing this.firstToken = TokenNameQUESTION; - this.scanner.recordLineSeparator = true; + this.scanner.recordLineSeparator = recordLineSeparators; } public void goForTypeDeclaration() { //tells the scanner to go for type (interface or class) declaration parsing @@ -11661,6 +12185,29 @@ public Expression parseLambdaExpression(char[] source, int offset, int length, C return parseExpression(source, offset, length, unit, recordLineSeparators); } +public char[][] parsePackageDeclaration(char[] source, CompilationResult result) { + initialize(); + goForPackageDeclaration(false); + this.referenceContext = + this.compilationUnit = + new CompilationUnitDeclaration( + problemReporter(), + result, + source.length); + this.scanner.setSource(source); + try { + parse(); + } catch (AbortCompilation ex) { + this.lastAct = ERROR_ACTION; + } + + if (this.lastAct == ERROR_ACTION) { + return null; + } + + return this.compilationUnit.currentPackage == null ? null : this.compilationUnit.currentPackage.getImportName(); + +} public Expression parseExpression(char[] source, int offset, int length, CompilationUnitDeclaration unit, boolean recordLineSeparators) { initialize(); @@ -11812,7 +12359,7 @@ protected void pushIdentifier(char [] identifier, long position) { } this.identifierLengthStack[this.identifierLengthPtr] = 1; if (this.parsingJava8Plus && identifier.length == 1 && identifier[0] == '_' && !this.processingLambdaParameterList) { - problemReporter().illegalUseOfUnderscoreAsAnIdentifier((int) (position >>> 32), (int) position, false /* not a lambda parameter */); + problemReporter().illegalUseOfUnderscoreAsAnIdentifier((int) (position >>> 32), (int) position, this.parsingJava9Plus); } } protected void pushIdentifier() { @@ -12640,6 +13187,11 @@ public boolean automatonWillShift(int token, int lastAction) { return lastAction != ERROR_ACTION; } } +@Override +public boolean isParsingModuleDeclaration() { + // It can be a null in case of a Vanguard parser, which means no module to be dealt with. + return (this.parsingJava9Plus && this.compilationUnit != null && this.compilationUnit.isModuleInfo()); +} // GROOVY add public void reset() { // standard Java parser, nothing to do diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java index 50dce29c81..f3bfae0436 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java @@ -13,24 +13,25 @@ /*An interface that contains static declarations for some basic information about the parser such as the number of rules in the grammar, the starting state, etc...*/ public interface ParserBasicInformation { - public final static int - ERROR_SYMBOL = 118, - MAX_NAME_LENGTH = 41, - NUM_STATES = 1102, + public final static int - NT_OFFSET = 118, - SCOPE_UBOUND = 290, - SCOPE_SIZE = 291, - LA_STATE_OFFSET = 16382, - MAX_LA = 1, - NUM_RULES = 800, - NUM_TERMINALS = 118, - NUM_NON_TERMINALS = 360, - NUM_SYMBOLS = 478, - START_STATE = 1580, - EOFT_SYMBOL = 60, - EOLT_SYMBOL = 60, - ACCEPT_ACTION = 16381, - ERROR_ACTION = 16382; + ERROR_SYMBOL = 128, + MAX_NAME_LENGTH = 41, + NUM_STATES = 1152, + + NT_OFFSET = 128, + SCOPE_UBOUND = 290, + SCOPE_SIZE = 291, + LA_STATE_OFFSET = 16451, + MAX_LA = 1, + NUM_RULES = 851, + NUM_TERMINALS = 128, + NUM_NON_TERMINALS = 388, + NUM_SYMBOLS = 516, + START_STATE = 895, + EOFT_SYMBOL = 60, + EOLT_SYMBOL = 60, + ACCEPT_ACTION = 16450, + ERROR_ACTION = 16451; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java index ac1c1e5c43..c1a1ac7058 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -20,6 +20,8 @@ import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleStatement; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.util.Util; @@ -72,6 +74,17 @@ public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValu this.updateSourceEndIfNecessary(previousAvailableLineEnd(nestedBlockDeclaration.sourceStart - 1)); return this.parent.add(nestedBlockDeclaration, bracketBalanceValue); } +/* + * Record an e reference + */ +public RecoveredElement add(ModuleStatement moduleStatement, int bracketBalanceValue){ + + /* default behavior is to delegate recording to parent if any */ + resetPendingModifiers(); + if (this.parent == null) return this; // ignore + this.updateSourceEndIfNecessary(previousAvailableLineEnd(moduleStatement.declarationSourceStart - 1)); + return this.parent.add(moduleStatement, bracketBalanceValue); +} /* * Record a field declaration */ @@ -125,6 +138,12 @@ public RecoveredElement add(Statement statement, int bracketBalanceValue) { this.updateSourceEndIfNecessary(previousAvailableLineEnd(statement.sourceStart - 1)); return this.parent.add(statement, bracketBalanceValue); } +public RecoveredElement add(ModuleDeclaration moduleDeclaration, int bracketBalanceValue){ + resetPendingModifiers(); + if (this.parent == null) return this; // ignore + this.updateSourceEndIfNecessary(previousAvailableLineEnd(moduleDeclaration.declarationSourceStart - 1)); + return this.parent.add(moduleDeclaration, bracketBalanceValue); +} /* * Record a type declaration */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExport.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExport.java new file mode 100644 index 0000000000..59fcdd745b --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExport.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; + +public class RecoveredExport extends RecoveredElement { + + public ExportsStatement exportReference; + RecoveredModuleReference[] targets; + int targetCount = 0; + + public RecoveredExport(ExportsStatement exportReference, RecoveredElement parent, int bracketBalance) { + super(parent, bracketBalance); + this.exportReference = exportReference; + } + public RecoveredElement add(ModuleReference target, int bracketBalance1) { + + if (this.targets == null) { + this.targets = new RecoveredModuleReference[5]; + this.targetCount = 0; + } else { + if (this.targetCount == this.targets.length) { + System.arraycopy( + this.targets, + 0, + (this.targets = new RecoveredModuleReference[2 * this.targetCount]), + 0, + this.targetCount); + } + } + RecoveredModuleReference element = new RecoveredModuleReference(target, this, bracketBalance1); + this.targets[this.targetCount++] = element; + + /* if target not finished, then target becomes current */ + if (target.sourceEnd == 0) return element; + return this; + + } + /* + * Answer the associated parsed structure + */ + public ASTNode parseTree(){ + return this.exportReference; + } + /* + * Answer the very source end of the corresponding parse node + */ + public int sourceEnd(){ + return this.exportReference.declarationSourceEnd; + } + public String toString(int tab) { + return tabString(tab) + "Recovered export: " + this.exportReference.toString(); //$NON-NLS-1$ + } + public ExportsStatement updatedExportReference(){ + if (this.targetCount > 0) { + int existingCount = this.exportReference.targets != null ? this.exportReference.targets.length : 0, actualCount = 0; + ModuleReference[] moduleRef1 = new ModuleReference[existingCount + this.targetCount]; + if (existingCount > 0) { + System.arraycopy(this.exportReference.targets, 0, moduleRef1, 0, existingCount); + actualCount = existingCount; + } + for (int i = 0, l = this.targetCount; i < l; ++i) { + moduleRef1[actualCount++] = this.targets[i].updatedModuleReference(); + } + this.exportReference.targets = moduleRef1; + } + return this.exportReference; + } + public void updateParseTree(){ + updatedExportReference(); + } + /* + * Update the declarationSourceEnd of the corresponding parse node + */ + public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ + if (this.exportReference.declarationSourceEnd == 0) { + this.exportReference.declarationSourceEnd = bodyEnd; + this.exportReference.declarationEnd = bodyEnd; + } + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExportsStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExportsStatement.java new file mode 100644 index 0000000000..1caba1422a --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExportsStatement.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; + +public class RecoveredExportsStatement extends RecoveredPackageVisibilityStatement { + + public RecoveredExportsStatement(ExportsStatement exportsStatement, RecoveredElement parent, int bracketBalance) { + super(exportsStatement, parent, bracketBalance); + } + public String toString(int tab) { + return tabString(tab) + "Recovered exports stmt: " + super.toString(); //$NON-NLS-1$ + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModule.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModule.java new file mode 100644 index 0000000000..3dccd22706 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModule.java @@ -0,0 +1,284 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleStatement; +import org.eclipse.jdt.internal.compiler.ast.OpensStatement; +import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement; +import org.eclipse.jdt.internal.compiler.ast.RequiresStatement; +import org.eclipse.jdt.internal.compiler.ast.UsesStatement; + +public class RecoveredModule extends RecoveredElement { + + public RecoveredExportsStatement[] exports; + public int exportCount; + public RecoveredOpensStatement[] opens; + public int opensCount; + public RecoveredRequiresStatement[] requires; + public int requiresCount; + public RecoveredUsesStatement[] uses; + public int usesCount; + public RecoveredProvidesStatement[] services; + public int servicesCount; + public ModuleDeclaration moduleDeclaration; + + public RecoveredModule(ModuleDeclaration moduleDeclaration, RecoveredElement parent, int bracketBalance) { + super(parent, bracketBalance); + this.moduleDeclaration = moduleDeclaration; + } + public RecoveredElement add(ModuleStatement moduleStatement, int bracketBalanceValue) { + + // TODO: can't we do away with all these additions except for ProvidesStatement - to check + // if there are any corner cases that uses these. + if (moduleStatement instanceof ExportsStatement) { + return add((ExportsStatement) moduleStatement, bracketBalanceValue); + } + if (moduleStatement instanceof OpensStatement) { + return add((OpensStatement) moduleStatement, bracketBalanceValue); + } + if (moduleStatement instanceof RequiresStatement) { + return add((RequiresStatement) moduleStatement, bracketBalanceValue); + } + if (moduleStatement instanceof ProvidesStatement) { + return add((ProvidesStatement) moduleStatement, bracketBalanceValue); + } + if (moduleStatement instanceof UsesStatement) { + return add((UsesStatement) moduleStatement, bracketBalanceValue); + } + + return this; + } + + public RecoveredElement add(ExportsStatement exportsStatement, int bracketBalanceValue) { + resetPendingModifiers(); + + if (this.exports == null) { + this.exports = new RecoveredExportsStatement[5]; + this.exportCount = 0; + } else { + if (this.exportCount == this.exports.length) { + System.arraycopy( + this.exports, + 0, + (this.exports = new RecoveredExportsStatement[2 * this.exportCount]), + 0, + this.exportCount); + } + } + RecoveredExportsStatement element = new RecoveredExportsStatement(exportsStatement, this, bracketBalanceValue); + this.exports[this.exportCount++] = element; + + return element; + } + public RecoveredElement add(OpensStatement opensStatement, int bracketBalanceValue) { + resetPendingModifiers(); + + if (this.opens == null) { + this.opens = new RecoveredOpensStatement[5]; + this.opensCount = 0; + } else { + if (this.opensCount == this.opens.length) { + System.arraycopy( + this.opens, + 0, + (this.opens = new RecoveredOpensStatement[2 * this.opensCount]), + 0, + this.opensCount); + } + } + RecoveredOpensStatement element = new RecoveredOpensStatement(opensStatement, this, bracketBalanceValue); + this.opens[this.opensCount++] = element; + + return element; + } + public RecoveredElement add(RequiresStatement requiresStatement, int bracketBalanceValue) { + if (this.requires == null) { + this.requires = new RecoveredRequiresStatement[5]; + this.requiresCount = 0; + } else { + if (this.requiresCount == this.requires.length) { + System.arraycopy( + this.requires, + 0, + (this.requires = new RecoveredRequiresStatement[2 * this.requiresCount]), + 0, + this.requiresCount); + } + } + RecoveredRequiresStatement element = new RecoveredRequiresStatement(requiresStatement, this, bracketBalanceValue); + this.requires[this.requiresCount++] = element; + return this; + } + public RecoveredElement add(ProvidesStatement providesStatement, int bracketBalanceValue) { + if (this.services == null) { + this.services = new RecoveredProvidesStatement[5]; + this.servicesCount = 0; + } else { + if (this.servicesCount == this.services.length) { + System.arraycopy( + this.services, + 0, + (this.services = new RecoveredProvidesStatement[2 * this.servicesCount]), + 0, + this.servicesCount); + } + } + RecoveredProvidesStatement element = new RecoveredProvidesStatement(providesStatement, this, bracketBalanceValue); + this.services[this.servicesCount++] = element; + return element; + } + public RecoveredElement add(UsesStatement usesStatement, int bracketBalanceValue) { + genAssign(usesStatement, bracketBalanceValue); + return this; + } + private void genAssign(UsesStatement usesStatement, int bracketBalanceValue) { + if (this.uses == null) { + this.uses = new RecoveredUsesStatement[5]; + this.usesCount = 0; + } else { + if (this.usesCount == this.uses.length) { + System.arraycopy( + this.uses, + 0, + (this.uses = new RecoveredUsesStatement[2 * this.usesCount]), + 0, + this.usesCount); + } + } + RecoveredUsesStatement element = new RecoveredUsesStatement(usesStatement, this, bracketBalanceValue); + this.uses[this.usesCount++] = element; + } + public String toString(int tab) { + StringBuffer result = new StringBuffer(tabString(tab)); + result.append("Recovered module:\n"); //$NON-NLS-1$ + result.append("module ");//$NON-NLS-1$ + result.append(CharOperation.charToString(this.moduleDeclaration.moduleName)); + result.append(" {");//$NON-NLS-1$ + if (this.exportCount > 0) { + for (int i = 0; i < this.exportCount; ++i) { + result.append("\n"); //$NON-NLS-1$ + result.append(this.exports[i].toString(tab + 1)); + } + } + if (this.requiresCount > 0) { + for (int i = 0; i < this.requiresCount; ++i) { + result.append("\n"); //$NON-NLS-1$ + result.append(this.requires[i].toString(tab + 1)); + } + } + if (this.usesCount > 0) { + for (int i = 0; i < this.usesCount; ++i) { + result.append("\n"); //$NON-NLS-1$ + result.append(this.uses[i].toString(tab + 1)); + } + } + if (this.servicesCount > 0) { + for (int i = 0; i < this.servicesCount; ++i) { + result.append("\n"); //$NON-NLS-1$ + result.append(this.services[i].toString(tab + 1)); + } + } + result.append("\n}");//$NON-NLS-1$ + return result.toString(); + } + public ModuleDeclaration updatedModuleDeclaration() { + + updateExports(this.moduleDeclaration); + updateOpens(this.moduleDeclaration); + updateRequires(this.moduleDeclaration); + updateUses(this.moduleDeclaration); + updateServices(this.moduleDeclaration); + return this.moduleDeclaration; + } + private void updateExports(ModuleDeclaration mod) { + if (this.exportCount > 0) { + int existingCount = mod.exportsCount, actualCount = 0; + ExportsStatement[] exports1 = new ExportsStatement[existingCount + this.exportCount]; + if (existingCount > 0){ + System.arraycopy(mod.exports, 0, exports1, 0, existingCount); + actualCount = existingCount; + } + for (int i = 0; i < this.exportCount; i++){ + exports1[actualCount++] = (ExportsStatement)this.exports[i].updatedPackageVisibilityStatement(); + } + mod.exports = exports1; + mod.exportsCount = actualCount; + } + } + private void updateOpens(ModuleDeclaration mod) { + if (this.opensCount > 0) { + int existingCount = mod.opensCount, actualCount = 0; + OpensStatement[] opens1 = new OpensStatement[existingCount + this.opensCount]; + if (existingCount > 0){ + System.arraycopy(mod.exports, 0, opens1, 0, existingCount); + actualCount = existingCount; + } + for (int i = 0; i < this.opensCount; i++){ + opens1[actualCount++] = (OpensStatement)this.opens[i].updatedPackageVisibilityStatement(); + } + mod.opens = opens1; + mod.opensCount = actualCount; + } + } + private void updateRequires(ModuleDeclaration mod) { + if (this.requiresCount > 0) { + int existingCount = mod.requiresCount, actualCount = 0; + RequiresStatement[] requiresStmts = new RequiresStatement[existingCount + this.requiresCount]; + if (existingCount > 0){ + System.arraycopy(mod.requires, 0, requiresStmts, 0, existingCount); + actualCount = existingCount; + } + for (int i = 0; i < this.requiresCount; i++){ + requiresStmts[actualCount++] = this.requires[i].updatedRequiresStatement(); + } + mod.requires = requiresStmts; + mod.requiresCount = actualCount; + } + } + private void updateUses(ModuleDeclaration mod) { + if (this.usesCount > 0) { + int existingCount = mod.usesCount, actualCount = 0; + UsesStatement[] usesStmts = new UsesStatement[existingCount + this.usesCount]; + if (existingCount > 0){ + System.arraycopy(mod.uses, 0, usesStmts, 0, existingCount); + actualCount = existingCount; + } + for (int i = 0; i < this.usesCount; ++i) { + usesStmts[actualCount++] = this.uses[i].updatedUsesStatement(); + } + mod.uses = usesStmts; + mod.usesCount = actualCount; + } + } + private void updateServices(ModuleDeclaration mod) { + if (this.servicesCount > 0) { + int existingCount = mod.servicesCount, actualCount = 0; + ProvidesStatement[] providesStmts = new ProvidesStatement[existingCount + this.servicesCount]; + if (existingCount > 0){ + System.arraycopy(mod.services, 0, providesStmts, 0, existingCount); + actualCount = existingCount; + } + for (int i = 0; i < this.servicesCount; ++i) { + providesStmts[actualCount++] = this.services[i].updatedProvidesStatement(); + } + mod.services = providesStmts; + mod.servicesCount = actualCount; + } + } + public void updateParseTree(){ + updatedModuleDeclaration(); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleReference.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleReference.java new file mode 100644 index 0000000000..2723250b29 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleReference.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; + +public class RecoveredModuleReference extends RecoveredElement { + + public ModuleReference moduleReference; +public RecoveredModuleReference(ModuleReference moduleReference, RecoveredElement parent, int bracketBalance){ + super(parent, bracketBalance); + this.moduleReference = moduleReference; +} +/* + * Answer the associated parsed structure + */ +public ASTNode parseTree(){ + return this.moduleReference; +} +/* + * Answer the very source end of the corresponding parse node + */ +public int sourceEnd(){ + return this.moduleReference.sourceEnd; +} +public String toString(int tab) { + return tabString(tab) + "Recovered ModuleReference: " + this.moduleReference.toString(); //$NON-NLS-1$ +} +public ModuleReference updatedModuleReference(){ + + return this.moduleReference; +} +public void updateParseTree(){ + updatedModuleReference(); +} +/* + * Update the declarationSourceEnd of the corresponding parse node + */ +//public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ +// if (this.moduleReference.declarationSourceEnd == 0) { +// this.moduleReference.declarationSourceEnd = bodyEnd; +// this.moduleReference.declarationEnd = bodyEnd; +// } +//} + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleStatement.java new file mode 100644 index 0000000000..6c1c143b11 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleStatement.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.ModuleStatement; + +public abstract class RecoveredModuleStatement extends RecoveredElement { + + public ModuleStatement moduleStatement; + + public RecoveredModuleStatement(ModuleStatement moduleStmt, RecoveredElement parent, int bracketBalance) { + super(parent, bracketBalance); + this.moduleStatement = moduleStmt; + } + /* + * Answer the associated parsed structure + */ + public ASTNode parseTree(){ + return this.moduleStatement; + } + /* + * Answer the very source end of the corresponding parse node + */ + public int sourceEnd(){ + return this.moduleStatement.declarationSourceEnd; + } + public String toString(int tab) { + return this.moduleStatement.toString(); + } + protected ModuleStatement updatedModuleStatement(){ + return this.moduleStatement; + } + public void updateParseTree(){ + updatedModuleStatement(); + } + /* + * Update the declarationSourceEnd of the corresponding parse node + */ + public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ + if (this.moduleStatement.declarationSourceEnd == 0) { + this.moduleStatement.declarationSourceEnd = bodyEnd; + this.moduleStatement.declarationEnd = bodyEnd; + } + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredOpensStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredOpensStatement.java new file mode 100644 index 0000000000..a0f239b4e1 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredOpensStatement.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.OpensStatement; + +public class RecoveredOpensStatement extends RecoveredPackageVisibilityStatement { + + public RecoveredOpensStatement(OpensStatement opensStatement, RecoveredElement parent, int bracketBalance) { + super(opensStatement, parent, bracketBalance); + } + public String toString(int tab) { + return tabString(tab) + "Recovered opens stmt: " + super.toString(); //$NON-NLS-1$ + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredPackageVisibilityStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredPackageVisibilityStatement.java new file mode 100644 index 0000000000..c3363b7368 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredPackageVisibilityStatement.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.ImportReference; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; +import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement; + +public class RecoveredPackageVisibilityStatement extends RecoveredModuleStatement { + + // PackageVisibilityStatement pvs; + RecoveredImport pkgRef; + RecoveredModuleReference[] targets; + int targetCount = 0; + + public RecoveredPackageVisibilityStatement(PackageVisibilityStatement pvs, RecoveredElement parent, int bracketBalance) { + super(pvs, parent, bracketBalance); + } + public RecoveredElement add(ImportReference pkgRef1, int bracketBalance1) { + this.pkgRef = new RecoveredImport(pkgRef1, this, bracketBalance1); + return this; + } + public RecoveredElement add(ModuleReference target, int bracketBalance1) { + if (this.targets == null) { + this.targets = new RecoveredModuleReference[5]; + this.targetCount = 0; + } else { + if (this.targetCount == this.targets.length) { + System.arraycopy( + this.targets, + 0, + (this.targets = new RecoveredModuleReference[2 * this.targetCount]), + 0, + this.targetCount); + } + } + RecoveredModuleReference element = new RecoveredModuleReference(target, this, bracketBalance1); + this.targets[this.targetCount++] = element; + return this; + + } + public String toString(int tab) { + return super.toString(); + } + public PackageVisibilityStatement updatedPackageVisibilityStatement(){ + PackageVisibilityStatement pvs = (PackageVisibilityStatement) this.moduleStatement; + if (this.pkgRef != null) { + pvs.pkgRef = this.pkgRef.updatedImportReference(); + } + if (this.targetCount > 0) { + int existingCount = pvs.targets != null ? pvs.targets.length : 0, actualCount = 0; + ModuleReference[] moduleRef1 = new ModuleReference[existingCount + this.targetCount]; + if (existingCount > 0) { + System.arraycopy(pvs.targets, 0, moduleRef1, 0, existingCount); + actualCount = existingCount; + } + for (int i = 0, l = this.targetCount; i < l; ++i) { + moduleRef1[actualCount++] = this.targets[i].updatedModuleReference(); + } + pvs.targets = moduleRef1; + } + return pvs; + } + public void updateParseTree(){ + updatedPackageVisibilityStatement(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredProvidesStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredProvidesStatement.java new file mode 100644 index 0000000000..17604957ac --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredProvidesStatement.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement; +import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; + +public class RecoveredProvidesStatement extends RecoveredModuleStatement { + SingleTypeReference impl; + + public RecoveredProvidesStatement(ProvidesStatement providesStatement, RecoveredElement parent, int bracketBalance) { + super(providesStatement, parent, bracketBalance); + } + public RecoveredElement add(SingleTypeReference impl1, int bracketBalance1) { + this.impl = impl1; + return this; + } + + public String toString(int tab) { + return tabString(tab) + "Recovered Provides: " + super.toString(); //$NON-NLS-1$ + } + public ProvidesStatement updatedProvidesStatement(){ + ProvidesStatement providesStatement = (ProvidesStatement) this.moduleStatement; + if (providesStatement.implementations == null) { // only for with - actual impl by normal parse + providesStatement.implementations = this.impl != null ? new TypeReference[] {this.impl} : new TypeReference[0]; // dummy for completion + } + return providesStatement; + } + public void updateParseTree(){ + updatedProvidesStatement(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredRequiresStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredRequiresStatement.java new file mode 100644 index 0000000000..0dd9214d75 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredRequiresStatement.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.RequiresStatement; + +public class RecoveredRequiresStatement extends RecoveredModuleStatement { + + public RecoveredRequiresStatement(RequiresStatement requiresStatement, RecoveredElement parent, int bracketBalance) { + super(requiresStatement, parent, bracketBalance); + } + public String toString(int tab) { + return tabString(tab) + "Recovered requires: " + super.toString(); //$NON-NLS-1$ + } + public RequiresStatement updatedRequiresStatement(){ + return (RequiresStatement)this.moduleStatement; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredTypeReference.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredTypeReference.java new file mode 100644 index 0000000000..547ae1497d --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredTypeReference.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; + +public class RecoveredTypeReference extends RecoveredElement { + public TypeReference typeReference; + + public RecoveredTypeReference(TypeReference typeReference, RecoveredElement parent, int bracketBalance) { + super(parent, bracketBalance); + this.typeReference = typeReference; + } + + /* + * Answer the associated parsed structure + */ + public ASTNode parseTree(){ + return this.typeReference; + } + public TypeReference updateTypeReference() { + return this.typeReference; + } + /* + * Answer the very source end of the corresponding parse node + */ + public String toString(int tab) { + return tabString(tab) + "Recovered typereference: " + this.typeReference.toString(); //$NON-NLS-1$ + } + public TypeReference updatedImportReference(){ + return this.typeReference; + } + public void updateParseTree(){ + updatedImportReference(); + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java index 0adf1b9019..3fcbd032ec 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -20,9 +20,11 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.Initializer; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; public class RecoveredUnit extends RecoveredElement { @@ -31,6 +33,7 @@ public class RecoveredUnit extends RecoveredElement { public RecoveredImport[] imports; public int importCount; + public RecoveredModule module; public RecoveredType[] types; public int typeCount; @@ -127,6 +130,10 @@ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanc } return this; // ignore } +public RecoveredElement add(ExportsStatement exportReference, int bracketBalanceValue) { + return this.module != null ? this.module.add(exportReference, bracketBalanceValue) : null; +} + public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) { resetPendingModifiers(); @@ -150,8 +157,12 @@ public RecoveredElement add(ImportReference importReference, int bracketBalanceV if (importReference.declarationSourceEnd == 0) return element; return this; } +public RecoveredElement add(ModuleDeclaration moduleDeclaration, int bracketBalanceValue){ + this.module = new RecoveredModule(moduleDeclaration, this, bracketBalanceValue); + return this.module; +} public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { - + if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0){ if (this.typeCount > 0) { // add it to the last type @@ -243,6 +254,9 @@ public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){ } this.unitDeclaration.imports = importRefences; } + if (this.module != null) { + this.unitDeclaration.moduleDeclaration = this.module.updatedModuleDeclaration(); + } /* update types */ if (this.typeCount > 0){ int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUsesStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUsesStatement.java new file mode 100644 index 0000000000..a0e9a05e9c --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUsesStatement.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.parser; + +import org.eclipse.jdt.internal.compiler.ast.UsesStatement; + +public class RecoveredUsesStatement extends RecoveredModuleStatement { + + public RecoveredUsesStatement(UsesStatement usesStatement, RecoveredElement parent, int bracketBalance) { + super(usesStatement, parent, bracketBalance); + } + public String toString(int tab) { + return tabString(tab) + "Recovered Uses: " + super.toString(); //$NON-NLS-1$ + } + public UsesStatement updatedUsesStatement(){ + return (UsesStatement)this.moduleStatement; + } + public void updateParseTree(){ + updatedUsesStatement(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java index 771f996b29..a8cf838f89 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,8 +15,12 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; +import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.util.Util; /** @@ -98,6 +102,17 @@ public class Scanner implements TerminalTokens { public int linePtr = -1; public boolean wasAcr = false; + public boolean fakeInModule = false; + /** + * The current context of the scanner w.r.t restricted keywords + * + */ + enum ScanContext { + EXPECTING_KEYWORD, EXPECTING_IDENTIFIER, AFTER_REQUIRES, INACTIVE + } + protected ScanContext scanContext = null; + protected boolean insideModuleInfo = false; + public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$ public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$ @@ -1149,7 +1164,15 @@ public int getNextToken() throws InvalidInputException { this.nextToken = TokenNameNotAToken; return token; // presumed to be unambiguous. } + if (this.scanContext == null) { // init lazily, since isInModuleDeclaration needs the parser to be known + this.scanContext = isInModuleDeclaration() ? ScanContext.EXPECTING_KEYWORD : ScanContext.INACTIVE; + } token = getNextToken0(); + if (areRestrictedModuleKeywordsActive()) { + if (isRestrictedKeyword(token)) + token = disambiguatedRestrictedKeyword(token); + updateScanContext(token); + } if (this.activeParser == null) { // anybody interested in the grammatical structure of the program should have registered. return token; } @@ -2530,6 +2553,51 @@ final char[] optimizedCurrentTokenSource6() { //newIdentCount++; return table[this.newEntry6 = max] = r; //(r = new char[] {c0, c1, c2, c3, c4, c5}); } +public boolean isInModuleDeclaration() { + return this.fakeInModule || this.insideModuleInfo || + (this.activeParser != null ? this.activeParser.isParsingModuleDeclaration() : false); +} +protected boolean areRestrictedModuleKeywordsActive() { + return this.scanContext != null && this.scanContext != ScanContext.INACTIVE; +} +void updateScanContext(int token) { + switch (token) { + case TerminalTokens.TokenNameSEMICOLON: // next could be a KEYWORD + case TerminalTokens.TokenNameRBRACE: + case TokenNameRPAREN: + this.scanContext = ScanContext.EXPECTING_KEYWORD; + break; + case TokenNameopen: + this.scanContext = ScanContext.EXPECTING_KEYWORD; + break; + case TokenNamerequires: + this.scanContext = ScanContext.AFTER_REQUIRES; + break; + case TokenNamemodule: + case TokenNameexports: + case TokenNameopens: + case TokenNameuses: + case TokenNameprovides: + case TokenNameto: + case TokenNamewith: + case TokenNametransitive: + case TokenNameDOT: + case TokenNameimport: + case TokenNameAT: + case TokenNameAT308: + case TokenNameCOMMA: + this.scanContext = ScanContext.EXPECTING_IDENTIFIER; + break; + case TokenNameIdentifier: + this.scanContext = ScanContext.EXPECTING_KEYWORD; + break; + case TerminalTokens.TokenNameLBRACE: + this.scanContext = ScanContext.EXPECTING_KEYWORD; + break; + default: // anything else is unexpected and should not alter the context + break; + } +} private void parseTags() { int position = 0; @@ -2744,6 +2812,21 @@ public void recordComment(int token) { * @param end the given end position */ public void resetTo(int begin, int end) { + resetTo(begin, end, isInModuleDeclaration()); +} +public void resetTo(int begin, int end, boolean isModuleInfo) { + resetTo(begin, end, isModuleInfo, null); +} +/** + * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position. + * Beyond this position, the scanner will answer EOF tokens (ITerminalSymbols.TokenNameEOF). + * + * @param begin the given start position + * @param end the given end position + * @param isModuleInfo if true apply rules for restricted keywords even without a connection to a properly configured parser + * @param context The scan context to use for restricted keyword support, use null to compute + */ +public void resetTo(int begin, int end, boolean isModuleInfo, ScanContext context) { //reset the scanner to a given position where it may rescan again this.diet = false; @@ -2757,6 +2840,20 @@ public void resetTo(int begin, int end) { this.foundTaskCount = 0; this.lookBack[0] = this.lookBack[1] = this.nextToken = TokenNameNotAToken; this.consumingEllipsisAnnotations = false; + this.insideModuleInfo = isModuleInfo; + this.scanContext = context == null ? getScanContext(begin) : context; +} + +private ScanContext getScanContext(int begin) { + if (!isInModuleDeclaration()) + return ScanContext.INACTIVE; + if (begin == 0) + return ScanContext.EXPECTING_KEYWORD; + CompilerOptions options = new CompilerOptions(); + options.complianceLevel = this.complianceLevel; + options.sourceLevel = this.sourceLevel; + ScanContextDetector parser = new ScanContextDetector(options); + return parser.getScanContext(this.source, begin - 1); } protected final void scanEscapeCharacter() throws InvalidInputException { @@ -3093,7 +3190,7 @@ else if ((data[index] == 'o') default : return TokenNameIdentifier; } - case 'e' : //else extends + case 'e' : //else extends exports switch (length) { case 4 : if (data[++index] == 'l') { @@ -3114,15 +3211,18 @@ else if ((data[index] == 'o') } return TokenNameIdentifier; case 7 : - if ((data[++index] == 'x') - && (data[++index] == 't') - && (data[++index] == 'e') - && (data[++index] == 'n') - && (data[++index] == 'd') - && (data[++index] == 's')) - return TokenNameextends; - else - return TokenNameIdentifier; + if ((data[++index] == 'x')) { + if ((data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'n') + && (data[++index] == 'd') && (data[++index] == 's')) { + return TokenNameextends; + } else if (areRestrictedModuleKeywordsActive() + && (data[index] == 'p') && (data[++index] == 'o') && (data[++index] == 'r') + && (data[++index] == 't') && (data[++index] == 's')) { + return TokenNameexports; + } else + return TokenNameIdentifier; + } else + return TokenNameIdentifier; default : return TokenNameIdentifier; } @@ -3256,6 +3356,22 @@ else if ((data[index] == 'o') } return TokenNameIdentifier; + case 'm': //module + switch (length) { + case 6 : + if (areRestrictedModuleKeywordsActive() + && (data[++index] == 'o') + && (data[++index] == 'd') + && (data[++index] == 'u') + && (data[++index] == 'l') + && (data[++index] == 'e')) + return TokenNamemodule; + else + return TokenNameIdentifier; + default : + return TokenNameIdentifier; + } + case 'n' : //native new null switch (length) { case 3 : @@ -3281,7 +3397,26 @@ else if ((data[index] == 'o') return TokenNameIdentifier; } - case 'p' : //package private protected public + case 'o': + switch (length) { + case 4 : + if (areRestrictedModuleKeywordsActive() && (data[++index] == 'p') && (data[++index] == 'e') && (data[++index] == 'n')) + return TokenNameopen; + else + return TokenNameIdentifier; + case 5 : + if (areRestrictedModuleKeywordsActive() + && (data[++index] == 'p') + && (data[++index] == 'e') + && (data[++index] == 'n') + && (data[++index] == 's')) + return TokenNameopens; + else + return TokenNameIdentifier; + default : + return TokenNameIdentifier; + } + case 'p' : //package private protected public provides switch (length) { case 6 : if ((data[++index] == 'u') @@ -3312,6 +3447,18 @@ else if ((data[index] == 'o') return TokenNameprivate; } else return TokenNameIdentifier; + case 8 : + if (areRestrictedModuleKeywordsActive() + && (data[++index] == 'r') + && (data[++index] == 'o') + && (data[++index] == 'v') + && (data[++index] == 'i') + && (data[++index] == 'd') + && (data[++index] == 'e') + && (data[++index] == 's')) { + return TokenNameprovides; + } else + return TokenNameIdentifier; case 9 : if ((data[++index] == 'r') && (data[++index] == 'o') @@ -3329,15 +3476,29 @@ else if ((data[index] == 'o') return TokenNameIdentifier; } - case 'r' : //return - if (length == 6) { - if ((data[++index] == 'e') - && (data[++index] == 't') - && (data[++index] == 'u') - && (data[++index] == 'r') - && (data[++index] == 'n')) { - return TokenNamereturn; - } + case 'r' : //return requires + switch (length) { + case 6: + if ((data[++index] == 'e') + && (data[++index] == 't') + && (data[++index] == 'u') + && (data[++index] == 'r') + && (data[++index] == 'n')) { + return TokenNamereturn; + } else + return TokenNameIdentifier; + case 8: + if (areRestrictedModuleKeywordsActive() + && (data[++index] == 'e') + && (data[++index] == 'q') + && (data[++index] == 'u') + && (data[++index] == 'i') + && (data[++index] == 'r') + && (data[++index] == 'e') + && (data[++index] == 's')) { + return TokenNamerequires; + } else + return TokenNameIdentifier; } return TokenNameIdentifier; @@ -3408,6 +3569,11 @@ else if ((data[index] == 'o') case 't' : //try throw throws transient this true switch (length) { + case 2: + if (areRestrictedModuleKeywordsActive() && data[++index] == 'o') + return TokenNameto; + else + return TokenNameIdentifier; case 3 : if ((data[++index] == 'r') && (data[++index] == 'y')) return TokenNametry; @@ -3453,11 +3619,33 @@ else if ((data[index] == 'o') return TokenNametransient; } else return TokenNameIdentifier; - + case 10: + if (areRestrictedModuleKeywordsActive() && (data[++index] == 'r') + && (data[++index] == 'a') + && (data[++index] == 'n') + && (data[++index] == 's') + && (data[++index] == 'i') + && (data[++index] == 't') + && (data[++index] == 'i') + && (data[++index] == 'v') + && (data[++index] == 'e')) { + return TokenNametransitive; + } else + return TokenNameIdentifier; + default : + return TokenNameIdentifier; + } + case 'u' : //uses + switch(length) { + case 4 : + if (areRestrictedModuleKeywordsActive() + && (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 's')) + return TokenNameuses; + else + return TokenNameIdentifier; default : return TokenNameIdentifier; } - case 'v' : //void volatile switch (length) { case 4 : @@ -3481,8 +3669,16 @@ else if ((data[index] == 'o') return TokenNameIdentifier; } - case 'w' : //while widefp + case 'w' : //while widefp with switch (length) { + case 4: + if (areRestrictedModuleKeywordsActive() + && (data[++index] == 'i') + && (data[++index] == 't') + && (data[++index] == 'h')) + return TokenNamewith; + else + return TokenNameIdentifier; case 5 : if ((data[++index] == 'h') && (data[++index] == 'i') @@ -3838,6 +4034,8 @@ public final void setSource(char[] sourceString){ this.initialPosition = this.currentPosition = 0; this.containsAssertKeyword = false; this.linePtr = -1; + this.scanContext = null; + this.insideModuleInfo = false; } /* * Should be used if a parse (usually a diet parse) has already been performed on the unit, @@ -3996,6 +4194,12 @@ public String toStringAction(int act) { return "volatile"; //$NON-NLS-1$ case TokenNamewhile : return "while"; //$NON-NLS-1$ + case TokenNamemodule : + return "module"; //$NON-NLS-1$ + case TokenNamerequires : + return "requires"; //$NON-NLS-1$ + case TokenNameexports : + return "exports"; //$NON-NLS-1$ case TokenNameIntegerLiteral : return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ @@ -4232,7 +4436,15 @@ public int getNextToken() throws InvalidInputException { this.nextToken = TokenNameNotAToken; return token; // presumed to be unambiguous. } + if (this.scanContext == null) { // init lazily, since isInModuleDeclaration may need the parser to be known + this.scanContext = isInModuleDeclaration() ? ScanContext.EXPECTING_KEYWORD : ScanContext.INACTIVE; + } token = getNextToken0(); + if (areRestrictedModuleKeywordsActive()) { + if (isRestrictedKeyword(token)) + token = disambiguatedRestrictedKeyword(token); + updateScanContext(token); + } if (token == TokenNameAT && atTypeAnnotation()) { if (((VanguardParser) this.activeParser).currentGoal == Goal.LambdaParameterListGoal) { token = disambiguatedToken(token); @@ -4244,7 +4456,7 @@ public int getNextToken() throws InvalidInputException { } } -private static final class Goal { +private static class Goal { int first; // steer the parser towards a single minded pursuit. int [] follow; // the definite terminal symbols that signal the successful reduction to goal. @@ -4321,7 +4533,7 @@ boolean hasBeenReached(int act, int token) { } } // Vanguard Parser - A Private utility helper class for the scanner. -private static final class VanguardParser extends Parser { +private static class VanguardParser extends Parser { public static final boolean SUCCESS = true; public static final boolean FAILURE = false; @@ -4331,6 +4543,10 @@ private static final class VanguardParser extends Parser { public VanguardParser(VanguardScanner scanner) { this.scanner = scanner; } + + public VanguardParser(ProblemReporter reporter) { + super(reporter, false); + } // Canonical LALR pushdown automaton identical to Parser.parse() minus side effects of any kind, returns the rule reduced. protected boolean parse(Goal goal) { @@ -4393,6 +4609,56 @@ public String toString() { } } +private class ScanContextDetector extends VanguardParser { + ScanContextDetector(CompilerOptions options) { + super(new ProblemReporter( + DefaultErrorHandlingPolicies.ignoreAllProblems(), + options, + new DefaultProblemFactory())); + this.problemReporter.options.performStatementsRecovery = false; + this.reportSyntaxErrorIsRequired = false; + this.reportOnlyOneSyntaxError = false; + } + + public void initializeScanner(){ + this.scanner = new Scanner( + false /*comment*/, + false /*whitespace*/, + false, /* will be set in initialize(boolean) */ + this.options.sourceLevel /*sourceLevel*/, + this.options.complianceLevel /*complianceLevel*/, + this.options.taskTags/*taskTags*/, + this.options.taskPriorities/*taskPriorities*/, + this.options.isTaskCaseSensitive/*taskCaseSensitive*/) + { + @Override + void updateScanContext(int token) { + if (token != TokenNameEOF) + super.updateScanContext(token); + } + }; + this.scanner.recordLineSeparator = false; + this.scanner.setActiveParser(this); + } + + public boolean isParsingModuleDeclaration() { + return true; + } + + public ScanContext getScanContext(char[] src, int begin) { + this.scanner.setSource(src); + this.scanner.resetTo(0, begin); + goForCompilationUnit(); + Goal goal = new Goal(TokenNamePLUS_PLUS, null, 0) { + boolean hasBeenReached(int act, int token) { + return token == TokenNameEOF; + } + }; + parse(goal); + return this.scanner.scanContext; + } +} + private VanguardParser getVanguardParser() { if (this.vanguardParser == null) { this.vanguardScanner = new VanguardScanner(this.sourceLevel, this.complianceLevel); @@ -4400,7 +4666,7 @@ private VanguardParser getVanguardParser() { this.vanguardScanner.setActiveParser(this.vanguardParser); } this.vanguardScanner.setSource(this.source); - this.vanguardScanner.resetTo(this.startPosition, this.eofPosition - 1); + this.vanguardScanner.resetTo(this.startPosition, this.eofPosition - 1, isInModuleDeclaration(), this.scanContext); return this.vanguardParser; } @@ -4489,6 +4755,63 @@ protected final boolean atTypeAnnotation() { // Did the '@' we saw just now hera public void setActiveParser(ConflictedParser parser) { this.activeParser = parser; this.lookBack[0] = this.lookBack[1] = TokenNameNotAToken; // no hand me downs please. + if (parser != null) { + this.insideModuleInfo = parser.isParsingModuleDeclaration(); + } +} +public static boolean isRestrictedKeyword(int token) { + switch(token) { + case TokenNameopen: + case TokenNamemodule: + case TokenNamerequires: + case TokenNametransitive: + case TokenNameexports: + case TokenNameto: + case TokenNameopens: + case TokenNameuses: + case TokenNameprovides: + case TokenNamewith: + return true; + default: + return false; + } +} +int disambiguatedRestrictedKeyword(int restrictedKeywordToken) { + int token = restrictedKeywordToken; + if (this.scanContext == ScanContext.EXPECTING_IDENTIFIER) + return TokenNameIdentifier; + + switch(restrictedKeywordToken) { + case TokenNametransitive: + if (this.scanContext != ScanContext.AFTER_REQUIRES) { + token = TokenNameIdentifier; + } else { + getVanguardParser(); + this.vanguardScanner.resetTo(this.currentPosition, this.eofPosition - 1, true, ScanContext.EXPECTING_IDENTIFIER); + try { + int lookAhead = this.vanguardScanner.getNextToken(); + if (lookAhead == TokenNameSEMICOLON) + token = TokenNameIdentifier; + } catch (InvalidInputException e) { + // + } + } + break; + case TokenNameopen: + case TokenNamemodule: + case TokenNameexports: + case TokenNameopens: + case TokenNamerequires: + case TokenNameprovides: + case TokenNameuses: + case TokenNameto: + case TokenNamewith: + if (this.scanContext != ScanContext.EXPECTING_KEYWORD) { + token = TokenNameIdentifier; + } + break; + } + return token; } int disambiguatedToken(int token) { final VanguardParser parser = getVanguardParser(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java index 117cafe323..ace84a03a3 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 IBM Corporation and others. + * Copyright (c) 2005, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -42,6 +42,7 @@ public class ScannerHelper { private static long[][][] Tables; private static long[][][] Tables7; private static long[][][] Tables8; + private static long[][][] Tables9; public final static int MAX_OBVIOUS = 128; public final static int[] OBVIOUS_IDENT_CHAR_NATURES = new int[MAX_OBVIOUS]; @@ -140,6 +141,9 @@ static void initializeTable17() { static void initializeTable18() { Tables8 = initializeTables("unicode6_2"); //$NON-NLS-1$ } +static void initializeTable19() { + Tables9 = initializeTables("unicode8"); //$NON-NLS-1$ +} static long[][][] initializeTables(String unicode_path) { long[][][] tempTable = new long[2][][]; tempTable[START_INDEX] = new long[3][]; @@ -286,8 +290,8 @@ public static boolean isJavaIdentifierPart(long complianceLevel, int codePoint) case 14 : return isBitSet(Tables7[PART_INDEX][3], codePoint & 0xFFFF); } - } else { - // java 7 supports Unicode 6.2 + } else if (complianceLevel <= ClassFileConstants.JDK1_8) { + // java 8 supports Unicode 6.2 if (Tables8 == null) { initializeTable18(); } @@ -301,6 +305,21 @@ public static boolean isJavaIdentifierPart(long complianceLevel, int codePoint) case 14 : return isBitSet(Tables8[PART_INDEX][3], codePoint & 0xFFFF); } + } else { + // java 9 supports Unicode 8 + if (Tables9 == null) { + initializeTable19(); + } + switch((codePoint & 0x1F0000) >> 16) { + case 0 : + return isBitSet(Tables9[PART_INDEX][0], codePoint & 0xFFFF); + case 1 : + return isBitSet(Tables9[PART_INDEX][1], codePoint & 0xFFFF); + case 2 : + return isBitSet(Tables9[PART_INDEX][2], codePoint & 0xFFFF); + case 14 : + return isBitSet(Tables9[PART_INDEX][3], codePoint & 0xFFFF); + } } return false; } @@ -348,7 +367,7 @@ public static boolean isJavaIdentifierStart(long complianceLevel, int codePoint) case 2 : return isBitSet(Tables7[START_INDEX][2], codePoint & 0xFFFF); } - } else { + } else if (complianceLevel <= ClassFileConstants.JDK1_8) { // java 7 supports Unicode 6 if (Tables8 == null) { initializeTable18(); @@ -361,6 +380,19 @@ public static boolean isJavaIdentifierStart(long complianceLevel, int codePoint) case 2 : return isBitSet(Tables8[START_INDEX][2], codePoint & 0xFFFF); } + } else { + // java 9 supports Unicode 7 + if (Tables9 == null) { + initializeTable19(); + } + switch((codePoint & 0x1F0000) >> 16) { + case 0 : + return isBitSet(Tables9[START_INDEX][0], codePoint & 0xFFFF); + case 1 : + return isBitSet(Tables9[START_INDEX][1], codePoint & 0xFFFF); + case 2 : + return isBitSet(Tables9[START_INDEX][2], codePoint & 0xFFFF); + } } return false; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java index 1de9ea0fb6..230d7f4096 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java @@ -30,127 +30,137 @@ public interface TerminalTokens { // special tokens not part of grammar - not autogenerated int TokenNameNotAToken = 0, - TokenNameWHITESPACE = 1000, - TokenNameCOMMENT_LINE = 1001, - TokenNameCOMMENT_BLOCK = 1002, - TokenNameCOMMENT_JAVADOC = 1003; + TokenNameWHITESPACE = 1000, + TokenNameCOMMENT_LINE = 1001, + TokenNameCOMMENT_BLOCK = 1002, + TokenNameCOMMENT_JAVADOC = 1003; - int TokenNameIdentifier = 22, - TokenNameabstract = 51, - TokenNameassert = 72, - TokenNameboolean = 97, - TokenNamebreak = 73, - TokenNamebyte = 98, - TokenNamecase = 99, - TokenNamecatch = 100, - TokenNamechar = 101, - TokenNameclass = 67, - TokenNamecontinue = 74, - TokenNameconst = 116, - TokenNamedefault = 75, - TokenNamedo = 76, - TokenNamedouble = 102, - TokenNameelse = 111, - TokenNameenum = 69, - TokenNameextends = 96, - TokenNamefalse = 38, - TokenNamefinal = 52, - TokenNamefinally = 109, - TokenNamefloat = 103, - TokenNamefor = 77, - TokenNamegoto = 117, - TokenNameif = 78, - TokenNameimplements = 114, - TokenNameimport = 104, - TokenNameinstanceof = 17, - TokenNameint = 105, - TokenNameinterface = 68, - TokenNamelong = 106, - TokenNamenative = 53, - TokenNamenew = 36, - TokenNamenull = 39, - TokenNamepackage = 95, - TokenNameprivate = 54, - TokenNameprotected = 55, - TokenNamepublic = 56, - TokenNamereturn = 79, - TokenNameshort = 107, - TokenNamestatic = 40, - TokenNamestrictfp = 57, - TokenNamesuper = 34, - TokenNameswitch = 80, - TokenNamesynchronized = 41, - TokenNamethis = 35, - TokenNamethrow = 81, - TokenNamethrows = 112, - TokenNametransient = 58, - TokenNametrue = 42, - TokenNametry = 82, - TokenNamevoid = 108, - TokenNamevolatile = 59, - TokenNamewhile = 71, - TokenNameIntegerLiteral = 43, - TokenNameLongLiteral = 44, - TokenNameFloatingPointLiteral = 45, - TokenNameDoubleLiteral = 46, - TokenNameCharacterLiteral = 47, - TokenNameStringLiteral = 48, - TokenNamePLUS_PLUS = 1, - TokenNameMINUS_MINUS = 2, - TokenNameEQUAL_EQUAL = 19, - TokenNameLESS_EQUAL = 12, - TokenNameGREATER_EQUAL = 13, - TokenNameNOT_EQUAL = 20, - TokenNameLEFT_SHIFT = 18, - TokenNameRIGHT_SHIFT = 14, - TokenNameUNSIGNED_RIGHT_SHIFT = 16, - TokenNamePLUS_EQUAL = 84, - TokenNameMINUS_EQUAL = 85, - TokenNameMULTIPLY_EQUAL = 86, - TokenNameDIVIDE_EQUAL = 87, - TokenNameAND_EQUAL = 88, - TokenNameOR_EQUAL = 89, - TokenNameXOR_EQUAL = 90, - TokenNameREMAINDER_EQUAL = 91, - TokenNameLEFT_SHIFT_EQUAL = 92, - TokenNameRIGHT_SHIFT_EQUAL = 93, - TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 94, - TokenNameOR_OR = 31, - TokenNameAND_AND = 30, - TokenNamePLUS = 4, - TokenNameMINUS = 5, - TokenNameNOT = 62, - TokenNameREMAINDER = 8, - TokenNameXOR = 23, - TokenNameAND = 21, - TokenNameMULTIPLY = 6, - TokenNameOR = 26, - TokenNameTWIDDLE = 63, - TokenNameDIVIDE = 9, - TokenNameGREATER = 15, - TokenNameLESS = 11, - TokenNameLPAREN = 24, - TokenNameRPAREN = 25, - TokenNameLBRACE = 49, - TokenNameRBRACE = 32, - TokenNameLBRACKET = 10, - TokenNameRBRACKET = 64, - TokenNameSEMICOLON = 28, - TokenNameQUESTION = 29, - TokenNameCOLON = 61, - TokenNameCOMMA = 33, - TokenNameDOT = 3, - TokenNameEQUAL = 70, - TokenNameAT = 37, - TokenNameELLIPSIS = 113, - TokenNameARROW = 110, - TokenNameCOLON_COLON = 7, - TokenNameBeginLambda = 50, - TokenNameBeginIntersectionCast = 65, - TokenNameBeginTypeArguments = 83, - TokenNameElidedSemicolonAndRightBrace = 66, - TokenNameAT308 = 27, - TokenNameAT308DOTDOTDOT = 115, - TokenNameEOF = 60, - TokenNameERROR = 118; + int TokenNameIdentifier = 22, + TokenNameabstract = 51, + TokenNameassert = 73, + TokenNameboolean = 97, + TokenNamebreak = 74, + TokenNamebyte = 98, + TokenNamecase = 99, + TokenNamecatch = 100, + TokenNamechar = 101, + TokenNameclass = 66, + TokenNamecontinue = 75, + TokenNameconst = 126, + TokenNamedefault = 71, + TokenNamedo = 76, + TokenNamedouble = 102, + TokenNameelse = 111, + TokenNameenum = 69, + TokenNameextends = 85, + TokenNamefalse = 39, + TokenNamefinal = 52, + TokenNamefinally = 109, + TokenNamefloat = 103, + TokenNamefor = 77, + TokenNamegoto = 127, + TokenNameif = 78, + TokenNameimplements = 122, + TokenNameimport = 104, + TokenNameinstanceof = 17, + TokenNameint = 105, + TokenNameinterface = 68, + TokenNamelong = 106, + TokenNamenative = 53, + TokenNamenew = 36, + TokenNamenull = 40, + TokenNamepackage = 84, + TokenNameprivate = 54, + TokenNameprotected = 55, + TokenNamepublic = 56, + TokenNamereturn = 79, + TokenNameshort = 107, + TokenNamestatic = 38, + TokenNamestrictfp = 57, + TokenNamesuper = 34, + TokenNameswitch = 80, + TokenNamesynchronized = 50, + TokenNamethis = 35, + TokenNamethrow = 81, + TokenNamethrows = 119, + TokenNametransient = 58, + TokenNametrue = 41, + TokenNametry = 82, + TokenNamevoid = 108, + TokenNamevolatile = 59, + TokenNamewhile = 72, + TokenNamemodule = 112, + TokenNameopen = 113, + TokenNamerequires = 114, + TokenNametransitive = 120, + TokenNameexports = 115, + TokenNameopens = 116, + TokenNameto = 123, + TokenNameuses = 117, + TokenNameprovides = 118, + TokenNamewith = 124, + TokenNameIntegerLiteral = 42, + TokenNameLongLiteral = 43, + TokenNameFloatingPointLiteral = 44, + TokenNameDoubleLiteral = 45, + TokenNameCharacterLiteral = 46, + TokenNameStringLiteral = 47, + TokenNamePLUS_PLUS = 2, + TokenNameMINUS_MINUS = 3, + TokenNameEQUAL_EQUAL = 19, + TokenNameLESS_EQUAL = 12, + TokenNameGREATER_EQUAL = 13, + TokenNameNOT_EQUAL = 20, + TokenNameLEFT_SHIFT = 18, + TokenNameRIGHT_SHIFT = 14, + TokenNameUNSIGNED_RIGHT_SHIFT = 16, + TokenNamePLUS_EQUAL = 86, + TokenNameMINUS_EQUAL = 87, + TokenNameMULTIPLY_EQUAL = 88, + TokenNameDIVIDE_EQUAL = 89, + TokenNameAND_EQUAL = 90, + TokenNameOR_EQUAL = 91, + TokenNameXOR_EQUAL = 92, + TokenNameREMAINDER_EQUAL = 93, + TokenNameLEFT_SHIFT_EQUAL = 94, + TokenNameRIGHT_SHIFT_EQUAL = 95, + TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 96, + TokenNameOR_OR = 31, + TokenNameAND_AND = 30, + TokenNamePLUS = 4, + TokenNameMINUS = 5, + TokenNameNOT = 62, + TokenNameREMAINDER = 9, + TokenNameXOR = 23, + TokenNameAND = 21, + TokenNameMULTIPLY = 8, + TokenNameOR = 27, + TokenNameTWIDDLE = 63, + TokenNameDIVIDE = 10, + TokenNameGREATER = 15, + TokenNameLESS = 11, + TokenNameLPAREN = 24, + TokenNameRPAREN = 25, + TokenNameLBRACE = 48, + TokenNameRBRACE = 33, + TokenNameLBRACKET = 6, + TokenNameRBRACKET = 64, + TokenNameSEMICOLON = 26, + TokenNameQUESTION = 29, + TokenNameCOLON = 61, + TokenNameCOMMA = 32, + TokenNameDOT = 1, + TokenNameEQUAL = 70, + TokenNameAT = 37, + TokenNameELLIPSIS = 121, + TokenNameARROW = 110, + TokenNameCOLON_COLON = 7, + TokenNameBeginLambda = 49, + TokenNameBeginIntersectionCast = 65, + TokenNameBeginTypeArguments = 83, + TokenNameElidedSemicolonAndRightBrace = 67, + TokenNameAT308 = 28, + TokenNameAT308DOTDOTDOT = 125, + TokenNameEOF = 60, + TokenNameERROR = 128; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java index 358ab95890..d624df8c11 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java @@ -2557,4 +2557,10 @@ public boolean atConflictScenario(int token) { */ return (token == TokenNameLPAREN || token == TokenNameAT || (token == TokenNameLESS && !this.lexStream.awaitingColonColon())); } + + @Override + public boolean isParsingModuleDeclaration() { + // + return this.parser.isParsingModuleDeclaration(); + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc index 4c2379ed19b4467092417f2e69e9fdee6883a73a..274fa5063ec2e68644931b3e3c94031887d0240a 100644 GIT binary patch literal 33634 zcmd5_3!DyB|37EunR%}B%zftBXO|XB?k(%GE~{nbvgqyYDtSeU%6*fH$ep}ysZ_5B zQIeLd5K-wZi%2Qm6Xg=Qq~21Y|L;8KnVn~!XLhZ2m%s1F&dix}ez)^G_jBe!2w!t? zK*2bONJQ-c0rWl~0N7cCU1%3-1Goy14rm0(Mps8M26-d!pa%dxfFHmkHvmV#AqKI? zh2Fr|qMr$H2Yj6af@nAT1@J%oPkcS#27qV*eTeqr8v!=~BrKti(5F}isQ6}pg7%=# z(8uU=^a=U`Yq&e$7A)X@VEuyVh&$p=fX+C81Ly<54)i79E3`O@C1@F1ie5qw6`?I^ zi?T|t;udxSv&^J*mM<;Prv@aGo7w4h}(SHDw0e_%B@vZ2; z=sh$7y$g6Jf|t<>^a{!ctOQI!ThX^@KYAFA25bhbBEU)bHrx}?18@aegeIX0XexRJ z(6a>Ggu0;X0RP0dJ?e&}|z8Vy7J0k;-IZ`21Bpu2IuDEj06xF$}+Y3Kmp z4zvc{gZiS^aBV;x^c~}oz6q`ti!CNQ= zX8@X@gMdS*2kL=CID`zONB$p1htWJhN7Nb60iZ@8qv8l5f-9n^f~unND6I&os2Zvf zMRjE32s(nh;ih;P#`r!w9Ot2$QPe^NS4L46S*VBVq52UtKn+ksKx04#paq~MpcSAt zs)K6dX3jvZaTtfud2}A%jqdNM&gG7 zSp?{9z@vB+piKm$@o0QCnij#ok%j4qVg`!EOk`meip6XckH-+foFY7q2%d=GNklL= zf~OF{(*!sha22{Cif-r@JO)1k7z^M4Z2>&`i2}DnO(MudO|cJ<190PUcszPOiq{dv z20Q^zK+UipHOK9vFtC9aYF9!Ibwk&(XV~rR2z0fuUK_xU2|t#4M609Kac6Vya9?VD z_*eMbwLAIlS}*NiT2H>_760bm;3l|cf;ZmpIuCVKlm@TA;*0-r48!H_wkwjVc=gK zQ8uA~{wTi%@O0PP%nV$e%Yu3WEMRL(Ex=7g8|*OGSl3y;kJL2L0{$Q6rrJPdlcNO& zMlG=3bC&nB)4>7*%LdB=MYRUh9{yq8E33SR!nmC_(7O=*DYl8XLa>204*cN9YN^^F zZIFMe_OLcq8y)e3@!$uew2|6F#1FIwwGrHTZHNW`EdSH~$F#}JjsA1~-vegAB_uJE zm`P|`AVp|}wn|OKRmgOY6Iwu=KKP{E!{+Q)zyq&QW*{ZF*be1S5Wn>N<@t-sY`^)tKCTX8{}eH_yVaolKn{Cz zeJ{GMN||hSq&dtFb&s`kn0b@`9Ul}j5_6bM6US=<(SXu&Sn20E%iP9Hy!adr@cuti zI&tr!2b8D%!$5`!$RIgf5kAh`#{G-m;u_1{!`Ct{f!CQ$7jFS~0s0S@Lp|L;OjOdw1?v$D2%T*o2u=Wha`YB)NrhPIb+ns! zi+h~6fLMwj60EDVQ`)(5sITC2$Yc8oyAkYEgRPNhDPU;5) zVw-VeGgmjLjW9FIKa9D`&4RRGDSk-(|KV1s5EZhgl^dMxmKK6NGuhst98PkqV@O_YN?btsvK)6rFXSo@#~3}f)R`klD93*Qs@KES#hpXyJ8dQ6d?h1@h^kC$;?q!&ecQWt>Lu9BLHnL_eO)cjxrsf(*B zNy~I7zXg2ree-#qy`F8rd={y7*Eb!=ye%H^kt1LS75NBB&iDK(cI+8q)P=WzW? zvjCgyISXT=|6RNVNGiFh)TQZTP1pK|Nw@mWN)w0$(2Esg0chb52wl1U!~%Fh(=YKM zA%mYnEg(0GwSYJR^~2vgwY(%A$n;rh7Qml-&T^?RI=N^c;Fh6ZiQf1RakPJ!e8bIfl31@|_zMQv^ay$U0Vj@|gwUaW(JxXZ6r!l)DGcjZ~2H?qZ=gH}y>ErHmW-o4;=uzg#-{H}6 zbFL5mEzx^j3%m$4eH1i()W)UIlz14a)HlkmJ!oGX#?Nm?NAIs| zuM4keTeWRkVPy2a8Ak8#Y42)pk zHC4aL^)Wk%9z4TF<<20mCw;oSh0GuXCwU9F{_d%Gl{JHq=zC=3PjwOsgnZ#OVU4g( zSQ|vbmY^661{I|Gr%1P>BReW50jM*m4g;f$YvQ`4?CBl5+NzudgVK*8x(feeK zl7iWdI3M~3?OpAKIl^N|6&AAd;;jyCdt}a}>}@-<4Y)6W8b05(B;sF1^JM;N{C@Nj zo2so-2IGaGb5_yW_YC#axX{kLyNcHTi|bu7X{BFhEEGG^yj(SbN!h{ z=rEpUOGw*x_j3OnoEJP_HdsAeM@=uX7o+XOTRn@oLhKe=6HWcA{U7PcY90S+_9VYw z+a*5E>|pk|`vw%emCf=Lxcf3ecVEBYITM_Mx3OWir8`f30eUmf7*(04g{P{taD>~#4n;zco{#@ zdnf+Q6H}{EO??vsd7x=byI$ITMQd91IcVGaSIu?G)4-g-YQ##JfsaIyDd3m8*ZPhK zlF-bvNC`8!%sJoB?mQ*zEzpzAYw#%XHGhV2)V#*uFnCJ57XK!#jL%blBlbhm;*|{* zt!eO8u25Jc&5UUJJaWlLZTaXNtuQrMR}{q#;vsRC`!3(4z-fQJf0y`>d??iAD@txa3|tksR$1Ww(sNep8W=)ayt2X4)E86U zNsA{=v0FU7wq9F!MQ@?E)?1PmPanj0*E99zdOf?v)9VrhW{U6NeNwLRA3TGvoAgei zp88-4zv>HB3{UY7d%W&#O6CsG1Z^D}%kK)-Wp|`MBpO^CF~{@abwhV}_KeUL!1#-$8riY4XqNOX_lI3E^p5i|NDv z*Uh;<(AIgL@K=$xaarO_>38`U{!6bzEFw-4CyF-&R(h+7%Y;{ifBItPeB*mXX0Dkl zykd4YdziNpA2Dy^yPLO|-OR4GkCEd)WAn7aLRxw5DoKjQnE#C>D zyZjk+u7%B(lI{EmcH?GB3sY*M4ZhXB)zU#>i?UBx=v%F<_36r2c#m4W)^Ieew0>Bi zN^rJ(%BHAX7j74RFi=HXr%Lj~>3YBbWw{%8Z=f5IQMOa8; zd8-QbWLDWwK{;?ptEC0By3$7}SlB5GyiXQw>k=*OrCZ7_}W`;=_&DmItGuWCD`#ab>`sGJWc%r04ZF5hEzl0WnxQ5q@xO3MK@!^zj! z46TE92hDTO*V<%TI&G>vNSmh3LmQwz87dvr*034E!oX1Nh)>rUd7n02+o7|ia?Dl3 z+TA*@R}W^Rf!Z#jul5|9tLvE4zcsEf1{>>*O+vP}OK?icCfl~O-H{$pJFvOnWe4mx zQL9(rdZp)8=?mo#GTP908lOr}>mQnkjyBBp@)Pb2@w~N^*fn$i)C;eft9PsIG4DGX ztgB8Xt*qKld&xLwawbo$Zo1Wtw$;rfvtB6E9NaM7+risGI@mBB*9%?i?GU=bY_F#o z>+rSi>Y=`&exadCbz^Vn#n8)mg}O}ct9jTV+Vao}{WD{2yv+9ct~tw`<)3QKH=i>X zMC!uXP!~RBK4Csa>Oymoxln2xdPC~R)L?2Pb&Q{fz-=mb z3l%1PX^s3~Oi`%Z!WAa{JLy=`$#9#b!_u$vR%5s^iOI0_CFK_g_$XHxK2;=lvhj2Hed&~RTIv`6RqAI}Nxnif<+nsJ zWnyu;lT(x$$vNu1o+e^7RO1d)S5^w-ACk>GoU9JU8(o9OquOj>}rda zLaAL!K}O1+d7|j~$~E5g4(H;o;U>G6FnhVJ(mwaEWTdQ&@%E`~sZ)}@!~Hi$Y<-m3 zD@-%7e}pBqf3AP6f3N@7fZ_efDA2ADXC!wOmWT4={Wwz+whKptzF^&8Ztz~^`{bu8 zTWaxJ`5Es%>LKWazJV*0|7%H&mWmT%ZLF@+mW8&fyU_{xx#Au|Y^+uKPCU7qfPiu7Eqo(M!DqCt#bG|b_jY!S!a0jG??r!dxmaV;2yuFN<*k6Pjd|u&p{byry z`0?m^LVcmQ+@WbnOU#w#7V{JHh59#?nyn8hPdtwbu$JTQ(Q}3hqx=byVaPP z9pWL}OWaYu9zP&yqP~V-q1NS(SGLsdhWL!T$U{6KuF!L)Qs$$%9fgPBvRYF zEnC|m#qZ)z8j+bORvo8Qap zzLZkKNJlH1hlmfBD)ov>EVW)Xsik{Ml{){@N{yiXEK4gCKl2*rAyB3-WgUWA zmQ8BmP^q?l{r{)b7x3#1msaYsmPXqnyl*60UEM*Xu87$>n@@HQnXR**>1-W&wrA_0 zHc2JEV$ar*_udY6D(g-Zt-IK({+ab8#hgtcBO)3uWm@lJuNXYbhQ>)>Cc{`P4S z$}he@!u-RM1D{E$Y28C#ceT{JWNGxV`dI%|eX{N%};60+B`^uaA=& zGszY-23lqKZ^6!UD@0pI@3^dtkyejx+r4L}PW&xo4lXJ&>O25|OqeHQL86 zUYbZKk*D=$emR$=q+7JmlQs>iJ6ZE`{hYkmJ(}#)qVY&-OJ*`hO+%?=8~oFvMXqH2 z)P6>d{Ix^9?PvRrP*iGb?@I?Qy5wrF&kAjXwpMIg6RRfD*11QMw_w@#tXLZ4CeWxw zQQWfJOz0smp)oBQRyzA?NfMiv)>~q`)LJPu;Y=c*S}QY)S;D*kSiHC(Qs6V8-fCgvLC8;f$ZOg`|C3#0J3u*tf(mG!WMf@d`Pb9P9WZB?X@p*5r zVwL}tB9)HT3zi(T+y&1_>G7OX*3*6ba6a+_?E~0h`L(uB`zF$cD6qrwEA30|3(|&= z9hR<{+HL|%|CXIR%b6Rke6T`euZjFx+)DV#NB$1K>>R>RIu);jZ9SvDQ6FX?ni-i! z^T-TDW0-+xYBVu2A~O&zjTSHi(Z~X6m8DfwC+EEcp5+zH?bYC!()nFF->~wD`i7e2 z9UE^~^)3B=dWKrh)APi=`WXEY@iSsqaWC{QM(YpjqljHCN?@&)@ieTJ{OBq?l+?sB zret{Qdh1FD6`1{m9%fyOUi{VWrP4Q^NV&ISiMNZlO9$zbc)JxtLh%yW-cm7TE$d^a zHdr$)xypW3vo2TeYiX5hC%lwc!O2d+6_v}GTHlGY$X_1AEud?OKK_U zvT^Qw**NElfs*SF{Ym{v7a*S?YaXs;x{;tKuMh7{bU4ssjSW{w&aTTb(5{< zzjI|42kQsxGm8`LXZI{G-hL9yR1nJIg3D9msMRi2ZrC=bxq(kzF3uWz**JTY3Z7dg zR=v>NGMju^xQ69#OZI8wm~jk7?5B;h#-EW9`#Bh~|74spPDV!TCye7TV*k-X@jV0d zt4!3N0x8moOT$MVd5QRJRHRbucHTG->krM$EVC7{n~7lkp^3?wnApwCG24ON{<2WA z-K3M3f{Q%xl5iPQ{y7Z0c1pan=N~RShao4-ro^-kPZ&>t&o42S881Y9{&Vp8=Z(e2 z(-EJ4%9smz_oRiyyp!IlOzLu8rBWX&uPVi>zc9W4%N#I{7>6U4`35Yr-}u(p7qQGy z;|H+JmlonJBfVXDwB>$yNhMMrpXhB?2$wCVmSVAT?75N$R2t{+ zycp<4*B--L6KhU;wayKDI%DB4c}~8XP%;;CHkGE;tI?|ym-M+5{-yR> zToFgdl{Gi5$ zde2rcz4;YPuY%_=(M@vt|?C-EkqP4%nX${e8MeO?BN>^G9XT`Cu=E~s0_)uGrXxnD-hqMmg zppJaE9==^~Nsyh>CW+kB8qN;2?#TWQCs-6{+h)bELaFYJf3m{=-W9$cQrl|VG}vE3 z{+AWFw)9qfUfN?Y{YU*rSi3oGq!~3xA5=dMYd5F#llqBBAGEGfQ)(=|VgsnnE`{3X z`sYCHTm7iMKSJ#oP}`?}qkm1P>0jwzN{#g|Ecj-X`j&~J+?4h)QIwm~F(!&~Q~H64 zqTG}YGf|YA(vM6O<)(C$iK5(;jxbS}F{kDJ{_c9(_Jkj$Cx*%`T`Chr@ivV<;WrOVD~Ro}j6RsdF)SL5VwK+|eWwer#-axvAJ z>hKq&V&ME*tNL`-m`ZGGn%oJzVHfdl`i9*RTeiF(2d6mscjhq)TmQs6!BqB>P{JL4 zMX%^9z*bDckx(HVi}%2tII?vptkl*u^O$pqBBy7(F=s2R^Voz6NlQ37m#f&an0YL* zM6q>};Tsne^z@ANRQzhCWFmXm;RNL;MonT$x2mnvzCJ6b&t2nyr|{*C1%9HG9wG+iMV{j9MU+ zqcI(8J1UzMJN9Z>hlG(575ffCKqK2GDVWM;+r(OJAm?tFHI{72_d1=?(p78k7UiKP zsgaql;v8YUD#PYT-!Ur)M{=5p)(U}-$+{4;$c{%Slei=vDbcje$T|cXtYIRj(40KH zRZj|%l35hlSGFi}KO;g5%4j0=2JY#;&cP|Mc7d|qGm;`wqCvW1Ef%5d#69wBtniDh zHV;xOz&h0#8e(ggo#R_UI9hfuP9G!*IMRO+egP3+)2DZ>dL~Eoi=|KBlt}-@i=huW zuqsi5(l`(qFOI{-(FY5as)6WSW{Tz<2sf#PQ!m1rm!MWIVKp@J`-N2E#J}ErZ@x9> z;LT5bPeN!MGoN_9H@}41XH0B==E8B>jCbZ`)uH5Vo2~J2v?MKwNSk=R5ersaEv$v5 zgTXbW*^9>Y<(3|Yc@uIj;a5o_E6hbUWj0%U?W=g7c%Nlc@xGXF_+1|;>Fp&>tYfd?Db45Z)>(a%oZ>2zj=WBA$ zYzh4o`pMEF^izrUjLt`rG-Zl&0YA3nh`mxtsIP=dSj&;?%5ZisaEw?M?h<}aFV=39 zc3I+33&+Yr?qj_+{vCW7po!eXDs^&`*!O{G4-DdD%9)mJ<;*hKtt5Yrv41Qt`~Cvb z?w9u$NxR=p6?-Qikc;*xz+D+^TcSqLk18D(kTxO-?S07yoGGdBue9=Srz($>*0}=5 z@~^8pv8ffu=4juk*(%JRmncC@u9g@lYRi(#zimqfMgZ|3zj16yiG9xPi@I6eT#A%2 zxmmiD^fx@?C7{nSQhuHogLSbkA|?6lV`mwm&jkPeu9UQ14~~LT9r>M6XC9=-Pb5f` zkA^TGG9N-)e=4?KcZy53S~m~-1i-a(Ilbjj(;@FJ)CzK>iJk@e&Xx8V+#f*>HQC!zuZ>ayIRWbtBIalJu-$jt&G zAfSjs5@8XM)%8F{LGyXx0jRsmCAWs})znnFXEKR_Ou}#Z|3X)HSHJqdSFi5s9)xhy zGXqi*pduA@1%%PNfH2^_GHgfNQ3pU{KodYyKu44p!@Wp~LPSddK|lx~pa1|z;YS?e zkq>ReZP51wxEXGj0EFA(=uNZ}?Lw2#J%E1#UL?SNoQFFCIsigw5&9eYD|!e$0~k;N zu0=i3)quXZ3+{w32ZYNYV;L&|_X>p2TUbR?2yi#t4PAjQN3Wt+aW3wTyQBL&xF7um zZ~$M4UPm{_VJ&iT3#tgi(5>htGzQ%cxG@d`(IB)A-GO_=&=dE>I@Yj;J^>6yFQYrr zZRizj0c`XsU?|{EfZ>2YqmgI?8jD5&Mx)WV7w!Y-4Y(R-0vy~Ir{OeIf-{he9za?Y zHu54P?u^{|6-RIcd9fL7Muz}d=rGDg*|-(X2K*6l9_|OY2J^`B;5Bp}t^+t9{U6{n z)F1W7KI}tj$cg@ajy^|o0Nv4*fNp^FC`=TOOhiy81|1n_GP(r82aP>=m`1&UjP_@Z^AdB-RLX85VRhR2aH3@&<6AzDn$EG7xZty+kkn1xqu01 z0=^Jmh`t6aL<{lFfQ#@&=vy=&a1^ira18Jb`UYPDxEOE?;8K*22LkF5pe=yE<68ms zqZot-;Rfj8C>}u!k0Of4kQa|5h9{60PohLjLj=>y@Dw6=I*J*HU}hAv5J3R}ZV1Ri ze~h6Qx*iY4w*iLWA?P?djvL`d=mgqJfpbucC|aSG=r{BmZj2kFlXxf|h8D+AgeZ#f z?f7nIl=5AG;4O3e+bk}U4>kzr(!a2XRaXH^d_Ubg9tn=+DQ;mC5`p-+BJ$e7pJnd>`L3 zzBhj-e~sA@XW%TH$sZO={P|iCcQQLx4bmt4zrx2u4aF(hL8%Zg3NH&y<))C7$n)rA z_4W6e*zy? z4~pGD|H)MY(?4{C)*1Nj&{P$L9t`{y>*i$K+SNahOY&d2*lM6>=~=kgy>qsnVQla} zsnp~8asBY5sAY_-`}qa@f`Cmuga3j5!L2zABkz_<8cHfmW4S2I*o6cYr%^ z=9X!&B-_M`aKVL7hNi}B1eQsKXK+)wNBHxjCEH2r89lt75qY`!?!ZheCDY&ko&P&@ zUS;}od&LrAma_KD^_QDKn-pzPLR0xV+({*ec!qvBG5^C8%o$KK9IP|UDRzoO1_#{-SI)e?PD>-DGE?C1 z2|Y(FBh2DXaVJALtWJMaCkD?a1*5xd~Id6L1|EzPgL5Txowg%4w+(eT6-CJ6qfMPx;;#cS#%M3%J4264g=F zgbPGl9!+h-O;nf0*`~eR9luxJHrP;?@>eCd4fGzP?L2-DY$NGAVBAA`lvMz0=lo); z7NGGm<#cFji#{#J<0a&2PIhf`w)(@EcDuL>OGYDAi|U`*_*0=laJc*;(_hPV^_NN@ z|0T3Nnf_WXeknXGnQs8ssQ$uqqJK;AEcDO!=Y#&sxh0{g%1SjO*ox?no=buLnc^;S z7k5?5Mlhm-vJw8wzc!c`=oV;2^+&IG^$&LRr~7Yg*)O^N!3NUDmFX`|5lhg7mUo}I z{^4S|9)F1F4XxR2{_R3LqCdYNQGa=pc|6*hRk@$*d!M@oZ3{dl7yD)s{exMqOxkw} zJsNscC~~i=9N&eXBNxlXD(CwIy)G7^JyM}FLATsE!6ne^x?F1OULj@I_X+5~1$_Tt|B`~ChN;lh+@stlcNZq0Os+T4w0tj7{aXDxxIt-*7jyGlwK2w` zT*LEE|4J+hi9}P*)4xXPd>5&|ZpLeh7lWt2fv4h5+)%^hhPp_ur!yh7nmU6>4X)j% zgp+F;dOY;FxBH0)Xxg%nUUSj+M^0YnV zX?qv7sj0Y2xH`F};X&a+P=enzPC_j|Mj01eADycr^Hl)URV>1}L{lwSFVS*&39NQ` zcq})c-;k)O?RU{7Gr+@5>)b)Kq8(z3z7E(sNZ#iTA2J)XO81=c)3% z@;uShw+pWg4@0|r$IJ{DzQbaX{w2}Wm=V?V#qcm(z;k@lz)$#SLOI3yYbcrDSCyBWsv_v$P7pt8iDX4df^;=6N8gm3VSVAtS&^hUT3 z|0~QqmO*GL771gCrsciCFZcy`;wkw@sRXU$Ci*{sKI?qvanST8&=lsV7=BMv>6B|T z+RF%kWGNVW8tSa~415+8}}^LNM0z3Orf1lTq1?IQ z>W{D%0h*e7^)}}<(FdaI!|!O13C+Wsh4BQy{SL)}^@SoMgl@sF$;I4DxR}d9=R-R% zODg1sW`2CxQh#5-9ATn3Nh}smDD~qtg$`^9I;Cflw!LadrKb38KHpe(-UzvYG@WQF zegrE!BKH+{nj4tb5O1)CYC~PVq_5`m%V?UpR^{a4^!mAPF!u^=d)1IiO=+IW4dq7uCyA!POqX4>54x0>Btzwt z#%Ke+3*Rl=+e!;`3@i-Up_ZX*LlY!TED9V2O>Yn*{$s%l#EHHhK|@?Gtm7wYGhA6j zQ~U<>*G37yfTo^yy|Qp>HC6vBch~C%b_QXEflJaeCAGPHwbm)P8E=uN$sYt;gntoE z2R;iP^gkZ#w)A68b4{twRSp#})3;v>PSJs5oaG%iH(93FWaIIJpY8Gk%ntEEh z%EGDCRCzYMUR|UdK-a5dh^C2r)sM8zS|??V+Ebeqd_}*(%_Tab2=x(*v{RtzP1?V; z9pQ!AUi~(GuzshSA3CV6QjfdwNv?vXW7XF{)3Ua%@(|NBnB&SJb+1z3ws=+}s}XJS ztS(k>(%M*ktzN=dtFzVCYC~H*s|5l0FU%F7iJC8CUiJ=GBGn{phb^lgMQBQDQgmy3 ze!kW>+#<5yEYRQ9hU*vc1#Q0&?^CzADJC1Ivh@{xi+)*fjy_z=R9;Y4bF=hiRHNiA zp4HDyH#92P3N6;2F$?$%@oIgLZz&Q&`}KqRQM6ce`1yg{w(khrwFa&=NIpp|tbTGq z_*-t4vRdg3Yi5hlZ(8t^{{cHUsNm2h*|6a_6e7aZeZZ#*`D>IcD1}`_(e^bV)A?YobXJXIC z8SD(Ee&CFD#ztq0$2ntQws@E`)EPqkz`2b8=F{53Xl!(FS!A8sP8+Pul9sAXG~H^h zy{-MGu27fjJ19a^!tYj`V%7UvZhpw4g1y5Nlv&W~A6J5rbvQxS>S?X1 zSwLq~Nc!$wWr6yr{)6GGcRbKH&{xQ>cU<2g7X?en4() zjN|<3=W;!{zPXqG(U>00(mXQ}q@^&P5}#5Wl`CJLs9*{3yp&koXm0K`dg;6|DzeU) zX{<9|HZ~ZdGte1m>O!C_+=ri}fAp*@>yL95%1O+r*$4GH*0*GV_DJ%B;>Kc?I7|Un;+Ee2T}JlcZvE zwmE=DG>7F2m3nRt>#fue6`!#HJuGwt%PRXzxAkft2IxJ7~RyYz##WYYA^F)?>c&@;P=G`SL|}xF-*B;gr}a@_gma#Ah5aYzQm3bJ-1y1q zgJ(JetwQHo?a$hLC*Qi!xyzBH#VFl6;0#FQ>{;Qv+qoN7_==oDXN|KVT4yhJ)&b@L@`mKpRCij*{%1_8^q@D71`RB+b(0?1H zX4NcfeY{^YZzJ{w58NboH+!W|Vyw}4m>pOW-Khh+b;$VK+-iP{Hfe9f+uh==3&{A~ z+7y^j6uCUF`8Pl?7W-rNJ zlf5zfP1teOU%4H1ROTqll$VrGlszia7V4|`>CW5w{~@`iSxb|GZ--A4*6PfR2eThR z&!bYtn*T67FZ1Ti(SadpeRR)iHL>;KbEz?!wdL!SM z3%nE7hKx=fS+vL>S?`(wb&X(Nm(m3 z+XJFnla%cn@=DRhD363(rtHWatkC%6f2ENd_J)k-h`qEe72C`1VfP3X*uCtl>_PSr z(&M&=*@K0#_CULj-JABf?Vb#DZ6>V_*a!C1X_>f&ErNKW4Y7!@o#~aVv?k71vABsx zsfn?+=KY?|D>4s4zNiif`IyM8@^j;*nrBTJFxIiN>al+1f08xS?loPX*MO}z|4*{s z@;}M?`~OMSKh!>JwYf6hTVLy$dS>M{oqJdPjf9OKYo9eq*UQ@FR9OgJkFIC;%>ZGY zirG0LkytIVKXeh9ont9L{~-F72RV0V=h$6$c8**LjKHlDdjRBp3%+OCPWA*nS_izc zLKl&%W&ynyT^aZYB|JgyrC&&PcGFm9NJ&_mLwWA}UiEi^&{UGOQsMXLJw1aS>Ho^p z-m|nZcYh4>EupY9eS~IMI=(^%UYbLBKJ_$3jf2Tbq z{5=CLzC2Fxs?XDWYk2dW*n5V8V_me>xrdA+!NbPJgd1&11BH<*}JwTQV&MdJ+@vQkK=6y}{pjZu~ zetE8R)*76%lvkazl#iUNl=aKbS;}+Ek6)wvkiN*cvd*xx7{A6w@~p-{O~qRRFr$(j z@|)(jLVj)O&W&O$Xgj9wXXj^rFxB2%@t%iF;qNPpykv`D$8pnm9@I(9jL@w&0b}%g1OQc z>^1hQ_9kL6`=9nkm@6%|i|j&bF?%&bd5dZFYE=63H7b3B-oIjBvNzkC!Iyjv?;wYZ zTIR5W!7``pllCt$%WSb@NVJSrKh?4`?qPL|wk*}M-TF%_ta$$2Ke*jW)_xE+FbaQ` z!utg;$A_>83gp@!t%m1?6WXiH&%LFBT+1qEE0E-!Ll%o3lf848bBY3X zoRwQej@AQT7MnODl5GiTF!j_BfjijDHT*UZ@! z*Qw0ffz9S@_Wq>%tp2_Jy=w&`JFhg@iCV#&?OWO`YFS#Rim*e_jSJy_5a#INFc;>8 zd@3^xqeZ5Ho67Hpxc*2|?@aN?)kv|tj1}_PO-d^DVCS&nTfYk%G) z^4_EMqBAW?f5P+qjHtK(^{$m%ud@xJMOf`&6u z#i@|JK~NXR>Q!1VG70QzV!bHc!-5s9F|Fl?LeaKmA76@rc3lY%P2{W>npmi9^$KTE%rQVuh?Fe$bNK8X-woYT|yU=y)14ImZsUP zm$%33jCaPf+7^B4vI@fbz0?F9W9^j*wKe$zc@A_pSStntg?YMQ!I!b%+)**&4R)4ZCH=l`2gWP$Bf{kvH?nARw<0# z1GZrEwm(|(Puo5iyK^@DCaQ+{KP$uCnuL9+-2BEZrOfBgti5I5ap4D$GG1}( z#H2S#GQNV^e=)ru-`=vTtc^-+otR8=M2n@R(o)tsNlU%=_yP3H`yChW{ffhkK}9i$ z_SMd((`p&2D@*I*K{fqH>*_&uWqq%?sIIIZv@%qCm-9XxL$xLC!7)@@(sww9YD@YL zj-lF;e#9|UTheJ9L$xK9;uxwe={FohbtQ3Y8LBPmMJ|SFOIppvP;E)8xEQJ}sgR4I z+LG3DF;rX9%UlfAmQ=*WP;E&YxEQJ}=@l-9w5!~HKv}=yEXVMf(9V+aQgzwkpBTL3 zP1fq-L5aPTjIUTP1y-9p>p|p+WaBaROH@o^)yA7ydVIP>3Q3prQmQtFY4bV-OBW^I z(OlsunWfU^btWOHc6Y(AsR2N%sC)!(;!t?UW9%9|nn%ddJVHUnfuP-8zc&ud9xPwZ zX^H+r=FWZl40z*(!ez^@(4+G&cUO7*9rp}1m5S&NDg9^nDhnBl$POvGyXX;jT>n!G!}9rx%`yK+>bpgkwiA-9q+H?8Y?G!fm=?v ze8Bz5JgL>=6tK4PnQIASE(<634|bOwi3}2s@6EHj>_|9p_q&YY`z6sg7YJkWyq7V3 zCK+SyC82oOOL;TwtpM@zudX`*EZwU;K^OiL4vrHa2awFTuyhxerGG+|DFF$n{8e)h$Eu^H$uLWFFb(AO%;JkK9Nmi5lLnamUg0a-`(_1<Q2`lVa4>UD5a<%rzQ(^y-gOshC9 zc_y$mu$9FPY^}`xEQRE@%`0txI=kE#ZsT=!nRMvNq`60Bx&psxNqYjyboV+7xlfZT ziK7K+y|kX`A+7&CA7L`{N;_Ovnb&(uH+#nY%5b|T9m-lkb{E#e;+RzK^~QgV{|Xhf zn~?vW_K?a?-mhx=4(PGkWe^{t43JDqM*KbaHpOA%FtwYq3bd8kZVjp2dT)GQQaMQG zrjh3=+*ecP!!$lCcky|d$SGn+Y?hais0}KM&pjC*zry_VtX@f_m6y19M#Odul`(-` zcg?hBtPas&Z&Wg9Ewz?RJFR6^m{dih*vh|d!s>E^A@`ftzd5~E8ZhbdlTiIJb`d)o+ z)k=SbEMq=R+Pq|d-`g%@z{;LCUZi=XIkTzvx;KnUPzm!_`1SDQ`{$C>RbCl1%q{-C zr(L$?pN6{Xm~pH!dsXf~+=twUl|4;UbY*bM%5&g8;67lsD1R5~&$92?B)iKk;1&q^ F{|_s@PXqt} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc index 2baa5b0777031d0aecfe08b76243079ccc241b4d..867a099f389ad6b78586e01df1ae15fa083fe88f 100644 GIT binary patch literal 582 zcmYk4%Su~e6otPnjnLAGM@{wMpauk;1R{h=u!$FJN29Blr+b#HoUB;QCJvA$)M)?AzLF^W)+1j~QY#gt*8=h!@6uzA5UF;hL#x zHdg7iIAzP?i)H30tJd{jX{M|2l=pZ?()#Q@E0$GlOF#q1Gz-`1TZSb|lV^zUoRZ@O zb-c0&M4pOvjlzvM#meHNrwyL;`1fisKSy5*!AC2EV7umnwFiABC>-#be? zU7NI4?R+amx05OqEwF~u$yvQcG{Ncl>T$7i{sbN~RhKcI_+$n7?4`&fC9?cy*6J9y zq;*>d^K4kVy=9Ewobi#D^o!R4hy3Cv2kf&acG(Hp#<3+f9h#oEl%;qOC!%Ppl&nWu zH+-OrP8u21W!q>Ce7@0lB=AkO=ejI}e*SN?Lu9K{q- zMvh(4%p#d1Vg<*tSaN9kur*i%PvSsiZHPmwm)0F= zQY5LNO_z=HDfC&ZZ&&DTk$-g3A}5W^sMgor_T|T2V_shKPIGkY;(@%m|8CU;(Z$`B L3*SccO3eQc5`AWY diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc index aac797f931d35d607e5ba9a5db13559fc605fd78..2c1fbd338b90b9ba90f90277a3334a7b23746ebc 100644 GIT binary patch literal 582 zcma)3u}T9`5S)F1AT}1kLj)^94#I^Ku@O106b|IbZ(I>ei;yyPKrUSl1w~RD@Fy(u z6@G=YyFAV^O!M~5zMY+UAqyFPBnegEDMAuQtV6~QvXW?Tguc-lDHbT4XSHx1C3%~Q zlrJYTL5`e!;l0|Ai(UaYaFfFQP+jj7^cb_F%Zgo79GTA! z$2gI-<@3zj3J(}i?-DDlSiho`DgDi476uCSc@T13t75o*6v; qPnH?g=52!)sj1lLKS-@UV;^(xoz_e|^Mt+2aw literal 582 zcma)3u}T9$5Ph>k5F3kdAcBpB+#!Jzu@O102?&Bqe&Y&LrU)sm19Ab21O-J>8}KJA z^ArAr;F}qivkb4<**80H-rG=w0^gE_Vc;o2GDoUI!49&LX>WqQ(Hc2ssGMgta~?H$ zn~Iz-2Qom3l6>X8+K-b?0hi=@@_|pRF~*~O5kJykifMSpIa$-jTIZuii&p1r)lKn@ z(uVGg``zHkRdFU8*`!@5h5FnHB`%N=ee`8zc&E~vEaX)pw%9U* r`~S%@qiEiic#=rHM*l&g`b>Syy>l9wc;N|qm*rG@E_zmY^2X$UAyZbJ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc index fef461549e0fd6121804fcda0a69b6396970a21e..07b4bf6bbf40d427e20f42e28e05c54d007b37c0 100644 GIT binary patch literal 2322 zcmZXWTZola6vx-fbR2r=B`>2!9uL`Z&T&RTkl@$_6N@fZ_$*k`Fi%Bq!uV!1sbEov z)k(4;%^91bg33c=P6^#e=*nOPJ(TufHzdq4fB&`j_njGhSpW53Yp=cbW$nGc&&+q( z0(;lYs%BTs@>i_iZ^pV2sSEw7)b3BUI{Wjz$d>`0mZ^M5? z(6+%2h}#DL6kLk;BD(IUVTWM5kTu8(|4wM#!M_bYH~2Tf=}FAj!8M90((gjo{S>J6 zR{Seaz3R?RVt*d|6R>Sf`v)!QW!I>v-%gc|Q^9-i6Q2hpZTDl zSFL=I^(R)^*-xw8k!vSy#yni-h#mKL>=~iIjjf8lhc#d)splTpkiUdKxQ!-@9(zpt zJ7AMGZq5lwu~}QgMsnoAX`JXX@?dUPhTVA_Rj_Sy>^byJnLnGg&en2vNq((*p1D;@ zej;0i)+uK{bELfcunH~S@EZFtJu1aCuJG=ikw=#D%=Bt@@=9xV(kZv{ndvqzFW1Bg z^GDb>&5)f>%=bkVm>X@oqb*^>HWNcuztt`=%8NvlEZH`eM^js^w2D4O4|JKQn${4R zGB4XsFnX*ok5jal{xVW$R&&XFUB(wPlwZB5tN#J+ApTscHmoUTFCeRUx6E&`F4Z)& zYP4E=7Z$rM?Zft<_ST<7GPl*TY{>Q}7V(o&fxxg&vZKa{7D`5QuZFD)D`}m0PKIp> z+{zf^G1vW6^kIBe@5Z;?&gXk-w$iV~lWwiqv1IdtW)`u!x#|9z|L$kw#*X8?$q0H_+JB9AC*ijEE{(_&eKw)1 zP9I-o3&V3Sp7ok_X=!%Jvp!~)Y|Zfp`dx!=1^$QiD49P-|DvxUEf?VpN|}4hjNBbdxhwgl&`HxPp&2B9 zk-La0#!z0}q#~}fl7huP_-xiW8DH~buw|S>y*)aC`r`N7`(U3vpINKJ{mUHF%592l zMf_B}h`Oy)_;~eg!n??h(C0$vK>juQ@Hc%WSVwwNPAa7ps$yuq&8pJ6sEfY9|KihM gjs8>g_kw25Y4?x9KSV|m{Y5nFFgSp$MP4?$43ObsFaQ7m literal 2322 zcmZXWO=z7}5Qb-nwXF!QZ0k?O+(cuNd+kq%c9W`5t6ltRx*n+ueK@uI<9NEU`}{H3U&yR|2=-eCDAvq;)_w~+;e7G? z_qK+pv*b93o<>&L7W&Lr%xub5+8*p)e-RYxvAx-%%`e4sxxWA|^XI{9d_Q=V?*p&) zz2L<@2DSxmwnOkm{w#P=V0&OKaH&6oe@Wotz!g4pl&88YbySdVEr7OM@Q|z9jhj!RbkiYSDw7K#25P(RF_p zd<&`hJD_^i{q3;jt@|6`lnvM~Xh|=-ri!kkO4C&EZhS?nPUa8OlKeko)sW@He2LF| z$iG&te8}1}tL*GoC2!BQlQug;{3~d7+{cZ2__!a$Rz+E#585f}$&UN|{uKV;Hjykp zOv`N%HD|}D-nkr`wKeRu967Rp587N6Ig;D)*=Qbzsxkg0b^v`t<~lp_>1=heOY&>g z%dE}Vh0JHNRkThy`?;WX980azl7_dj4-2DGTjK(+&Sx4?{bd#1@@jVSO3N#qax0(N z2+~!pi4*2q*f-6PolnenMiq8O+i0{UY}gPnWc8c4$20aS5fw|ey_rW-TU%w7KBWh` z%F~(F5}7iu+GZF%R+`5t?UlcZ)S1;>@?KZ*Wrp&r7d7-Rz+J?Do~jM&6XU%xUa^O; z`)#pm8d^14tGx@0U6=MJY*2ga+mOs{tt=a+s=*?DE-DZh_9@PoaiWEiiQKDU>%&S~ zC!UjGTLa1JFUMSWQ&Hx}I)22r-G23SPt9)B?X9fIWV52oB33sy-Cy(1{8Mt7AM^u$ zme&b|`S zO}~f&^@_+!x-gA@hka|Clux5%{wU{6FO@tg#{7(J$LeJ!x*Mv_n4gY!C*dveT^ft8 ziTZ3Ns?!IE>#{2%%RP8DXx5db*(J}0m|3zl$FGp{NHg$vvOGZMkI*0MYe>r<@D5}) zEPb)ePGc`Z>uz>bH+5Uw8m&dILCZ=}={7em@R!?P-i3~IS0Z<<%Dwe}xm%WU*XU7B znqCRbAo)w~5>>`fUfrY;*IG$oX&?S(ohRdKK1uAqoI|}m!};64+VmA$WiMG`%@+6L zIi{K06xodU`FIg^TmQtzt54)VphW);(t-SIT*vr*&V7$Fcv;SQK31rTu~Od?by**E n`GmgT;L~5tZnXYh(9AjQ&=L3t$ONMAXT$Ube*{^F95(w8tyoWs diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc index e54bfa2ebd3d79810169e75a6ee899ac11960f36..56d678fa710c7c470efc1acc881b1997405d5606 100644 GIT binary patch literal 1466 zcmb7^eM}o=9LJx)_1fdEz3VG&X?rcuLf>fV+x7a6EP)XgByq8eLnoRon32&$Cis$3 z%zW7Z`6NTw(vArJ+Y8tMWpaf>F5HH&e+Fvcna!Ayd&j~6nd{No>&-1ED8 zp5O2H{e8X<0B8bzfWC|90Kggmkj4ODQfylY4`~4i-3Y7U8{0?^!YBZ|9stCx;!XgH zlp<90l4wO+rfZ=36z>5*Ndd6L4I2OyUPUOhgFpcwTJZk-uE~7tQ{oAsTi6Hy;>@r5 z^3TTr#A=8|@sIv+fDF{z=i!<@2ms!NF9RT~rG65QDG#VmtCvM~(Z!Owl8d}6WU*$f zWJ|or?vu7lFUvHtYjQib7n_m)pokQW;AX{Iag!#lL{vShY(8@@s=!|mEt6--JCe5n zpmkJ&Jr00=(V!<7a)?}_($uE-OYu4Y_5lXbPSHAgmR#@;JC**suKV^%=Q+5Gp0y8z z*2snYTIoFJx}T5D!f!CjAP@fsK=*5TQZfWpQ6{uCx>nu!e5a2Ueurdulf1t z5)`0vO3JGfW_elk9tMau;cp9Esx~~67zgXrn z=*y0j&6M-Ycab zxcoOolj2e_ulPX4hGE=ytN070LYYv0qGD8MRQJ^N>XiD=l6@s38dCF|X1dZ{*+DzB zHKkAM_`258G2MA54XYPsF+|jib&E1wbz~6M$Mwfg3JQ32`HueXAy3a5!Dy#qHDVUd zxNz1V=7rH;0;C=Z)ay;;5S6gRB{_0Qzf0U|pQjH>+*M90%^nwb8aB9@Xr`g^@O1k? z;C&>+Pm&9Q0^2&w!aNdy6Ho>={S=%?V1LjS+|T7^5dX0M?zZk?mY*zDI=e$phC19Y z3JOA#!I5Al{E8*ctCQs1r^4y*w-Hsu8oeC79_fhmM!x1{V^UZRGhx_>wri%jQzJK` z>ZlERB6ry$?ZUC3ETIi%^|q?3nmGxVKe4NDg{5iOcHd6T0a@1jp47cdq}A>+|uVl;-> zn?t=t48DvP5I9yPk_B2sZ}Pqg|BOBxoG*GS=40o=teAbMQD`z|#NvsS8;rgH9UqL@>~w-w0ZhGpL^y#Ti#M{UG;0#JL*h?nrG9s7|O6Xz;b6aJb z%S=?Z#VwpuCjR8PDAkP3G>kww&Ml(b+F%5v!Abj(} zstW)R?W&AwMBS)w;_|w2*mrjdk@S*>gg+YW5#AYPgPS{RZ4Y0&8yo1sKi43l}8;GN195916(eA%(v0?KDPvSIntF_Y@SLB z{T#RC+bE2|_7WTo^*>$@fZ>v*k7gkg?HWC0@E9^e=4Q!&l#_K3hlz)BM)s{dCv!=* zNk^3#q)lEc{~G77@R; z!DIT(kZ~`-=#?2Xr(D1kWW5+2ISu0z^OH03oOBdv6LSC{Hjn2kj}qIKtW{0WQ&iTeb)V3UyE`2ZE8kP4T(?4(O|@c8bls3VJiQY0WTl*( zq0;i4dj{STnyaE*zs4UWYLcHMZzP^coJx!!ZOLUAjr%!MZL(h1EuNaVpOhw3 z&=JYg&=Zl5_+fsBYnh)c!+1rN;EN|Y&{Ig;%1%MaF4=AXuq~3OR@XFn2C5o5iXNm| zX%kd8^cFftk3lW{Tjvx4l@48peN{w|4~jRaSyA(NukU5_GpRY;W7-+(^Sl-v#scIa zY)D~HoaEy;YKlhhBEM94kI6tTx>=D7Ke-wgA!Ee~8Igvm7QPF~dXb9w zYKRm>twTj9Gmr(;O(+YMqwB^Fay=qbsBm)Hy#Q5&=bdb_+Ix~#4``=Yb2V%EN^B4H=&eGa?xit82E1@;e4&!xDGcgFk3SMKlj zkB9J(C$znyy$n;O3XG})j=k`G2%W8(3#-Br(TV2P|GM!1dJsAg;k0YY^A(cSeF$Cn Iqz3``2S@s$H~;_u diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc index 960d87142cf091ee2c2bf1d10dbe172df120a6ab..9e8f5966ee96bc1ceb2ecb1976ea7998c2651d84 100644 GIT binary patch literal 2306 zcmeH{>2H)(6vm&Y2n7*YJIoZ(i4~#*wfIFNmZd2zf(j~iHzC1DAyJ4T1{9(u)Q)Wv zaEU=#KCm>QNCB5o0L(;z#+HtT@i*Fk-t5A~7W(?0Fe ze!Z((bhD0VhNf$pZqUpqw@z!dO3xxQPA}_4t1BN zb)$}{OIP95o9a-b-d0LE)oX{gt4V)&yn5qb6S9H6Qj^g<0naz7MVr;CEqX;;wNu;l zmR`k5xf^_iuXM35_gHnfuSV-6{{HDP*yzwM-|c%`52eE^e2uU6WvcU~zBX!Iui*d6 zVAJP&fCqV?hj_4ud8kt^QO?8BFkbh0ub*<4i-~TRZ_`7*T@U+CJ>t8x*mr1=_dp-x z-rld{N_(2xi6=)KjWW^o(K~)U#OVr8@Namt6whB$Emf%{>)|{_RjTCllecIuRmh`f zIax^QOC-}SVzuGX6V%cwCby@c@4&_>&TZJ}<2Rr?a?@n63@zp8so)z{g_rsJ;2#wj zg~ndvmPYq zvsyxLcag8E(_V!9v<2H>kbOQg%J>4_$e1@B3H~JZOszKS9 zm60L4o{T41R)}bgvYxL}_aL#@e|etQ_@o-0_t%~We=U?P-b&xJ`e*vrGS3X; zwcfu|v6Lt3lqX?rE|QZt&xMzVnxf0fK!o`TsDci~`W3v8S_aH!bamkS9L}ZSdsG#D zu5_ge&d~*ld_8DmJ9I^-I_be~YJAvKn#eZCwJFY43-i^&WVN!kF=KhAYp1{Ucdl^_ z7P?~G*y6s9doJE9;pK>613JQlCM(e!G@Y5%s4ePEEc_c8WI=c}*$mSY?U9W%n`~>L zj{8$~fr!_6p_@E|dNosvY9?(vv(`wiYMH8K-Ut48s1EhXx~fQ^YW z51{#1|DsZQVwp1JHiP{X)JdFk%tLYtbCrf(hW79cxGdEuM0|$-Qsld!WxbTllrq7^ z)axG^PqbY}=UCl7>N@7B0_<$hMq5gcvU8m6>y$0(1+PLGcl!%!7!UuvXLxIp++>0s?1pbbDQH2|$s0u0 zyRlPsmg^_Uj`=6j(~-5Kui8JTMsvIoZ}0bO5g#g$q5H!Ow9x(Co)Rf_NQVxnX6iTk mM_%k;yEO2?R}%;Mf(P2mJsxDW zN%B5bsZ<#)Q?>5XV2#ue_19>P)ff%b4Bey~)lb%KTBGODJdExJeXf%_r&Bts&vZhk zbx3FQsTwp-zvxjtqzCn|9*cIH^ny0)MQkSNRlTg&RH-d`N!!(?@t{@c8y(RcUC>rv zX%IYKM!pXpmsz*tqr`6_PsP&=Y*k=Y4Ni`4cyeCi;~_rSuEH*(Ms=fIqGSA*@*WFb z;x0%wpp%c1!F0&L*cT&WEr#m`4b?DgM(P&btWml(=^tAtTTq(aRlbYj zZV|hQpjJoR;4RcP!M~0f`fo(U9S-hDx^h%+cLqO+$G!*>?LL&y#|5~X+8afTA+pp? z1Xp2rre}MVQhv@W-LADNkGYQy9Qt1H%XvcFoOprCe4dOJ`3KMUT7R!rzvY7GbDl@C z#oOqFtv*d(72vv#ce}r!B5B{F%btRt25hFVZs4o~X_|ScKqJgT&?@SDtWVJksa4R~ z1XdTdp38a|`WH1TMqA?=6}^HgC-yC9r(iQw{jd(xW8FIDFV#a0OPP)E?1*!+i&@#l zl}7gdVW){XS?LdnDH|$5Ey}6tk7zadh%R|N z^WE%i-l}K7IqNejQ^89VIy_5;X{1wF=jrfd6(%KvyaM#_4SMD9UyS-${>!j0AS?G` z{0?I#2T`GaY*_cWkuFK8+h4npzRICn?|RVEdX_iOI^{`7f95QwtUvZas+MRJz1p+2 z)<5B+l&Z4e5bg`? zYxxgdl}vrnMf#zgSbN;5`Vg5$!FF;>B|JCBzR&6+S!bEegpq8(z;E~_lA@OPqUPYb z8$VO~PW=>;9{ypkH?vOgYJGy6V6oeXcAj64`hoW>T^@RUGhN>8X;IRMb*OtSb#C)X mZrR|wES#Y~ojl-+Gqk)F@gXSGb00t$;`w6B7rm$6Em1US%Fb}V-Xuja&raa GN=5+CRtB;F delta 18 acmcb@wvcT?A`=6{#wntVn^!ZgWCQ>?q6OIi diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc index 2d3072abbd9e93280217a9576204a288e58ef209..266bf1bcf60fe62621df7a9e9a2d8aa252e270b3 100644 GIT binary patch literal 7491 zcmcIp2YcJd5gn2e-~_g4(&l0Tu53`Un4VDSg_I~tqAs~hm6hIXIf+u-((W$hzvs;? z$X$Q{>B}YjKI$&+I{eFu($u{ zVED0*f8vv$`t)Z$`?=BK=fCj9FMatdU;WzGzrku_nuTZQbn(_VzxDPz-~P^bzxVwg zFr@MzulM(b>1xPZ68nlLG4oMY|G-10<1iNR~ zXXn{~07+?T@L;qCa!jwW=PWoo4}+57nvD38ioU!uTif^UuZ3*DCWZ{cH-l`Om%G8k zUVV7R;Fz-{AF{{6Fq9(VC6>(n-u<*55_m(fM8sEEl1?~dBDTK$4A!$RI~*QtMD>th z`S^0ehEsv1q@-~v+3DW9-=i4W+UK<7Bm*vo&Zexa&*HQ5i~c`&UG(QA{U845$3OY$ z&wl=kU;gUX)3=Cd4v2R>2yfkPu($863V{(NmOv&1&Wh{1@xy!f`@=c{rJp{ zA&){0g9#V};)9o~sZ4$*9t@F;)OhiN!e-00;xPb{bV}+}XXz{HU!|JcE;Mc$q4JeN zc@rzRO4)R&A$sKps|=vU*Xse;RTs1A+4*Vpp}dYYJ?k5g;NAq1u0`b?fKOG;9+zE0 zxd3%|Gn^8gwgE6IR%jcJ8UVY62XMLy(39HsW&qDQCD$^j^nw~__}S33**YzDPAWuk z2lkZ@6vaB3SO?aWW}WDKojaK56Q;9fD=?SrZR|+2>;ciCNAdFLI6d)xyON*xV>Fm2 zPb2!xZ+}O>|HB{ugw_H;OlUfj*(X`Tjt;FxifpFF(Q$YZ%rK%wYNpT5Q$v^@GB(|B zMpnai-=kwXA!+~EBcaHst?fi67v=52rrb!MZjfjowA2VfQf-aE@Hr7;)c2Iw6+EqR zi#j^)pCA_@r*`yR>hi4F5K}^5!=0ApHdT>nwq};SlXo8Mr7^%atY;h6H|cL!r|DY! zj0S7hDO-=9(fW1Tgg@B8Z@LLTThD)x>m!Yk9$sv8jEwASqyp!RTsJ85Ge9(SP|6uj zB}~9Q=x{PezJ|+zcNeLNJxeti`ywZ}*ige%wl_-R+@_#n{XuM!h0lVlDkn{HwnjgL zKFJ6H9+mnkS@^VSf7V~ek34+wdC7hpLCn)K@XO6&M7QrC5*>x(X<`%QF;PR*3qI_t z<$`Y(@kM@)QEE`>G!M|x1#ySmX)j|!hk2#gODPB?CKzcTk2&2CdLs|q#i%RR7+`L{ z(nrVpsEiRsq(T&=hEYldAv8>9Wd~b?j*bJAum;!OAerZ`>-G(G>D> zlYaHOV<=40agh=EwHk~d-=N-VR?X4r^Q@A*^=~Db8qfHW5%R?v>deU1I?Jf9Q^H*j zWt&cdFp6L?L~+GcN-SQrz*&6hTYO6__M*11xYg z9}U6lE+(eI+*Uc;dD_KwYil4~fGduj*}zh%ju8$S&U3~3`-^qLx>Qlub*Aho>S$}j z>N+gYd8MV8@k{y{)-zj)!EbdP`Wy*sjcnu zdzmbTYlR`IUFph@EMvH}Juj_sU-vCr>`Xn~Neaw?%d@N(wKPT*%zN`PD&BhKoZS0g zJuOcPoFm+=iX3g`@Z~dsp+tC<%LIC;?+|qN$4XX^e~gQw@RhLpu zs0L3OY>8q!Mz!l#t?=8vt-exh644HEaodLjxq3^o^DYOdI}pfdjw)+3UmdWHDs^;R z=({MZ&6ZBl*SJe?r9_p2Q}D_YaFBnox0Fu~HEx;cDM^AO`{e1taB-oT^b+T^F`r)5TDTm??>zz&eu>` z5WKv?FV?J|3a4hpb+qcu5AmoXH|!0z=`z~L&)}4^94}3<$-&V2ow}$I&h_rw7_y8w0HQ4;JX6rf6HfV%c4?5@0FGr> zBr54zEjAXMS?yqGTO59mQpdnyB1;O7Wv?U%eKOI~2PtMr_5p8>n)ax`Ig$UX;&BR~ zDf_{SiGth2eH+7Ra$q4R!j?XHei*YO5;y_|91K~Q$1Vsv6!%T+wtKq0;W{TFp0^SV zlKZvbgOZ2{&-t&1;*I&6tpw@ad`s-fuFO9U5Dy&T8sq%p2^gpBzG2A4ha-f`Q-j*} zyNXZ~+NkEc8CPm7Vt&T=g&-c-k1R$Igf@Q^{#`2mO@>SACH_2lO3Qar{`c7>q-HGo H-+%rC7xs6~ literal 7756 zcmc&&33t@U5iXGJu_f>@10%K6GH49rV>g$`oy>rZ$!rqmc9Pwk7;qBj0CtoA|6abT z?v`3J(%5YFz05Ostm?0>uez#RL^p2YC&0g6#9!9dH+q{}F)0dkPCY8Z-G`4Rd;156 zAAI*0;a&-S2&W=l%nRoIL+Q@1r07=*Oo&`RUJo{)=D!3eU_> zKoKi@&3~Q78)|b)=XdW>L7z({Yk_ys=2k?ka!yv|Hr*+P-74Q65Dd0@2`#x%N%R_O z&W8v*BArLKZWsM-l~cm!#!UoH9C%~{kMS8Ot#uAb@#y{W+x<9Id5*->cpSVpo<<6I z0)B0MoUO<*ofGE+KOy^19&wrj3#LL`c+ubP-$6=Zq+~;HZmm!`r5$=8TBR1sTBR+i ze

RHW=Q$H~K6g%1SczV@V}XzLPxYXNu)uhc>t7o{W-T|K_(JfAYKE|KX2+`ZIiG z_C^gB5S zp`=K&G)G3@@7VLfTceWcETbcO)}}xubbSSHTRad2&#ebuCkn6cL7Zk}6-W`=G=AX< z@{Sx#lWTg=r2utVB@yh`mEeUy%)&|qbCZL@OJcmJpqoa7U=?)Pr(imxUPlfn(Nzea zQ-PPnjtpGw!3$dlD->LGhfuT79zuckHJz=kcjO@FIv5)dPNAViN&H$(XIf}n?5R}G zS2O^-Q$`+vC9BV_4zR(|z*CTNnFZHU5Ik#fUiyWiOxp$>Hrn4P=Mu2tx1!HDC#WGV zLet;9?m0S5@-)j=c~{QpQ-Svw{=8{j_RvZ=td|YzrI(wl;pO-W@>QDYk9f9F(bDHA zVYwZBPEMGyckk))j2X8hA+qN!dQ5Sw*4DMA{Ork7I&RG=9%gInZ1v?UB8(d1Q4>ds z&UD15k+C^V^r-n%r0b^(F&b`FQb_(aXNHHI09Z+dT^jw+P(4coW(~`0n^-Nq%yL{vZpku)jiomK4a3#dCFn(bC)CsLle_ z>Fy{?;;`=Z11ycO@i#mR386imNSESG|)@mlV z17zDauQz^%na7$GZ!lN9EtQECjC7}D~=ojI! zESgc=Q)#HtTx-W%`$Jc~adT{}jJaA;IdCP$F?0B`RvHjflMxE+$XJQliVk&*t`zev zbdKY^tI7PacNs7cM}VJTAfP53r(Ea~hlM;dRc|1vv`W6$J5Cx9 z#1Rm29LN^$4aCt`nlz0xWQc?I_EXpS6V4Vxu=NDO264b}-BuNUjM0#Ulxjcg~7HOf1GR6N^|G z0HSf#GO^HN_yp}rMpC#P+(8wGN&^xrGsVzav=19jh`{ zIfglEOOh_oi?~>j|6!kx~=e9gjdM)kveazn3)yxl`BSRI=~sp=$LaeYv_O52CxJY{3VB7rxrcn=9fHKF>^laRi!r<;B|boo>#8*6I#;=o+gw4u zFiF!z`2rqtN|np?vi|py;~2i^pWqGKILV~ho2GrT@(ba~opitx_C7L%Hz|JC6Bbg| zuq;cfbJDVmlGJijR~fzI%#h8j^L!bb3wFk%xX!xA>KFOckCm$d-n7+7nl`*?pxS(F zb@6|H*ySEHqan3;o@WrzT53c@n16)bIkLNggW@eW$%T|Cp*$-&R9t4zVKsVB&ZEEC zn^M+Ec`B2M(3@~|L7zfDOW$&n17Hb5TwZu%ihBecoosF$9CEXiPxY#L3b5UUUWO%t zw%|Iqv`i-q&iY+u-PBlHWu-b`aW6*4m(Q~A%j;WIT>DWQiS41lomN({v+Q%**#qq5 zUP7Vi1=!0xHxv_S+suTrgF|7PL#z@m@e=db)OTijxa}=XS>5**`ie{UQX**he|Tg= zYcB#WMEOjJu2+bS7&x34WMBVY5-k%E-zhq!x)&*j;T~JTG^_;a7x-E2CMGVl{BCDZv8G5 z5!CgKN;3jPFebb+TM)>i#*rCKfLs&cx24rz-d9=_L=J%#%{DZKD1J=M$q>a9;z4AG XsF=lnXwmZZwEBKRrzcMO9>4z!rwDBL diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc index 1edaa27c8a..df3f4df043 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc @@ -1,11 +1,2 @@ -ooF m!qF @@@@11m  ===!q##""  Bd=  # c!=s -G  1HH111 - -lab   `!! ! !EFF - -nDKC`=E - - - -  % - %S"#  \ No newline at end of file +ooF!!m yF!!@@@@00m!!!!=== y##""!!Cd=!!!#!c =}H  0II000lab   +U  EFFnDGBU=E  % %S"#  \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc index 34c1880c2064d5ec608269ab36f11714deccd5e7..3a3cedb52aa3a2ea47dcfd531d358328b1577417 100644 GIT binary patch literal 31930 zcmeHO2ej1G7JXvD4k~;EMXXprJ}N4TiUkW|SL_9_V8H_F2fe2}5V2rE1qDRu3RtLi zqzEY3sZtdbkR~V~McO|}UM9)B%%sfC46Nn4E0c5f*=L`dOmcIR$?(SFqFfs<@hb3O z-o`)kSzOV=c{6Wy82k&*FD~NW9K^PG0beDNt8L$J&A$p`63_CB1!4RSKgDhNNZwyG ze&mZRK5q!h3y$+9UdnSsbs%5j$L1Msl;7mpbdDQwY?x471ic);w8cLZ7ty0UuXH3j z!gH-0p2lUOXUEOpFWi}Qi`z47x>@$*Bk8E&<9&Xpu&2s$rhiN#e`bp0iepEA1%AOF zw^3ehTYhUY&Vt&0kuVrDPnLb?*&F0K|H5eaarii{#WnaJzgTIE+R8Sp;O|RE1iwMP z$+!F>HpcJSR@60r$IE!8oyFg#tkZ4FTH_O5-}3kyy4MenhVhI3e7f8Z=cD);KitN6 zqHSeb^N385Y&iFJNBJwR?)W_3u(>WCkM$hXvG@o&3*K=2+$_36#=MfP#7x=H0x$<56?z zX=*<@xMM*($Btw1Lwq00@qj1U*(}#F9gSUE%jWn*ACdp~wKMIUtssh*&9D&O zRkU|8Z2BM*Co>M5ITkiT!we>-#&A41dnWDWjdQW|UB(t{Xy7EC)u0=#5!AdU+nBND z7~3h=26Ah}xAA-@mr_TfgGr^OmdC?!8xM6y9249d_-S6`cwUS9$hMrxJ>4jGm+z^Y2kFW+-M(eh0{O=OTN)3CK#Op^ zFf3e$7aKg9pNY+{p&X^MU9Y+s+(owjQ5zxOnL1A4&ceFD%zg!?+wAabULBsBnTg+_ zobQO~3_2ET3H}JVs$i+3h_GZL_oH@VSidYwvZOa~yeT2wXHF0#(ExZ)($9*l7 zp98sl7b|kkoilUCj=St81u#_lm?BFxF9-k)hljXSmA*dQ33#}~< zwBlnV>$da^KAI0p$AWz*HAf82$;9CHR)o^dBCf`V7!j^2%fYgg<9&H2F5*U5mA242 z`dhwh^T;+>w33#C+#k~t`kfXE`=IoC^lLg2#)q{1A123-Ltl7Nl(Em-=ySuTPl*Yr z4Yj66s1>y|v4;dV&s&l+mTsqJ)RdagjdTrNExwEZbQxVj7gIyJh%S`l;&C#sd|v$^ zj~fIr!o=x3s*kJb4CzxnI+dTtnwhikF4q(xOUKkt)yuRF2H+AnikY z(jLOvop$3BNbW7NH`*mVPG#g9@12f{;!d&@;a1!t@y+-TZo~~J=Zw4IpSTKFqKq}T z0+-`5BZf#5ePsc^L5P!pO+}Uw$e&3skzv2R%k8*9spS=-5{*#Wx@o|oS z7S1k><1CzsKjBoI%tJ~?Ed;-oo=w7u_!WMciQ~p`0*=RV_yx7Yu{cI@N83>xh30u* zqB~MzpJ8fL!;*0p<-P~y-W6rmfR*iB|22MyA2<;lfx~f_?c-3xLfI}XXJaNZSdjPe zJ^4&s_2C_S2M6Im@YzT1+;BDyz`ocA-^ACsBX-Aba%{@??cZRgKb{K;KVVncy4SD^ zzF_I#b6!1sTH+n(G%xCSDAy@$Creugi(+9*lyTf>crTXBw@j}&-igid7F!E%E@9my z%o}964jbb&b~Mu(+u+rB6<%b=(YOwrC(F5b4xWf7V9AW0O6C(cNE`{meS$aUa|h%VNohiDghmM7v=T zY=teb$@Yyktd~VbNLUMNU^V;&t6(Mk0V`lREP@5N7tDcKFb$@{*Dy({WIR&bnwf3* z%8J34B;T~R(Vt#luLt8`EQ~QUVKj__&tW8d=B@xEBr+6+z+iYE-h=+o5BfqMI^E5& zZ0HGH=}wUQbLe6qRHZaWCjy<}6?+U*E{2A15nKot!1>Ss z&VzH|95|cywi)&s>cd%ZCY%BFK#m@eGX{Ivu_V?|7fyxLY!FVCnsuByaFSz7Wo1ZeLv>O}=N5J857#s@K;1H+^ z2g5;71uDaV!mb1|JEGrguDyne600D+zRO0ESi=FZKbRvel!tOsabMWSt^<3+Ua%+Z z0lPz4*bR1tU0`P@13Tdin_;b?NNrPF)fTl`ZBqXf7paZXYuEYVW$W#qn%-`)$eMtTBH`L-;~@{ss+Mm>SgHl z)O_`eGUvu>o}sMfI{IpknyqH3nd&DsLrquH)KoP^O;$guAEZ}39iEx@z4}glEBP{y zSH>LHGwOJ`xqE7onyAdHocdBtP~+7&mAVU7W7QZnT8&bltC8w6^{M(qeXKrGAL1L{ zy6OWpLJe2L)KE1<4VGTZy#wCp<>>X4%!1Xswx)VVyg?~%pcVJ)@phPpJ+{`mEZkCsaGtRu%jA2OId~g+pOkaBVz0n3Hb?r;egbl~Jx& zg=x5JVd{FTQe&?l=BF>=t8o2bE|j{T2+m2CL4O77gUrLXuZE`v z_Xkq*;b3mQ87%jf{tZ6y$9DvjYR2y+q@JV4*NB^mr^L4oYOf1TgToc3fH_Iqyr`azzzRPt9>wmIVyzodJC zo~KJmSM$@y7JlfCf>GN0DSG;i=KE@Tw4$k?w&x?!>dIS8A4kp5#fOh{DMi)6h)*%2 z>ihH2eB;eOmK;hGlhbx9Q#ZGloK5YM({?M9`5u=WNy4TcNvNi4QrC1O37-#7LN$&i zY5CVqrpoksric!l68)Wr5_|?pi9YS2S9R>&=o*y3Q&g)L)Fpav!e!8R;doJ5^lj9P zaD3_=ju(|hy`pA>*8jH z&7^~n~E8l#ebHAl_!=hJikcs!Ik#>?~1!qzm+KeBzIFhA*j@h!m>XlgJg zKMaz8PU>p(t}Z2+Icj_ph@R2duf@8wXpuIhdD@g*|546Oljh`>?_|?#$Ii{7S-Isq z*)-I#bF*kjZuw3&4R-9@ERz3g>uDta#MaYjkRBZwSq5rTdRm*(Q`(d|=u*NG0 zVDZ`{R2@ya%dwNNFwx%tjUJ=M-%$Ma0BC*g#bn@z!pf$zI3yf7&5-}t|K JV8`79{|69Dfv^Ao literal 31288 zcmeHP3A_#U7e`r2T1d$jB2P5X;B`Tqi}PlK!N2hmF3j&5h+%PU-fDPu7T3zi#wF=4yI5?D*Ya~3gPs?K6Lb;R z)I2^KJIhU!ck!=WjaNnE@*n01J*jzI-;5bHSH=4cFPepQqeY_Q)G`?36`^sxHu4?O zGI)QqNFq3X5j~q1$A~SLJ@;_*cw!M|*%BMA8l1=KC&S}SW>p9ri~O+}GuznM?1kHW ztE@xCaMX=YCwX@y4_ilK{vlWc_6F6skMupuQ0Aqwr)7U6zVH~Xz~jO4=`&P0!?2}; zYvpH)8A+ARFY!s7sa4}edQH4fx6C6in8WZkueKhu$r|2Ds+Bm9YO#XoW#`pGVv<_1v=eWJ}AYHs%2+jNbrPY?F*Xt(`D zx$nnd^5eSA{WJ@^(hordC+ZPxfn7#OH z9<1fDtS!&eEV>uJj;_RGc@RGvBi<-_Ot$JMsUq7TzJ+E6^LQpcN`YAgJ`taiIg2u+ zrx_&spTE~|e##uxZN5~utRt1teEv@RO%a(~!pg>qR^Ppcm$>ITF}XQS*En=2HWR;z z7Uzg71pXb3>lKIJyk(@;G^QO`Iu5MSr%_$9X0xz-Uswfb@lAF(1lRX&HNnT|CY z%Y&$M!dO{$F)ArNoX{c^IEL*w*j=LeNJYjlGy{jgy5dX1dr*$)OYnCqm#0XTx2>2v z52DO8++~|tc!BOw)O#F_fw$9TI@1^-bVSoa9mBh@3J$}ttwwWX8_du-UPgG$3)>wR zcSYmzWV;B<6$=90!yy`?Gx#`9kiEJ?_k$yk(?*P=Yk1kJl!%8d&Dkik1bl>LUtv2Q zjpqkrBGPY*-M^{nR82P4Qwx4Kd1cUv*LCh{ERz;IMoH2R|FUAq+8m^+pr(Lz@yAq z01xeLVJr)eCGKNYO#`c8B^+s0!yLMgQMNQ3fSE8J#`2q@P>M%zJ3S*fQfR(zMcsHj z$qmabhu;V?F*HiIZ^9BeBYXgFz^lO+zs~ZB=U4d^`7NJg9?rvbeI6j(cVGk~11s*u zJ^4007Rr9w>bv(imwT==lY`IPo{;{#b2omByK)z?JM+cXT<*jV^FtcO+I8&#J<1)q z1Gne<1-qAR^3vpgPmveJAIzvb4FdZb@YYH7O)ZALI$t}~FM|)|v#vS7%(mmlkXCFRv<~T8^ z6*Z%#)Px#S;JCtftr^sa8d81fupZq;b#R9@DtK-A3G8#KMK{rnRFi7Z4OE@3r)pG% zBW9~qnJR^AIQ!h#nd6>86?rH{+#gT{DsO1eX~Xu%qH8_bnN)}_l}eVoHM*DzP<}x#pmXUQO^L&fB+8?qlsoV{7v&WD?AR6QEOVT4 zP<9dpJQGB@p*bq}X*`7|Wjuk$@faS(!+1zz;9qzUBR=!Ehc3iFaT{*M?N*&cJlukt z`32mB8>Q|BT#s^}hri-Ft0vxL^%M1QEv~`UnhLJMmHd3bT7kk{CJUGjRWUB-Sd0IyqFuaYpQStj>9q7 z5Bu~Qu!m0Qwm!mc*abUb2W*FJB=bk}0$X7VY!)RsGqL3?Yi7B(VKuCRm9PSq!+diV zgw7=}59XS2%?8u?0=@_BY%mR`!W5VclVBoDfN_F+3!lMg7zOXaTQCw{f#EO=UXrbT zPq>;_A6^XfFqDpa&GgEL7Xp=@haoT+2ElWBJ`98b@GSI)XP_Ts08{2CCddE+1ONqn zp%3&XfL_oOLT49v3ZA5@x>9mScmjIJo_O4-0^Ok-JO*9iQFufmU7#~`f`>_F;^qY& zf(PLN=!oN?1GI;B!qjG^rt^fE?T-y@;XW{3ncyC1V<^Mj(Aw~%pH^^}bd-5F9*jXt zXrWoq9GXE>8Jo!QHp86fw+)TqP6(Whp;4%ZhI$QX0QIGZJ9Ix3m%Aj~ABNR~+n}z7 zft;s`+ zLq~%nPO0P=&J`QbwOxj?$k{9IdketU2}6K|$- z9+r3JB%gtId#izEyz#RJ8%t!3KD>2-ff<{(obw^@|=9ksum z;{bp4+^bVtD=&M*!?=gDIdrqtj8W}6an@hNW>R@OOi5 z*~#W{)5r?&dL;JWL1>HL>%xa36}d=fO_g*l~*blp=OsWR!M9V(}rgJ-)oiEZP={#fQ+= z`0^sNXj&u|A3|Y&`5vE&mPJ$I&$VXKWUC*)M-$@DwPwq+wP+eh*#W`#IO(zk(d_?LBdHb)_M4?k#Z!Vd5J9E(L7n+%ML2<|LZ|i<4a; zs1H6p)ufI_zu@zeK11103vIuJh4DZI60J>koaKx7k&|T6U;k7@YJ=DK$Fa z;#)OH@M$6!Omtm%h_eFscjjP*GbgzW_ApQ7zRB&yy*jsc=5qCD9BvgY;y=!ZV`*}W zSW#;X{?i ycbggpx_CPelk}#Y`!&ROoVjqynUfj@c$~XiyP`2xKOT<~dWVC$$5YeKoPPk07Q|8j diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc index 0802e32b8eadf71fdfad00e7e6b07c8c1709bbb1..8bdb123d8bbdbd0f6d40fdeb33adb9f1563b8e35 100644 GIT binary patch delta 961 zcmah{%Syvg5S>z}n1X`PDimFabSb!Ttrn#PAI17uxGI`z&^ED2YhA^E$Pc)2<4VX6 z_y=zM5W%Gz&rDKt?-lJL+?z9J&Yd|k&!hK;+{>k*~6`m^A@-x zHy=oVTN^PSSb%RR88(fO<02Lyk|`t^E|39mTVftqF7h0_m>_or5xa^%@{U#9%W8=p z%at&ztPXx#vieX|c(f%s_Xe6U9O^*cmRCL0r)QcRJ=&sR2Tuk_@8au8dk1LMlmYP< zPm_vX7fZ8;&`|7*HkRg#igC=DW_5na=fA1r#5T!p>c%m)*+OeQx|G2g>Y73OsE#|Z z$Y4dQg-U2(X=Y{|k8u*mqHS#n^kE(0{XXin;gdSJUDWS~0D0%wRJEZdT_Ytc{V$O* zL&QX764Rm|o2gErx>l*Q>{(2AIs_DI@Z={+m_e#3EUbdxL5Y;{T8Qw z6xEjM=z1%E>;e{|&$@EzU}>HEYEgCJpz77uwI6Qjl-B8sj@Re|=6q8nzZ2gJ;zv34+0lD0^b#|HUkUVj PZ`iY!eiU8J3I2s|Srat6 delta 20 ccmZ2r+F`VTmwBSVj?KQT4>&g4@+I>C08a4-0{{R3 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser22.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser22.rsc index bdedb092ee1ee9e90ab608d17594052f5675e7aa..518ee2acf0f0cbe8d688bfbe60487e9cfa88a6f9 100644 GIT binary patch delta 24 gcmcb_+Qqhkk#XYxgvp7Ft0o#~Oy*`fKG8q`0CXk@$^ZZW delta 19 bcmeBTyTrPIk#RCJW8CC;#x;|TnT`VhJPHOq diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser23.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser23.rsc index 4f2c8cdea764d4aa9e8eead3bf4a965c91eccc37..c8dd03c3454d784b551bdb0eaf6b2395d32f2c1a 100644 GIT binary patch literal 90 vcmZQzU=U+qV2}ZmAQm!~1oI&xFmWlMST2JBgCdZY0Ah$51_n29wq5&(Ia0_y+( diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser24.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser24.rsc index c68a5c525bf9094ee01d0c19a9cad15113930e17..ec7d7e618c050f6f112783198371f2971622f660 100644 GIT binary patch delta 30 hcmcb_+QqiPk#VvuQ`Ka9CIKLxJW+rXNZ9~!IslU@2<89) delta 25 bcmeBTyTrP|k#X{FMuCX}AwX&tgxL%LcJB!q diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc index 1a28e797d8d63935ce7613ef7c271f61b4a93293..95008983e977ef09ec999dcac0a66ac087d07842 100644 GIT binary patch literal 2306 zcmcIlZ)lZe6o1aYm!W2m)R*W(S{e>(vW-DTfnB6=iJ{Im7k!DqKQRqw<{A^h?XtvD z+7vFk$e;!yhJWrgmvhdR=;d0?UDH&A(Vrnh3j88%b+7%N_s;If_Aw66`#$gUoadb1 zbI$pl*EvUg$X$_}F7Dzy50ccp4B4EZMjqix*KI>K^2PHuXjlyDzQ&bIEK`Zp@1bexV+l1|tGcU9lggeGK|V$?1J6qBXYZr3#duTgzlB32!|Yt?o`&S(N}h#M(j z0_J=CKBUR}$=fwps8Z%A-dPPWFz19_ z0|G=+>b2a?*`RdUe8~q9mzDcLDZQza`YaGlYMGW%-ev7Yx4~uUQI~~D*DN<}tDXvG%Pp4;cG_*Zz)IuJayBstEea_X{Ym`Q= zE`T>Bly-esIfwZeR`YJXe^SQ1go@8t4PsfR=W!NxT^!Lk2#itQ1S~#BS!90zP@^3Axn^e)WP`MhrGm0^AL_Xr!+b5#69IJ<<*pP)8sgEep6$MHuQmpfsk!70xa9Yp2+;VT6U z@AaH!NT!)-r;&Pbj{M}b3^5;=ig;Gg9}(pUq0jQHFg7uZ zg*M{w;(3H>1+G!{{U-&VJ8V0=C5yZ8g6P0Y7XP20?W~=Z{S@IO&q7tC=zBw7r75e0 zj##h@B->Gu{x-lERzQ-I&~Nc);CI~T2vW~|HedtrSz|G158=DUYTOQFu*PGP26vh& z_z+c0Nu~6IUEf)!eQpOJokgKN)ERv5TAK7v!e6_JwTH-QXpW^g9oob)tYc|qfkO5rsboA=x%HX7}^-LS>g#K zumRi%S=(j<@kmP3=tU*vD=5*8$j8D0At;eU+i*a;rT*q^WmW9eOy2+h-n{vGGxHlF zdJuL}S{H_?FvS}{6J|P_lZmIpSDc}j?4I4DBa-E3I46hXu$96gN(ocFWN8srAoiU- zOLHJ)TnST_v3~2PL0GJCg>Hk&RQ4O5W!<_!=Y-891%X&E% zj!366t)ZV}l0W04cHN$%_jRQuxx=k$i*@rL4~3OgFW{Z$i~Jp5;ve}6|IF9;DqrW4 z40DryDlDw?Br6AW7QUqIat?!Rm_83VOwThP7dJ zcsr~M9icsJ3L8Ub*enfU3l(_-Vo%W?_hNIY7*epG^{mN3-7dG~mb_|9WzudScaLmD zwi@e3&f%NZG!-djE2*AR{4%AmSE}cnlPPlh9_2ZMcUP*h$sNvnG&r+f#_K1vS(_;p zrsS^tB9q8r%GO5-zxmQ{L)mj1%2cqAXfWPw!#5{elyp1(o%($!>q6_%VJqljN+p(9 zvo4Nay20yC7^QTXUXHradu@mJ|BLhZ++<8eW6n`g>mZlYcW9TsX4tI=wu#1g#q+i=)Mj3A%kz50W8 z(ms2g$4z+@-PyzA^d{|-+j!9_aE<21Z=Sl4|Gc$93l`yp`7C0{h2>b@-zhmJk9;S` zV1LAKbOFxuQOPLfQJ`LBXpVc0K}qyNMlaDAvNdLJ5F&8C*AM@mgmGV(&kw*Iv1VJE zFl&z8!$#Vn%fdqKurt7h)A@*#i@?f7pyU$hDqjKONq9be$n}Fm_|HrfQ|0xMwm+;P@y?E*Fsz3M| z4P_YxYQ|$t>JY;YVCRP11a696IZ8`G-_cD#$~f}f0$E2)5jZ*E1mt{9d2lm83^4ES zz^NixJ%d*`3d(ZV3e}xgBkm$L{4Sy_W*jqMkOmD^gx6D8qcn%cIF~RzSku9tPys?8 zV-TWpEvWS$vS0SYnp;QaLa%n|HqWj1BBIIZIdsOyE`b`>fllZS?>hYkbK;g1LPKbP z{HU~gjroKl#{0n+Djfe+ZA1c^zQNqm3)JTmG~V`NUVH%k37Vq^U1nOAFg>5gndlSU zfyjPGX6rPKOqZ*94h`~}V}nn?capYwugP&a9&Jp)s%OY2C1aNO9I3$P9oq$O6SZ6P zE^-1dDJ$vMaud`FixaTd3ylF-#DuI`g_cvat7+SX&WmSgd)+6XHDJB21DT9h1~e8( z%2I~UHt_LwRG`h;!X4DD&0~|pw1)e`PVS$k0Zjl!{c=)H%P{Cd>fP5Uo<=V##lm;V1LJ4SgU$ymEwu=X0s3wnqAsk6vfwA&VZ9461SNPX|!=Mz?4ATF--#TXo zX5e0^KFsURIcKlE_S$P7N&EDYUezIetUkS=BO24oI-p_o>zsa9S#>p3k@(gO-_Pod zPU<5~>qC8@_jOvQG@~U}zXC%c@(NC{_pK)>{pf>VEtsE4cY>d@v=%ZKqgPIP9 zE-HiJ6&*ykLqxZhM^JMe2D7@x-PRS!%X%atxAo0Yq$=lo%@B2` z7u$8qA>RV1OKm<2#BIWVF=L1IydLt5j^lZhQm^f?n&l9ok2q_6I-p1hjJ; zrh5<4$wNWcgCH4znPE=9$g51GQeet{RpI$YV78GHtH7Q@Sa1C}gT*cnUdUBb9xK+> z0Q@)y1-uhHS>l;^I!Zo{XZLliJom94ye`$>;qy7~(cfBuVdwns*r|eKIAD1}1^f=j$d-N(B`XLea9+k2ohzv67^o?cVooDyfIAyV|C2EUq|UhdJuLVFq|xy;(t z9_tT1(Nq1&$yU9&EP!=5AQw8X^x%ur)w9)if}OQV*qi4I!imi81$tra7Yrss7v3Ku!4U%1zlbht<*o8OuWnL~RoomDmJxBKy z;x@xX?%d<@=dcywKFF_&Z+XJ2YoP|7iSbv;&I-@WiMw_ySI^kpdpF)aqW}5ilzA(d zH=1>@OoHD3HgY?q7&@)B%l#!z@iffwEm!Hqw&f}I6T6H(#W%7iXz(d&e2gxpK@pkn zy^$^BqHFl!PTkp!lJzQob>*@TL+W*WhXNqd<_N%0N zsGoFGKj^By*ERj9LwZ9kE$I`rRn-SNsSkBpAL)!f)>*x;?{q`o>N?#MZEH)<^i==o zu^#Dx?(2%a(Pbu&)2`CzJo8@whcQ&N$W#yYFW>*xh8p~Q#b;k@N;_IpU6)i+O$(aW zyLwM2^p573W>&jATV|dHU5zT^Wtf#Fe695Azu=TR#CaP1iB@3GGsTJ0fc?}EdZWq^ zw)Y@67uCQ_3yuy2G!J0lDI7cs9NdQyfn_3~xU0W(M}O)M{jT41TfgcT-3t76>C)t+ ztGuma`bv`lZC!8b2-v4}QP06^2UI!toUcti>7nWL*v+tH{4P^fu(^(QO_=ht7pZ-i zs%KH}3@V-m(>AJF;Vsl`_w+m2SFjSMa-DLHz7^_5P9yXAGc;g7?VY=hTW-K<8E;*~ zV^?AOCcGyHI&Cqhe^J*;U}=pm_SnxLFQLK|oZm))TQGkIHSVH=)iCef@I-~5`8s7) ztftRTqRcc*9@g=oSy?lBOGokM94@tA7tnCv%+ZZKfww#Od<}=!g8B{mSA$oCTFXH% z_i=})VN`Fga`~z)fxAV;1m0ire2L#<6+2*Wjs4U&b8${1FJi|jF<``8L{`QbX);p- z%x0iSy$;i+u;7!PyTorBz2AnneU#Ie;micQPW2I+|LuNeZuL|18E$k=og<$flTb0O zR$sl;bfMOqnugOIxHW-t&@0mI;4Y>_86`{j+2k#>bbC+vux80s?3LZ zmia4>+fC9m-T{%@jUjeZa9!c)SG|Pq(!JTsd3$1JDCyllOMCBd33d0=-cA?ws+_8G zdYo%l*$K0!g?m{F8`#|^C*sy7VQ&Y_dEW=z4R|wWMq=JX^7$s83eHZ!TZPMAW-i7R zH`gr1tueaIUXpGUsy~k1jw;i=$t0Ct%1ki9d|)=d8RR>}w`}C!I}u&g4Gh~2ujiW@ z9p}Mm<#(8)Ma7BGxfXbF{Ym~?u(S;*FHTS@GRi#8J$d z%S^e%oNXpmP;iM!?}1o&SA4p__ZNIE1ROhj(gK|sHk!D5MQQ1+GpagW4(4zc?rK!- zu%~{b$$y)2LXKl9GmCf5Z()8DN%32iuAQ)h**jM8=GlLCU!~A%eghNtLNoB-yDa{d z@MM+G%!v1~F@$w=Tk?{|cXdpDS5C-?ygc^(XqT+#rl`Be6!jgNfZ_ku$gYv4 zu7jTDe*BHFPK_+j<1OSnXpobeg&IGB!|2Gt+t{E&c8e8jm5?1mjd7pYvv~VI5?U;! diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc index 0fb6df5babf738283b7d4bcff47ffe09d59a627f..f56c662a2dd74a382ebb483e5d22de6a5f6f41ac 100644 GIT binary patch literal 2306 zcmeHI-Ahza5dX~-5ke5rLs9kteHjr_QcFk(LWJ}n6+s12d)tSKz7T>?wymu|6p_{! z(+Z-O0c<2l2}6aF?x#VH*>D5Mpn-ehdXD!XU@!=a{;VIf=3ufBQ8Nu zk}<8<2imO%WQ~kspS+ciauDq}BhO4zzG*?0YJyFu$7XE6I_<|^VhQ&KT$4H^_7OG` z?&2cu^hRuR>^K_{_Alw?t>1#Dx?^W1myOYp|LIz~R}@3L`boZznt zTX0G)>M&OyPth)4P^7F~`*au`@=U&v@A+vT@!`}i_I*b7b4BnBBIcCPbKawz)Do?? zVvAQS#s|cP(|ZXWtkYuZX5Bx}L;G6foVrQ=keo-ER2dO+(#FU;&Pfrjn^n-lCW!gNZYjA3X>2qzmhJMh4`f160=J|n&=J9$~ige zbMO+8Hp#d=F{$(rb~((mKW)YfOV{wOBwEidz9y#^XN^w}S)2Q?yyAvi2V;5R+*j#t z{P)gDwGH=E`JPHTk@c*|V<$OvzP!K0GJ&q1B&AW7A=d|I@oQ=mEa!wi#Z@U|j@cb! z2klHTV;`4evi|RU{ZT6dr!t&NMtJ5C&vvR?mW9QR*`*tL8jtaroZb9t^^V@*{>ZaR z!kyy{YtTcoow8MYnW-zSzDJa(90 z#LBO7t6Ck@L3xT1*1ed{UwB`eF#1y*t8^py{xGi!?t4$ux|%QYhoqIVoEGJ9HK#n9 z-OnvF@!!+%E3ecoxPF;aGoSR0!Eg_d)*u I^>0<+2P4~jbpQYW literal 2206 zcmeHIO-NKx6#mW$q9TH5Bh!o#nf1yTB9bBs2@0ZGL_gCk!nDDDFbPQv8M1;_L9}ap zktGe0h)B?~Rl5o#LZm`w-!6m*Bc$(~`$osmO}ij2@7{C1^Lx*^_dWoR5Mu!2*d@y# z=$B!c(V{l%ep#n0(IRiOJ21+8OXL2b;tyMmMR4l$=3E>oLig?OeO~#du|2ogz;Do1|*v1b=gL zC!R||B8jwzyXepq1}W>%9*J;KhBQUo^V1$p5ewOte67iTsR*7yjyc8jJYiAj@2q>h zNNfxDaoT+`cj{)4H%<=nD@!{pUW6R-dWjXy;|20^1iMLxJbIaJ8?MO>>U&iUXEo9` z5NQTO*ud_M(w4C}rn%-Z?Ha?x$4#1aB#nOhX>!|p#74}5`4w=%d{Q%(>#kdpH!ia% z#7K|JD(=AJhUoJ%a`W^b)Ll$*cT=>_u|7GEIE4@7OU@N2E6GXrXi?7#(WT=oEin%m z(FW`cStL13GlOZ;AJDJcv{@do7op;@w&^ixlRMT~5qf^E8|8^f^$O=+pC`zjs#;L* zD^GtcGiZ~wM0a2xPcF}J7+z7MtwSX_@hq1=&zOX|Ux5QI&Qcg(SVwQh_UzJ#SeU<*Dih;?NVC@JdZfsBHo#-w#aeHR@>c12XFdXR)0_%gg26-z!Nvf z`mZ<6&$69oI}^t7rWmzQ7I@ATyD79U;6CRs)?toO%+}b<$_iFl=%-9H3OAEA8*^RW zbyjY#oN%t%)zGy)0n@BDQ>#wT>ruI#=sopL7UdcF5$m=rx0p3?EfafN{MO7%+`baL z*v#6FV1k*?*6K=Q~2Q z!W#LzRF!zVvNTeb*H*bThfl~F_j403`M=06=9Rid*N=EQI<=GUY8p3*yrPZeQ1RZh Z;G=1gFB%>wX<;T6&g`FI|Hr>uf!|HI4G;hT diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc index 44ce172e8f30fb86eb508b126702288c01775e96..28c6b22efb09fce1a46b3bc294772e866a2fc8cb 100644 GIT binary patch literal 1380 zcmZ{k*>B8I6vw}(3~e%lS|XM<5h8wo|lYl&Yw|fd~4e z(#4wwu|;VxEiR6oFm7=UD~gQka*)tq4{jxaAQ! z9h87QwwtkDZyC4vajj>1h^*&zlJO3>%hz36ZnB%rT%VES? zVmA?c5PSv4*#q4J@d4FB)X?b`Mw=n!D!i_)Zq=X=>;Q34O6(iYeY>1e-@$L}^RYQ~ z6AIa4=FOmiZ_Vn|Wwq!6T3qo;q%?5e?){ASnlDL3apG;_s)#Gks_hWVNET0-dptkD zN1afUE)rd5i)^?J!-EK}*{CykONZU5 zYW!z>PCBk1uP14yO|~5NJuvKpO)sqG_*0S@{{Q!O`BK`Xy68SUTtA0-M`9IaAEdi1 zOx4D@daFy_aOk%%6>g!@oq7nPfX+*)x0Q7VyxLJXiPBAJzOAS&%k>@V{x0p_uMO=3 zyi(rMC3doD__|JZey+-{Uads9YB}az>W9TA8<9TUc?9Nqtkwc$-Nr^`aqPzD7@mR8 zIgo{uWR-MGNX4uc>b=gQg8PfO&XQ^e_ylBh-8HCHNOkN#=$vXY{cW}99Aw;5wx68W Fr9ZJM%hUh> literal 1292 zcmZvc*>6oz6vn^(aKx3{P&K5I)(}F7a363GNx51nq1qZFtr*{1HB}?1sK0>+8ZX*( z@TNgb5h5gtgcw4EAQD5&<$>SY=Z@jw+h?!6*YK@x?|mdUM>VQdwW`#p;VM*-MyNm~ zDpsjRDX9kSP?JIhDpO1e#nr5GNw+0e<5t<+4Z=PME`tN$9e4!pv9|%t1&j5Jl?QG* z^OdfOaUqzc^W|6CBSl3_})w4 zDmNbt1zUWVyU2bCd<2j6gmHgPt$$Tc*S5ONzDH9!NxmUq4e{5&7v|f*0_HbBQ%bRb zb2821=#o{f-fIdsJvGjH4}NJd@!P>#tj~O>=_q69dsxbB9T<QsyNsg3&GI-*|nsLS6RyWK)d%Oke}g<~j{zzVVJ-DLgHcV-o= znu_^7wL4{cm#gHaNw0K>I-SJK(_33{n{7FDQo+ydFO#DnU#9mtEpS??bjdfNeB0(Pj`q8$q}8wo>az=RpHx@ z_iGJcMIKfo)K7BOxrxeC#cgFh^c>Ty2JoAt7dp;~+F!w5jHwsuIp3E$p`Cd<*>m4Z MxOrso`@)ZgeB3yw8v%&-km90sZ zBE>4?s#7UdifW~H>|6SmEhCm4d-CkXt2ggTeAv@$)S^{u)@?g-=0}wbdCGn2_HEvf zT7Ay7Xw#$Lgee<#9XRo2#jr?GqQ!_6CtiX?Ns_f{*P&CF0pn)OS+MEUm5gfpndx(McMmf$-QD&5_IjT#Ql#oup;Daz)f%*G5|A!SqiowU zrO8lhP>p6S>h%iiR4%AZmvdM4lD2H$sY`dBy?FKJ-G^46hOCG?lyKzCtw+Bis)Tg- z@?%QOq8?9%jhZ%V&bm# NZuE&JZ!>CPIsD9o$mq{`m?KC8~ zYdMKUKI%lykjPn*xKFmPS=lvS=LR>q#cf~lC&&4O6|Cb2e&|Pj>?eNeXEyL_8~Tmk z`kmkVgN=jc?HO;GDGoOz+!L4q0hr8U%0ERP`G_G=ubgq+OexLLyOIXrpe8JEC!Y{4o zSJrp4@c{x7#A=`Rd51XCd8Am-A{MonrL5`}w-Lfj!kNWJ;@H7XcCnj1?ByWGI8FkW zN#&k-%xh_%^$-8@Uq?IE@y;;X7&p4deI8^GVT@w|F~qZlWU|Or3tQYWzGpj!I?S1_ z^RP#}?B`&I8|o;>IL9bs-R%JndDP>c^t6eld)qr^2lCL5{tRX)!Hi%G)qgfkD1^J&zRv2Z~DO8K!BhdRvRj$kIUnd3-DalwmT z^0HSP?HI>0jPp!k7V|koUjsAA$UL$O3+&8xcCeFOT;i(14B;eCa+))o<(z@cY6sq^ z(T!~!;~LNSCNQBXOlc}po5r-JGrbwiXeKk8#gfi)wu{-o00wi-80_OG3yoqltJ#fS z4Cet)`6h04r@P$k9{0M>{T}e3hdk^Nk9y4G+~bLzobN&xxy0r4WFVth!cmTKoD-bn z6!&?{JKpnwulzQViA`cslbPH(&h@6Z=+9a{^2>&{asY>U%nM%ficf}ho(mYnG^R6y ztsLYC7rDb-KJ(pz7PpFRY;Q+agpnt7~eKUcWHEuQh3FUGWpjcjUf zr@7X3p7ny)7|J+Svxd!VVH>;I!(I+>nd{u-HV^q{7{eLf2QYy^#`SJ=i`(4c3D0@ntKOkIJ?KL}0vN(b#xRz3Y-AJ9`N1Fl z8r0y1G?bx@Xe6T=%e>~ZkmW3I1uI$ECN{UFee7#L1Dxm-r#r)yZg7*E-R>z*d&cYD I@HUzM19y(Z_y7O^ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc index 3a2935f14b6e5cff5390342610b0e4721c4072a4..4b693991e9ebc0ecf32ac49e9587c6beb5584ff8 100644 GIT binary patch literal 14858 zcmbtb33OCdn!fMes#MmhN~#hJA|QJp5<^IsBtX6UDpmrrrPX%nc8O!V1q5wnX&uoP z5nI~PRv1wbT241d88|qufzCMNHZzFpv1ia`Mo-(*)3!?65Oh$H`Tl#~t9n&=^@?WB zJ(XJC`~Umhf4l$x-xtPMC!ZHML%d}sdBS*xhcTLXQ|mr_Zcw9*(`cbra5Ha_1N?Hi zi`^3JXV>sKbuaKa@}!?Dsd%e@LD~aX<_DGeD1~HNNjKE zsL@jb&jrpeKU8{VN&m?0!I`6u1pkqBidsTBWIk{4LOH6(e26#bE5Xg|r*gn}M(!$q z7AUV3HFbwXjePlJP>M|z_e26EttDF_r`|{@p)`~EQJP6Y8Q;sBG?wtBV1GuIqk4Fp z4|7n)_iB`8GT0BC^Gipv9~i6te<(?o^rFAUs(iB4D0xf80bYp#eG^Kp@9=hGRd`GI z;Zv@cEAjj0@KI>|Hn~f_AM9`LoO-NzRP=hj=wwjxMP{-(ZYE1p#?!nvyoyj3w~q<= zqYPZY6TyB5Cs20ewaXT{%M1kjryOd$w0>6oY5cmALU|ou9O#4eo-m$rP#SxTr}ClH z-cz<*p^WmV_8$IvK9t5&a+h^5*dKm%Z2y>!y3vW1Cxg;Bi#3)`@xffp)`|nzm4*&d??v|$P#vGoo9WQWGSCM8I)!+^fhKXmo-N)}?H zBe60bS~l)UN0y=Vm)eYwzh~`*c`=$O1*Qy4IFphf4yL zz7p7`a1z$6!4k}}2CReDSHRH%Keu;1<5_%G@+9eqTF9GhZ_r?!I)WztiC1b(8}EvW z)_tw}fH698lg0@tg-biMrAF4sU7sm3x48SK@TYAh>$GIz&}*U_FSKj0l+$h<7Y z+fp5rz`72$rdG*1u^XjV$!lRNkWA~o;ASf>2h5nbx1T;czIXh+8l_bo z>^~utuQ>AaLK$mwcJ^3ntlin!VZ%@H_3TsS4;f^xtRrL3#^1yGH}M{fuA=p}Kj2&I zoqYC*$_i2)%~O1?<^mn{C7b3IS-fN2+gG2nukSG?Aww?`kfr z+d;tZPzYZ3lOgYj?Bc1hgc>q%BN*S8g`fZzwwI^atTdNw8NB3=08u$5@6)u#|72tU zG;S>v;KG`C%IdYbNW7CB^t26CGI-G+!Nd!o!JBQ`@8m^LfQuN1bsW)LGIjvY6q&K( zd&fi_nMW_?soD}v%ihn6pa2)lnv#iJ1o)K@>@I)+8a(4CHto8+2nulFOL@wCKyxvk z!@JS~yHO!1;Em-gfM7pgfYHT1wh`c)vV(LbVea;g&>gIir^-LlTtK-%Az08lM0U93caSxkyV+;NMa;|~;B^W?0Y4gB1nQVZz|Y8opuj3% z$tnIGEV1goJO~P{;wkJcOZa5sVmymX)z*S>kN>i*ku+Dfl8e^Ts?W#(AEJM8tSJ;&u)1+;>dq!RVm)j-EkQK{(i3_ia~2vA}9=B`x-5gY$mOB6`b63z1M z0$M=?PpQlgnuzV?3&Cw6{S^}R2vXOn$*HGNJ<`(Gvbg2JhR++eG%TO8wc%f<+>&@_ z%HH~;^{-F*d{ob*yJAcE)X2LNzYg|~{c7Uay7PIZu7vG%SbjSNNkOe0`*roHE=eX_ zlJtzUp=GE8wpAWUu0gLv$1_M$Wp6!XQM|`Gs1cOjd7=nRw=PqK5M(m1ECdwKdLY+v zKrm7x2p;f75QA@hpmiC#)ul@}ft{?>ow%aD$ZcnXdna>u^eBlYO1~=ckpduXI0bS!6VgcsRB6>3uFnhKzZb} zl`abey*Qg)nN2_LpqB+3eVRV^8sow^H9Tp#+14`Y4Gf5D|}10=6!{@i}AFY1mg zkptQnRc#e9HdgIO{>0HpNnptA+#$NePNy=WIplYFxNIwU-^&uA?V+QgJ%KPwpbIvW zDsPrR1YU@&A8|vD5B7^%c1+@WNu4tXOT_zfNA4UG_c3YLt_Nujqa+YU{HtKi8hcT9 z{B1cPTKSi##QIsY>Sdq<;>;19TRkCn&>Ye3==`>eA+Ig8pM=I1J<6tr<9rXz!Osqa z9j_JBN=K?Zq6Id55UWw~SJ^PC-RS51Dm{~^owzB!D0c*olf)`7r#VPs^*^t_3B8S( zqJsZ9G%hqrL<3>HI%hSFeR802wV7=E5OXYvZe;Dzjmf*5)$k>`@{0G-YO-u7Z6oL* zVKt~>!@{&}7JUO11q*au$UCh-rt^|TPd4vEZ+;>w*g27_L|YzuvT+~!w*J z#ys@2J|BAPx1hf>u+H5%%EC|Cj351npufw9p7w4Zdh-bAUq^??%7dSFUO)Q7==;27 zj7?shq382JbAnm9`3%MD;9Ky^OqJ`VPsc3ptls<=R23If7bg#WI!1ZZ%m1YL(Yw4R z4}ID`^Uxna=5d3JTgXU(L1!;+`~|X6`5T@Z|AjT*xHk`df!s^Jr}4M^S04HTnUhJC z)eq$zBtP`Q6n-aah7f0rc?}Dw<2hw=!-Odz!Ka+3`(UwmLEx}D z=50=#DXGhiGVw(^&KO@iaVCC7c-5qrcqigaQ+AxudlDjZ6JiIAt8j&>P<|4k-Epamtu4Dk8;V_=p{#|8s^O=Y6WbtokrM@-L~=^OO7x zobss-JLFHcs^%{gryzflAK?#o+w}9Gb30Cna{np?`6J?lI&E_KN!bQxKaS2blMQV0 ze!>%3B6xhS_7lvBdCN9r`$^^S@-n)w`nQgspzoSzKgKDQz2}Fwht-MQqzguNWcvwg zWNp#S@RR4|fNbYilo;eE)3%Q6fOPKHb0mdzeDEBQ|4xTLbtBB=^!Lnv<9iI~ljh(@ zD1&L;N0~}dH#~bl_tTNRoEx2LEH{?3Pc?u3fU&%KUGC7nK4iW#hrE@dE$f^yG`@!T zn-3BH=;qdaW)hv*WKnmC0bjqKumt;~=T%ONEF<62a|HXF))rWUT|Gd$F=q|oRWt{2 zWWUsFFyL+B?Kqo5=4X6OQqug5Z@l!7E2EMZ;~#O$_=Y-nv<6Em{&&!6kLJ&QP#tet zODAx}(~T9z3U-O+k6duYVEiJSlM|(5e&tPy{|sb!sOillA|GOns;GT@#d=6o)Xdbj zUiqQ6btl`VnC^YrVixzd;{C`h*JG-@XBwrkf6+NW+hgSvrYwB}H z7XJpF-vy3i_3%wcznGOePoF|QA5;BI77PAs&<#5>;SXv2os}QewC4^l{zOflO8iA} zAS|I*QDgwW@d@!S|DE*___qYs1&*6*n$~Lk8IQYY>SZmFLxxCri#=h_>2Y<;y>upEB z@P_q69?KorXS3_dblzLNf$$ftM+`k=*CpBc+Vhm((%Q=A;za*p`<(YNQBnCT_{;H3 zT_a|RSy?>NIor(lh(}dV^+2*ra8a#!h#{0C)9~Su&f6w#QarA-QdU%O8hZ}ofH z0%wBkThc4VP5-m15mlQq z^jZdD4xY0>ci4kIZBy2CrH4nW5Ca64wk{odynEB9?TN1>dfCpVRBaZ#>c2C3Y`sR~ z_nbd%OQ=dgpL~#StNH`zv+O|A8xaruX*<&Ek5$UwStDT2ztrD`A^x2%xjw9wLi1xzYxCAru`avRkaBDq^Pa^46*hJ z%F(KpSKZh$yM?uk#gjt7ko&}tXcraM>t=Fj7wWMdTL#MZFsG00#hP`!kGr~rY1$Ryzia&(e9`HDh(Lq2CG~Yq8gSKGAEL;ao-6UkdN37y99q|AEt;i?pxQ z9PNyYTtTd^Ti5PkkwC zyqu2by}B~dzOdwjk>HQp9>JOO2J^1KtHb{^{jgYV+-oMo$f!rWW+tmP zRy|^FIAa?_&M3a59sndJrv*-Xp?n&++s|Z`%td5L+q-c;=*OWia4vE|Dcj@)RB4&X zvBT^&uclAt)oLW|_l5is{$}VVx-xk1 zuIZ;a8nR~jOB;I8&j&!8a#J=Tut#qu*e;-6YP4d)0(SyJzTMOdT1@3wGMlQcC86` z20=v8kxTE?!Tt$LKp}^RoE4Q{Yaa7nk$KEx0I@T0Vt9y74Z#nHlw{OCoQ){rn7f^_Lc-aYu!aVF78mfh3}ozJB1yqakTVF zdbhf`lz1is1N7>NAJ3V*c3gIu-tA9xZnjb`4J+LyBjo81@b?So%gYEa`EXU}z&`C0QT^p|sY>}4@;sJ}J zHG1aiHm2VKb>t^2ec0N+A~MqVDBOMMfXi;(JkgT4`uwu?zd zyw_{)(*5c`mQ>CVX-9V|?Va)xP{SS&>l7dTS6dp{gGUTJ<~0NRzIpV_5&T&3iVPnY z7w~pVpMPy|Pc9c1t=IRJy{If=z2c_rb*bho#uH!T{=dv#@$BBp3^MwZjZR-<==|wi z$rIg0=Fw~(87__m(RI?1wn9%Xmk#CvJ`44FGW>x<*|oRTv+ohk!NWXCJ6eWI1|fd) z*wMTY@|$Q^3q0!PLVPG{l#R{)Re$s1LTl2t?WUmLh>yOKYxSOdka?;#5~kNgibQ_C)TVx?5vr-Gj!P1doydsNe2DWtaJ0C!*qvwsXORi>itJ5HKm&) z(d7=hOLL^>fAm#4`AUy9`V%_!YnAt3LZV2G*m|s1>k6B`-QWM-narD) znIv-Vc{6Y3-T(K;{onu0V~jOTxl+4~5Ay+xb|Y;KT0^|OYD8%2j$nfE5#El^NOUb9 zuv*y=Z`1m$72*VM6Em%gct^B5`rL|5rEPi{#;jPKJkxhMcu}-LpOrnt^!bm9>A))K zisdwTdn`5QnkhF2gDutQ80-r@T52^zYBMV_z>HY zs0WuLRx9yKTrT{dh2Igw)>>wq5|_v39~Q^>2VaIuBMsew7qLj`PI5T{jm9LGgM5(L z>@h!=wJ9ULcs<`x+i)se@`ubJBWCzLL8dR<-e4MDmT`QQ?~SgSL+WPj#I z!9_|GEM8yU3~tu)hpg6kkC7%_R#%_#c-d~TqB?RaT#6M&nl;gfJWg>b;x3m}BYrNe zUHVb|XmsuJ<5sKIN5fhXKP^5xK1-~$9y}%bD~&XVo_zFg2%{gLYq#24A^&++tMzq$ zp7i*O*v0(375|xEb1L+Cl6CPxq5J5UhSBGzO*_P|1^siaR#@s>qQ7MBS-7q=jP$9{ z7Yz*$igTvS5%qG&h>Is(`bOHXf5jzh()z>=PQ7T6)st>k*+wz2Ttqed9f!QU;eAh{+RifnYey)n)#mtmPXbL3x6IS7EWs z2}|XHAT0Lj_8ImZd#=5}uCf=}74|%PzFi6F0T1q_^f*KM=#gOQ@oT@4p8Bj9M5Y*V zq#vdX;D^Ump!VPg{Z`&IQw+i%bq8KbZ+$AI9}41IBtY}qQc9B4Hz2*Du2z^q!UF06 zx~F+#hw{+IqQv!BwPuLCg72C0%!;a!+&9b$8Wo$=*_>aSimqL}-fFFFP##*4@2q!i z%0szaxp;?lwYz3{E0?nlwkaEN$M?Z!j-pR7DWXQ&_0a4*R-1}fEM6a7Tibv&>1Wm! zieu}JK>9la>BptdWYN#olC{5hfm%7mnu3nvvf?f7$_eN>$a@pOD-VZMy7*Moh?I3R zj>^MpL=9WNs8y6sh7X0O&;lO7i4@|kh7SOPk;TEzYzY)((Q`rv7X-OGlLJVwJCK7A zJacxt91u3*K--YT!H!@K<_sf4FCh*JAIs!`|4aP~fgFV3DZVC~174oRL3c0*a}NtW zF15$9biket2HvgAhE0+guLJmy{L8 zcw$#D2W-=*4xY>80IPQ}2O)SC?HJ|Yoe&N>LpU&8PxQw^{9breP%MPt(PE<ceItZ}kSNj$gpQR59GLqjptmL|j1}$Tc(A3L#OHvjm>_32{(G zT2w0&FzMW>rh`_=G5!#3DZdNV3*g{W=ff7Tt2P~L_uW?eicOIoTJ_I-_{@j1s({a< z4RqH(;8oKQN4^L|T@_Hhh=fM@^j^xRl}2VZ!zxGhpnq)+u>r-AD1rsCGJxa9RW9LE z{TwVm9?XHc7BR4l^oRN|Lw|uBgxCOntFr^jhuBi`q5Qj`zc@d_j}(_L*}LS2bsI%P zU94_##RE0pt|_bjOYQ&FoLhUy7(8oU)nirvyzq4+y`WM*$4FN`sP*xo(^HiN^PSyi zJW17`I1$4APh|u^f4MLF^p^fE_`d9SWwNs294m z8FN$iNgs7p)%&d%NL?f%kDPwMNT1yWc+f>}peDE1rJi^&yz&(ZcEpW6`x>9+f~b%2 zcvV$FcGS;Po+Qr)^+7t~dxq?JwZXDWuWQ8Ilzr8N)I+jgY z?yuAyi#XyZSS`EUp|{JW8*Qo2M>e}9wp;5%MId+ejm3#yyV@may8IgG|IWf`h};)x7v)mX z@7M3Ao(i44;Zf0#N?9%=tuS;hh>AXFf=nLe>H<)l(|SSvutpt0IaDtJRvt!Mvr)v(eMaUA#V?L{F>5 zx($0Vqc)}WEncsGK)XV*v}lo{rS<9UI`u(cr?WS5_PBZjcIeIB!4+JaTbNsfj%c&^ zZ@y#IdG7sa3w6$r+wX(Mx>bL#v9Pwmm56l34Ex_aozXXvC~(KQgY;&;p*3q$ot!84 z{J@VrKko?Mv$GANU&}3w(4OBqr0f|8zcUyfdg(XL%{xa7+8gj)`a>Z6j$nBEWAqHJ z1SIH>3*Q|KPxP&CnxBe6vu9lR?c>0IgXptexd5Lu)JugXYK_+iQ z9Om<#DhDJlrR80qr6CYfovDbpnXV>HvWtL`G|Ok^4n5-HF`KlOq$BOQMJDW8K3HHl1x%DEps zk3S;QTw?#NiWF4XNz$1QJ|t63J0$vxY6%{_adQ+Nw#$MK$y5ZNe2C!rZ1JuOPgyGq zJ|t7YQ~HZcMIW9jBOUx783P}Zsfd1R9lMV0{;K<%OGRp|%SiiW z5ksyltFOwGrT#KkV+A+xPVp@N0co=GK&Hm#R)7QbB(%*(r6ZdPYjUZGmx&6ygzDld z?6Zi9wI8+8eixH|lnp6akiB+leI*5|RT93Q-0H*D{*VR_EC3-hep$eRL75vz}KT73&{e9k*GoCEqC3}kMeItTkNg$)K$EV&x^(`(0Z9HsHhm}dz7o1}tO?-B8wvN};&dW?Tc(O39(VsGM!Xp2~7wHoPJC7|+Z&K^*i zn?YqH`APB>HEE2f*i>=C^Wz_}COr9RQBQv2mx9W= zD!dawdCG2AvS@wDbTVD2H%_CoH{g?wEcL6T^&7++z*x)bh)VPbJh)T#EYMS6^&S=T zq>M&MA@y^2m&EE*(NvT#Fw%7PhG%`zKvW_hiUa(h_^n{BEaG*yJ7L}HQCWVRsHpu* z$!s@Hfc=8h1xC8$yL9#jt8irzuPIp|NmBHcyh&67VDy)%w3{*Q2lh;9WZPAuSjXasC z@NOgBID@}nZ*?`M^`-Wt_E>MQCOUfq)u3Y+H%kH%P>!)IMgF-bQC{h&Np-;^!m_v&b(&WuMg8OIq{t<3?KD zqy2NV1$A93zb#fzR50%~WMgz(TpufmltlP`tSmTtqx3zOig^i9;gl0)kBX>3{+Xos#R$A>BI~1p2WVyi}qGUg%6bME!k_n+Bl2O-Y}1imy1aj zu}|h`e>I1dgPznAH~7}eo>x!mr`=4?s&Qvf9@W0HL@Nozft8nVOwUQYl{hSVaV4Mj z<2-pBJH(X|$K{E)t;a-f!RAaH{6_5m9ss`a`RKMbN?CSU*YWE`@AT&~aR7R-0Dd|F z4y-4HV@BzW>&>I0cgDeN9Fx!oG9Te!&leXK7l~fGS>doQCw+(uC#BO)g=1!A$yEhw z{W`7N#?BgpW2VzvmAfHv6}*3>^d?`8H~JQZ`Fr%SZvg((OtQYar-Ps4O2YHc2wqd2 zbb15B_Z9|b=~4@+nL}ci10U#HT9ou)!n@2@M6dNkrY^PVsPvJMls$s|%6ymL?Y|&5 z&GhR4{tS4;`Q~xpcf?K-d?TJO%&HHDAD4c2@xuhqw^_fL^}|zu-=3=xyjU06IWNnG zF8|}w@3MYP@J71$XY+3N)33Q#$v-Z9XYq>)-uf-(`Qp<0JAxPMvf#7owBq+2`hO&N zzRk0r`2p@^=Z0ZRzVJlxgjet(hDDijrz~bqc`@nUHC5jzV6@8yd(A+Yhq2+H&<^o(s}F4KNh|511eImr@<;` zeh7#;`D+yf>e)MKpMjW_Pi7X()gCgBGv_%8>ZO}XZlYXHXKzs56x*P7fCRhfU4eSi z-NOP`v$zlyt$ZW3PG9{oW>P0hu3NIk<2g7Rla*;s zW_EPDtO33|CdQQB34^M>U3wGiT?D-~5D=LGTm(dAz^s6X445@G8uiIr2Dx^f8g8qZ?J zXq6tRz}2AHX?7|o#iKgXUH{1Z75=2&WtM9&u*fwSXIZz<|M^t)b(< zVeTl0;9J&vxToNh-%J!^1p&79y&nL4c)vJcmhX8^=qz6(gwFE$bLcFeKZnlp`E%$j zzdsLCKEvGQnU|1FsFgDlOODe`IHO#%l)r02_EAe%TCK65dAIVn60nNko=k^(*?t6oLJz3b_K zzOlb|dGKT4N93=Tf@ShdM?bWj^ACix#Bdqa=3@uei7^?)zfLequGbUQ zTlGToq$K`G+d(`kX@htaHbs1-!bm5yOdnNVOL`dVqhocYtehS3E>$}Fqn)mzcc@&G zIZM=kSx-|miGP2Lc~Li(|FL(J4U3%|=jIc(O!4NPy(|43f}q`(a}WJ~@)dWcd-fpw zenj{2mTXWZ(CJnJGzU8}RSDoZALWz4-?{_u%C#AOr2fMy^Vul2(P|^!gX-F)F`A#^ zchdhbY0y50cB1MSM?K=+r)M6}IF4#BljQ5I)Bh?Es`39gy4s=CaYMq^}Zxpud11F|$*t)JCe5k&V^N45$+mD1oZV zm;ng}DmkJOT}l!uLsQl9@!flVj*CEqA|WK+CBAoe@9w?xXZz*(;xo-x`7Jk?GdX4! zZ`@&_Fh4}T01<5jaYuyV{+RhR?$1@Zvm0&3 z?;ncZ=wX=Fy~;{s_!atDvqu%~khj{@`f057-PTIH$L)m=wf1p^xJ6HD?L*|r4*f_b9VfjM{S-Y;mVite@-bcJ7T0$|Tr;6ea`kc1R{8j4Hn{mr z^dYPIyXQXpL>^~>xUu1!NIz&D#u6ED6f7s&y4cjsl&luk7+;WPat|2+Tqe`!f?h$F z0`V(oa+M3y?+S4dFpCrQxUF@Whk}IZ3J$rzISE?JPmSX9BYnY*hG$qS|uN_@8A{GcdJ6|xqdHzLH zU~KzYo(|Fp{L!>Uung|VA>a_04gveSWFMgEqMVmQz#-rea0oaA90Cpjhrs`ifZ0C= z{~Qc9FQqg4dHusCZmMXO~m{9_VzX=yCv_`W>%>k-8PPnI|Lj8 z4grV2UqZmF;$|ryg?2r5twX>e;1Kv8f$0||bcsGn$3D{VLIe>uH*P1LUG) A@&Et; literal 0 HcmV?d00001 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part1.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part1.rsc new file mode 100644 index 0000000000000000000000000000000000000000..0a96c078f7c768c105efdb58bca550fb84f9668c GIT binary patch literal 8192 zcmeHMu};H4481A?5=+F66gIvA36W3W4`6_u4`4_KBxaVb?EFOf2mJ$5iJ=mR7KtIC zlA32bPOFmA0hLC|S-P{&_TAauDd079J-QvTc!^3nU6#7W2i7vG|(a_~P6;*(IulKOsTM)8;b2OW9t;>}Pg} zm0!SeJRkQlX0kPI5!Gz+b`>q?N;!c==E6h{saNY@QJc>;CLMPwz1cU-b$6n!qdxXZ z4ogKqe0TsYQ-wQau4k!|LrN}^)0tZQY}bf`^2Fa?3!=~av5TU?uzPgBE+5@ZR|&|a z%l=lPrCut`;(`C3R?9q!<@xKzwpJH)X!5!_b#@D^&ekNIB>9gW=dP8dDA?90JrSFP zO&ek{{I|vZxwoOpe2yLgkAO#@c?kUVxi`P(1@ak-%z0Cqo%%I~EJBfP-3*DZzPxAh3r zB0%&sRKqb?II4AWZhwV-rP}IWct-R>kC$LZlWRy>HcCZNe4Pvby^GnLYb)gcMaG(> zZ1^8R+?WRW%D}v#6$oe@{Ol$9MBkU248(3e>mmBdS)TVEde1i@O~+{d`O)MQ=wZ0XIO^SrOGDTnlhgc@1MUp-6AIM)|B&qEcB(sH(|G-L!wS}Zt$$?5r zJ1q>}rn68yut-Ao_W6A?J9`%);Y>gT=W#dletd6c_S>Dgn^_TQ3uIcg+`+fG*j%Bl zR@Hq`T}4FJjU@V(ZBbtLeT}xxR6lif|FTw#q>h#&ZOW?pRx*`oj2IT9A~T|84rX(ezxlC+A(jWXo;(7h;-f$RZn-1W?GW$ zNmr5ww0Ck@5V?n>&Ue^n`#Jhagm~JgyUyN2Jkf*skE;h?r`Q4GiukafGnAm{{HW}k zl5}C;X77k&qzHFq3G5Y?7vjWba|B>?mAyFk?PWQ*^_1p7WTWzh%5N~cm*XpB;yqJ;)df*mZQ5o^8KN~i1doXeUJ@UJYMQFzqc5Os^r1k^q0!a{bC^{PWqcsp z(nuNeSK}f-_09U)Qt^a2B6o8SZ;T)YGg04{S+jXDUo(orG7{@v?5E+OJ z{LaAS%Tjs{%69k?d&3U(`APlf^s{pYB;EoB^`bgG7pU+>{fJRQ--KilO3DE<>a zq_s)3CoqT~6C`m%lvuSZZ|1I&T^g(`#lo7W{ANslkuXmE5UaQW<)qdhp_4S9t6EH5 z6gO<847QM5xV*#Gt2!vE`Sg*39#wYrx6VWRS=~nr(0O=bO(D$ODech15lZ}?b4PM4 zb6vljS5=CM$8UxAAGZ@22b_K<_NnUKFUO}%Kir}!Zil+S<-EUHSdEca7%Ed=m*nb~ zwbsq;GM;x z$lqKkIR1~o2mlT9-T-9_Z3O{bhLuz{li$m&G~Q6rgM2Z<2Bv3uKDrydTo3*H9i#Cc MVndCr%uXWk1#=ZJTmS$7 literal 0 HcmV?d00001 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start2.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start2.rsc new file mode 100644 index 0000000000000000000000000000000000000000..f89f5812bfcd3b4f5dc4a3ced3b0f6300ed20786 GIT binary patch literal 8192 zcmeI!u?+wq2n0YkaTG^$bd?3Lu_4|!6c|G;6s#o#2oNAZfB*pk1PBlyK!5-N0t5&U ps3p)Mv)0U}eJ{{@{%5SoI8UMq0RjXF5Fqe}Kz<$EyP;J1e%QToDL4QC literal 0 HcmV?d00001 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part0.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part0.rsc new file mode 100644 index 0000000000000000000000000000000000000000..6b106b0dc0b0d170610d84bd27494d84e05ee1f5 GIT binary patch literal 8192 zcmeHMF>4e-6n=XfycFuDGlj4z6zo!(5HAz(59Akkg0;Ou%&ZW&($03REyT)7xziw5 zULj~*VMi9aIl9_q$&3iMm-|X(q%=%0V0l()4b0%qS z>Bb!v=sbyh0T6A5=0{D6Mi>{TkY^+O7Q_PsvbdB*3m`v^=DKrxoWK^d?8GS1g99FOBo^+a~0CX{nT z;ac2Zg7ta=0SNa(4m#mpL|Yi;kfI9ii3Res)X6A3{wC#s-)*ihr#liubhnEdz$?dT zb(de10eja7yOR>Q4u+xFnC&wdQDig?kTxP4nWBq!ZQ{ap^X}-{7V(0>v-2J8+vi_2 zg^Y`OmZyWv0RE`kGFTdSa11yGW@DiET`C@+*`l16W56-s7;p?Y1{?#90ms1q&VX4z zs(+6KyRHq*d4=pW&l{mVwF|jOL(LPrB9p7`lRIe zxL};c$wc^|*o^H$ZN{I|n1yYYW2$O0{QWu1_>vtdB6BH(K&?;nP*R<(+(=v;J;53N z!Efm0YhHup2=JV;$88;AhWzlTzDgbNiS@trZs2B+r*k*kPY+8xi&=W&e}0Y;Z%>C1 z!o}e0&goMf=xUlTLn!C*wnf=r&>ow^uj_8HdNS%G$4jYvK2!6U^Ks;e_MzF$$ab$4 z){g2vDowuPjXRdlRBGLprmbgYqfYQVX;({PppooXblP)YQahgJjWMvSt(Mx3Z>)VU z*BNjII%ME~|NcCj^D=pnnzj-ON=>7vD+~}vbe>J;7dxL$(JyA`>ggp9A@D+c+IMjV zoB?OR8E^)ifp^b9_U;+zhyXjEh4g(Xm60FNcds3lQ=wZ0Ki^W|Nm=vi(Sf0A%y_i2wiq literal 0 HcmV?d00001 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start0.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start0.rsc new file mode 100644 index 0000000000000000000000000000000000000000..7b6ff8e8003bcf3e60be88bac527654092d7a635 GIT binary patch literal 8192 zcmeHMziSjh6n=MmdMOg_$`pYK1ko;*7D@KNe;|K>k)*b_kn9#h{sSu^))r!~k^_~L zc3K#`O=qEaV3CCE?eqKQ?e1M5hBGP%&LcbfethrE?6*6U+gTCm3Z$)C?BHlEwpM6s zqUsNvE+ZoAP9lBHT9lUqJEPXA>W7~0T~sxX>S!_6nu)4aNmbeyF)T(!W<-lVLiCwD zmi}E?E)gTcsb(TgiHT_4BsND*quYW9iZtL6XF6@l5`2)M7Py)Q?6)J;likCajzrI; zC(%9HJDDtq+#&ue?9;uh*_23#r+u=UpcPIw-Vw)0qZIuugS|ZAg?LHQIRY@c(q5eV@~jwMdqi_6vQhdm5=WT7PUxjuB&|3* z>~F5b6`#H6h*foQ&!47jR+Cl5AH+9&eoR5j4#_x$y~MFst7d$cE6*>Vck2xFQ#5qn z+aO#e8mKgIQ12LwxEHgU$MM+j7y-3qk}LjzTE&%fSU7+`^aP+#kibA-U`ht;zs7j>O_>&8fq}q4 zU?4CM7zhjm1_A^BIRpNkG5+^RuyMn24`@ zqV!R)F@{&#qZjqQknPvxH@GzjL8X{GGY;u6lX4Sl_&{{P-80)YRDF{$-Z@&^1P~$% zZM`Le%_O|9Z*On2PW?{J_;@?a<3ke|2n+-U0t0`W0bA*9nLkdj4hIPg1O@^F=Q1$; zY80P=vKYS(ZX_dpa$Ns7{aAi7G%UUXo=G~#h|l;+d|rQ}Q<=A6>wq8dvbvrt^LFqB U2Z1ikK7QyHN$H1gYa!3`AGv~~xc~qF literal 0 HcmV?d00001 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start1.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start1.rsc new file mode 100644 index 0000000000000000000000000000000000000000..7ad1dc83c764e00df7a83dccbd896598e57a4c26 GIT binary patch literal 8192 zcmeHMy-ve05O$OSi6sooWZ)s#@W@-h!dozeffr!u%Fe{bgvyhUZb%^Ln4*#%_nm#M zQQD#k8nwYEIro3Izq1;*y(cP&$uL>65QTO;hg~Rl22~evL?KlC2{dEmY4LPbA&UQ) zGFU@`-LgUa{9sAkEK01}m4~_WWK%dRN};gkDZlQ+Ut7efpG7i9E;fa1os67E)h#K^Wg(IJ&`!keFHRZZCqxj(X750SV!~3TCgxOC$O{b z)+O=##vDjn#=3s=E1^C;6v#y4;ag4gaWh~w9VD>+M3`q<@2(kLO#PWSMfLcZJzZd! zCp`=eOJr1o`;v#s&{rin`o7kxxoyT{k8Kk67WPBucBe(PCij@QmbVE|$LDGy-L6IZ z-f@`Y_7))USEtRFm-o(ssiHX|5D|z7d_&;3pFiO}ui#>{;?`@-mzFgvj0i*oA_5VCh(JVOD-cMxVwD|Sq~6bR|JyjWnDTF^9o%Z% zQbeGEfS!NhCDAKAoikG!Ua(Y_&wVk}pJ&3CKP=pp8#R?IV94KG1#|vCf`?m3Ry7tB t4gU%OJ`8iogCO6RHyM!KYSQBk3{R`7ciVfp%4qz~BfdX2xoI1;wl4yHrQHAk literal 0 HcmV?d00001 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start2.rsc b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start2.rsc new file mode 100644 index 0000000000000000000000000000000000000000..d88c8d42ef193abc2cf9d1559bc633032d286ed6 GIT binary patch literal 8192 zcmeIyF$w@73Ki^W|Nm=vi(Sf0A%y_i2wiq literal 0 HcmV?d00001 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java index 8517aac9df..82c6cd1943 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -202,6 +202,8 @@ public String getInternalCategoryMessage() { return "nls"; //$NON-NLS-1$ case CAT_RESTRICTION: return "restriction"; //$NON-NLS-1$ + case CAT_MODULE: + return "module"; //$NON-NLS-1$ } return null; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 207ad332c6..5437149389 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -80,6 +80,8 @@ import java.io.StringWriter; import java.util.Iterator; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; @@ -129,9 +131,13 @@ import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; import org.eclipse.jdt.internal.compiler.ast.NameReference; import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; +import org.eclipse.jdt.internal.compiler.ast.OpensStatement; +import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; @@ -167,6 +173,7 @@ import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; @@ -175,6 +182,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.SplitPackageBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; @@ -197,7 +205,7 @@ public class ProblemReporter extends ProblemHandler { public ReferenceContext referenceContext; private Scanner positionScanner; - private boolean underScoreIsLambdaParameter; + private boolean underScoreIsError; private final static byte // TYPE_ACCESS = 0x0, FIELD_ACCESS = 0x4, @@ -237,6 +245,13 @@ public static int getIrritant(int problemID) { case IProblem.UsingDeprecatedField : return CompilerOptions.UsingDeprecatedAPI; + case IProblem.OverridingTerminallyDeprecatedMethod : + case IProblem.UsingTerminallyDeprecatedType : + case IProblem.UsingTerminallyDeprecatedMethod : + case IProblem.UsingTerminallyDeprecatedConstructor : + case IProblem.UsingTerminallyDeprecatedField : + return CompilerOptions.UsingTerminallyDeprecatedAPI; + case IProblem.LocalVariableIsNeverUsed : return CompilerOptions.UnusedLocalVariable; @@ -617,6 +632,11 @@ public static int getIrritant(int problemID) { return CompilerOptions.UnlikelyCollectionMethodArgumentType; case IProblem.UnlikelyEqualsArgumentType: return CompilerOptions.UnlikelyEqualsArgumentType; + + case IProblem.NonPublicTypeInAPI: + case IProblem.NotExportedTypeInAPI: + case IProblem.MissingRequiresTransitiveForTypeInAPI: + return CompilerOptions.APILeak; } return 0; } @@ -678,6 +698,7 @@ public static int getProblemCategory(int severity, int problemID) { case CompilerOptions.NonNullTypeVariableFromLegacyInvocation : case CompilerOptions.UnlikelyCollectionMethodArgumentType : case CompilerOptions.UnlikelyEqualsArgumentType: + case CompilerOptions.APILeak: return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM; case CompilerOptions.OverriddenPackageDefaultMethod : @@ -704,6 +725,7 @@ public static int getProblemCategory(int severity, int problemID) { return CategorizedProblem.CAT_UNNECESSARY_CODE; case CompilerOptions.UsingDeprecatedAPI : + case CompilerOptions.UsingTerminallyDeprecatedAPI : return CategorizedProblem.CAT_DEPRECATION; case CompilerOptions.NonExternalizedString : @@ -716,6 +738,7 @@ public static int getProblemCategory(int severity, int problemID) { case CompilerOptions.MissingJavadocTags : case CompilerOptions.InvalidJavadoc : case CompilerOptions.InvalidJavadoc|CompilerOptions.UsingDeprecatedAPI : + case CompilerOptions.InvalidJavadoc|CompilerOptions.UsingTerminallyDeprecatedAPI : return CategorizedProblem.CAT_JAVADOC; case CompilerOptions.UncheckedTypeOperation : @@ -755,6 +778,8 @@ public static int getProblemCategory(int severity, int problemID) { return CategorizedProblem.CAT_TYPE; if ((problemID & (IProblem.FieldRelated|IProblem.MethodRelated|IProblem.ConstructorRelated)) != 0) return CategorizedProblem.CAT_MEMBER; + if ((problemID & IProblem.ModuleRelated) != 0) + return CategorizedProblem.CAT_MODULE; } return CategorizedProblem.CAT_INTERNAL; } @@ -1344,7 +1369,7 @@ public void cannotReferToNonFinalOuterLocal(LocalVariableBinding local, ASTNode nodeSourceStart(local, location), nodeSourceEnd(local, location)); } -public void cannotReferToNonEffectivelyFinalOuterLocal(LocalVariableBinding local, ASTNode location) { +public void cannotReferToNonEffectivelyFinalOuterLocal(VariableBinding local, ASTNode location) { String[] arguments = new String[] { new String(local.readableName()) }; this.handle( IProblem.OuterLocalMustBeEffectivelyFinal, @@ -1353,6 +1378,15 @@ public void cannotReferToNonEffectivelyFinalOuterLocal(LocalVariableBinding loca nodeSourceStart(local, location), nodeSourceEnd(local, location)); } +public void cannotReferToNonFinalField(VariableBinding local, ASTNode location) { + String[] arguments = new String[] { new String(local.readableName()) }; + this.handle( + IProblem.FieldMustBeFinal, + arguments, + arguments, + nodeSourceStart(local, location), + nodeSourceEnd(local, location)); +} public void cannotReturnInInitializer(ASTNode location) { this.handle( IProblem.CannotReturnInInitializer, @@ -1606,7 +1640,7 @@ public int computeSeverity(int problemID){ case IProblem.ToleratedMisplacedTypeAnnotations: return ProblemSeverities.Warning; case IProblem.IllegalUseOfUnderscoreAsAnIdentifier: - return this.underScoreIsLambdaParameter ? ProblemSeverities.Error : ProblemSeverities.Warning; + return this.underScoreIsError ? ProblemSeverities.Error : ProblemSeverities.Warning; case IProblem.ProblemNotAnalysed: return ProblemSeverities.Info; // Not configurable } @@ -1676,21 +1710,17 @@ public void defaultModifierIllegallySpecified(int sourceStart, int sourceEnd) { } public void deprecatedField(FieldBinding field, ASTNode location) { - int severity = computeSeverity(IProblem.UsingDeprecatedField); - if (severity == ProblemSeverities.Ignore) return; this.handle( - IProblem.UsingDeprecatedField, + (field.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0 ? IProblem.UsingDeprecatedField : IProblem.UsingTerminallyDeprecatedField, new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, - severity, nodeSourceStart(field, location), nodeSourceEnd(field, location)); } public void deprecatedMethod(MethodBinding method, ASTNode location) { boolean isConstructor = method.isConstructor(); - int severity = computeSeverity(isConstructor ? IProblem.UsingDeprecatedConstructor : IProblem.UsingDeprecatedMethod); - if (severity == ProblemSeverities.Ignore) return; + boolean terminally = (method.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0; if (isConstructor) { int start = -1; if(location instanceof AllocationExpression) { @@ -1703,10 +1733,9 @@ public void deprecatedMethod(MethodBinding method, ASTNode location) { start = allocationExpression.type.sourceStart; } this.handle( - IProblem.UsingDeprecatedConstructor, + terminally ? IProblem.UsingTerminallyDeprecatedConstructor : IProblem.UsingDeprecatedConstructor, new String[] {new String(method.declaringClass.readableName()), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), typesAsString(method, true)}, - severity, (start == -1) ? location.sourceStart : start, location.sourceEnd); } else { @@ -1717,10 +1746,9 @@ public void deprecatedMethod(MethodBinding method, ASTNode location) { start = (int) (((MessageSend)location).nameSourcePosition >>> 32); } this.handle( - IProblem.UsingDeprecatedMethod, + terminally ? IProblem.UsingTerminallyDeprecatedMethod : IProblem.UsingDeprecatedMethod, new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, - severity, (start == -1) ? location.sourceStart : start, location.sourceEnd); } @@ -1732,8 +1760,6 @@ public void deprecatedType(TypeBinding type, ASTNode location) { // a deprecated type in a qualified reference (see bug 292510) public void deprecatedType(TypeBinding type, ASTNode location, int index) { if (location == null) return; // 1G828DN - no type ref for synthetic arguments - int severity = computeSeverity(IProblem.UsingDeprecatedType); - if (severity == ProblemSeverities.Ignore) return; type = type.leafComponentType(); int sourceStart = -1; if (location instanceof QualifiedTypeReference) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300031 @@ -1743,10 +1769,9 @@ public void deprecatedType(TypeBinding type, ASTNode location, int index) { } } this.handle( - IProblem.UsingDeprecatedType, + ((type.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0) ? IProblem.UsingDeprecatedType : IProblem.UsingTerminallyDeprecatedType, new String[] {new String(type.readableName())}, new String[] {new String(type.shortReadableName())}, - severity, (sourceStart == -1) ? location.sourceStart : sourceStart, nodeSourceEnd(null, location, index)); } @@ -2701,6 +2726,15 @@ public void illegalModifierCombinationForInterfaceMethod(AbstractMethodDeclarati methodDecl.sourceStart, methodDecl.sourceEnd); } +public void illegalModifierCombinationForPrivateInterfaceMethod(AbstractMethodDeclaration methodDecl) { + String[] arguments = new String[] {new String(methodDecl.selector)}; + this.handle( + IProblem.IllegalModifierCombinationForPrivateInterfaceMethod9, + arguments, + arguments, + methodDecl.sourceStart, + methodDecl.sourceEnd); +} public void illegalModifierForAnnotationField(FieldDeclaration fieldDecl) { String name = new String(fieldDecl.name); @@ -2758,6 +2792,15 @@ public void illegalModifierForClass(SourceTypeBinding type) { type.sourceStart(), type.sourceEnd()); } +public void illegalModifierForModule(ModuleDeclaration module) { + String[] arguments = new String[] {new String(module.moduleName)}; + this.handle( + IProblem.IllegalModifierForModule, + arguments, + arguments, + module.sourceStart(), + module.sourceEnd()); +} public void illegalModifierForEnum(SourceTypeBinding type) { String[] arguments = new String[] {new String(type.sourceName())}; this.handle( @@ -2819,13 +2862,14 @@ public void illegalModifierForInterfaceField(FieldDeclaration fieldDecl) { fieldDecl.sourceStart, fieldDecl.sourceEnd); } -public void illegalModifierForInterfaceMethod(AbstractMethodDeclaration methodDecl, boolean isJDK18orGreater) { +public void illegalModifierForInterfaceMethod(AbstractMethodDeclaration methodDecl, long level) { + + int problem = level < ClassFileConstants.JDK1_8 ? IProblem.IllegalModifierForInterfaceMethod : + level < ClassFileConstants.JDK9 ? IProblem.IllegalModifierForInterfaceMethod18 : IProblem.IllegalModifierForInterfaceMethod9; // cannot include parameter types since they are not resolved yet // and the error message would be too long this.handle( - isJDK18orGreater - ? IProblem.IllegalModifierForInterfaceMethod18 - : IProblem.IllegalModifierForInterfaceMethod, + problem, new String[] { new String(methodDecl.selector) }, @@ -3115,7 +3159,8 @@ public void importProblem(ImportReference importRef, Binding expectedImport) { String[] shortArguments = null; switch (expectedImport.problemId()) { case ProblemReasons.NotVisible : - id = IProblem.NotVisibleField; + case ProblemReasons.NotAccessible : + id = (expectedImport.problemId() == ProblemReasons.NotVisible) ? IProblem.NotVisibleField : IProblem.NotAccessibleField; readableArguments = new String[] {CharOperation.toString(importRef.tokens), new String(field.declaringClass.readableName())}; shortArguments = new String[] {CharOperation.toString(importRef.tokens), new String(field.declaringClass.shortReadableName())}; break; @@ -3139,6 +3184,18 @@ public void importProblem(ImportReference importRef, Binding expectedImport) { return; } + if (expectedImport instanceof PackageBinding && expectedImport.problemId() == ProblemReasons.NotAccessible) { + char[][] compoundName = ((PackageBinding)expectedImport).compoundName; + String[] arguments = new String[] {CharOperation.toString(compoundName)}; + this.handleUntagged( + IProblem.NotAccessiblePackage, + arguments, + arguments, + importRef.sourceStart, + (int) importRef.sourcePositions[compoundName.length - 1]); + return; + } + if (expectedImport.problemId() == ProblemReasons.NotFound) { char[][] tokens = expectedImport instanceof ProblemReferenceBinding ? ((ProblemReferenceBinding) expectedImport).compoundName @@ -3165,6 +3222,46 @@ public void importProblem(ImportReference importRef, Binding expectedImport) { } invalidType(importRef, (TypeBinding)expectedImport); } +public void conflictingPackagesFromModules(SplitPackageBinding splitPackage, int sourceStart, int sourceEnd) { + ModuleBinding enclosingModule = splitPackage.enclosingModule; + String modules = splitPackage.incarnations.stream() + .filter(enclosingModule::canAccess) + .map(p -> String.valueOf(p.enclosingModule.readableName())) + .sorted() + .collect(Collectors.joining(", ")); //$NON-NLS-1$ + String[] arguments = new String[] { + CharOperation.toString(splitPackage.compoundName), + modules }; + this.handle( + IProblem.ConflictingPackageFromModules, + arguments, + arguments, + sourceStart, + sourceEnd); +} +public void conflictingPackagesFromModules(PackageBinding pack, Set modules, int sourceStart, int sourceEnd) { + String moduleNames = modules.stream() + .map(p -> String.valueOf(p.name())) + .sorted() + .collect(Collectors.joining(", ")); //$NON-NLS-1$ + String[] arguments = new String[] { + CharOperation.toString(pack.compoundName), + moduleNames }; + this.handle( + IProblem.ConflictingPackageFromModules, + arguments, + arguments, + sourceStart, + sourceEnd); +} +public void conflictingPackagesFromOtherModules(ImportReference currentPackage, Set declaringModules) { + String moduleNames = declaringModules.stream() + .map(p -> String.valueOf(p.name())) + .sorted() + .collect(Collectors.joining(", ")); //$NON-NLS-1$ + String[] arguments = new String[] { CharOperation.toString(currentPackage.tokens), moduleNames }; + this.handle(IProblem.ConflictingPackageFromOtherModules, arguments, arguments, currentPackage.sourceStart, currentPackage.sourceEnd); +} public void incompatibleExceptionInThrowsClause(SourceTypeBinding type, MethodBinding currentMethod, MethodBinding inheritedMethod, ReferenceBinding exceptionType) { if (TypeBinding.equalsEquals(type, currentMethod.declaringClass)) { int id; @@ -3632,6 +3729,13 @@ public void invalidConstructor(Statement statement, MethodBinding targetConstruc shownConstructor = problemConstructor.closestMatch.original(); } break; + case ProblemReasons.NotAccessible : + id = IProblem.NotAccessibleConstructor; + problemConstructor = (ProblemMethodBinding) targetConstructor; + if (problemConstructor.closestMatch != null) { + shownConstructor = problemConstructor.closestMatch.original(); + } + break; case ProblemReasons.Ambiguous : if (insideDefaultConstructor){ id = IProblem.AmbiguousConstructorInDefaultConstructor; @@ -3881,8 +3985,9 @@ public void invalidField(FieldReference fieldRef, TypeBinding searchedType) { */ break; case ProblemReasons.NotVisible : + case ProblemReasons.NotAccessible : this.handle( - IProblem.NotVisibleField, + (field.problemId() == ProblemReasons.NotVisible) ? IProblem.NotVisibleField : IProblem.NotAccessibleField, new String[] {new String(fieldRef.token), new String(field.declaringClass.readableName())}, new String[] {new String(fieldRef.token), new String(field.declaringClass.shortReadableName())}, nodeSourceStart(field, fieldRef), @@ -3956,10 +4061,11 @@ public void invalidField(NameReference nameRef, FieldBinding field) { nodeSourceEnd(field, nameRef)); return; case ProblemReasons.NotVisible : + case ProblemReasons.NotAccessible : char[] name = field.readableName(); name = CharOperation.lastSegment(name, '.'); this.handle( - IProblem.NotVisibleField, + (field.problemId() == ProblemReasons.NotVisible) ? IProblem.NotVisibleField : IProblem.NotAccessibleField, new String[] {new String(name), new String(field.declaringClass.readableName())}, new String[] {new String(name), new String(field.declaringClass.shortReadableName())}, nodeSourceStart(field, nameRef), @@ -4047,9 +4153,10 @@ public void invalidField(QualifiedNameReference nameRef, FieldBinding field, int nodeSourceEnd(field, nameRef)); return; case ProblemReasons.NotVisible : + case ProblemReasons.NotAccessible : fieldName = new String(nameRef.tokens[index]); this.handle( - IProblem.NotVisibleField, + (field.problemId() == ProblemReasons.NotVisible) ? IProblem.NotVisibleField : IProblem.NotAccessibleField, new String[] {fieldName, new String(field.declaringClass.readableName())}, new String[] {fieldName, new String(field.declaringClass.shortReadableName())}, nodeSourceStart(field, nameRef), @@ -4098,6 +4205,20 @@ public void invalidFileNameForPackageAnnotations(Annotation annotation) { annotation.sourceEnd); } +public void nonStaticOrAlienTypeReceiver(MessageSend messageSend, MethodBinding method) { + this.handle( + IProblem.NonStaticOrAlienTypeReceiver, + new String[] { + new String(method.declaringClass.readableName()), + new String(method.selector), + }, + new String[] { + new String(method.declaringClass.shortReadableName()), + new String(method.selector), + }, + (int) (messageSend.nameSourcePosition >>> 32), + (int) messageSend.nameSourcePosition); +} public void invalidMethod(MessageSend messageSend, MethodBinding method, Scope scope) { if (isRecoveredName(messageSend.selector)) return; @@ -4159,7 +4280,8 @@ public void invalidMethod(MessageSend messageSend, MethodBinding method, Scope s } break; case ProblemReasons.NotVisible : - id = IProblem.NotVisibleMethod; + case ProblemReasons.NotAccessible : + id = (method.problemId() == ProblemReasons.NotVisible) ? IProblem.NotVisibleMethod : IProblem.NotAccessibleMethod; problemMethod = (ProblemMethodBinding) method; if (problemMethod.closestMatch != null) { shownMethod = problemMethod.closestMatch.original(); @@ -4178,18 +4300,7 @@ public void invalidMethod(MessageSend messageSend, MethodBinding method, Scope s id = IProblem.StaticMethodRequested; break; case ProblemReasons.NonStaticOrAlienTypeReceiver: - this.handle( - IProblem.NonStaticOrAlienTypeReceiver, - new String[] { - new String(method.declaringClass.readableName()), - new String(method.selector), - }, - new String[] { - new String(method.declaringClass.shortReadableName()), - new String(method.selector), - }, - (int) (messageSend.nameSourcePosition >>> 32), - (int) messageSend.nameSourcePosition); + nonStaticOrAlienTypeReceiver(messageSend, method); return; case ProblemReasons.InterfaceMethodInvocationNotBelow18: this.handle( @@ -4521,6 +4632,9 @@ else if (type instanceof ArrayBinding) { case ProblemReasons.NotVisible : id = IProblem.NotVisibleType; break; + case ProblemReasons.NotAccessible : + id = IProblem.NotAccessibleType; + break; case ProblemReasons.Ambiguous : id = IProblem.AmbiguousType; break; @@ -4740,14 +4854,6 @@ public void invalidUsageOfTypeAnnotations(Annotation annotation) { annotation.sourceStart, annotation.sourceEnd); } -public void toleratedMisplacedTypeAnnotations(Annotation first, Annotation last) { - this.handle( - IProblem.ToleratedMisplacedTypeAnnotations, - NoArgument, - NoArgument, - first.sourceStart, - last.sourceEnd); -} public void misplacedTypeAnnotations(Annotation first, Annotation last) { this.handle( IProblem.MisplacedTypeAnnotations, @@ -6874,7 +6980,8 @@ public void operatorOnlyValidOnNumericType(CompoundAssignment assignment, TypeB } public void overridesDeprecatedMethod(MethodBinding localMethod, MethodBinding inheritedMethod) { this.handle( - IProblem.OverridingDeprecatedMethod, + (inheritedMethod.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0 + ? IProblem.OverridingTerminallyDeprecatedMethod : IProblem.OverridingDeprecatedMethod, new String[] { new String( CharOperation.concat( @@ -7473,7 +7580,7 @@ public void repeatableAnnotationWithRepeatingContainer(Annotation annotation, Re public void reset() { this.positionScanner = null; } -public void resourceHasToImplementAutoCloseable(TypeBinding binding, TypeReference typeReference) { +public void resourceHasToImplementAutoCloseable(TypeBinding binding, ASTNode reference) { if (this.options.sourceLevel < ClassFileConstants.JDK1_7) { return; // Not supported in 1.7 would have been reported. Hence another not required } @@ -7481,8 +7588,8 @@ public void resourceHasToImplementAutoCloseable(TypeBinding binding, TypeReferen IProblem.ResourceHasToImplementAutoCloseable, new String[] {new String(binding.readableName())}, new String[] {new String(binding.shortReadableName())}, - typeReference.sourceStart, - typeReference.sourceEnd); + reference.sourceStart, + reference.sourceEnd); } private int retrieveClosingAngleBracketPosition(int start) { if (this.referenceContext == null) return start; @@ -8235,16 +8342,23 @@ public void unhandledException(TypeBinding exceptionType, ASTNode location) { sourceEnd); } public void unhandledExceptionFromAutoClose (TypeBinding exceptionType, ASTNode location) { - LocalVariableBinding localBinding = ((LocalDeclaration)location).binding; - if (localBinding != null) { + Binding binding = null; + if (location instanceof LocalDeclaration) { + binding = ((LocalDeclaration)location).binding; + } else if (location instanceof NameReference) { + binding = ((NameReference) location).binding; + } else if (location instanceof FieldReference) { + binding = ((FieldReference) location).binding; + } + if (binding != null) { this.handle( IProblem.UnhandledExceptionOnAutoClose, new String[] { new String(exceptionType.readableName()), - new String(localBinding.readableName())}, + new String(binding.readableName())}, new String[] { new String(exceptionType.shortReadableName()), - new String(localBinding.shortReadableName())}, + new String(binding.shortReadableName())}, location.sourceStart, location.sourceEnd); } @@ -9032,8 +9146,8 @@ public void useEnumAsAnIdentifier(int sourceStart, int sourceEnd) { sourceStart, sourceEnd); } -public void illegalUseOfUnderscoreAsAnIdentifier(int sourceStart, int sourceEnd, boolean lambdaParameter) { - this.underScoreIsLambdaParameter = lambdaParameter; +public void illegalUseOfUnderscoreAsAnIdentifier(int sourceStart, int sourceEnd, boolean reportError) { + this.underScoreIsError = reportError; try { this.handle( IProblem.IllegalUseOfUnderscoreAsAnIdentifier, @@ -9042,7 +9156,7 @@ public void illegalUseOfUnderscoreAsAnIdentifier(int sourceStart, int sourceEnd, sourceStart, sourceEnd); } finally { - this.underScoreIsLambdaParameter = false; + this.underScoreIsError = false; } } public void varargsArgumentNeedCast(MethodBinding method, TypeBinding argumentType, InvocationSite location) { @@ -9277,13 +9391,25 @@ public void wrongSequenceOfExceptionTypes(TypeReference typeRef, TypeBinding exc typeRef.sourceEnd); } -public void autoManagedResourcesNotBelow17(LocalDeclaration[] resources) { +public void autoManagedResourcesNotBelow17(Statement[] resources) { + Statement stmt0 = resources[0]; + Statement stmtn = resources[resources.length - 1]; + int sourceStart = stmt0 instanceof LocalDeclaration ? ((LocalDeclaration) stmt0).declarationSourceStart : stmt0.sourceStart; + int sourceEnd = stmtn instanceof LocalDeclaration ? ((LocalDeclaration) stmtn).declarationSourceEnd : stmtn.sourceEnd; this.handle( IProblem.AutoManagedResourceNotBelow17, NoArgument, NoArgument, - resources[0].declarationSourceStart, - resources[resources.length - 1].declarationSourceEnd); + sourceStart, + sourceEnd); +} +public void autoManagedVariableResourcesNotBelow9(Expression resource) { + this.handle( + IProblem.AutoManagedVariableResourceNotBelow9, + NoArgument, + NoArgument, + resource.sourceStart, + resource.sourceEnd); } public void cannotInferElidedTypes(AllocationExpression allocationExpression) { String arguments [] = new String [] { allocationExpression.type.toString() }; @@ -9318,6 +9444,14 @@ public void diamondNotWithAnoymousClasses(TypeReference type) { type.sourceStart, type.sourceEnd); } +public void anonymousDiamondWithNonDenotableTypeArguments(TypeReference type, TypeBinding tb) { + this.handle( + IProblem.NonDenotableTypeArgumentForAnonymousDiamond, + new String[]{new String(tb.leafComponentType().shortReadableName()), type.toString()}, + new String[]{new String(tb.leafComponentType().shortReadableName()), type.toString()}, + type.sourceStart, + type.sourceEnd); +} public void redundantSpecificationOfTypeArguments(ASTNode location, TypeBinding[] argumentTypes) { int severity = computeSeverity(IProblem.RedundantSpecificationOfTypeArguments); if (severity != ProblemSeverities.Ignore) { @@ -10527,6 +10661,55 @@ public void invalidTypeArguments(TypeReference[] typeReference) { typeReference[0].sourceStart, typeReference[typeReference.length - 1].sourceEnd); } +public void invalidModule(ModuleReference ref) { + this.handle(IProblem.UndefinedModule, + NoArgument, new String[] { CharOperation.charToString(ref.moduleName) }, + ref.sourceStart, ref.sourceEnd); +} +public void invalidOpensStatement(OpensStatement statement, ModuleDeclaration module) { + this.handle(IProblem.InvalidOpensStatement, + NoArgument, new String[] { CharOperation.charToString(module.moduleName) }, + statement.declarationSourceStart, statement.declarationSourceEnd); +} +public void invalidPackageReference(int problem, PackageVisibilityStatement ref) { + invalidPackageReference(problem, ref, ProblemSeverities.Error); +} +public void invalidPackageReference(int problem, PackageVisibilityStatement ref, int severity) { + this.handle(problem, NoArgument, 0, new String[] { CharOperation.charToString(ref.pkgName) }, severity, + ref.pkgRef.sourceStart, ref.pkgRef.sourceEnd, this.referenceContext, + this.referenceContext == null ? null : this.referenceContext.compilationResult()); +} +public void duplicateModuleReference(int problem, ModuleReference ref) { + this.handle(problem, + NoArgument, new String[] { CharOperation.charToString(ref.moduleName) }, + ref.sourceStart, ref.sourceEnd); +} +public void duplicateTypeReference(int problem, TypeReference ref) { + this.handle(problem, + NoArgument, new String[] { ref.toString() }, + ref.sourceStart, ref.sourceEnd); +} +public void duplicateTypeReference(int problem, TypeReference ref1, TypeReference ref2) { + this.handle(problem, + NoArgument, new String[] { ref1.toString(), ref2.toString() }, + ref1.sourceStart, ref2.sourceEnd); +} +public void duplicateResourceReference(Reference ref) { + this.handle(IProblem.DuplicateResource, + NoArgument, new String[] {ref.toString() }, + ProblemSeverities.Warning, + ref.sourceStart, ref.sourceEnd); +} +public void cyclicModuleDependency(ModuleBinding binding, ModuleReference ref) { + this.handle(IProblem.CyclicModuleDependency, + NoArgument, new String[] { CharOperation.charToString(binding.moduleName), CharOperation.charToString(ref.moduleName) }, + ref.sourceStart, ref.sourceEnd); +} +public void invalidServiceRef(int problem, TypeReference type) { + this.handle(problem, + NoArgument, new String[] { CharOperation.charToString(type.resolvedType.readableName()) }, + type.sourceStart, type.sourceEnd); +} public void unlikelyArgumentType(Expression argument, MethodBinding method, TypeBinding argumentType, TypeBinding receiverType, DangerousMethod dangerousMethod) @@ -10546,4 +10729,39 @@ public void unlikelyArgumentType(Expression argument, MethodBinding method, Type argument.sourceStart, argument.sourceEnd); } + +public void nonPublicTypeInAPI(TypeBinding type, int sourceStart, int sourceEnd) { + handle(IProblem.NonPublicTypeInAPI, + new String[] { new String(type.readableName()) }, + new String[] { new String(type.shortReadableName()) }, + sourceStart, + sourceEnd); +} + +public void notExportedTypeInAPI(TypeBinding type, int sourceStart, int sourceEnd) { + handle(IProblem.NotExportedTypeInAPI, + new String[] { new String(type.readableName()) }, + new String[] { new String(type.shortReadableName()) }, + sourceStart, + sourceEnd); +} + +public void missingRequiresTransitiveForTypeInAPI(ReferenceBinding referenceBinding, int sourceStart, int sourceEnd) { + String moduleName = new String(referenceBinding.fPackage.enclosingModule.readableName()); + handle(IProblem.MissingRequiresTransitiveForTypeInAPI, + new String[] { new String(referenceBinding.readableName()), moduleName }, + new String[] { new String(referenceBinding.shortReadableName()), moduleName }, + sourceStart, + sourceEnd); +} + +public void unnamedPackageInNamedModule(ModuleBinding module) { + String[] args = { new String(module.readableName()) }; + handle(IProblem.UnnamedPackageInNamedModule, + args, + args, + ProblemSeverities.Warning, + 0, + 0); +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties index 9467accb5b..b661b2d63b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties @@ -5,7 +5,6 @@ # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # -# # Contributors: # IBM Corporation - initial API and implementation # Benjamin Muskalla - Contribution for bug 239066 @@ -666,6 +665,7 @@ 666 = Syntax error, type annotations are illegal here 667 = Super method references to interface default methods are allowed only at source level 1.8 or above 668 = References to interface static methods are allowed only at source level 1.8 or above +669 = Field {0} must be final ### NULL ANALYSIS FOR OTHER EXPRESSIONS 670 = Null comparison always yields false: this expression cannot be null @@ -865,13 +865,63 @@ 1062 = Nullness default is redundant with a default specified for the variable {0} 1063 = Nullness default is redundant with a default specified for the field {0} +1070 = Illegal combination of modifiers for the private interface method {0}; additionally only one of static and strictfp is permitted +1071 = Illegal modifier for the interface method {0}; only public, private, abstract, default, static and strictfp are permitted + 1100 = Problem detected during type inference: {0} #1101 is already used up but deprecated 1102 = At least one of the problems in category ''{0}'' is not analysed due to a compiler option being ignored + # more programming problems: 1200 = Unlikely argument type {0} for {1} on a {2} 1201 = Unlikely argument type for equals(): {0} seems to be unrelated to {2} +### Autoclosable try +1251 = Duplicate resource reference {0} + +# Java9 - Module declaration related +1300 = {0} cannot be resolved to a module +1301 = Duplicate requires entry: {0} +1302 = Duplicate exports entry: {0} +1303 = Duplicate uses entry: {0} +1304 = Duplicate service entry: {0} +1305 = Cycle exists in module dependencies, Module {0} requires itself via {1} +1306 = Invalid service implementation, the type {0} is abstract +1307 = The service implementation {0} must define a public static provider method or a no-arg constructor +1308 = The no-arg constructor of service implementation {0} is not public +1309 = Invalid service implementation, the type {0} is an inner class +1310 = Service implementation {0} is not defined in the module with the provides directive +1311 = The package {0} does not exist or is empty +1312 = Type {0} inferred for {1}, is not valid for an anonymous class with ''<>'' +1313 = Duplicate opens entry: {0} +1314 = Duplicate module name: {0} +1315 = opens statement is not allowed, as module {0} is declared open +1316 = Invalid service interface {0}, must be a class, interface or annotation type +1317 = Invalid service implementation {0}, must be a public class or interface type +1318 = Illegal modifier for module {0}; only open is permitted + +#### Java 9 +1351 = Variable resource not allowed here for source level below 9 + +# Java 9 - advanced deprecation +1400 = The type {0} has been deprecated and marked for removal +1401 = The method {1}({2}) from the type {0} has been deprecated and marked for removal +1402 = The constructor {0}({1}) has been deprecated and marked for removal +1403 = The field {0}.{1} has been deprecated and marked for removal +1404 = The method {0} overrides a method from {1} that has been deprecated and marked for removal + +1450 = The type {0} is not accessible +1451 = The field {1}.{0} is not accessible +1452 = The method {1}({2}) from the type {0} is not accessible +1453 = The constructor {0}({1}) is not accessible +1454 = The package {0} is not accessible +1455 = The package {0} is accessible from more than one module: {1} +1456 = The package {0} conflicts with a package accessible from another module: {1} +1457 = The type {0} is not accessible to clients that require this module +1458 = The type {0} is not exported from this module +1459 = The type {0} from module {1} may not be accessible to clients due to missing ''requires transitive'' +1460 = Must declare a named package because this compilation unit is associated to the named module ''{0}'' + ### ELABORATIONS ## Access restrictions 78592 = The type ''{1}'' is not API (restriction on classpath entry ''{0}'') diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfModule.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfModule.java new file mode 100644 index 0000000000..3b9f59b496 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfModule.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.util; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; + +public final class HashtableOfModule { + // to avoid using Enumerations, walk the individual tables skipping nulls + public char[] keyTable[]; + public ModuleBinding valueTable[]; + + public int elementSize; // number of elements in the table + int threshold; + public HashtableOfModule() { + this(3); // usually not very large + } + public HashtableOfModule(int size) { + this.elementSize = 0; + this.threshold = size; // size represents the expected number of elements + int extraRoom = (int) (size * 1.75f); + if (this.threshold == extraRoom) + extraRoom++; + this.keyTable = new char[extraRoom][]; + this.valueTable = new ModuleBinding[extraRoom]; + } + public boolean containsKey(char[] key) { + int length = this.keyTable.length, + index = CharOperation.hashCode(key) % length; + int keyLength = key.length; + char[] currentKey; + while ((currentKey = this.keyTable[index]) != null) { + if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) + return true; + if (++index == length) { + index = 0; + } + } + return false; + } + public ModuleBinding get(char[] key) { + int length = this.keyTable.length, + index = CharOperation.hashCode(key) % length; + int keyLength = key.length; + char[] currentKey; + while ((currentKey = this.keyTable[index]) != null) { + if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) + return this.valueTable[index]; + if (++index == length) { + index = 0; + } + } + return null; + } + public ModuleBinding put(char[] key, ModuleBinding value) { + int length = this.keyTable.length, + index = CharOperation.hashCode(key) % length; + int keyLength = key.length; + char[] currentKey; + while ((currentKey = this.keyTable[index]) != null) { + if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) + return this.valueTable[index] = value; + if (++index == length) { + index = 0; + } + } + this.keyTable[index] = key; + this.valueTable[index] = value; + + // assumes the threshold is never equal to the size of the table + if (++this.elementSize > this.threshold) + rehash(); + return value; + } + private void rehash() { + HashtableOfModule newHashtable = new HashtableOfModule(this.elementSize * 2); // double the number of expected elements + char[] currentKey; + for (int i = this.keyTable.length; --i >= 0;) + if ((currentKey = this.keyTable[i]) != null) + newHashtable.put(currentKey, this.valueTable[i]); + + this.keyTable = newHashtable.keyTable; + this.valueTable = newHashtable.valueTable; + this.threshold = newHashtable.threshold; + } + public int size() { + return this.elementSize; + } + public String toString() { + String s = ""; //$NON-NLS-1$ + ModuleBinding pkg; + for (int i = 0, length = this.valueTable.length; i < length; i++) + if ((pkg = this.valueTable[i]) != null) + s += pkg.toString() + "\n"; //$NON-NLS-1$ + return s; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java new file mode 100644 index 0000000000..8633fede5c --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java @@ -0,0 +1,453 @@ +/******************************************************************************* + * Copyright (c) 2015, 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.util; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.env.IModule; + +public class JRTUtil { + + public static final String JAVA_BASE = "java.base"; //$NON-NLS-1$ + public static final char[] JAVA_BASE_CHAR = JAVA_BASE.toCharArray(); + static final String MODULES_SUBDIR = "/modules"; //$NON-NLS-1$ + static final String[] DEFAULT_MODULE = new String[]{JAVA_BASE}; + static final String[] NO_MODULE = new String[0]; + static final String MULTIPLE = "MU"; //$NON-NLS-1$ + static final String DEFAULT_PACKAGE = ""; //$NON-NLS-1$ + static String MODULE_TO_LOAD = null; + public static final String JRT_FS_JAR = "jrt-fs.jar"; //$NON-NLS-1$ + static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$ + public static int NOTIFY_FILES = 0x0001; + public static int NOTIFY_PACKAGES = 0x0002; + public static int NOTIFY_MODULES = 0x0004; + public static int NOTIFY_ALL = NOTIFY_FILES | NOTIFY_PACKAGES | NOTIFY_MODULES; + + // TODO: Java 9 Think about clearing the cache too. + private static Map images = null; + + private static final Object lock = new Object(); + + public interface JrtFileVisitor { + + public FileVisitResult visitPackage(T dir, T mod, BasicFileAttributes attrs) throws IOException; + + public FileVisitResult visitFile(T file, T mod, BasicFileAttributes attrs) throws IOException; + /** + * Invoked when a root directory of a module being visited. The element returned + * contains only the module name segment - e.g. "java.base". Clients can use this to control + * how the JRT needs to be processed, for e.g., clients can skip a particular module + * by returning FileVisitResult.SKIP_SUBTREE + */ + public FileVisitResult visitModule(T mod) throws IOException; + } + + static abstract class AbstractFileVisitor implements FileVisitor { + @Override + public FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(T file, BasicFileAttributes attrs) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(T file, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(T dir, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + } + + public static JrtFileSystem getJrtSystem(File image) { + Map i = images; + if (images == null) { + synchronized (lock) { + i = images; + if (i == null) { + images = i = new HashMap<>(); + } + } + } + JrtFileSystem system = null; + synchronized(i) { + if ((system = images.get(image)) == null) { + try { + images.put(image, system = new JrtFileSystem(image)); + } catch (IOException e) { + e.printStackTrace(); + // Needs better error handling downstream? But for now, make sure + // a dummy JrtFileSystem is not created. + } + } + } + return system; + } + + /** TEST ONLY (use when changing the "modules.to.load" property). */ + public static void reset() { + images = null; + MODULE_TO_LOAD = System.getProperty("modules.to.load"); //$NON-NLS-1$ + } + + /** + * Given the path of a modular image file, this method walks the archive content and + * notifies the supplied visitor about packages and files visited. + * + * The file system contains the following top level directories: + * /modules/$MODULE/$PATH + * /packages/$PACKAGE/$MODULE + * The latter provides quick look up of the module that contains a particular package. However, + * this method only notifies its clients of the entries within the modules sub-directory. The + * clients can decide which notifications they want to receive. See {@link JRTUtil#NOTIFY_ALL}, + * {@link JRTUtil#NOTIFY_FILES}, {@link JRTUtil#NOTIFY_PACKAGES} and {@link JRTUtil#NOTIFY_MODULES}. + * + * @param image a java.io.File handle to the JRT image. + * @param visitor an instance of JrtFileVisitor to be notified of the entries in the JRT image. + * @param notify flag indicating the notifications the client is interested in. + * @throws IOException + */ + public static void walkModuleImage(File image, final JRTUtil.JrtFileVisitor visitor, int notify) throws IOException { + getJrtSystem(image).walkModuleImage(visitor, false, notify); + } + + public static InputStream getContentFromJrt(File jrt, String fileName, String module) throws IOException { + return getJrtSystem(jrt).getContentFromJrt(fileName, module); + } + public static byte[] getClassfileContent(File jrt, String fileName, String module) throws IOException, ClassFormatException { + return getJrtSystem(jrt).getClassfileContent(fileName, module); + } + public static ClassFileReader getClassfile(File jrt, String fileName, IModule module) throws IOException, ClassFormatException { + return getJrtSystem(jrt).getClassfile(fileName, module); + } + public static ClassFileReader getClassfile(File jrt, String fileName, String module) throws IOException, ClassFormatException { + return getJrtSystem(jrt).getClassfile(fileName, module); + } + public static List getModulesDeclaringPackage(File jrt, String qName, String moduleName) { + return getJrtSystem(jrt).getModulesDeclaringPackage(qName, moduleName); + } + + public static boolean hasCompilationUnit(File jrt, String qualifiedPackageName, String moduleName) { + return getJrtSystem(jrt).hasClassFile(qualifiedPackageName, moduleName); + } +} +class JrtFileSystem { + private final Map packageToModule = new HashMap(); + + private final Map> packageToModules = new HashMap>(); + + FileSystem jrtSystem = null; + + /** + * The jrt file system is based on the location of the JRE home whose libraries + * need to be loaded. + * + * @param jrt the path to the root of the JRE whose libraries we are interested in. + * @throws IOException + */ + public JrtFileSystem(File jrt) throws IOException { + initialize(jrt); + } + void initialize(File jrt) throws IOException { + URL jrtPath = null; + String jdkHome = null; + if (jrt.toString().endsWith(JRTUtil.JRT_FS_JAR)) { + jrtPath = jrt.toPath().toUri().toURL(); + jdkHome = jrt.getParentFile().getParent(); + } else { + jdkHome = jrt.toPath().toString(); + jrtPath = Paths.get(jdkHome, "lib", JRTUtil.JRT_FS_JAR).toUri().toURL(); //$NON-NLS-1$ + + } + JRTUtil.MODULE_TO_LOAD = System.getProperty("modules.to.load"); //$NON-NLS-1$ + String javaVersion = System.getProperty("java.version"); //$NON-NLS-1$ + if (javaVersion != null && javaVersion.startsWith("1.8")) { //$NON-NLS-1$ + JRTUtil.MODULE_TO_LOAD = System.getProperty("modules.to.load"); //$NON-NLS-1$ + URLClassLoader loader = new URLClassLoader(new URL[] { jrtPath }); + HashMap env = new HashMap<>(); + this.jrtSystem = FileSystems.newFileSystem(JRTUtil.JRT_URI, env, loader); + } else { + HashMap env = new HashMap<>(); + env.put("java.home", jdkHome); //$NON-NLS-1$ + this.jrtSystem = FileSystems.newFileSystem(JRTUtil.JRT_URI, env); + } + walkModuleImage(null, true, 0 /* doesn't matter */); + } + + public List getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) { + qualifiedPackageName = qualifiedPackageName.replace('.', '/'); + String module = this.packageToModule.get(qualifiedPackageName); + if (moduleName == null) { + // wildcard search: + if (module == null) + return null; + if (module == JRTUtil.MULTIPLE) + return this.packageToModules.get(qualifiedPackageName); + return Collections.singletonList(module); + } + if (module != null) { + // specific search: + if (module == JRTUtil.MULTIPLE) { + List list = this.packageToModules.get(qualifiedPackageName); + if (list.contains(moduleName)) + return Collections.singletonList(moduleName); + } else { + if (module.equals(moduleName)) + return Collections.singletonList(moduleName); + } + } + return null; + } + public String[] getModules(String fileName) { + int idx = fileName.lastIndexOf('/'); + String pack = null; + if (idx != -1) { + pack = fileName.substring(0, idx); + } else { + pack = JRTUtil.DEFAULT_PACKAGE; + } + String module = this.packageToModule.get(pack); + if (module != null) { + if (module == JRTUtil.MULTIPLE) { + List list = this.packageToModules.get(pack); + return list.toArray(new String[list.size()]); + } else { + return new String[]{module}; + } + } + return JRTUtil.DEFAULT_MODULE; + } + public boolean hasClassFile(String qualifiedPackageName, String module) { + if (module == null) + return false; + // easy checks first: + String knownModule = this.packageToModule.get(qualifiedPackageName); + if (knownModule == null || (knownModule != JRTUtil.MULTIPLE && !knownModule.equals(module))) + return false; + Path packagePath = this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, module, qualifiedPackageName); + if (!Files.exists(packagePath)) + return false; + // iterate files: + try { + return Files.list(packagePath) + .anyMatch(filePath -> filePath.toString().endsWith(SuffixConstants.SUFFIX_STRING_class) + || filePath.toString().endsWith(SuffixConstants.SUFFIX_STRING_CLASS)); + } catch (IOException e) { + return false; + } + } + + public InputStream getContentFromJrt(String fileName, String module) throws IOException { + if (module != null) { + return Files.newInputStream(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, module, fileName)); + } + String[] modules = getModules(fileName); + for (String mod : modules) { + return Files.newInputStream(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName)); + } + return null; + } + private ClassFileReader getClassfile(String fileName) throws IOException, ClassFormatException { + String[] modules = getModules(fileName); + byte[] content = null; + String module = null; + for (String mod : modules) { + try { + content = Files.readAllBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName)); + if (content != null) { + module = mod; + break; + } + } catch(NoSuchFileException e) { + continue; + } + } + if (content != null) { + ClassFileReader reader = new ClassFileReader(content, fileName.toCharArray()); + reader.moduleName = module.toCharArray(); + return reader; + } + return null; + } + + byte[] getClassfileContent(String fileName, String module) throws IOException, ClassFormatException { + byte[] content = null; + if (module != null) { + content = getClassfileBytes(fileName, new String(module.toCharArray())); + } else { + String[] modules = getModules(fileName); + for (String mod : modules) { + try { + content = Files.readAllBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName)); + if (content != null) { + break; + } + } catch(NoSuchFileException e) { + continue; + } + } + } + return content; + } + private byte[] getClassfileBytes(String fileName, String module) throws IOException, ClassFormatException { + byte[] content = null; + try { + content = Files.readAllBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, module, fileName)); + } catch(NoSuchFileException e) { + return null; + } + return content; + } + public ClassFileReader getClassfile(String fileName, String module) throws IOException, ClassFormatException { + ClassFileReader reader = null; + if (module == null) { + reader = getClassfile(fileName); + } else { + byte[] content = getClassfileBytes(fileName, module); + if (content != null) { + reader = new ClassFileReader(content, fileName.toCharArray()); + reader.moduleName = module.toCharArray(); + } + } + return reader; + } + public ClassFileReader getClassfile(String fileName, IModule module) throws IOException, ClassFormatException { + ClassFileReader reader = null; + if (module == null) { + reader = getClassfile(fileName); + } else { + byte[] content = getClassfileBytes(fileName, new String(module.name())); + if (content != null) { + reader = new ClassFileReader(content, fileName.toCharArray()); + } + } + return reader; + } + + void walkModuleImage(final JRTUtil.JrtFileVisitor visitor, boolean visitPackageMapping, final int notify) throws IOException { + Iterable roots = this.jrtSystem.getRootDirectories(); + for (java.nio.file.Path path : roots) { + try (DirectoryStream stream = Files.newDirectoryStream(path)) { + for (final java.nio.file.Path subdir: stream) { + if (subdir.toString().equals(JRTUtil.MODULES_SUBDIR)) { + if (visitPackageMapping) continue; + Files.walkFileTree(subdir, new JRTUtil.AbstractFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs) throws IOException { + int count = dir.getNameCount(); + if (count == 2) { + // e.g. /modules/java.base + java.nio.file.Path mod = dir.getName(1); + if ((JRTUtil.MODULE_TO_LOAD != null && JRTUtil.MODULE_TO_LOAD.length() > 0 && + JRTUtil.MODULE_TO_LOAD.indexOf(mod.toString()) == -1)) { + return FileVisitResult.SKIP_SUBTREE; + } + return ((notify & JRTUtil.NOTIFY_MODULES) == 0) ? + FileVisitResult.CONTINUE : visitor.visitModule(mod); + } + if (dir == subdir || count < 3 || (notify & JRTUtil.NOTIFY_PACKAGES) == 0) { + // We are dealing with a module or not client is not interested in packages + return FileVisitResult.CONTINUE; + } + return visitor.visitPackage(dir.subpath(2, count), dir.getName(1), attrs); + } + + @Override + public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException { + if ((notify & JRTUtil.NOTIFY_FILES) == 0) + return FileVisitResult.CONTINUE; + int count = file.getNameCount(); + // This happens when a file in a default package is present. E.g. /modules/some.module/file.name + if (count == 3) { + cachePackage(JRTUtil.DEFAULT_PACKAGE, file.getName(1).toString()); + } + return visitor.visitFile(file.subpath(2, file.getNameCount()), file.getName(1), attrs); + } + }); + } else if (visitPackageMapping) { + Files.walkFileTree(subdir, new JRTUtil.AbstractFileVisitor() { + @Override + public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException { + // e.g. /modules/java.base + java.nio.file.Path relative = subdir.relativize(file); + cachePackage(relative.getParent().toString(), relative.getFileName().toString()); + return FileVisitResult.CONTINUE; + } + }); + } + } + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + } + + void cachePackage(String packageName, String module) { + packageName = packageName.intern(); + module = module.intern(); + packageName = packageName.replace('.', '/'); + Object current = this.packageToModule.get(packageName); + if (current == null) { + this.packageToModule.put(packageName, module); + } else if(current == module || current.equals(module)) { + return; + } else if (current == JRTUtil.MULTIPLE) { + List list = this.packageToModules.get(packageName); + if (!list.contains(module)) { + if (JRTUtil.JAVA_BASE == module || JRTUtil.JAVA_BASE.equals(module)) { + list.add(0, JRTUtil.JAVA_BASE); + } else { + list.add(module); + } + } + } else { + String first = (String) current; + this.packageToModule.put(packageName, JRTUtil.MULTIPLE); + List list = new ArrayList(); + // Just do this as comparator might be overkill + if (JRTUtil.JAVA_BASE == current || JRTUtil.JAVA_BASE.equals(current)) { + list.add(first); + list.add(module); + } else { + list.add(module); + list.add(first); + } + this.packageToModules.put(packageName, list); + } + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/ObjectVector.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/ObjectVector.java index 07dbfba4b3..d103b9aca8 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/ObjectVector.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/ObjectVector.java @@ -10,7 +10,9 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; -public final class ObjectVector { +import java.util.Iterator; + +public final class ObjectVector implements Iterable { static int INITIAL_SIZE = 10; @@ -132,4 +134,19 @@ public String toString() { s += this.elements[i].toString() + "\n"; //$NON-NLS-1$ return s; } + + @Override + public Iterator iterator() { + return new Iterator() { + int i=0; + @Override + public boolean hasNext() { + return this.i < ObjectVector.this.size; + } + @Override + public Object next() { + return ObjectVector.this.elementAt(this.i++); + } + }; + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java index 61b919bc8c..f5f9d90819 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,8 @@ public interface SuffixConstants { public final static String EXTENSION_CLASS = "CLASS"; //$NON-NLS-1$ public final static String EXTENSION_java = "java"; //$NON-NLS-1$ public final static String EXTENSION_JAVA = "JAVA"; //$NON-NLS-1$ + public final static String EXTENSION_jmod = "jmod"; //$NON-NLS-1$ + public final static String EXTENSION_JMOD = "JMOD"; //$NON-NLS-1$ public final static String SUFFIX_STRING_class = "." + EXTENSION_class; //$NON-NLS-1$ public final static String SUFFIX_STRING_CLASS = "." + EXTENSION_CLASS; //$NON-NLS-1$ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java index 56a86efb3d..337bb81890 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * daolaf@gmail.com - Contribution for bug 3292227 @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.StringTokenizer; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -35,8 +36,10 @@ import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.batch.FileSystem; +import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; import org.eclipse.jdt.internal.compiler.batch.Main; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; @@ -45,7 +48,6 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; -@SuppressWarnings({"rawtypes", "unchecked"}) public class Util implements SuffixConstants { /** @@ -232,6 +234,10 @@ public interface Displayable { public static final String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$ public static final String EMPTY_STRING = new String(CharOperation.NO_CHAR); + /** + * @since 3.14 + */ + public static final String COMMA_SEPARATOR = new String(CharOperation.COMMA_SEPARATOR); public static final int[] EMPTY_INT_ARRAY= new int[0]; /** @@ -742,6 +748,51 @@ public final static boolean isPotentialZipArchive(String name) { } return true; // it is neither a ".java" file nor a ".class" file, so this is a potential archive name } + + public static final int ZIP_FILE = 0; + public static final int JMOD_FILE = 1; + + /** + * Returns the kind of archive this file is. The format is one of + * #ZIP_FILE or {@link #JMOD_FILE} + */ + public final static int archiveFormat(String name) { + int lastDot = name.lastIndexOf('.'); + if (lastDot == -1) + return -1; // no file extension, it cannot be a zip archive name + if (name.lastIndexOf(File.separatorChar) > lastDot) + return -1; // dot was before the last file separator, it cannot be a zip archive name + int length = name.length(); + int extensionLength = length - lastDot - 1; + + if (extensionLength == EXTENSION_java.length()) { + for (int i = extensionLength-1; i >=0; i--) { + if (Character.toLowerCase(name.charAt(length - extensionLength + i)) != EXTENSION_java.charAt(i)) { + break; // not a ".java" file, check ".class" file case below + } + if (i == 0) { + return -1; // it is a ".java" file, it cannot be a zip archive name + } + } + } + if (extensionLength == EXTENSION_class.length()) { + for (int i = extensionLength-1; i >=0; i--) { + if (Character.toLowerCase(name.charAt(length - extensionLength + i)) != EXTENSION_class.charAt(i)) { + return ZIP_FILE; // not a ".class" file, so this is a potential archive name + } + } + return -1; // it is a ".class" file, it cannot be a zip archive name + } + if (extensionLength == EXTENSION_jmod.length()) { + for (int i = extensionLength-1; i >=0; i--) { + if (Character.toLowerCase(name.charAt(length - extensionLength + i)) != EXTENSION_jmod.charAt(i)) { + return ZIP_FILE; // not a ".jmod" file, so this is a potential archive name + } + } + return JMOD_FILE; + } + return ZIP_FILE; // it is neither a ".java" file nor a ".class" file, so this is a potential archive name + } /** * Returns true iff str.toLowerCase().endsWith(".class") @@ -851,6 +902,14 @@ public final static boolean isJavaFileName(String name) { return true; } + /** + * Returns true iff str.toLowerCase().endsWith("jrt-fs.jar") + * implementation is not creating extra strings. + */ + public final static boolean isJrt(String name) { + return name.endsWith(JRTUtil.JRT_FS_JAR); + } + public static void reverseQuickSort(char[][] list, int left, int right) { int original_left= left; int original_right= right; @@ -1007,6 +1066,7 @@ public static void writeToDisk(boolean generatePackagesStructure, String outputP output.close(); } } + @SuppressWarnings({ "rawtypes", "unchecked" }) public static void recordNestedType(ClassFile classFile, TypeBinding typeBinding) { if (classFile.visitedTypes == null) { classFile.visitedTypes = new HashSet(3); @@ -1093,24 +1153,42 @@ public static File getJavaHome() { return null; } - public static void collectRunningVMBootclasspath(List bootclasspaths) { - for (String filePath : collectFilesNames()) { - FileSystem.Classpath currentClasspath = FileSystem.getClasspath(filePath, null, null, null); - if (currentClasspath != null) { - bootclasspaths.add(currentClasspath); - } - } + public static void collectVMBootclasspath(List bootclasspaths, File javaHome) { + List classpaths = collectPlatformLibraries(javaHome); + bootclasspaths.addAll(classpaths); } - - public static List collectFilesNames() { + public static void collectRunningVMBootclasspath(List bootclasspaths) { + collectVMBootclasspath(bootclasspaths, null); + } + public static long getJDKLevel(File javaHome) { + String version = System.getProperty("java.version"); //$NON-NLS-1$ + return CompilerOptions.versionToJdkLevel(version); + } + public static List collectFilesNames() { + return collectPlatformLibraries(null); + } + public static List collectPlatformLibraries(File javaHome) { /* no bootclasspath specified * we can try to retrieve the default librairies of the VM used to run * the batch compiler */ - String javaversion = System.getProperty("java.version");//$NON-NLS-1$ + String javaversion = null; + javaversion = System.getProperty("java.version"); //$NON-NLS-1$ + // Surely, this ain't required anymore? if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$ throw new IllegalStateException(); } + long jdkLevel = CompilerOptions.versionToJdkLevel(javaversion); + if (jdkLevel >= ClassFileConstants.JDK9) { + List filePaths = new ArrayList<>(); + if (javaHome == null) { + javaHome = getJavaHome(); + } + if (javaHome != null) { + filePaths.add(FileSystem.getJrtClasspath(javaHome.getAbsolutePath(), null, null, null)); + return filePaths; + } + } /* * Handle >= JDK 1.2.2 settings: retrieve the bootclasspath @@ -1125,7 +1203,7 @@ public static List collectFilesNames() { bootclasspathProperty = System.getProperty("org.apache.harmony.boot.class.path"); //$NON-NLS-1$ } } - List filePaths = new ArrayList<>(); + Set filePaths = new HashSet<>(); if ((bootclasspathProperty != null) && (bootclasspathProperty.length() != 0)) { StringTokenizer tokenizer = new StringTokenizer(bootclasspathProperty, File.pathSeparator); while (tokenizer.hasMoreTokens()) { @@ -1133,7 +1211,9 @@ public static List collectFilesNames() { } } else { // try to get all jars inside the lib folder of the java home - final File javaHome = getJavaHome(); + if (javaHome == null) { + javaHome = getJavaHome(); + } if (javaHome != null) { File[] directoriesToCheck = null; if (System.getProperty("os.name").startsWith("Mac")) {//$NON-NLS-1$//$NON-NLS-2$ @@ -1159,7 +1239,14 @@ public static List collectFilesNames() { } } } - return filePaths; + List classpaths = new ArrayList<>(); + for (String filePath : filePaths) { + FileSystem.Classpath currentClasspath = FileSystem.getClasspath(filePath, null, null, null); + if (currentClasspath != null) { + classpaths.add(currentClasspath); + } + } + return classpaths; } public static int getParameterCount(char[] methodSignature) { try { @@ -1628,5 +1715,4 @@ public static void appendEscapedChar(StringBuffer buffer, char c, boolean string } } } - } \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java index c262cecf39..3d646e94b2 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -113,7 +113,7 @@ public final class AST { *

* * @since 3.0 - * @deprecated Clients should use the {@link #JLS8} AST API instead. + * @deprecated Clients should use the {@link #JLS9} AST API instead. */ public static final int JLS2 = 2; @@ -137,7 +137,7 @@ public final class AST { *

* * @since 3.1 - * @deprecated Clients should use the {@link #JLS8} AST API instead. + * @deprecated Clients should use the {@link #JLS9} AST API instead. */ public static final int JLS3 = 3; @@ -161,7 +161,7 @@ public final class AST { *

* * @since 3.7.1 - * @deprecated Clients should use the {@link #JLS8} AST API instead. + * @deprecated Clients should use the {@link #JLS9} AST API instead. */ public static final int JLS4 = 4; @@ -185,9 +185,40 @@ public final class AST { *

* * @since 3.10 + * @deprecated Clients should use the {@link #JLS9} AST API instead. */ public static final int JLS8 = 8; + /** + * Internal synonym for {@link #JLS8}. Use to alleviate + * deprecation warnings. + * @since 3.14 + */ + /*package*/ static final int JLS8_INTERNAL = JLS8; + + /** + * Constant for indicating the AST API that handles JLS9. + *

+ * This API is capable of handling all constructs in the + * Java language as described in the Java Language + * Specification, Java SE 9 Edition (JLS9). + * JLS9 is a superset of all earlier versions of the + * Java language, and the JLS9 API can be used to manipulate + * programs written in all versions of the Java language + * up to and including Java SE 9 (aka JDK 9). + *

+ * + * @since 3.14 + */ + public static final int JLS9 = 9; + + /** + * Internal synonym for {@link #JLS9}. Use to alleviate + * deprecation warnings once JLS9 is deprecated + * @since 3.14 + */ + /*package*/ static final int JLS9_INTERNAL = JLS9; + /* * Must not collide with a value for ICompilationUnit constants */ @@ -278,7 +309,7 @@ public static CompilationUnit convertCompilationUnit( * Creates a new Java abstract syntax tree * (AST) following the specified set of API rules. *

- * Clients should use this method specifying {@link #JLS8} as the + * Clients should use this method specifying {@link #JLS9} as the * AST level in all cases, even when dealing with source of earlier JDK versions like 1.3 or 1.4. *

* @@ -658,8 +689,8 @@ public static CompilationUnit parseCompilationUnit( * Creates a new, empty abstract syntax tree using default options. * * @see JavaCore#getDefaultOptions() - * @deprecated Clients should port their code to use the new JLS4 AST API and call - * {@link #newAST(int) AST.newAST(AST.JLS4)} instead of using this constructor. + * @deprecated Clients should port their code to use the latest JLS* AST API and call + * {@link #newAST(int) AST.newAST(AST.JLS9)} instead of using this constructor. */ public AST() { this(JavaCore.getDefaultOptions()); @@ -701,7 +732,7 @@ private AST(int level) { null/*taskPriorities*/, true/*taskCaseSensitive*/); break; - case JLS8 : + case JLS8_INTERNAL : this.apiLevel = level; // initialize a scanner this.scanner = new Scanner( @@ -714,6 +745,19 @@ private AST(int level) { null/*taskPriorities*/, true/*taskCaseSensitive*/); break; + case JLS9 : + this.apiLevel = level; + // initialize a scanner + this.scanner = new Scanner( + true /*comment*/, + true /*whitespace*/, + false /*nls*/, + ClassFileConstants.JDK9 /*sourceLevel*/, + ClassFileConstants.JDK9 /*complianceLevel*/, + null/*taskTag*/, + null/*taskPriorities*/, + true/*taskCaseSensitive*/); + break; default: throw new IllegalArgumentException("Unsupported JLS level"); //$NON-NLS-1$ } @@ -740,8 +784,8 @@ private AST(int level) { * @param options the table of options (key type: String; * value type: String) * @see JavaCore#getDefaultOptions() - * @deprecated Clients should port their code to use the new JLS4 AST API and call - * {@link #newAST(int) AST.newAST(AST.JLS4)} instead of using this constructor. + * @deprecated Clients should port their code to use the latest JLS* AST API and call + * {@link #newAST(int) AST.newAST(AST.JLS9)} instead of using this constructor. */ public AST(Map options) { this(JLS2); @@ -1129,7 +1173,7 @@ public ArrayInitializer newArrayInitializer() { */ public ArrayType newArrayType(Type elementType) { ArrayType result; - if (this.apiLevel < AST.JLS8) { + if (this.apiLevel < JLS8_INTERNAL) { result = new ArrayType(this); setArrayComponentType(result, elementType); return result; @@ -1173,7 +1217,7 @@ public ArrayType newArrayType(Type elementType, int dimensions) { throw new IllegalArgumentException(); } ArrayType result; - if (this.apiLevel < AST.JLS8) { + if (this.apiLevel < JLS8_INTERNAL) { if (dimensions < 1) { throw new IllegalArgumentException(); } @@ -1460,11 +1504,24 @@ public EnumDeclaration newEnumDeclaration() { return result; } + /** + * Creates and returns a new unparented exports directive + * node for an unspecified, but legal, name; no target modules + * + * @return a new unparented exports directive node + * @exception UnsupportedOperationException if this operation is used in an AST with level less than JLS9 + * @since 3.14 + */ + public ExportsDirective newExportsStatement() { + ExportsDirective result = new ExportsDirective(this); + return result; + } + /** * Creates an unparented expression method reference node owned by this AST. * By default, the expression and method name are unspecified (but legal), * and there are no type arguments. - * + * * @return a new unparented expression method reference expression node * @exception UnsupportedOperationException if this operation is used in a JLS2, JLS3 or JLS4 AST * @since 3.10 @@ -1819,6 +1876,23 @@ public Modifier newModifier(Modifier.ModifierKeyword keyword) { return result; } + /** + * Creates and returns a new unparented module modifier node for the given + * module modifier. + * + * @param keyword one of the module modifier keyword constants + * @return a new unparented module modifier node + * @exception IllegalArgumentException if the primitive type code is invalid + * @exception UnsupportedOperationException if this operation is used in + * an AST with level less than JLS9 + * @since 3.14 + */ + public ModuleModifier newModuleModifier(ModuleModifier.ModuleModifierKeyword keyword) { + ModuleModifier result = new ModuleModifier(this); + result.setKeyword(keyword); + return result; + } + /** * Creates and returns a list of new unparented modifier nodes * for the given modifier flags. When multiple modifiers are @@ -1880,6 +1954,20 @@ public List newModifiers(int flags) { return result; } + /** + * Creates and returns a new unparented module declaration + * node for an unspecified, but legal, name; no modifiers; no javadoc; + * and an empty list of statements. + * + * @return a new unparented module declaration node + * @exception UnsupportedOperationException if this operation is used in an AST with level less than JLS9 + * @since 3.14 + */ + public ModuleDeclaration newModuleDeclaration() { + ModuleDeclaration result = new ModuleDeclaration(this); + return result; + } + /** * Creates and returns a new unparented name node for the given name. * The name string must consist of 1 or more name segments separated @@ -2043,6 +2131,19 @@ public NumberLiteral newNumberLiteral(String literal) { return result; } + /** + * Creates and returns a new unparented opens directive + * node for an unspecified, but legal, name; no target modules + * + * @return a new unparented opens directive node + * @exception UnsupportedOperationException if this operation is used in an AST with level less than JLS9 + * @since 3.14 + */ + public OpensDirective newOpensDirective() { + OpensDirective result = new OpensDirective(this); + return result; + } + /** * Creates an unparented package declaration node owned by this AST. * The package declaration initially declares a package with an @@ -2126,6 +2227,19 @@ public PrimitiveType newPrimitiveType(PrimitiveType.Code typeCode) { return result; } + /** + * Creates and returns a new unparented provides directive + * node for an unspecified, but legal, type; no target types + * + * @return a new unparented provides directive node + * @exception UnsupportedOperationException if this operation is used in an AST with level less than JLS9 + * @since 3.14 + */ + public ProvidesDirective newProvidesDirective() { + ProvidesDirective result = new ProvidesDirective(this); + return result; + } + /** * Creates and returns a new unparented qualified name node for the given * qualifier and simple name child node. @@ -2172,6 +2286,19 @@ public QualifiedType newQualifiedType(Type qualifier, SimpleName name) { return result; } + /** + * Creates and returns a new unparented requires directive + * node for an unspecified, but legal, name; + * + * @return a new unparented requires directive node + * @exception UnsupportedOperationException if this operation is used in an AST with level less than JLS9 + * @since 3.14 + */ + public RequiresDirective newRequiresDirective() { + RequiresDirective result = new RequiresDirective(this); + return result; + } + /** * Creates a new unparented return statement node owned by this AST. * By default, the return statement has no expression. @@ -2539,6 +2666,19 @@ public UnionType newUnionType() { return new UnionType(this); } + /** + * Creates and returns a new unparented uses directive + * node for an unspecified, but legal, name; + * + * @return a new unparented uses directive node + * @exception UnsupportedOperationException if this operation is used in level less than JLS9 + * @since 3.14 + */ + public UsesDirective newUsesDirective() { + UsesDirective result = new UsesDirective(this); + return result; + } + /** * Creates a new unparented intersection type node owned by this AST. * By default, the intersection type has no types. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java index 6b57ef70ae..a40312f1ba 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,11 +14,13 @@ package org.eclipse.jdt.core.dom; +import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; @@ -28,9 +30,11 @@ import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; +import org.eclipse.jdt.core.dom.ModuleModifier.ModuleModifierKeyword; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; +import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; import org.eclipse.jdt.internal.compiler.ast.IntersectionCastTypeReference; import org.eclipse.jdt.internal.compiler.ast.JavadocArgumentExpression; @@ -38,6 +42,7 @@ import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MessageSend; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; import org.eclipse.jdt.internal.compiler.ast.NameReference; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; @@ -483,11 +488,10 @@ private int checkLength(int start, int end) { int len = end - start + 1; return len > 0 ? len : 0; } - protected void completeRecord(ArrayType arrayType, org.eclipse.jdt.internal.compiler.ast.ASTNode astNode) { ArrayType array = arrayType; this.recordNodes(arrayType, astNode); - if (this.ast.apiLevel() >= AST.JLS8) { + if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) { this.recordNodes(arrayType.getElementType(), astNode); return; } @@ -549,7 +553,7 @@ public ASTNode convert(boolean isInterface, org.eclipse.jdt.internal.compiler.as int methodHeaderEnd = methodDeclaration.sourceEnd; int thrownExceptionsLength = thrownExceptions == null ? 0 : thrownExceptions.length; if (thrownExceptionsLength > 0) { - if (this.ast.apiLevel() < AST.JLS8) { + if (this.ast.apiLevel() < AST.JLS8_INTERNAL) { Name thrownException; int i = 0; do { @@ -573,7 +577,7 @@ public ASTNode convert(boolean isInterface, org.eclipse.jdt.internal.compiler.as } if (methodDeclaration.receiver != null) { - if(this.ast.apiLevel >= AST.JLS8) { + if(this.ast.apiLevel >= AST.JLS8_INTERNAL) { convertAndSetReceiver(methodDeclaration, methodDecl); } else { methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); @@ -633,7 +637,7 @@ public ASTNode convert(boolean isInterface, org.eclipse.jdt.internal.compiler.as // get the positions of the right parenthesis int rightParenthesisPosition = retrieveEndOfRightParenthesisPosition(end, method.bodyEnd); int extraDimensions = typeReference.extraDimensions(); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { setExtraAnnotatedDimensions(rightParenthesisPosition, method.bodyEnd, typeReference, methodDecl.extraDimensions(), extraDimensions); } else { @@ -693,8 +697,9 @@ public ASTNode convert(boolean isInterface, org.eclipse.jdt.internal.compiler.as } if (block != null) { if ((methodDeclaration.modifiers & (ClassFileConstants.AccAbstract | ClassFileConstants.AccNative)) != 0 - || (isInterface && (this.ast.apiLevel < AST.JLS8 || - (methodDeclaration.modifiers & (ClassFileConstants.AccStatic | ExtraCompilerModifiers.AccDefaultMethod)) == 0))) { + || (isInterface && (this.ast.apiLevel < AST.JLS8_INTERNAL || + (methodDeclaration.modifiers & (ClassFileConstants.AccStatic | ExtraCompilerModifiers.AccDefaultMethod | + (this.ast.apiLevel > AST.JLS8_INTERNAL ? ClassFileConstants.AccPrivate : 0))) == 0))) { methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); } } @@ -956,7 +961,7 @@ public SingleVariableDeclaration convert(org.eclipse.jdt.internal.compiler.ast.A final int typeSourceEnd = argument.type.sourceEnd; TypeReference typeReference = argument.type; final int extraDimensions = typeReference.extraDimensions(); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { setExtraAnnotatedDimensions(nameEnd + 1, typeSourceEnd, typeReference, variableDecl.extraDimensions(), extraDimensions); } else { @@ -979,7 +984,7 @@ public SingleVariableDeclaration convert(org.eclipse.jdt.internal.compiler.ast.A */ if (isVarArgs) { Dimension lastDimension = null; - if (this.ast.apiLevel() >= AST.JLS8) { + if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) { if (type.isArrayType()) { // should always be true List dimensions = ((ArrayType) type).dimensions(); if (!dimensions.isEmpty()) { @@ -989,7 +994,7 @@ public SingleVariableDeclaration convert(org.eclipse.jdt.internal.compiler.ast.A } setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions + 1); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391898 - if (this.ast.apiLevel() >= AST.JLS8) { + if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) { if (lastDimension != null) { // should always be true List annotations = lastDimension.annotations(); Iterator iter = annotations.iterator(); @@ -1062,7 +1067,7 @@ public ArrayCreation convert(org.eclipse.jdt.internal.compiler.ast.ArrayAllocati if (type.isArrayType()) { arrayType = (ArrayType) type; if (expression.annotationsOnDimensions != null) { - if (this.ast.apiLevel() < AST.JLS8) { + if (this.ast.apiLevel() < AST.JLS8_INTERNAL) { arrayType.setFlags(arrayType.getFlags() | ASTNode.MALFORMED); } else { setTypeAnnotationsAndSourceRangeOnArray(arrayType, expression.annotationsOnDimensions); @@ -1418,24 +1423,37 @@ public CompilationUnit convert(org.eclipse.jdt.internal.compiler.ast.Compilation } } - org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = unit.types; - if (types != null) { - int typesLength = types.length; - for (int i = 0; i < typesLength; i++) { - org.eclipse.jdt.internal.compiler.ast.TypeDeclaration declaration = types[i]; - if (CharOperation.equals(declaration.name, TypeConstants.PACKAGE_INFO_NAME)) { - continue; - } - ASTNode type = convert(declaration); - if (type == null) { - compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED); - } else { - compilationUnit.types().add(type); + org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration mod = unit.moduleDeclaration; + if (mod != null) { + ASTNode declaration = convertToModuleDeclaration(mod); + if (declaration == null) { + compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED); + } else { + compilationUnit.setModule((ModuleDeclaration) declaration); + } + } else { + org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = unit.types; + if (types != null) { + int typesLength = types.length; + for (int i = 0; i < typesLength; i++) { + org.eclipse.jdt.internal.compiler.ast.TypeDeclaration declaration = types[i]; + if (CharOperation.equals(declaration.name, TypeConstants.PACKAGE_INFO_NAME)) { + continue; + } + ASTNode type = convert(declaration); + if (type == null) { + compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED); + } else { + if (type instanceof ModuleDeclaration) + compilationUnit.setModule((ModuleDeclaration) type); + else + compilationUnit.types().add(type); + } } } } compilationUnit.setSourceRange(unit.sourceStart, unit.sourceEnd - unit.sourceStart + 1); - + int problemLength = unit.compilationResult.problemCount; if (problemLength != 0) { CategorizedProblem[] resizedProblems = null; @@ -1612,7 +1630,7 @@ public EnumConstantDeclaration convert(org.eclipse.jdt.internal.compiler.ast.Fie if (anonymousType != null) { AnonymousClassDeclaration anonymousClassDeclaration = new AnonymousClassDeclaration(this.ast); int start = retrieveStartBlockPosition(anonymousType.sourceEnd, anonymousType.bodyEnd); - int end = retrieveRightBrace(anonymousType.bodyEnd + 1, declarationSourceEnd); + int end = retrieveRightBrace(anonymousType.bodyEnd +1, declarationSourceEnd); if (end == -1) end = anonymousType.bodyEnd; anonymousClassDeclaration.setSourceRange(start, end - start + 1); enumConstantDeclaration.setAnonymousClassDeclaration(anonymousClassDeclaration); @@ -1734,6 +1752,33 @@ public Statement convert(org.eclipse.jdt.internal.compiler.ast.ExplicitConstruct return newStatement; } + private ModulePackageAccess getPackageVisibilityStatement( + org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement pvsStmt, ModulePackageAccess stmt) { + int sourceEnd = pvsStmt.declarationSourceEnd; + if (pvsStmt.declarationEnd > sourceEnd) sourceEnd = pvsStmt.declarationEnd; // TODO: working around a compiler issue + Name name = getImportName(pvsStmt.pkgRef); + stmt.setName(name); + if (this.resolveBindings) { + recordNodes(name, pvsStmt.pkgRef); + } + int tmp = sourceEnd; + if (pvsStmt.targets != null && pvsStmt.targets.length > 0) { + List modules = stmt.modules(); + for (ModuleReference moduleRef : pvsStmt.getTargetedModules()) { + Name target = getName(moduleRef, CharOperation.splitOn('.', moduleRef.moduleName), moduleRef.sourcePositions); + modules.add(target); + if (tmp < moduleRef.sourceEnd) tmp = moduleRef.sourceEnd; + if (this.resolveBindings) { + this.recordNodes(target, moduleRef); + } + + } + } + if (tmp > sourceEnd) sourceEnd = tmp; + stmt.setSourceRange(pvsStmt.declarationSourceStart, sourceEnd - pvsStmt.declarationSourceStart + 1); + return stmt; + } + public Expression convert(org.eclipse.jdt.internal.compiler.ast.Expression expression) { if ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) { return convertToParenthesizedExpression(expression); @@ -2055,54 +2100,50 @@ public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteralMin return literal; } - public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) { - if (bodyDeclaration.getJavadoc() == null) { - if (javadoc != null) { - if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) { - this.commentMapper = new DefaultCommentMapper(this.commentsTable); - } - Comment comment = this.commentMapper.getComment(javadoc.sourceStart); - if (comment != null && comment.isDocComment() && comment.getParent() == null) { - Javadoc docComment = (Javadoc) comment; - if (this.resolveBindings) { - recordNodes(docComment, javadoc); - // resolve member and method references binding - Iterator tags = docComment.tags().listIterator(); - while (tags.hasNext()) { - recordNodes(javadoc, (TagElement) tags.next()); - } + interface IGetJavaDoc { + Javadoc getJavaDoc(); + } + interface ISetJavaDoc { + void setJavadoc(Javadoc javadoc); + } + public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, IGetJavaDoc getJ, ISetJavaDoc setJ) { + if (getJ.getJavaDoc() == null) { + Javadoc docComment = convert(javadoc); + if (docComment != null) + setJ.setJavadoc(docComment); + } + } + private Javadoc convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc) { + Javadoc docComment = null; + if (javadoc != null) { + if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) { + this.commentMapper = new DefaultCommentMapper(this.commentsTable); + } + Comment comment = this.commentMapper.getComment(javadoc.sourceStart); + if (comment != null && comment.isDocComment() && comment.getParent() == null) { + docComment = (Javadoc) comment; + if (this.resolveBindings) { + recordNodes(docComment, javadoc); + // resolve member and method references binding + Iterator tags = docComment.tags().listIterator(); + while (tags.hasNext()) { + recordNodes(javadoc, (TagElement) tags.next()); } - bodyDeclaration.setJavadoc(docComment); } } } + return docComment; + } + public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) { + convert(javadoc, bodyDeclaration::getJavadoc, bodyDeclaration::setJavadoc); + } + public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, ModuleDeclaration moduleDeclaration) { + convert(javadoc, moduleDeclaration::getJavadoc, moduleDeclaration::setJavadoc); } public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, PackageDeclaration packageDeclaration) { - switch(this.ast.apiLevel) { - case AST.JLS2_INTERNAL : - return; - } - if (packageDeclaration.getJavadoc() == null) { - if (javadoc != null) { - if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) { - this.commentMapper = new DefaultCommentMapper(this.commentsTable); - } - Comment comment = this.commentMapper.getComment(javadoc.sourceStart); - if (comment != null && comment.isDocComment() && comment.getParent() == null) { - Javadoc docComment = (Javadoc) comment; - if (this.resolveBindings) { - recordNodes(docComment, javadoc); - // resolve member and method references binding - Iterator tags = docComment.tags().listIterator(); - while (tags.hasNext()) { - recordNodes(javadoc, (TagElement) tags.next()); - } - } - packageDeclaration.setJavadoc(docComment); - } - } - } + if (this.ast.apiLevel == AST.JLS2_INTERNAL) return; + convert(javadoc, packageDeclaration::getJavadoc, packageDeclaration::setJavadoc); } public LabeledStatement convert(org.eclipse.jdt.internal.compiler.ast.LabeledStatement statement) { @@ -2265,7 +2306,7 @@ public Expression convert(MessageSend expression) { } public Expression convert(org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambda) { - if (this.ast.apiLevel < AST.JLS8) { + if (this.ast.apiLevel < AST.JLS8_INTERNAL) { return createFakeNullLiteral(lambda); } final LambdaExpression lambdaExpression = new LambdaExpression(this.ast); @@ -2623,7 +2664,7 @@ public Expression convert(org.eclipse.jdt.internal.compiler.ast.Reference refere } public Expression convert(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression reference) { - if (this.ast.apiLevel < AST.JLS8) { + if (this.ast.apiLevel < AST.JLS8_INTERNAL) { return createFakeNullLiteral(reference); } Expression result = null; @@ -2908,8 +2949,7 @@ public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.TrueLiteral public TryStatement convert(org.eclipse.jdt.internal.compiler.ast.TryStatement statement) { final TryStatement tryStatement = new TryStatement(this.ast); tryStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1); - LocalDeclaration[] localDeclarations = statement.resources; - int resourcesLength = localDeclarations.length; + int resourcesLength = statement.resources.length; if (resourcesLength > 0) { switch(this.ast.apiLevel) { case AST.JLS2_INTERNAL : @@ -2917,15 +2957,41 @@ public TryStatement convert(org.eclipse.jdt.internal.compiler.ast.TryStatement s // convert it to a simple try statement tagged as MALFORMED tryStatement.setFlags(tryStatement.getFlags() | ASTNode.MALFORMED); break; - default: + case AST.JLS4_INTERNAL: + case AST.JLS8_INTERNAL: for (int i = 0; i < resourcesLength; i++) { - LocalDeclaration localDeclaration = localDeclarations[i]; + if (!(statement.resources[i] instanceof LocalDeclaration)) { + tryStatement.setFlags(tryStatement.getFlags() | ASTNode.MALFORMED); + break; + } + LocalDeclaration localDeclaration = (LocalDeclaration)statement.resources[i]; VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression(localDeclaration); int start = variableDeclarationExpression.getStartPosition(); int end = localDeclaration.declarationEnd; variableDeclarationExpression.setSourceRange(start, end - start + 1); tryStatement.resources().add(variableDeclarationExpression); } + break; + default: + for (int i = 0; i < resourcesLength; i++) { + org.eclipse.jdt.internal.compiler.ast.Statement resource = statement.resources[i]; + if (resource instanceof LocalDeclaration) { + LocalDeclaration localDeclaration = (LocalDeclaration)resource; + VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression(localDeclaration); + int start = variableDeclarationExpression.getStartPosition(); + int end = localDeclaration.declarationEnd; + variableDeclarationExpression.setSourceRange(start, end - start + 1); + tryStatement.resources().add(variableDeclarationExpression); + } else if (resource instanceof NameReference) { + tryStatement.resources().add(convert((NameReference) resource)); + } else if (resource instanceof FieldReference) { + tryStatement.resources().add(convert((FieldReference) resource)); + } else { + tryStatement.setFlags(tryStatement.getFlags() | ASTNode.MALFORMED); + break; + } + } + break; } } tryStatement.setBody(convert(statement.tryBlock)); @@ -3128,30 +3194,9 @@ public WhileStatement convert(org.eclipse.jdt.internal.compiler.ast.WhileStateme public ImportDeclaration convertImport(org.eclipse.jdt.internal.compiler.ast.ImportReference importReference) { final ImportDeclaration importDeclaration = new ImportDeclaration(this.ast); + Name name = getImportName(importReference); + importDeclaration.setName(name); final boolean onDemand = (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OnDemand) != 0; - final char[][] tokens = importReference.tokens; - int length = importReference.tokens.length; - final long[] positions = importReference.sourcePositions; - // GROOVY add - if (!CharOperation.equals(tokens[length - 1], importReference.getSimpleName())) { - tokens[length - 1] = CharOperation.concat(tokens[length - 1], ' ', new char[] {'a','s'}, ' ', importReference.getSimpleName()); - } - if (positions.length > 0 && (int)(positions[0]>>>32) > 0) - // GROOVY end - if (length > 1) { - importDeclaration.setName(setQualifiedNameNameAndSourceRanges(tokens, positions, importReference)); - } else { - final SimpleName name = new SimpleName(this.ast); - name.internalSetIdentifier(new String(tokens[0])); - final int start = (int)(positions[0]>>>32); - final int end = (int)(positions[0] & 0xFFFFFFFF); - name.setSourceRange(start, end - start + 1); - name.index = 1; - importDeclaration.setName(name); - if (this.resolveBindings) { - recordNodes(name, importReference); - } - } importDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1); importDeclaration.setOnDemand(onDemand); int modifiers = importReference.modifiers; @@ -3174,6 +3219,38 @@ public ImportDeclaration convertImport(org.eclipse.jdt.internal.compiler.ast.Imp return importDeclaration; } + public Name getImportName(org.eclipse.jdt.internal.compiler.ast.ImportReference importReference) { + return getName(importReference, importReference.tokens, importReference.sourcePositions); + } + + private Name getName(org.eclipse.jdt.internal.compiler.ast.ASTNode node, final char[][] tokens, + final long[] positions) { + Name name; + int length = tokens != null ? tokens.length : 0; + // GROOVY add + if (node instanceof org.eclipse.jdt.internal.compiler.ast.ImportReference) { + org.eclipse.jdt.internal.compiler.ast.ImportReference importReference = (org.eclipse.jdt.internal.compiler.ast.ImportReference)node; + if (!CharOperation.equals(tokens[length - 1], importReference.getSimpleName())) { + tokens[length - 1] = CharOperation.concat(tokens[length - 1], ' ', new char[] {'a','s'}, ' ', importReference.getSimpleName()); + } + } + // GROOVY end + if (length > 1) { + name = setQualifiedNameNameAndSourceRanges(tokens, positions, node); + } else { + name = new SimpleName(this.ast); + ((SimpleName)name).internalSetIdentifier(new String(tokens[0])); + final int start = (int)(positions[0]>>>32); + final int end = (int)(positions[0] & 0xFFFFFFFF); + name.setSourceRange(start, end - start + 1); + name.index = 1; + if (this.resolveBindings) { + recordNodes(name, node); + } + } + return name; + } + public PackageDeclaration convertPackage(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration) { org.eclipse.jdt.internal.compiler.ast.ImportReference importReference = compilationUnitDeclaration.currentPackage; final PackageDeclaration packageDeclaration = new PackageDeclaration(this.ast); @@ -3218,7 +3295,7 @@ public PackageDeclaration convertPackage(org.eclipse.jdt.internal.compiler.ast.C private ArrayType convertToArray(Type elementType, int sourceStart, int length, int dimensions, org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDimensions) { ArrayType arrayType = this.ast.newArrayType(elementType, dimensions); if (length > 0) arrayType.setSourceRange(sourceStart, length); - if (this.ast.apiLevel() < AST.JLS8) { + if (this.ast.apiLevel() < AST.JLS8_INTERNAL) { if (annotationsOnDimensions != null) { arrayType.setFlags(arrayType.getFlags() | ASTNode.MALFORMED); } @@ -3288,6 +3365,119 @@ protected FieldDeclaration convertToFieldDeclaration(org.eclipse.jdt.internal.co return fieldDeclaration; } + /** + * If there is a parsing error causing a recovered module the source positions may be updated only partially. + * See bug 518843 for a case where this issue occurred. This method provide a safety net with + * source positions updated even in case of a recovery - if there is no recovery, the source positions will + * be retained in-tact identical to the compile time ast module node. + */ + private int getKnownEnd(ModuleDeclaration md, int sourceEnd, int declSourceEnd) { + int end = retrieveRightBrace(md.getStartPosition() + 1, this.compilationUnitSourceLength); + end = end > sourceEnd ? end : sourceEnd; + end = end > declSourceEnd ? end : declSourceEnd; + return end; + } + public ModuleDeclaration convertToModuleDeclaration(org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration moduleDeclaration) { + checkCanceled(); + if (this.scanner.sourceLevel < ClassFileConstants.JDK9 + || this.ast.apiLevel < AST.JLS9_INTERNAL) return null; + ModuleDeclaration moduleDecl = this.ast.newModuleDeclaration(); + // TODO + //convert(moduleDeclaration.javadoc, moduleDecl); + setAnnotations(moduleDecl, moduleDeclaration); // only annotations + moduleDecl.setOpen(moduleDeclaration.isOpen()); + Name moduleName = getName(moduleDeclaration, CharOperation.splitOn('.', moduleDeclaration.moduleName), moduleDeclaration.sourcePositions); + moduleDecl.setName(moduleName); + + List stmts = moduleDecl.moduleStatements(); + TreeSet tSet = new TreeSet<> (new Comparator() { + public int compare(Object o1, Object o2) { + int p1 = ((ModuleDirective) o1).getStartPosition(); + int p2 = ((ModuleDirective) o2).getStartPosition(); + return p1 < p2 ? -1 : p1 == p2 ? 0 : 1; + } + }); + for (int i = 0; i < moduleDeclaration.exportsCount; ++i) { + tSet.add(getPackageVisibilityStatement(moduleDeclaration.exports[i], new ExportsDirective(this.ast))); + } + for (int i = 0; i < moduleDeclaration.opensCount; ++i) { + tSet.add(getPackageVisibilityStatement(moduleDeclaration.opens[i], new OpensDirective(this.ast))); + } + for (int i = 0; i < moduleDeclaration.requiresCount; ++i) { + org.eclipse.jdt.internal.compiler.ast.RequiresStatement req = moduleDeclaration.requires[i]; + ModuleReference moduleRef = req.module; + RequiresDirective stmt = new RequiresDirective(this.ast); + Name name = getName(moduleRef, CharOperation.splitOn('.', moduleRef.moduleName), moduleRef.sourcePositions); + stmt.setName(name); + if (this.resolveBindings) { + recordNodes(name, moduleRef); + } + + setModuleModifiers(req, stmt); + stmt.setSourceRange(req.declarationSourceStart, req.declarationEnd - req.declarationSourceStart + 1); + tSet.add(stmt); + } + for (int i = 0; i < moduleDeclaration.usesCount; ++i) { + org.eclipse.jdt.internal.compiler.ast.UsesStatement usesStatement = moduleDeclaration.uses[i]; + UsesDirective stmt = new UsesDirective(this.ast); + TypeReference usesRef = usesStatement.serviceInterface; + Name name = convert(usesRef); + stmt.setName(name); + stmt.setSourceRange(usesStatement.declarationSourceStart, usesStatement.declarationSourceEnd - usesStatement.declarationSourceStart + 1); + tSet.add(stmt); + } + for (int i = 0; i < moduleDeclaration.servicesCount; ++i) { + org.eclipse.jdt.internal.compiler.ast.ProvidesStatement pStmt = moduleDeclaration.services[i]; + ProvidesDirective stmt = new ProvidesDirective(this.ast); + stmt.setName(convert(pStmt.serviceInterface)); + TypeReference[] impls = pStmt.implementations; + for (TypeReference impl : impls) { + stmt.implementations().add(convert(impl)); + } + stmt.setSourceRange(pStmt.declarationSourceStart, pStmt.declarationSourceEnd - pStmt.declarationSourceStart + 1); + tSet.add(stmt); + } + // The javadoc comment is now got from list store in compilation unit declaration + if (this.resolveBindings) { + recordNodes(moduleDecl, moduleDeclaration); + recordNodes(moduleName, moduleDeclaration); + moduleDecl.resolveBinding(); + } + stmts.addAll(tSet); + int end = getKnownEnd(moduleDecl, moduleDeclaration.sourceEnd, moduleDeclaration.declarationSourceEnd); + moduleDecl.setSourceRange(moduleDeclaration.declarationSourceStart, end - moduleDeclaration.declarationSourceStart + 1); + return moduleDecl; + } + + private void setModuleModifiers(org.eclipse.jdt.internal.compiler.ast.RequiresStatement req, RequiresDirective stmt) { + boolean fakeInModule = this.scanner.fakeInModule; + this.scanner.fakeInModule = true; + this.scanner.resetTo(req.declarationSourceStart, req.sourceEnd); + try { + int token; + ModuleModifier modifier; + while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) { + switch(token) { + case TerminalTokens.TokenNamestatic: + modifier = createModuleModifier(ModuleModifier.ModuleModifierKeyword.STATIC_KEYWORD); + break; + case TerminalTokens.TokenNametransitive: + modifier = createModuleModifier(ModuleModifier.ModuleModifierKeyword.TRANSITIVE_KEYWORD); + break; + default : + continue; + } + if (modifier != null) { + stmt.modifiers().add(modifier); + } + } + } catch(InvalidInputException e) { + // ignore + } finally { + this.scanner.fakeInModule = fakeInModule; + } + } + public ParenthesizedExpression convertToParenthesizedExpression(org.eclipse.jdt.internal.compiler.ast.Expression expression) { final ParenthesizedExpression parenthesizedExpression = new ParenthesizedExpression(this.ast); if (this.resolveBindings) { @@ -3331,7 +3521,7 @@ protected SingleVariableDeclaration convertToSingleVariableDeclaration(LocalDecl variableDecl.setName(name); TypeReference typeReference = localDeclaration.type; final int extraDimensions = typeReference.extraDimensions(); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { setExtraAnnotatedDimensions(nameEnd + 1, localDeclaration.declarationSourceEnd, typeReference, variableDecl.extraDimensions(), extraDimensions); } else { @@ -3379,7 +3569,7 @@ protected VariableDeclarationFragment convertToVariableDeclarationFragment(org.e int end = start; TypeReference typeReference = fieldDeclaration.type; int extraDimensions = typeReference.extraDimensions(); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { setExtraAnnotatedDimensions(fieldDeclaration.sourceEnd + 1, fieldDeclaration.declarationSourceEnd, typeReference, variableDeclarationFragment.extraDimensions(), extraDimensions); } else { @@ -3423,7 +3613,7 @@ protected VariableDeclarationFragment convertToVariableDeclarationFragment(org.e org.eclipse.jdt.internal.compiler.ast.Expression initialization = localDeclaration.initialization; TypeReference typeReference = localDeclaration.type; int extraDimension = typeReference.extraDimensions(); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { setExtraAnnotatedDimensions(localDeclaration.sourceEnd + 1, this.compilationUnitSourceLength, typeReference, variableDeclarationFragment.extraDimensions(), extraDimension); } else { @@ -4005,7 +4195,7 @@ private Type createBaseType(TypeReference typeReference, long[] positions, } boolean createNameQualifiedType = typeAnnotations != null && typeAnnotations[firstTypeIndex] != null; - if (createNameQualifiedType && this.ast.apiLevel >= AST.JLS8) { + if (createNameQualifiedType && this.ast.apiLevel >= AST.JLS8_INTERNAL) { NameQualifiedType nameQualifiedType = new NameQualifiedType(this.ast); nameQualifiedType.setQualifier(name); nameQualifiedType.setName(createSimpleName(typeReference, positions, tokens, firstTypeIndex)); @@ -4147,6 +4337,18 @@ private Modifier createModifier(ModifierKeyword keyword) { return modifier; } + /** + * @return a new module modifier + */ + private ModuleModifier createModuleModifier(ModuleModifierKeyword keyword) { + final ModuleModifier modifier = new ModuleModifier(this.ast); + modifier.setKeyword(keyword); + int start = this.scanner.getCurrentTokenStartPosition(); + int end = this.scanner.getCurrentTokenEndPosition(); + modifier.setSourceRange(start, end - start + 1); + return modifier; + } + protected InfixExpression.Operator getOperatorFor(int operatorID) { switch (operatorID) { case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL : @@ -4343,7 +4545,6 @@ protected boolean isPrimitiveType(char[] name) { } return false; } - private void lookupForScopes() { if (this.pendingNameScopeResolution != null) { for (Iterator iterator = this.pendingNameScopeResolution.iterator(); iterator.hasNext(); ) { @@ -5136,6 +5337,9 @@ protected void setModifiers(AnnotationTypeMemberDeclaration annotationTypeMember * @param bodyDeclaration */ protected void setModifiers(BodyDeclaration bodyDeclaration, org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations, int modifiersEnd) { + setModifiers(bodyDeclaration.modifiers(), annotations, modifiersEnd); + } + protected void setModifiers(List modifiers, org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations, int modifiersEnd) { this.scanner.tokenizeWhiteSpace = false; try { int token; @@ -5196,7 +5400,7 @@ protected void setModifiers(BodyDeclaration bodyDeclaration, org.eclipse.jdt.int break; } if (modifier != null) { - bodyDeclaration.modifiers().add(modifier); + modifiers.add(modifier); } } } catch(InvalidInputException e) { @@ -5276,6 +5480,10 @@ protected void setModifiers(MethodDeclaration methodDecl, AbstractMethodDeclarat } } + protected void setAnnotations(ModuleDeclaration moduleDecl, org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration moduleDeclaration) { + this.scanner.resetTo(moduleDeclaration.declarationSourceStart, moduleDeclaration.sourceStart); + this.setModifiers(moduleDecl.annotations(), moduleDeclaration.annotations, moduleDeclaration.sourceStart); + } /** * @param variableDecl * @param argument @@ -5771,7 +5979,7 @@ protected void setTypeForField(FieldDeclaration fieldDeclaration, Type type, int fieldDeclaration.setType(type); } } else { - if (type.isArrayType() && (this.ast.apiLevel() < AST.JLS8)) { + if (type.isArrayType() && (this.ast.apiLevel() < AST.JLS8_INTERNAL)) { // update positions of the component types of the array type int dimensions = ((ArrayType) type).getDimensions(); updateInnerPositions(type, dimensions); @@ -5789,7 +5997,7 @@ protected void setTypeForField(FieldDeclaration fieldDeclaration, Type type, int private ArrayType extractSubArrayType(ArrayType arrayType, int remainingDimensions, int dimensionsToRemove) { ArrayType subArrayType = arrayType; int start = subArrayType.getStartPosition(); - if (this.ast.apiLevel() < AST.JLS8) { + if (this.ast.apiLevel() < AST.JLS8_INTERNAL) { while (dimensionsToRemove > 0 ) { subArrayType = (ArrayType) componentType(subArrayType); dimensionsToRemove--; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java index 088f31425a..98b5785631 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -335,7 +335,7 @@ public boolean match(ArrayType node, Object other) { } ArrayType o = (ArrayType) other; int level = node.getAST().apiLevel; - if (level < AST.JLS8) { + if (level < AST.JLS8_INTERNAL) { return safeSubtreeMatch(componentType(node), componentType(o)); } return safeSubtreeMatch(node.getElementType(), o.getElementType()) @@ -615,7 +615,8 @@ public boolean match(CompilationUnit node, Object other) { } CompilationUnit o = (CompilationUnit) other; return ( - safeSubtreeMatch(node.getPackage(), o.getPackage()) + (node.getAST().apiLevel >= AST.JLS9_INTERNAL ? safeSubtreeMatch(node.getModule(), o.getModule()) : true) + && safeSubtreeMatch(node.getPackage(), o.getPackage()) && safeSubtreeListMatch(node.imports(), o.imports()) && safeSubtreeListMatch(node.types(), o.types())); } @@ -874,6 +875,31 @@ && safeSubtreeListMatch( o.bodyDeclarations())); } + /** + * Returns whether the given node and the other object match. + *

+ * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + *

+ * + * @param node the node + * @param other the other object, or null + * @return true if the subtree matches, or + * false if they do not match or the other object has a + * different node type or is null + * @since 3.14 + */ + public boolean match(ExportsDirective node, Object other) { + if (!(other instanceof ExportsDirective)) { + return false; + } + ExportsDirective o = (ExportsDirective) other; + return ( + safeSubtreeMatch(node.getName(), o.getName()) + && safeSubtreeListMatch(node.modules(), o.modules())); + } + /** * Returns whether the given node and the other object match. *

@@ -1474,12 +1500,12 @@ && safeSubtreeMatch(node.getReturnType2(), o.getReturnType2()) // n.b. compare return type even for constructors && safeSubtreeMatch(node.internalGetReturnType(), o.internalGetReturnType())) && safeSubtreeMatch(node.getName(), o.getName()) - && (level >= AST.JLS8 + && (level >= AST.JLS8_INTERNAL ? safeSubtreeMatch(node.getReceiverType(), o.getReceiverType()) && safeSubtreeMatch(node.getReceiverQualifier(), o.getReceiverQualifier()) : true) && safeSubtreeListMatch(node.parameters(), o.parameters()) - && (level >= AST.JLS8 + && (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.extraDimensions(), o.extraDimensions()) && safeSubtreeListMatch(node.thrownExceptionTypes(), o.thrownExceptionTypes()) : node.getExtraDimensions() == o.getExtraDimensions() @@ -1540,6 +1566,56 @@ public boolean match(Modifier node, Object other) { return (node.getKeyword() == o.getKeyword()); } + /** + * Returns whether the given node and the other object match. + *

+ * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + *

+ * + * @param node the node + * @param other the other object, or null + * @return true if the subtree matches, or + * false if they do not match or the other object has a + * different node type or is null + * @since 3.14 + */ + public boolean match(ModuleDeclaration node, Object other) { + if (!(other instanceof ModuleDeclaration)) { + return false; + } + ModuleDeclaration o = (ModuleDeclaration) other; + return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) + && safeSubtreeListMatch(node.annotations(), o.annotations()) + && node.isOpen() == o.isOpen() + && safeSubtreeMatch(node.getName(), o.getName()) + && safeSubtreeListMatch(node.moduleStatements(), o.moduleStatements())); + } + + /** + * Returns whether the given node and the other object match. + *

+ * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + *

+ * + * @param node the node + * @param other the other object, or null + * @return true if the subtree matches, or + * false if they do not match or the other object has a + * different node type or is null + * @since 3.14 + */ + public boolean match(ModuleModifier node, Object other) { + if (!(other instanceof ModuleModifier)) { + return false; + } + ModuleModifier o = (ModuleModifier) other; + return (node.getKeyword() == o.getKeyword()); + } + /** * Returns whether the given node and the other object match. *

@@ -1632,6 +1708,31 @@ public boolean match(NumberLiteral node, Object other) { return safeEquals(node.getToken(), o.getToken()); } + /** + * Returns whether the given node and the other object match. + *

+ * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + *

+ * + * @param node the node + * @param other the other object, or null + * @return true if the subtree matches, or + * false if they do not match or the other object has a + * different node type or is null + * @since 3.14 + */ + public boolean match(OpensDirective node, Object other) { + if (!(other instanceof OpensDirective)) { + return false; + } + OpensDirective o = (OpensDirective) other; + return ( + safeSubtreeMatch(node.getName(), o.getName()) + && safeSubtreeListMatch(node.modules(), o.modules())); + } + /** * Returns whether the given node and the other object match. *

@@ -1776,10 +1877,36 @@ public boolean match(PrimitiveType node, Object other) { } PrimitiveType o = (PrimitiveType) other; int level = node.getAST().apiLevel; - return (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true) + return (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true) && node.getPrimitiveTypeCode() == o.getPrimitiveTypeCode(); } + /** + * Returns whether the given node and the other object match. + *

+ * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + *

+ * + * @param node the node + * @param other the other object, or null + * @return true if the subtree matches, or + * false if they do not match or the other object has a + * different node type or is null + * @since 3.14 + + */ + public boolean match(ProvidesDirective node, Object other) { + if (!(other instanceof ProvidesDirective)) { + return false; + } + ProvidesDirective o = (ProvidesDirective) other; + return ( + safeSubtreeMatch(node.getName(), o.getName()) + && safeSubtreeListMatch(node.implementations(), o.implementations())); + } + /** * Returns whether the given node and the other object match. *

@@ -1825,7 +1952,32 @@ public boolean match(QualifiedType node, Object other) { QualifiedType o = (QualifiedType) other; int level = node.getAST().apiLevel; return safeSubtreeMatch(node.getQualifier(), o.getQualifier()) - && (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true) + && (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true) + && safeSubtreeMatch(node.getName(), o.getName()); + } + + /** + * Returns whether the given node and the other object match. + *

+ * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + *

+ * + * @param node the node + * @param other the other object, or null + * @return true if the subtree matches, or + * false if they do not match or the other object has a + * different node type or is null + * + * @since 3.14 + */ + public boolean match(RequiresDirective node, Object other) { + if (!(other instanceof RequiresDirective)) { + return false; + } + RequiresDirective o = (RequiresDirective) other; + return safeSubtreeListMatch(node.modifiers(), o.modifiers()) && safeSubtreeMatch(node.getName(), o.getName()); } @@ -1893,7 +2045,7 @@ public boolean match(SimpleType node, Object other) { } SimpleType o = (SimpleType) other; int level = node.getAST().apiLevel; - return (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true) + return (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true) && safeSubtreeMatch(node.getName(), o.getName()); } @@ -1949,14 +2101,14 @@ public boolean match(SingleVariableDeclaration node, Object other) { ? safeSubtreeListMatch(node.modifiers(), o.modifiers()) : node.getModifiers() == o.getModifiers()) && safeSubtreeMatch(node.getType(), o.getType()) - && (level >= AST.JLS8 && node.isVarargs() + && (level >= AST.JLS8_INTERNAL && node.isVarargs() ? safeSubtreeListMatch(node.varargsAnnotations(), o.varargsAnnotations()) : true) && (level >= AST.JLS3_INTERNAL ? node.isVarargs() == o.isVarargs() : true) && safeSubtreeMatch(node.getName(), o.getName()) - && ((level >= AST.JLS8) + && ((level >= AST.JLS8_INTERNAL) ? safeSubtreeListMatch(node.extraDimensions(), o.extraDimensions()) : node.getExtraDimensions() == o.getExtraDimensions()) && safeSubtreeMatch(node.getInitializer(), o.getInitializer()); @@ -2424,7 +2576,7 @@ public boolean match(TypeParameter node, Object other) { } TypeParameter o = (TypeParameter) other; int level = node.getAST().apiLevel; - return (level >= AST.JLS8 ? safeSubtreeListMatch(node.modifiers(), o.modifiers()) : true) + return (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.modifiers(), o.modifiers()) : true) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.typeBounds(), o.typeBounds()); } @@ -2452,6 +2604,29 @@ public boolean match(UnionType node, Object other) { return safeSubtreeListMatch(node.types(), o.types()); } + /** + * Returns whether the given node and the other object match. + *

+ * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + *

+ * + * @param node the node + * @param other the other object, or null + * @return true if the subtree matches, or + * false if they do not match or the other object has a + * different node type or is null + * @since 3.14 + */ + public boolean match(UsesDirective node, Object other) { + if (!(other instanceof UnionType)) { + return false; + } + UsesDirective o = (UsesDirective) other; + return safeSubtreeMatch(node.getName(), o.getName()); + } + /** * Returns whether the given node and the other object match. *

@@ -2511,7 +2686,7 @@ public boolean match(VariableDeclarationFragment node, Object other) { VariableDeclarationFragment o = (VariableDeclarationFragment) other; int level = node.getAST().apiLevel; return safeSubtreeMatch(node.getName(), o.getName()) - && (level >= AST.JLS8 + && (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.extraDimensions(), o.extraDimensions()) : node.getExtraDimensions() == o.getExtraDimensions()) && safeSubtreeMatch(node.getInitializer(), o.getInitializer()); @@ -2596,7 +2771,7 @@ public boolean match(WildcardType node, Object other) { } WildcardType o = (WildcardType) other; int level = node.getAST().apiLevel; - return (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true) + return (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true) && node.isUpperBound() == o.isUpperBound() && safeSubtreeMatch(node.getBound(), o.getBound()); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java index 73e9b9daae..0982216599 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -896,6 +896,62 @@ public abstract class ASTNode { */ public static final int TYPE_METHOD_REFERENCE = 92; + /** + * Node type constant indicating a node of type + * ModuleDeclaration. + * @see ModuleDeclaration + * @since 3.14 + */ + public static final int MODULE_DECLARATION = 93; + + /** + * Node type constant indicating a node of type + * RequiresDirective. + * @see RequiresDirective + * @since 3.14 + */ + public static final int REQUIRES_DIRECTIVE = 94; + + /** + * Node type constant indicating a node of type + * ExportsDirective. + * @see ExportsDirective + * @since 3.14 + */ + public static final int EXPORTS_DIRECTIVE = 95; + + /** + * Node type constant indicating a node of type + * OpensDirective. + * @see OpensDirective + * @since 3.14 + */ + public static final int OPENS_DIRECTIVE = 96; + + /** + * Node type constant indicating a node of type + * UsesDirective. + * @see UsesDirective + * @since 3.14 + */ + public static final int USES_DIRECTIVE = 97; + + /** + * Node type constant indicating a node of type + * ProvidesDirective. + * @see ProvidesDirective + * @since 3.14 + */ + public static final int PROVIDES_DIRECTIVE = 98; + + /** + * Node type constant indicating a node of type + * ModuleModifier. + * @see ModuleModifier + * @since 3.14 + */ + public static final int MODULE_MODIFIER = 99; + /** * Returns the node class for the corresponding node type. * @@ -964,6 +1020,8 @@ public static Class nodeClassForType(int nodeType) { return EnumConstantDeclaration.class; case ENUM_DECLARATION : return EnumDeclaration.class; + case EXPORTS_DIRECTIVE : + return ExportsDirective.class; case EXPRESSION_METHOD_REFERENCE : return ExpressionMethodReference.class; case EXPRESSION_STATEMENT : @@ -1010,6 +1068,10 @@ public static Class nodeClassForType(int nodeType) { return MethodRefParameter.class; case MODIFIER : return Modifier.class; + case MODULE_DECLARATION : + return ModuleDeclaration.class; + case MODULE_MODIFIER : + return ModuleModifier.class; case NAME_QUALIFIED_TYPE : return NameQualifiedType.class; case NORMAL_ANNOTATION : @@ -1018,6 +1080,8 @@ public static Class nodeClassForType(int nodeType) { return NullLiteral.class; case NUMBER_LITERAL : return NumberLiteral.class; + case OPENS_DIRECTIVE : + return OpensDirective.class; case PACKAGE_DECLARATION : return PackageDeclaration.class; case PARAMETERIZED_TYPE : @@ -1030,10 +1094,14 @@ public static Class nodeClassForType(int nodeType) { return PrefixExpression.class; case PRIMITIVE_TYPE : return PrimitiveType.class; + case PROVIDES_DIRECTIVE : + return ProvidesDirective.class; case QUALIFIED_NAME : return QualifiedName.class; case QUALIFIED_TYPE : return QualifiedType.class; + case REQUIRES_DIRECTIVE : + return RequiresDirective.class; case RETURN_STATEMENT : return ReturnStatement.class; case SIMPLE_NAME : @@ -1082,6 +1150,8 @@ public static Class nodeClassForType(int nodeType) { return TypeParameter.class; case UNION_TYPE : return UnionType.class; + case USES_DIRECTIVE : + return UsesDirective.class; case VARIABLE_DECLARATION_EXPRESSION : return VariableDeclarationExpression.class; case VARIABLE_DECLARATION_FRAGMENT : @@ -1964,18 +2034,33 @@ final void unsupportedIn2_3() { * @since 3.10 */ final void unsupportedIn2_3_4() { - if (this.ast.apiLevel < AST.JLS8) { + if (this.ast.apiLevel < AST.JLS8_INTERNAL) { throw new UnsupportedOperationException("Operation only supported in JLS8 and later AST"); //$NON-NLS-1$ } } - + + /** + * Checks that this AST operation is not used when + * building JLS2, JLS3, JLS4 or JLS8 level ASTs. + *

+ * Use this method to prevent access to new properties that have been added in JLS9. + *

+ * + * @exception UnsupportedOperationException if this operation is used below JLS9 + * @since 3.14 + */ + final void unsupportedBelow9() { + if (this.ast.apiLevel < AST.JLS9_INTERNAL) { + throw new UnsupportedOperationException("Operation only supported in JLS9 and later AST"); //$NON-NLS-1$ + } + } /** * Checks that this AST operation is only used when * building JLS2 level ASTs. *

* Use this method to prevent access to deprecated properties (deprecated in JLS3). *

- * + * * @exception UnsupportedOperationException if this operation is used in an AST later than JLS2 * @since 3.0 */ @@ -1998,7 +2083,7 @@ final void supportedOnlyIn2() { */ // In API Javadocs, add: * @deprecated In the JLS8 API, this method is replaced by {@link #replacement()}. final void supportedOnlyIn2_3_4() { - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { throw new UnsupportedOperationException("Operation only supported in JLS2, JLS3 and JLS4 ASTs"); //$NON-NLS-1$ } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java index 70a6e25f89..cb5691673a 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2016 IBM Corporation and others. + * Copyright (c) 2004, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -35,6 +35,7 @@ import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.batch.Main; +import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData; @@ -226,7 +227,8 @@ public static ASTParser newParser(int level) { case AST.JLS2_INTERNAL: case AST.JLS3_INTERNAL: case AST.JLS4_INTERNAL: - case AST.JLS8: + case AST.JLS8_INTERNAL: + case AST.JLS9_INTERNAL: break; default: throw new IllegalArgumentException(); @@ -235,9 +237,9 @@ public static ASTParser newParser(int level) { initializeDefaults(); } - private List getClasspath() throws IllegalStateException { + private List getClasspath() throws IllegalStateException { Main main = new Main(new PrintWriter(System.out), new PrintWriter(System.err), false/*systemExit*/, null/*options*/, null/*progress*/); - ArrayList allClasspaths = new ArrayList(); + ArrayList allClasspaths = new ArrayList(); try { if ((this.bits & CompilationUnitResolver.INCLUDE_RUNNING_VM_BOOTCLASSPATH) != 0) { org.eclipse.jdt.internal.compiler.util.Util.collectRunningVMBootclasspath(allClasspaths); @@ -1132,19 +1134,27 @@ private ASTNode internalCreateAST(IProgressMonitor monitor) { } PackageFragment packageFragment = (PackageFragment) this.typeRoot.getParent(); BinaryType type = (BinaryType) this.typeRoot.findPrimaryType(); - IBinaryType binaryType = (IBinaryType) type.getElementInfo(); - // file name is used to recreate the Java element, so it has to be the toplevel .class file name - char[] fileName = binaryType.getFileName(); - int firstDollar = CharOperation.indexOf('$', fileName); - if (firstDollar != -1) { - char[] suffix = SuffixConstants.SUFFIX_class; - int suffixLength = suffix.length; - char[] newFileName = new char[firstDollar + suffixLength]; - System.arraycopy(fileName, 0, newFileName, 0, firstDollar); - System.arraycopy(suffix, 0, newFileName, firstDollar, suffixLength); - fileName = newFileName; + String fileNameString = null; + if (type != null) { + IBinaryType binaryType = (IBinaryType) type.getElementInfo(); + // file name is used to recreate the Java element, so it has to be the toplevel .class file name + char[] fileName = binaryType.getFileName(); + + int firstDollar = CharOperation.indexOf('$', fileName); + if (firstDollar != -1) { + char[] suffix = SuffixConstants.SUFFIX_class; + int suffixLength = suffix.length; + char[] newFileName = new char[firstDollar + suffixLength]; + System.arraycopy(fileName, 0, newFileName, 0, firstDollar); + System.arraycopy(suffix, 0, newFileName, firstDollar, suffixLength); + fileName = newFileName; + } + fileNameString = new String(fileName); + } else { + // assumed to be "module-info.class" (which has no type): + fileNameString = this.typeRoot.getElementName(); } - sourceUnit = new BasicCompilationUnit(sourceString.toCharArray(), Util.toCharArrays(packageFragment.names), new String(fileName), this.project); + sourceUnit = new BasicCompilationUnit(sourceString.toCharArray(), Util.toCharArrays(packageFragment.names), fileNameString, this.project); } catch(JavaModelException e) { // an error occured accessing the java element StringWriter stringWriter = new StringWriter(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java index 9e86e96929..45b0ba6e5b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2014 IBM Corporation and others. + * Copyright (c) 2006, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -51,6 +51,8 @@ class ASTRecoveryPropagator extends DefaultASTVisitor { this.endingTokens.put(Initializer.class, new int[]{TerminalTokens.TokenNameRBRACE}); this.endingTokens.put(MethodDeclaration.class, new int[]{NOTHING, TerminalTokens.TokenNameSEMICOLON}); this.endingTokens.put(MethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN}); + this.endingTokens.put(ModuleDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE}); + this.endingTokens.put(ModuleDirective.class, new int[]{TerminalTokens.TokenNameSEMICOLON}); this.endingTokens.put(NullLiteral.class, new int[]{TerminalTokens.TokenNamenull}); this.endingTokens.put(NumberLiteral.class, new int[]{TerminalTokens.TokenNameIntegerLiteral, TerminalTokens.TokenNameLongLiteral, TerminalTokens.TokenNameFloatingPointLiteral, TerminalTokens.TokenNameDoubleLiteral}); this.endingTokens.put(PackageDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON}); @@ -192,6 +194,7 @@ protected void endVisitNode(ASTNode node) { case ASTNode.IMPORT_DECLARATION: case ASTNode.INITIALIZER: case ASTNode.METHOD_DECLARATION: + case ASTNode.MODULE_DECLARATION: case ASTNode.PACKAGE_DECLARATION: case ASTNode.TYPE_DECLARATION: case ASTNode.MARKER_ANNOTATION: diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java index 85906727f4..e3ab43eaa9 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -96,6 +96,13 @@ public boolean visit(MethodDeclaration node) { return checkAndTagAsMalformed(node); } + /* + * Module declared on ASTVisitor. + */ + public boolean visit(ModuleDeclaration node) { + return checkAndTagAsMalformed(node); + } + /* * Method declared on ASTVisitor. */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java index d902b9ba67..88cfc4846a 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -644,6 +644,23 @@ public boolean visit(EnumDeclaration node) { return true; } + /** + * Visits the given type-specific AST node. + *

+ * The default implementation does nothing and return true. + * Subclasses may re-implement. + *

+ * + * @param node the node to visit + * @return true if the children of this node should be + * visited, and false if the children of this node should + * be skipped + * @since 3.14 + */ + public boolean visit(ExportsDirective node) { + return true; + } + /** * Visits the given type-specific AST node. *

@@ -1041,6 +1058,40 @@ public boolean visit(Modifier node) { return true; } + /** + * Visits the given type-specific AST node. + *

+ * The default implementation does nothing and return true. + * Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @return true if the children of this node should be + * visited, and false if the children of this node should + * be skipped + * @since 3.14 + */ + public boolean visit(ModuleDeclaration node) { + return true; + } + + /** + * Visits the given type-specific AST node. + *

+ * The default implementation does nothing and return true. + * Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @return true if the children of this node should be + * visited, and false if the children of this node should + * be skipped + * @since 3.14 + */ + public boolean visit(ModuleModifier node) { + return true; + } + /** * Visits the given type-specific AST node. *

@@ -1107,6 +1158,23 @@ public boolean visit(NumberLiteral node) { return true; } + /** + * Visits the given type-specific AST node. + *

+ * The default implementation does nothing and return true. + * Subclasses may re-implement. + *

+ * + * @param node the node to visit + * @return true if the children of this node should be + * visited, and false if the children of this node should + * be skipped + * @since 3.14 + */ + public boolean visit(OpensDirective node) { + return true; + } + /** * Visits the given type-specific AST node. *

@@ -1188,6 +1256,23 @@ public boolean visit(PrefixExpression node) { return true; } + /** + * Visits the given type-specific AST node. + *

+ * The default implementation does nothing and return true. + * Subclasses may re-implement. + *

+ * + * @param node the node to visit + * @return true if the children of this node should be + * visited, and false if the children of this node should + * be skipped + * @since 3.14 + */ + public boolean visit(ProvidesDirective node) { + return true; + } + /** * Visits the given type-specific AST node. *

@@ -1237,6 +1322,23 @@ public boolean visit(QualifiedType node) { return true; } + /** + * Visits the given type-specific AST node. + *

+ * The default implementation does nothing and return true. + * Subclasses may re-implement. + *

+ * + * @param node the node to visit + * @return true if the children of this node should be + * visited, and false if the children of this node should + * be skipped + * @since 3.14 + */ + public boolean visit(RequiresDirective node) { + return true; + } + /** * Visits the given type-specific AST node. *

@@ -1633,6 +1735,23 @@ public boolean visit(UnionType node) { return true; } + /** + * Visits the given type-specific AST node. + *

+ * The default implementation does nothing and return true. + * Subclasses may re-implement. + *

+ * + * @param node the node to visit + * @return true if the children of this node should be + * visited, and false if the children of this node should + * be skipped + * @since 3.14 + */ + public boolean visit(UsesDirective node) { + return true; + } + /** * Visits the given type-specific AST node. *

@@ -2050,6 +2169,19 @@ public void endVisit(EnumDeclaration node) { // default implementation: do nothing } + /** + * End of visit the given type-specific AST node. + *

+ * The default implementation does nothing. Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @since 3.14 + */ + public void endVisit(ExportsDirective node) { + // default implementation: do nothing + } + /** * End of visit the given type-specific AST node. *

@@ -2341,6 +2473,32 @@ public void endVisit(Modifier node) { // default implementation: do nothing } + /** + * End of visit the given type-specific AST node. + *

+ * The default implementation does nothing. Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @since 3.14 + */ + public void endVisit(ModuleDeclaration node) { + // default implementation: do nothing + } + + /** + * End of visit the given type-specific AST node. + *

+ * The default implementation does nothing. Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @since 3.14 + */ + public void endVisit(ModuleModifier node) { + // default implementation: do nothing + } + /** * End of visit the given type-specific AST node. *

@@ -2391,6 +2549,19 @@ public void endVisit(NumberLiteral node) { // default implementation: do nothing } + /** + * End of visit the given type-specific AST node. + *

+ * The default implementation does nothing. Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @since 3.14 + */ + public void endVisit(OpensDirective node) { + // default implementation: do nothing + } + /** * End of visit the given type-specific AST node. *

@@ -2464,6 +2635,19 @@ public void endVisit(PrimitiveType node) { // default implementation: do nothing } + /** + * End of visit the given type-specific AST node. + *

+ * The default implementation does nothing. Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @since 3.14 + */ + public void endVisit(ProvidesDirective node) { + // default implementation: do nothing + } + /** * End of visit the given type-specific AST node. *

@@ -2489,6 +2673,19 @@ public void endVisit(QualifiedType node) { // default implementation: do nothing } + /** + * End of visit the given type-specific AST node. + *

+ * The default implementation does nothing. Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @since 3.14 + */ + public void endVisit(RequiresDirective node) { + // default implementation: do nothing + } + /** * End of visit the given type-specific AST node. *

@@ -2784,6 +2981,19 @@ public void endVisit(UnionType node) { // default implementation: do nothing } + /** + * End of visit the given type-specific AST node. + *

+ * The default implementation does nothing. Subclasses may reimplement. + *

+ * + * @param node the node to visit + * @since 3.14 + */ + public void endVisit(UsesDirective node) { + // default implementation: do nothing + } + /** * End of visit the given type-specific AST node. *

diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java index 4d33f984a8..626f1779d3 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -75,7 +75,7 @@ public final ChildListPropertyDescriptor getAnnotationsProperty() { */ AnnotatableType(AST ast) { super(ast); - if (ast.apiLevel >= AST.JLS8) { + if (ast.apiLevel >= AST.JLS8_INTERNAL) { this.annotations = new ASTNode.NodeList(getAnnotationsProperty()); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java index 0e8f6dbb6b..7ae703550b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 BEA Systems, Inc. + * Copyright (c) 2005, 2017 BEA Systems, Inc, IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -132,6 +132,11 @@ public IJavaElement getJavaElement() { if (methodBinding == null) return null; parentElement = methodBinding.getJavaElement(); break; + case ASTNode.MODULE_DECLARATION: + IModuleBinding moduleBinding = ((ModuleDeclaration) parent).resolveBinding(); + if (moduleBinding == null) return null; + parentElement = moduleBinding.getJavaElement(); + break; case ASTNode.VARIABLE_DECLARATION_STATEMENT: fragment = (VariableDeclarationFragment) ((VariableDeclarationStatement) parent).fragments().get(0); variableBinding = fragment.resolveBinding(); @@ -178,6 +183,8 @@ private String getRecipientKey() { return fragment.resolveBinding().getKey(); case ASTNode.METHOD_DECLARATION: return ((MethodDeclaration) recipient).resolveBinding().getKey(); + case ASTNode.MODULE_DECLARATION: + return ((ModuleDeclaration) recipient).resolveBinding().getKey(); case ASTNode.VARIABLE_DECLARATION_STATEMENT: fragment = (VariableDeclarationFragment) ((VariableDeclarationStatement) recipient).fragments().get(0); return fragment.resolveBinding().getKey(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java index 7c4f63be23..6873d00a5f 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java @@ -144,7 +144,7 @@ public static List propertyDescriptors(int apiLevel) { */ ArrayType(AST ast) { super(ast); - if (ast.apiLevel >= AST.JLS8) { + if (ast.apiLevel >= AST.JLS8_INTERNAL) { this.dimensions = new ASTNode.NodeList(DIMENSIONS_PROPERTY); // single dimension array is the default this.dimensions().add(this.ast.newDimension()); @@ -224,7 +224,7 @@ final int getNodeType0() { */ ASTNode clone0(AST target) { ArrayType result; - if (this.ast.apiLevel < AST.JLS8) { + if (this.ast.apiLevel < AST.JLS8_INTERNAL) { result = new ArrayType(target); result.setComponentType((Type) getComponentType().clone(target)); } else { @@ -252,7 +252,7 @@ void accept0(ASTVisitor visitor) { boolean visitChildren = visitor.visit(this); if (visitChildren) { // visit children in normal left to right reading order - if (this.ast.apiLevel < AST.JLS8) { + if (this.ast.apiLevel < AST.JLS8_INTERNAL) { acceptChild(visitor, getComponentType()); } else { acceptChild(visitor, getElementType()); @@ -332,7 +332,7 @@ private void internalSetType(Type componentType, ChildPropertyDescriptor propert * @return the element type node */ public Type getElementType() { - if (this.ast.apiLevel() < AST.JLS8) { + if (this.ast.apiLevel() < AST.JLS8_INTERNAL) { Type t = getComponentType(); while (t.isArrayType()) { t = ((ArrayType) t).getComponentType(); @@ -376,7 +376,7 @@ public void setElementType(Type type) { * @return the number of dimensions (always positive) */ public int getDimensions() { - if (this.ast.apiLevel() >= AST.JLS8) { + if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) { return dimensions().size(); } Type t = getComponentType(); @@ -419,7 +419,7 @@ int memSize() { int treeSize() { return memSize() - + (this.type == null ? 0 : (this.ast.apiLevel() < AST.JLS8 ? getComponentType().treeSize() : getElementType().treeSize()) + + (this.type == null ? 0 : (this.ast.apiLevel() < AST.JLS8_INTERNAL ? getComponentType().treeSize() : getElementType().treeSize()) + (this.dimensions == null ? 0 : this.dimensions.listSize())); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java index d450161972..7b03581859 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2013 IBM Corporation and others. + * Copyright (c) 2004, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -101,6 +101,13 @@ static boolean isEqual(Binding declaringElement, Binding declaringElement2, Hash return importBinding.isStatic() == importBinding2.isStatic() && importBinding.onDemand == importBinding2.onDemand && CharOperation.equals(importBinding.compoundName, importBinding2.compoundName); + } else if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.ModuleBinding) { + if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.ModuleBinding)) { + return false; + } + org.eclipse.jdt.internal.compiler.lookup.ModuleBinding moduleBinding = (org.eclipse.jdt.internal.compiler.lookup.ModuleBinding) declaringElement; + org.eclipse.jdt.internal.compiler.lookup.ModuleBinding moduleBinding2 = (org.eclipse.jdt.internal.compiler.lookup.ModuleBinding) declaringElement2; + return isEqual(moduleBinding, moduleBinding2); } return false; } @@ -125,6 +132,18 @@ && isEqual(methodBinding.typeVariables, methodBinding2.typeVariables, visitedTyp && isEqual(methodBinding.parameters, methodBinding2.parameters, visitedTypes); } + /* + * Assumption here is that there is only one module with the same name. + */ + static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.ModuleBinding moduleBinding, + org.eclipse.jdt.internal.compiler.lookup.ModuleBinding moduleBinding2) { + if (moduleBinding == null) + return moduleBinding2 == null; + if (moduleBinding2 == null) + return false; + return CharOperation.equals(moduleBinding.moduleName, moduleBinding2.moduleName); + } + static boolean isEqual(VariableBinding variableBinding, VariableBinding variableBinding2) { return (variableBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (variableBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag) && CharOperation.equals(variableBinding.name, variableBinding2.name) diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java index 2776bb31f4..4a707c49a5 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -153,6 +153,21 @@ IMemberValuePairBinding getMemberValuePairBinding(ElementValuePair valuePair) { return null; } + /** + * Returns the new module binding corresponding to the given old module binding. + *

+ * The default implementation of this method returns null. + * Subclasses may reimplement. + *

+ * + * @param moduleBinding the old module binding + * @return the new module binding + * + */ + IModuleBinding getModuleBinding(org.eclipse.jdt.internal.compiler.lookup.ModuleBinding moduleBinding) { + return null; + } + /** * Returns the new package binding corresponding to the given old package binding. *

@@ -661,6 +676,29 @@ IMethodBinding resolveMethod(SuperMethodInvocation method) { return null; } + /** + * Resolves the given module declaration and returns the binding for it. + *

+ * The implementation of ModuleDeclaration.resolveBinding + * forwards to this method. How the method resolves is often a function of + * the context in which the method declaration node is embedded as well as + * the method declaration subtree itself. + *

+ *

+ * The default implementation of this method returns null. + * Subclasses may reimplement. + *

+ * + * @param module declaration of interest + * @return the binding for the given module declaration, or + * null if no binding is available + * + * @since 3.14 + */ + IModuleBinding resolveModule(ModuleDeclaration module) { + return null; + } + /** * Resolves the given name and returns the type binding for it. *

diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java index e12487eef9..d36d6360b7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -29,19 +29,29 @@ /** * Java compilation unit AST node type. This is the type of the root of an AST. + * In JLS9 and later, this node can also contain a ModuleDeclaration (with a completely different grammar). *

* The source range for this type of node is ordinarily the entire source file, * including leading and trailing whitespace and comments. *

*
  * CompilationUnit:
- *    [ PackageDeclaration ]
- *        { ImportDeclaration }
- *        { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | ; }
+ *     OrdinaryCompilationUnit
+ *     ModularCompilationUnit
+ *     
+ * OrdinaryCompilationUnit:
+ *     [ PackageDeclaration ]
+ *         { ImportDeclaration }
+ *         { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | ; }
+ * 
+ * ModularCompilationUnit:
+ *     {ImportDeclaration}
+ *         ModuleDeclaration
  * 
* * @since 2.0 * @noinstantiate This class is not intended to be instantiated by clients. + * @noextend This class is not intended to be subclassed by clients. */ @SuppressWarnings({ "rawtypes", "unchecked" }) public class CompilationUnit extends ASTNode { @@ -72,6 +82,14 @@ public class CompilationUnit extends ASTNode { public static final ChildPropertyDescriptor PACKAGE_PROPERTY = new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$ + /** + * The "module" structural property of this node type (child type: {@link ModuleDeclaration}) (added in JLS9 API). + * + * @since 3.14 + */ + public static final ChildPropertyDescriptor MODULE_PROPERTY = + new ChildPropertyDescriptor(CompilationUnit.class, "module", ModuleDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$ + /** * A list of property descriptors (element type: * {@link StructuralPropertyDescriptor}), @@ -80,6 +98,14 @@ public class CompilationUnit extends ASTNode { */ private static final List PROPERTY_DESCRIPTORS; + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + * @since 3.14 + */ + private static final List PROPERTY_DESCRIPTORS_9_0; + /** * The "types" structural property of this node type (element type: {@link AbstractTypeDeclaration}). * @@ -95,6 +121,14 @@ public class CompilationUnit extends ASTNode { addProperty(IMPORTS_PROPERTY, properyList); addProperty(TYPES_PROPERTY, properyList); PROPERTY_DESCRIPTORS = reapPropertyList(properyList); + + properyList = new ArrayList(5); + createPropertyList(CompilationUnit.class, properyList); + addProperty(PACKAGE_PROPERTY, properyList); + addProperty(IMPORTS_PROPERTY, properyList); + addProperty(TYPES_PROPERTY, properyList); + addProperty(MODULE_PROPERTY, properyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList); } /** @@ -109,7 +143,10 @@ public class CompilationUnit extends ASTNode { * @since 3.0 */ public static List propertyDescriptors(int apiLevel) { - return PROPERTY_DESCRIPTORS; + if (apiLevel < AST.JLS9_INTERNAL) + return PROPERTY_DESCRIPTORS; + else + return PROPERTY_DESCRIPTORS_9_0; } /** @@ -168,11 +205,16 @@ public static List propertyDescriptors(int apiLevel) { */ private PackageDeclaration optionalPackageDeclaration = null; + /** + * The module declaration, or null if none; initially + * null. + */ + private ModuleDeclaration module = null; /** * Problems reported by the compiler during parsing or name resolution. */ private IProblem[] problems = EMPTY_PROBLEMS; - + /** * Internal data used to perform statements recovery. */ @@ -210,6 +252,9 @@ void accept0(ASTVisitor visitor) { boolean visitChildren = visitor.visit(this); if (visitChildren) { // visit children in normal left to right reading order + if (this.ast.apiLevel >= AST.JLS9_INTERNAL) { + acceptChild(visitor, getModule()); + } acceptChild(visitor, getPackage()); acceptChildren(visitor, this.imports); acceptChildren(visitor, this.types); @@ -224,6 +269,9 @@ ASTNode clone0(AST target) { CompilationUnit result = new CompilationUnit(target); // n.b do not copy line number table or messages result.setSourceRange(getStartPosition(), getLength()); + if (this.ast.apiLevel >= AST.JLS9_INTERNAL) { + result.setModule((ModuleDeclaration) ASTNode.copySubtree(target, getModule())); + } result.setPackage( (PackageDeclaration) ASTNode.copySubtree(target, getPackage())); result.imports().addAll(ASTNode.copySubtrees(target, imports())); @@ -539,6 +587,18 @@ final int getNodeType0() { return COMPILATION_UNIT; } + /** + * Returns the node for the module declaration of this compilation + * unit, or null if this compilation unit is not a module info. + * + * @return the module declaration node, or null if none + * @since 3.14 + */ + public ModuleDeclaration getModule() { + unsupportedBelow9(); + return this.module; + } + /** * Returns the node for the package declaration of this compilation * unit, or null if this compilation unit is in the @@ -719,6 +779,14 @@ final List internalGetChildListProperty(ChildListPropertyDescriptor property) { * Method declared on ASTNode. */ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == MODULE_PROPERTY) { + if (get) { + return getModule(); + } else { + setModule((ModuleDeclaration) child); + return null; + } + } if (property == PACKAGE_PROPERTY) { if (get) { return getPackage(); @@ -1002,6 +1070,28 @@ void setLineEndTable(int[] lineEndTable) { this.lineEndTable = lineEndTable; } + /** + * Sets or clears the module declaration of this compilation unit + * node to the given module declaration node. + * + * @param module the new module declaration node, or + * null if this compilation unit does not have a module + * @exception IllegalArgumentException if: + *
    + *
  • the node belongs to a different AST
  • + *
  • the node already has a parent
  • + *
+ * @exception UnsupportedOperationException if this operation is used below JLS9 + * @since 3.14 + */ + public void setModule(ModuleDeclaration module) { + unsupportedBelow9(); + ASTNode oldChild = this.module; + preReplaceChild(oldChild, module, MODULE_PROPERTY); + this.module = module; + postReplaceChild(oldChild, module, MODULE_PROPERTY); + } + /** * Sets or clears the package declaration of this compilation unit * node to the given package declaration node. @@ -1061,6 +1151,9 @@ final boolean subtreeMatch0(ASTMatcher matcher, Object other) { */ int treeSize() { int size = memSize(); + if (this.module != null) { + size += getModule().treeSize(); + } if (this.optionalPackageDeclaration != null) { size += getPackage().treeSize(); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java index 704cdf49a4..406f1798b2 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -60,6 +60,7 @@ import org.eclipse.jdt.internal.compiler.util.Messages; import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.jdt.internal.core.BinaryMember; +import org.eclipse.jdt.internal.core.BinaryModule; import org.eclipse.jdt.internal.core.CancelableNameEnvironment; import org.eclipse.jdt.internal.core.CancelableProblemFactory; import org.eclipse.jdt.internal.core.INameEnvironmentWithProgress; @@ -252,7 +253,9 @@ else if (existing instanceof ArrayList) } else { char[] key = resolver.hasTypeName() ? resolver.getKey().toCharArray() // binary binding - : CharOperation.concatWith(resolver.compoundName(), '.'); // package binding or base type binding + : resolver.hasModuleName() + ? resolver.moduleName() + : CharOperation.concatWith(resolver.compoundName(), '.'); // package binding or base type binding this.requestedKeys.put(key, resolver); } worked(1); @@ -779,6 +782,8 @@ else if (element instanceof LocalVariable) key = ((LocalVariable) element).getKey(true/*open to get resolved info*/); else if (element instanceof org.eclipse.jdt.internal.core.TypeParameter) key = ((org.eclipse.jdt.internal.core.TypeParameter) element).getKey(true/*open to get resolved info*/); + else if (element instanceof BinaryModule) + key = ((BinaryModule) element).getKey(true); else throw new IllegalArgumentException(element + " has an unexpected type"); //$NON-NLS-1$ binaryElementPositions.put(key, i); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java index 326f07111b..7b501e7e06 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -183,6 +183,12 @@ public void endVisit(MethodRefParameter node) { public void endVisit(Modifier node) { endVisitNode(node); } + public void endVisit(ModuleDeclaration node) { + endVisitNode(node); + } + public void endVisit(ModuleDirective node) { + endVisitNode(node); + } public void endVisit(NameQualifiedType node) { endVisitNode(node); } @@ -468,6 +474,12 @@ public boolean visit(MethodRef node) { public boolean visit(Modifier node) { return visitNode(node); } + public boolean visit(ModuleDeclaration node) { + return visitNode(node); + } + public boolean visit(ModuleDirective node) { + return visitNode(node); + } public boolean visit(MethodRefParameter node) { return visitNode(node); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java index 6e07687512..fb6313aabb 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -39,6 +39,7 @@ import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MessageSend; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference; @@ -229,6 +230,8 @@ IBinding getBinding(org.eclipse.jdt.internal.compiler.lookup.Binding binding) { return new TypeBinding(this, (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) binding); case Binding.METHOD: return getMethodBinding((org.eclipse.jdt.internal.compiler.lookup.MethodBinding) binding); + case Binding.MODULE: + return getModuleBinding((org.eclipse.jdt.internal.compiler.lookup.ModuleBinding) binding); case Binding.FIELD: case Binding.LOCAL: return getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding); @@ -296,6 +299,20 @@ synchronized IMemberValuePairBinding getMemberValuePairBinding(ElementValuePair return binding; } + /** + * @see org.eclipse.jdt.core.dom.BindingResolver#getModuleBinding(org.eclipse.jdt.internal.compiler.lookup.ModuleBinding) + */ + synchronized IModuleBinding getModuleBinding(org.eclipse.jdt.internal.compiler.lookup.ModuleBinding moduleBinding) { + if (moduleBinding != null) { + IModuleBinding binding = (IModuleBinding) this.bindingTables.compilerBindingsToASTBindings.get(moduleBinding); + if (binding == null) { + binding = new ModuleBinding(this, moduleBinding); + this.bindingTables.compilerBindingsToASTBindings.put(moduleBinding, binding); + } + return binding; + } + return null; + } /* * Method declared on BindingResolver. */ @@ -1155,6 +1172,8 @@ synchronized ITypeBinding resolveTypeBindingForName(Name name) { } } } else if (node instanceof ImportReference) { + if ((node.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.inModule) != 0) + return null; ImportReference importReference = (ImportReference) node; int importReferenceLength = importReference.tokens.length; if (index >= 0) { @@ -1373,10 +1392,11 @@ synchronized IBinding resolveName(Name name) { } else if (node instanceof ImportReference) { ImportReference importReference = (ImportReference) node; int importReferenceLength = importReference.tokens.length; + boolean inModule = (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.inModule) != 0; if (index >= 0) { Binding binding = null; if (this.scope == null) return null; - if (importReferenceLength == index) { + if (importReferenceLength == index && !inModule) { try { binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OnDemand) != 0, importReference.isStatic()); } catch (AbortCompilation e) { @@ -1384,7 +1404,7 @@ synchronized IBinding resolveName(Name name) { } } else { try { - binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic()); + binding = this.scope.getImport(inModule ? importReference.tokens : CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic()); } catch (AbortCompilation e) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357 } @@ -1425,6 +1445,18 @@ synchronized IBinding resolveName(Name name) { if (methodBinding != null) { return methodBinding; } + } else if (node instanceof ModuleReference) { + ModuleReference moduleReference = (ModuleReference) node; + IModuleBinding moduleBinding = getModuleBinding(moduleReference.binding); + if (moduleBinding != null) { + return moduleBinding; + } + } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration) { + org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration moduleDeclaration = (org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration) node; + IModuleBinding moduleBinding = getModuleBinding(moduleDeclaration.binding); + if (moduleBinding != null) { + return moduleBinding; + } } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) { org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node; ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding); @@ -1589,6 +1621,30 @@ synchronized IMemberValuePairBinding resolveMemberValuePair(org.eclipse.jdt.core return null; } + /** + * @see BindingResolver#resolveModule(ModuleDeclaration) + * @since 3.14 + */ + @Override + IModuleBinding resolveModule(ModuleDeclaration module) { + Object oldNode = this.newAstToOldAst.get(module); + if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration) { + org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration moduleDeclaration = (org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration) oldNode; + IModuleBinding moduleBinding = getModuleBinding(moduleDeclaration.binding); + if (moduleBinding == null) { + return null; + } + this.bindingsToAstNodes.put(moduleBinding, module); + String key = moduleBinding.getKey(); + if (key != null) { + this.bindingTables.bindingKeysToBindings.put(key, moduleBinding); + } + return moduleBinding; + } + + return null; + } + /* (non-Javadoc) * @see BindingResolver#resolveReference(MethodRef) * @since 3.0 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java index 6bb53903a3..9f5dc885d7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java @@ -144,7 +144,7 @@ protected Object createArgumentReference(char[] name, int dim, boolean isVarargs } } argument.setType(argType); - if (this.ast.apiLevel > AST.JLS8) { + if (this.ast.apiLevel > AST.JLS8_INTERNAL) { argument.setVarargs(isVarargs); } argument.setSourceRange(argStart, argEnd - argStart + 1); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExportsDirective.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExportsDirective.java new file mode 100644 index 0000000000..7215c56d7a --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExportsDirective.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Exports directive AST node type (added in JLS9 API). + *
+ * ExportsDirective:
+ *     exports PackageName [ to  ModuleName {, ModuleName } ] ;
+ * 
+ * + * @since 3.14 + * + * @noextend This class is not intended to be subclassed by clients. + * @noinstantiate This class is not intended to be instantiated by clients. + */ +@SuppressWarnings({"rawtypes"}) +public class ExportsDirective extends ModulePackageAccess { + + /** + * The "name" structural property of this node type (child type: {@link Name}). + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + internalNamePropertyFactory(ExportsDirective.class); + + /** + * The "modules" structural property of this node type (element type: {@link Name}). + */ + public static final ChildListPropertyDescriptor MODULES_PROPERTY = + internalModulesPropertyFactory(ExportsDirective.class); + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_9_0; + + static { + List properyList = new ArrayList(3); + createPropertyList(ExportsDirective.class, properyList); + addProperty(NAME_PROPERTY, properyList); + addProperty(MODULES_PROPERTY, properyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * AST.JLS* constants + + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_9_0; + } + + /** + * Creates a new AST node for an export directive owned by the + * given AST. The export directive initially is a regular (non-targetted) + * single package export for an unspecified, but legal, Java package name. + *

+ * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + *

+ * + * @param ast the AST that is to own this node + */ + ExportsDirective(AST ast) { + super(ast); + } + + @Override + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + @Override + final ChildPropertyDescriptor internalNameProperty() { + return NAME_PROPERTY; + } + + @Override + final ChildListPropertyDescriptor internalModulesProperty() { + return MODULES_PROPERTY; + } + + @Override + final int getNodeType0() { + return EXPORTS_DIRECTIVE; + } + + @Override + ASTNode clone0(AST target) { + return cloneHelper(target, new ExportsDirective(target)); + } + + @Override + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + @Override + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + acceptVisitChildren(visitChildren, visitor); + visitor.endVisit(this); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java index 72927a08d8..b9a48e5ac1 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -88,6 +88,16 @@ public interface IBinding { */ public static final int MEMBER_VALUE_PAIR = 6; + /** + * Kind constant (value 7) indicating a module binding (added in JLS9 API). + * Bindings of this kind can be safely cast to IModuleBinding. + * + * @see #getKind() + * @see IModuleBinding + * @since 3.14 + */ + public static final int MODULE = 7; + /** * Returns the resolved declaration annotations associated with this binding. *
    @@ -123,7 +133,8 @@ public interface IBinding { * VARIABLE, * METHOD, * ANNOTATION, - * or MEMBER_VALUE_PAIR. + * MEMBER_VALUE_PAIR, or + * MODULE. *

    * Note that additional kinds might be added in the * future, so clients should not assume this list is exhaustive and diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IModuleBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IModuleBinding.java new file mode 100644 index 0000000000..127dd4784e --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IModuleBinding.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.jdt.core.dom; + +/** + * A module binding represents a module (added in JLS9 API). + * + * @since 3.14 + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IModuleBinding extends IBinding { + + @Override + public default int getKind() { + return IBinding.MODULE; + } + + /** + * Returns whether this module is open or not. + * + * @return true if open, false otherwise + */ + public abstract boolean isOpen(); + + /** + * Returns all required modules. + *

    The resulting bindings are in no particular order.

    + * + * @return all required modules + */ + public abstract IModuleBinding[] getRequiredModules(); + + /** + * Returns all exported packages. + *

    The resulting bindings are in no particular order.

    + * + * @return array of exported package bindings + */ + public abstract IPackageBinding[] getExportedPackages(); + + /** + * If this module exports the given package to specific modules, returns the array of names of + * modules, otherwise returns an empty array. + * + * @param packageBinding a package binding for which targeted modules are declared + * @return array of names of targeted modules + */ + public abstract String[] getExportedTo(IPackageBinding packageBinding); + + /** + * Returns all opened packages. + *

    The resulting bindings are in no particular order.

    + * + * @return array of package bindings + */ + public abstract IPackageBinding[] getOpenedPackages(); + + /** + * If this module opens the given package to specific modules, returns the array of names of + * modules, otherwise returns an empty array. + *

    The resulting bindings are in no particular order.

    + * + * @param packageBinding a package binding for which targeted modules are declared + * @return array of names of targeted modules + */ + public abstract String[] getOpenedTo(IPackageBinding packageBinding); + + /** + * Returns the services used by this module. + *

    The resulting bindings are in no particular order.

    + * + * @return array of type bindings + */ + public abstract ITypeBinding[] getUses(); + + /** + * Returns the services provided by this module. + *

    The resulting services are in no particular order.

    + * + * @return array of services + */ + public abstract ITypeBinding[] getServices(); + + /** + * Returns the implementations that implement the given service in this module. + * + * @return array of implementation type bindings, in declaration order + */ + public abstract ITypeBinding[] getImplementations(ITypeBinding service); +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java index d98778efc1..0603d9e8d0 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,7 +14,7 @@ package org.eclipse.jdt.core.dom; /** - * A type binding represents fully-resolved type. There are a number of + * A type binding represents a fully-resolved type. There are a number of * different kinds of type bindings: *
      *
    • a class - represents the class declaration; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java index c8eedbfa84..88fce6cc96 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java @@ -254,7 +254,7 @@ public class MethodDeclaration extends BodyDeclaration { public static List propertyDescriptors(int apiLevel) { if (apiLevel == AST.JLS2_INTERNAL) { return PROPERTY_DESCRIPTORS_2_0; - } else if (apiLevel < AST.JLS8) { + } else if (apiLevel < AST.JLS8_INTERNAL) { return PROPERTY_DESCRIPTORS_3_0; } else { return PROPERTY_DESCRIPTORS_8_0; @@ -379,7 +379,7 @@ public static List propertyDescriptors(int apiLevel) { if (ast.apiLevel >= AST.JLS3_INTERNAL) { this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY); } - if (ast.apiLevel < AST.JLS8) { + if (ast.apiLevel < AST.JLS8_INTERNAL) { this.thrownExceptions = new ASTNode.NodeList(THROWN_EXCEPTIONS_PROPERTY); } else { this.extraDimensions = new ASTNode.NodeList(EXTRA_DIMENSIONS2_PROPERTY); @@ -575,18 +575,18 @@ ASTNode clone0(AST target) { } result.setConstructor(isConstructor()); result.setName((SimpleName) getName().clone(target)); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.setReceiverType((Type) ASTNode.copySubtree(target, getReceiverType())); result.setReceiverQualifier((SimpleName) ASTNode.copySubtree(target, getReceiverQualifier())); } result.parameters().addAll( ASTNode.copySubtrees(target, parameters())); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.extraDimensions().addAll(ASTNode.copySubtrees(target, extraDimensions())); } else { result.setExtraDimensions(getExtraDimensions()); } - if (this.ast.apiLevel() >= AST.JLS8) { + if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) { result.thrownExceptionTypes().addAll(ASTNode.copySubtrees(target, thrownExceptionTypes())); } else { result.thrownExceptions().addAll(ASTNode.copySubtrees(target, thrownExceptions())); @@ -621,12 +621,12 @@ void accept0(ASTVisitor visitor) { } // n.b. visit return type even for constructors acceptChild(visitor, getName()); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { acceptChild(visitor, this.optionalReceiverType); acceptChild(visitor, this.optionalReceiverQualifier); } acceptChildren(visitor, this.parameters); - if (this.ast.apiLevel() >= AST.JLS8) { + if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) { acceptChildren(visitor, this.extraDimensions); acceptChildren(visitor, this.thrownExceptionTypes); } else { @@ -1169,7 +1169,7 @@ int treeSize() { + (this.optionalReceiverQualifier == null ? 0 : this.optionalReceiverQualifier.treeSize()) + (this.returnType == null ? 0 : this.returnType.treeSize()) + this.parameters.listSize() - + (this.ast.apiLevel < AST.JLS8 + + (this.ast.apiLevel < AST.JLS8_INTERNAL ? this.thrownExceptions.listSize() : this.extraDimensions.listSize() + this.thrownExceptionTypes.listSize()) + (this.optionalBody == null ? 0 : getBody().treeSize()); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleBinding.java new file mode 100644 index 0000000000..7cdae1fd91 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleBinding.java @@ -0,0 +1,237 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.Arrays; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.util.Util; +import org.eclipse.jdt.internal.core.NameLookup; +import org.eclipse.jdt.internal.core.NameLookup.Answer; +import org.eclipse.jdt.internal.core.SearchableEnvironment; + +/** + * Internal implementation of module bindings. + * @since 3.14 + */ +class ModuleBinding implements IModuleBinding { + + protected static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0]; + private String name = null; + private volatile String key; + private boolean isOpen = false; + + private org.eclipse.jdt.internal.compiler.lookup.ModuleBinding binding; + protected BindingResolver resolver; + + private IAnnotationBinding[] annotations; + private IModuleBinding[] requiredModules; + private IPackageBinding[] exports; // cached + private IPackageBinding[] opens; // cached + private ITypeBinding[] uses; // cached + private ITypeBinding[] services; // cached + + ModuleBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.ModuleBinding binding) { + this.resolver = resolver; + this.binding = binding; + this.isOpen = binding.isOpen(); + } + + @Override + public IAnnotationBinding[] getAnnotations() { + if (this.annotations == null) { + this.annotations = resolveAnnotationBindings(this.binding.getAnnotations()); + } + return this.annotations; + } + + private IAnnotationBinding[] resolveAnnotationBindings(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations) { + int length = internalAnnotations == null ? 0 : internalAnnotations.length; + if (length != 0) { + IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length]; + int convertedAnnotationCount = 0; + for (int i = 0; i < length; i++) { + org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i]; + if (internalAnnotation == null) + break; + IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation); + if (annotationInstance == null) + continue; + tempAnnotations[convertedAnnotationCount++] = annotationInstance; + } + if (convertedAnnotationCount != length) { + if (convertedAnnotationCount == 0) { + return this.annotations = AnnotationBinding.NoAnnotations; + } + System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount); + } + return tempAnnotations; + } + return AnnotationBinding.NoAnnotations; + } + + @Override + public String getName() { + if (this.name == null) { + char[] tmp = this.binding.moduleName; + return tmp != null && tmp.length != 0 ? new String(tmp) : Util.EMPTY_STRING; + } + return this.name; + } + + @Override + public int getModifiers() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean isDeprecated() { + return false; + } + + @Override + public boolean isRecovered() { + return false; + } + + @Override + public boolean isSynthetic() { + // TODO Auto-generated method stub + // TODO Java 9 no reference seen in jvms draft - only in sotm + // check on version change and after compiler ast implements isSynthetic return this.binding.isSynthetic(); + + return false; + } + + @Override + public IJavaElement getJavaElement() { + INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; + if (!(nameEnvironment instanceof SearchableEnvironment)) return null; + NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup; + if (nameLookup == null) return null; + Answer answer = nameLookup.findModule(this.getName().toCharArray()); + if (answer == null) return null; + return answer.module; + } + + @Override + public String getKey() { + if (this.key == null) { + char[] k = this.binding.computeUniqueKey(); + this.key = k == null || k == CharOperation.NO_CHAR ? Util.EMPTY_STRING : new String(k); + } + return this.key; + } + + @Override + public boolean isEqualTo(IBinding other) { + if (other == this) // identical binding - equal (key or no key) + return true; + if (other == null) // other binding missing + return false; + + if (!(other instanceof ModuleBinding)) + return false; + + org.eclipse.jdt.internal.compiler.lookup.ModuleBinding otherBinding = ((ModuleBinding) other).binding; + return BindingComparator.isEqual(this.binding, otherBinding); + } + + @Override + public boolean isOpen() { + return this.isOpen; + } + @Override + public IModuleBinding[] getRequiredModules() { + if (this.requiredModules != null) + return this.requiredModules; + + org.eclipse.jdt.internal.compiler.lookup.ModuleBinding[] reqs = this.binding.getRequires(); + IModuleBinding[] result = new IModuleBinding[reqs != null ? reqs.length : 0]; + for (int i = 0, l = result.length; i < l; ++i) { + org.eclipse.jdt.internal.compiler.lookup.ModuleBinding req = reqs[i]; + result[i] = req != null ? this.resolver.getModuleBinding(req) : null; + } + return this.requiredModules = result; + } + + @Override + public IPackageBinding[] getExportedPackages() { + if (this.exports == null) { + org.eclipse.jdt.internal.compiler.lookup.PackageBinding[] compilerExports = this.binding.getExports(); + this.exports = Arrays.stream(compilerExports) + .map(e -> this.resolver.getPackageBinding(e)) + .toArray(IPackageBinding[]::new); + } + return this.exports; + } + + @Override + public String[] getExportedTo(IPackageBinding packageBinding) { + return this.binding.getExportRestrictions(((PackageBinding) packageBinding).getCompilerBinding()); + } + + @Override + public IPackageBinding[] getOpenedPackages() { + if (this.opens == null) { + org.eclipse.jdt.internal.compiler.lookup.PackageBinding[] compilerOpens = this.binding.getOpens(); + this.opens = Arrays.stream(compilerOpens) + .map(o -> this.resolver.getPackageBinding(o)) + .toArray(IPackageBinding[]::new); + } + return this.opens; + } + + @Override + public String[] getOpenedTo(IPackageBinding packageBinding) { + return this.binding.getOpenRestrictions(((PackageBinding) packageBinding).getCompilerBinding()); + } + + /* + * helper method + */ + private ITypeBinding[] getTypes(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] types) { + int length = types == null ? 0 : types.length; + TypeBinding[] result = new TypeBinding[length]; + for (int i = 0; i < length; ++i) { + result[i] = (TypeBinding) this.resolver.getTypeBinding(types[i]); + } + return result; + } + + @Override + public ITypeBinding[] getUses() { + if (this.uses == null) + this.uses = getTypes(this.binding.getUses()); + return this.uses; + } + + @Override + public ITypeBinding[] getServices() { + if (this.services == null) + this.services = getTypes(this.binding.getServices()); + return this.services; + } + @Override + public ITypeBinding[] getImplementations(ITypeBinding service) { + return getTypes(this.binding.getImplementations(((TypeBinding) service).binding)); + } + /** + * For debugging purpose only. + * @see java.lang.Object#toString() + */ + public String toString() { + return this.binding.toString(); + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDeclaration.java new file mode 100644 index 0000000000..e876e01ef3 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDeclaration.java @@ -0,0 +1,364 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Module declaration AST node type representing the module descriptor file (added in JLS9 API). + * + *
      + * ModuleDeclaration:
      + *  [ Javadoc ] { Annotation } [ open ] module Name {
      + *        { RequiresDirective | ExportsDirective | OpensDirective | UsesDirective | ProvidesDirective }
      + *  }
      + * 
      + *

      + *

      + * + * @since 3.14 + * + * @noextend This class is not intended to be subclassed by clients. + * @noinstantiate This class is not intended to be instantiated by clients. + */ +@SuppressWarnings("rawtypes") +public class ModuleDeclaration extends ASTNode { + + /** + * The "javadoc" structural property of this node type (child type: {@link Javadoc}). + */ + public static final ChildPropertyDescriptor JAVADOC_PROPERTY = + new ChildPropertyDescriptor(ModuleDeclaration.class, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "annotations" structural property of this node type (element type: {@link Annotation}). + */ + public static final ChildListPropertyDescriptor ANNOTATIONS_PROPERTY = + new ChildListPropertyDescriptor(ModuleDeclaration.class, "annotations", Annotation.class, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "open" structural property of this node type (type: {@link Boolean}). + */ + public static final SimplePropertyDescriptor OPEN_PROPERTY = + new SimplePropertyDescriptor(ModuleDeclaration.class, "open", boolean.class, MANDATORY); //$NON-NLS-1$ + + /** + * The "name" structural property of this node type (child type: {@link Name}). + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + new ChildPropertyDescriptor(ModuleDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "moduleDirectives" structural property of this node type (element type: {@link ModuleDirective}). + */ + public static final ChildListPropertyDescriptor MODULE_DIRECTIVES_PROPERTY = + new ChildListPropertyDescriptor(ModuleDeclaration.class, "moduleDirectives", ModuleDirective.class, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_9_0; + + static { + List properyList = new ArrayList(6); + createPropertyList(ModuleDeclaration.class, properyList); + addProperty(JAVADOC_PROPERTY, properyList); + addProperty(ANNOTATIONS_PROPERTY, properyList); + addProperty(OPEN_PROPERTY, properyList); + addProperty(NAME_PROPERTY, properyList); + addProperty(MODULE_DIRECTIVES_PROPERTY, properyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * AST.JLS* constants + + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_9_0; + } + + /** + * The doc comment, or null if none. + * Defaults to none. + */ + private Javadoc optionalDocComment = null; + + /** + * The annotations (element type: {@link Annotation}). + * Defaults to an empty list. + * + */ + private ASTNode.NodeList annotations = new ASTNode.NodeList(ANNOTATIONS_PROPERTY); + + /** + * open versus normal; defaults to normal module. + */ + private boolean isOpen = false; + + /** + * The referenced module name; lazily initialized; defaults to a unspecified, + * legal Java identifier. + */ + private Name name = null; + + /** + * The list of statements (element type: {@link ModuleDirective}). + * Defaults to an empty list. + */ + private ASTNode.NodeList moduleStatements = new ASTNode.NodeList(MODULE_DIRECTIVES_PROPERTY); + + ModuleDeclaration(AST ast) { + super(ast); + unsupportedBelow9(); + } + + @Override + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) { + if (property == OPEN_PROPERTY) { + if (get) { + return isOpen(); + } else { + setOpen(value); + return false; + } + } + // allow default implementation to flag the error + return super.internalGetSetBooleanProperty(property, get, value); + } + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == JAVADOC_PROPERTY) { + if (get) { + return getJavadoc(); + } else { + setJavadoc((Javadoc) child); + return null; + } + } + if (property == NAME_PROPERTY) { + if (get) { + return getName(); + } else { + setName((Name) child); + return null; + } + } + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == ANNOTATIONS_PROPERTY) { + return annotations(); + } + if (property == MODULE_DIRECTIVES_PROPERTY) { + return moduleStatements(); + } + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + @Override + int getNodeType0() { + return MODULE_DECLARATION; + } + + @SuppressWarnings("unchecked") + @Override + ASTNode clone0(AST target) { + ModuleDeclaration result = new ModuleDeclaration(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setJavadoc((Javadoc) ASTNode.copySubtree(target, getJavadoc())); + result.setOpen(isOpen()); + result.annotations().addAll(ASTNode.copySubtrees(target, annotations())); + result.setName((SimpleName) getName().clone(target)); + result.moduleStatements().addAll(ASTNode.copySubtrees(target, moduleStatements())); + return result; + } + + @Override + boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + @Override + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + // visit children in normal left to right reading order + acceptChild(visitor, getJavadoc()); + acceptChildren(visitor, this.annotations); + acceptChild(visitor, getName()); + acceptChildren(visitor, this.moduleStatements); + } + visitor.endVisit(this); + + } + /** + * Returns the doc comment node. + * + * @return the doc comment node, or null if none + */ + public Javadoc getJavadoc() { + return this.optionalDocComment; + } + + /** + * Sets or clears the doc comment node. + * + * @param docComment the doc comment node, or null if none + * @exception IllegalArgumentException if the doc comment string is invalid + */ + public void setJavadoc(Javadoc docComment) { + ChildPropertyDescriptor p = JAVADOC_PROPERTY; + ASTNode oldChild = this.optionalDocComment; + preReplaceChild(oldChild, docComment, p); + this.optionalDocComment = docComment; + postReplaceChild(oldChild, docComment, p); + } + + /** + * Returns the live ordered list of annotations + * of this declaration. + * + * @return the live list of annotations + * (element type: {@link Annotation}) + */ + public List annotations() { + return this.annotations; + } + + /** + * Returns whether this module declaration is open or not. + * + * @return true if this is open, else + * false + */ + public boolean isOpen() { + return this.isOpen; + } + + /** + * Sets whether this module declaration is open or not. + * + * @param isOpen true if this is an open module, + * and false if not + */ + public void setOpen(boolean isOpen) { + preValueChange(OPEN_PROPERTY); + this.isOpen = isOpen; + postValueChange(OPEN_PROPERTY); + } + + /** + * Returns the name of this module declaration. + * + * @return the module name + */ + public Name getName() { + if (this.name == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.name == null) { + preLazyInit(); + this.name =this.ast.newQualifiedName( + new SimpleName(this.ast), new SimpleName(this.ast)); + postLazyInit(this.name, NAME_PROPERTY); + } + } + } + return this.name; + } + + /** + * Sets the module name in to the given name. + * + * @param name the new module name + * @exception IllegalArgumentException if: + *
        + *
      • the node belongs to a different AST
      • + *
      • the node already has a parent
      • + *
      + */ + public void setName(Name name) { + if (name == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.name; + preReplaceChild(oldChild, name, NAME_PROPERTY); + this.name = name; + postReplaceChild(oldChild, name, NAME_PROPERTY); + } + + /** + * Returns the live list of statements in this module. Adding and + * removing nodes from this list affects this node dynamically. + * All nodes in this list must be ModuleDirectives; + * attempts to add any other type of node will trigger an + * exception. + * + * @return the live list of statements in this module declaration + * (element type: {@link ModuleDirective}) + */ + public List moduleStatements() { + return this.moduleStatements; + } + + /** + * Resolves and returns the binding for the module. + *

      + * Note that bindings are generally unavailable unless requested when the + * AST is being built. + *

      + * + * @return the binding, or null if the binding cannot be + * resolved + */ + public IModuleBinding resolveBinding() { + return this.ast.getBindingResolver().resolveModule(this); + } + + @Override + int memSize() { + return BASE_NODE_SIZE + 5 * 4; + } + + @Override + int treeSize() { + return memSize() + + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize()) + + this.annotations.listSize() + + (this.name == null ? 0 : getName().treeSize()) + + this.moduleStatements.listSize(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDirective.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDirective.java new file mode 100644 index 0000000000..67a05a7872 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDirective.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +/** + * Abstract base class of AST nodes that represent module directives (added in JLS9 API). + * + *
      + * ModuleDirective:
      + *    {@link RequiresDirective}
      + *    {@link ExportsDirective}
      + *    {@link OpensDirective}
      + *    {@link UsesDirective}
      + *    {@link ProvidesDirective}
      + * 
      + * + * @noextend This class is not intended to be subclassed by clients. + * @since 3.14 + */ +public abstract class ModuleDirective extends ASTNode { + + ModuleDirective(AST ast) { + super(ast); + unsupportedBelow9(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleModifier.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleModifier.java new file mode 100644 index 0000000000..59d7807d3f --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleModifier.java @@ -0,0 +1,360 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Module Modifier node - represents the modifiers for the requires directive in module declaration (added in JLS9 API). + *
      + * ModuleModifier:
      + *    static
      + *    transitive
      + * 
      + *

      + * The numeric values of these flags match the ones for class + * files as described in the Java Virtual Machine Specification. + * Note that the value of static does not correspond to the value of {@link Modifier#STATIC}! + *

      + * + * @since 3.14 + * @noinstantiate This class is not intended to be instantiated by clients. + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public final class ModuleModifier extends ASTNode { + + /** + * Module Modifier keywords (typesafe enumeration). + */ + public static class ModuleModifierKeyword { + + /** "static" modifier with flag value {@link ModuleModifier#STATIC_PHASE}. */ + public static final ModuleModifierKeyword STATIC_KEYWORD = new ModuleModifierKeyword("static", STATIC_PHASE);//$NON-NLS-1$ + + /** "transitive" modifier with flag value {@link ModuleModifier#TRANSITIVE}. */ + public static final ModuleModifierKeyword TRANSITIVE_KEYWORD = new ModuleModifierKeyword("transitive", TRANSITIVE);//$NON-NLS-1$ + + + /** + * Map from token to operator (key type: String; + * value type: Operator). + */ + private static final Map KEYWORDS; + + static { + KEYWORDS = new HashMap(2); + ModuleModifierKeyword[] ops = { + STATIC_KEYWORD, + TRANSITIVE_KEYWORD, + }; + for (int i = 0; i < ops.length; i++) { + KEYWORDS.put(ops[i].toString(), ops[i]); + } + } + + /** + * Returns the module modifier corresponding to the given single-bit flag value, + * or null if none or if more than one bit is set. + *

      + * fromFlagValue is the converse of toFlagValue: + * that is, ModuleModifierKind.fromFlagValue(k.toFlagValue()) == k for + * all module modifier keywords k. + *

      + * + * @param flagValue the single-bit flag value for the module modifier + * @return the module modifier keyword, or null if none + * @see #toFlagValue() + */ + public static ModuleModifierKeyword fromFlagValue(int flagValue) { + for (Iterator it = KEYWORDS.values().iterator(); it.hasNext(); ) { + ModuleModifierKeyword k = (ModuleModifierKeyword) it.next(); + if (k.toFlagValue() == flagValue) { + return k; + } + } + return null; + } + + /** + * Returns the module modifier corresponding to the given string, + * or null if none. + *

      + * toKeyword is the converse of toString: + * that is, ModuleModifierKind.toKeyword(k.toString()) == k for + * all module modifier keywords k. + *

      + * + * @param keyword the lowercase string name for the module modifier + * @return the module modifier keyword, or null if none + * @see #toString() + */ + public static ModuleModifierKeyword toKeyword(String keyword) { + return (ModuleModifierKeyword) KEYWORDS.get(keyword); + } + + /** + * The flag value for the module modifier. + */ + private int flagValue; + + /** + * The keyword module modifier string. + */ + private String keyword; + + /** + * Creates a new module modifier with the given keyword. + *

      + * Note: this constructor is private. The only instances + * ever created are the ones for the standard modifiers. + *

      + * + * @param keyword the character sequence for the module modifier + * @param flagValue flag value as described in the Java Virtual Machine Specification + */ + private ModuleModifierKeyword(String keyword, int flagValue) { + this.keyword = keyword; + this.flagValue = flagValue; + } + + /** + * Returns the module modifier flag value corresponding to this module modifier keyword. + * These flag values are as described in the Java Virtual Machine Specification. + * + * @return one of the ModuleModifier constants + * @see #fromFlagValue(int) + */ + public int toFlagValue() { + return this.flagValue; + } + + /** + * Returns the keyword for the module modifier. + * + * @return the keyword for the module modifier + * @see #toKeyword(String) + */ + public String toString() { + return this.keyword; + } + } + + /** + * The "keyword" structural property of this node type (type: {@link ModuleModifier.ModuleModifierKeyword}). + */ + public static final SimplePropertyDescriptor KEYWORD_PROPERTY = + new SimplePropertyDescriptor(ModuleModifier.class, "keyword", ModuleModifier.ModuleModifierKeyword.class, MANDATORY); //$NON-NLS-1$ + + /** + * Module Modifier constant (bit mask, value 0) indicating no module modifiers. + */ + public static final int NONE = 0x0000; + + /** + * "static" module modifier constant (bit mask). + * Applicable to requires directive. + *

      + * Note that the value of static does not correspond to the value of {@link Modifier#STATIC}! + *

      + */ + public static final int STATIC_PHASE = 0x0040; + + /** + * "transitive" module modifier constant (bit mask). + * Applicable only to requires directive. + */ + public static final int TRANSITIVE = 0x0080; + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS; + + static { + List properyList = new ArrayList(2); + createPropertyList(ModuleModifier.class, properyList); + addProperty(KEYWORD_PROPERTY, properyList); + PROPERTY_DESCRIPTORS = reapPropertyList(properyList); + } + + /** + * Returns whether the given flags includes the "transitive" module modifier. + * + * @param flags the module modifier flags + * @return true if the TRANSITIVE bit is + * set, and false otherwise + */ + public static boolean isTransitive(int flags) { + return (flags & TRANSITIVE) != 0; + } + + /** + * Returns whether the given flags includes the "static" module modifier. + * + * @param flags the module modifier flags + * @return true if the STATIC bit is + * set, and false otherwise + */ + public static boolean isStatic(int flags) { + return (flags & STATIC_PHASE) != 0; + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * AST.JLS* constants + + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS; + } + + /** + * The modifier keyword; defaults to an unspecified modifier. + */ + private ModuleModifierKeyword modifierKeyword = ModuleModifierKeyword.STATIC_KEYWORD; + + /** + * Creates a new unparented MODULE modifier node owned by the given AST. + * By default, the node has unspecified (but legal) modifier. + *

      + * N.B. This constructor is package-private. + *

      + * + * @param ast the AST that is to own this node + */ + ModuleModifier(AST ast) { + super(ast); + unsupportedBelow9(); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + void accept0(ASTVisitor visitor) { + visitor.visit(this); + visitor.endVisit(this); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + ASTNode clone0(AST target) { + ModuleModifier result = new ModuleModifier(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setKeyword(getKeyword()); + return result; + } + + /** + * Returns the modifier keyword of this modifier node. + * + * @return the modifier keyword + */ + public ModuleModifierKeyword getKeyword() { + return this.modifierKeyword; + } + + /** + * Sets the module modifier keyword of this module modifier node. + * + * @param modifierKeyord the module modifier keyword + * @exception IllegalArgumentException if the argument is null + */ + public void setKeyword(ModuleModifierKeyword modifierKeyord) { + if (modifierKeyord == null) { + throw new IllegalArgumentException(); + } + preValueChange(KEYWORD_PROPERTY); + this.modifierKeyword = modifierKeyord; + postValueChange(KEYWORD_PROPERTY); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final int getNodeType0() { + return MODULE_MODIFIER; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) { + if (property == KEYWORD_PROPERTY) { + if (get) { + return getKeyword(); + } else { + setKeyword((ModuleModifierKeyword) value); + return null; + } + } + // allow default implementation to flag the error + return super.internalGetSetObjectProperty(property, get, value); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + /** + * Answer true if the receiver is the static module modifier, false otherwise. + * + * @return true if the receiver is the static module modifier, false otherwise + */ + public boolean isStatic() { + return this.modifierKeyword == ModuleModifierKeyword.STATIC_KEYWORD; + } + + /** + * Answer true if the receiver is the transitive module modifier, false otherwise. + * + * @return true if the receiver is the transitive module modifier, false otherwise + */ + public boolean isTransitive() { + return this.modifierKeyword == ModuleModifierKeyword.TRANSITIVE_KEYWORD; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int memSize() { + // treat ModifierKeyword as free + return BASE_NODE_SIZE + 1 * 4; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int treeSize() { + return memSize(); + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModulePackageAccess.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModulePackageAccess.java new file mode 100644 index 0000000000..d6aeaf1752 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModulePackageAccess.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.List; + +/** + * Abstract base class of AST nodes that represent exports and opens directives (added in JLS9 API). + * + *
      + * ModulePackageAccess:
      + *    {@link ExportsDirective}
      + *    {@link OpensDirective}
      + * 
      + * + * @noextend This class is not intended to be subclassed by clients. + * @since 3.14 + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public abstract class ModulePackageAccess extends ModuleDirective { + + /** + * The package name; lazily initialized; defaults to a unspecified, + * legal Java identifier. + */ + protected Name name = null; + + /** + * The target modules + * (element type: {@link Name}). + * Defaults to an empty list. (see constructor) + */ + protected ASTNode.NodeList modules = null; + + /** + * Returns structural property descriptor for the "modules" property + * of this node (element type: {@link Name}). + * + * @return the property descriptor + */ + abstract ChildListPropertyDescriptor internalModulesProperty(); + + /** + * Returns structural property descriptor for the "name" property + * of this node (child type: {@link Name}). + * + * @return the property descriptor + */ + abstract ChildPropertyDescriptor internalNameProperty(); + + /** + * Returns structural property descriptor for the "name" property + * of this node (child type: {@link Name}). + * + * @return the property descriptor + */ + public final ChildPropertyDescriptor getNameProperty() { + return internalNameProperty(); + } + + /** + * Creates and returns a structural property descriptor for the + * "name" property declared on the given concrete node type (child type: {@link Name}). + * + * @return the property descriptor + */ + static final ChildPropertyDescriptor internalNamePropertyFactory(Class nodeClass) { + return new ChildPropertyDescriptor(nodeClass, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + } + + /** + * Creates and returns a structural property descriptor for the + * "modules" property declared on the given concrete node type (element type: {@link Name}). + * + * @return the property descriptor + */ + static final ChildListPropertyDescriptor internalModulesPropertyFactory(Class nodeClass) { + return new ChildListPropertyDescriptor(nodeClass, "modules", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$ + } + + /** + *

      + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + *

      + * + * @param ast the AST that is to own this node + */ + ModulePackageAccess(AST ast) { + super(ast); + this.modules = new ASTNode.NodeList(internalModulesProperty()); + } + + @Override + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == internalNameProperty()) { + if (get) { + return getName(); + } else { + setName((Name) child); + return null; + } + } + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + @Override + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == internalModulesProperty()) { + return modules(); + } + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + /** + * Returns the name of the package. + * + * @return the package name node + */ + public Name getName() { + if (this.name == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.name == null) { + preLazyInit(); + this.name =this.ast.newQualifiedName( + new SimpleName(this.ast), new SimpleName(this.ast)); + ChildPropertyDescriptor p = internalNameProperty(); + postLazyInit(this.name, p); + } + } + } + return this.name; + } + + /** + * Sets the name of the package to the given name. + * + * @param name the new package name + * @exception IllegalArgumentException if: + *
        + *
      • the node belongs to a different AST
      • + *
      • the node already has a parent
      • + *
      + */ + public void setName(Name name) { + if (name == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.name; + ChildPropertyDescriptor p = internalNameProperty(); + preReplaceChild(oldChild, name, p); + this.name = name; + postReplaceChild(oldChild, name, p); + } + + /** + * Returns the live ordered list of target modules for this + * directive. + * + * @return the live list of target modules + * (element type: {@link Name}) + */ + public List modules() { + return this.modules; + } + + protected ASTNode cloneHelper(AST target, ModulePackageAccess result) { + result.setSourceRange(getStartPosition(), getLength()); + result.setName((Name) getName().clone(target)); + result.modules().addAll(ASTNode.copySubtrees(target, modules())); + return result; + } + + protected void acceptVisitChildren(boolean visitChildren, ASTVisitor visitor) { + if (visitChildren) { + acceptChild(visitor, getName()); + acceptChildren(visitor, this.modules); + } + } + + @Override + int memSize() { + return BASE_NODE_SIZE + 2 * 4; + } + + @Override + int treeSize() { + return + memSize() + + (this.name == null ? 0 : getName().treeSize()) + + this.modules.listSize(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NameEnvironmentWithProgress.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NameEnvironmentWithProgress.java index e05f7caf74..9e0db9a7f6 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NameEnvironmentWithProgress.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NameEnvironmentWithProgress.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2016 IBM Corporation and others. + * Copyright (c) 2010, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -41,14 +41,12 @@ private void checkCanceled() { throw new AbortCompilation(true/*silent*/, new OperationCanceledException()); } } - - public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { - return findType(typeName, packageName, true); + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName) { + return findType(typeName, packageName, true, moduleName); } - - public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes) { + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes, char[] moduleName) { checkCanceled(); - NameEnvironmentAnswer answer = super.findType(typeName, packageName); + NameEnvironmentAnswer answer = super.findType(typeName, packageName, moduleName); if (answer == null && searchWithSecondaryTypes) { NameEnvironmentAnswer suggestedAnswer = null; String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/')); @@ -57,6 +55,12 @@ public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boo for (int i = 0, length = this.classpaths.length; i < length; i++) { if (!(this.classpaths[i] instanceof ClasspathDirectory)) continue; ClasspathDirectory classpathDirectory = (ClasspathDirectory) this.classpaths[i]; + LookupStrategy strategy = LookupStrategy.get(moduleName); + if (!strategy.matchesWithName(classpathDirectory, + loc -> loc.getModule() != null, + loc -> loc.servesModule(moduleName))) { + continue; + } answer = classpathDirectory.findSecondaryInClass(typeName, qualifiedPackageName, qualifiedBinaryFileName); if (answer != null) { if (!answer.ignoreIfBetter()) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/OpensDirective.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/OpensDirective.java new file mode 100644 index 0000000000..8352605986 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/OpensDirective.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Opens directive AST node type (added in JLS9 API). + *
      + * OpensDirective:
      + *     opens PackageName [ to  ModuleName {, ModuleName } ] ;
      + * 
      + * + * @since 3.14 + * + * @noextend This class is not intended to be subclassed by clients. + * @noinstantiate This class is not intended to be instantiated by clients. + */ +@SuppressWarnings({"rawtypes"}) +public class OpensDirective extends ModulePackageAccess { + + /** + * The "name" structural property of this node type (child type: {@link Name}). + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + internalNamePropertyFactory(OpensDirective.class); + /** + * The "modules" structural property of this node type (element type: {@link Name}). + */ + public static final ChildListPropertyDescriptor MODULES_PROPERTY = + internalModulesPropertyFactory(OpensDirective.class); + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_9_0; + + static { + List properyList = new ArrayList(3); + createPropertyList(OpensDirective.class, properyList); + addProperty(NAME_PROPERTY, properyList); + addProperty(MODULES_PROPERTY, properyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * AST.JLS* constants + + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_9_0; + } + + /** + * Creates a new AST node for an opens directive owned by the + * given AST. The open directive initially is a regular (non-targetted) + * single package open for an unspecified, but legal, Java package name. + *

      + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + *

      + * + * @param ast the AST that is to own this node + */ + OpensDirective(AST ast) { + super(ast); + } + + @Override + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + @Override + final ChildPropertyDescriptor internalNameProperty() { + return NAME_PROPERTY; + } + + @Override + final ChildListPropertyDescriptor internalModulesProperty() { + return MODULES_PROPERTY; + } + + @Override + final int getNodeType0() { + return OPENS_DIRECTIVE; + } + + @Override + ASTNode clone0(AST target) { + return cloneHelper(target, new OpensDirective(target)); + } + + @Override + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + @Override + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + acceptVisitChildren(visitChildren, visitor); + visitor.endVisit(this); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java index cf5a4aff8d..4e97184a14 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -259,6 +259,10 @@ private void computeNameAndComponents() { } } + org.eclipse.jdt.internal.compiler.lookup.PackageBinding getCompilerBinding() { + return this.binding; + } + /* * For debugging purpose only. * @see java.lang.Object#toString() diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java index 93fc3e6242..f2ee6220d2 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java @@ -285,7 +285,7 @@ final int getNodeType0() { ASTNode clone0(AST target) { PrimitiveType result = new PrimitiveType(target); result.setSourceRange(getStartPosition(), getLength()); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.annotations().addAll( ASTNode.copySubtrees(target, annotations())); } @@ -308,7 +308,7 @@ void accept0(ASTVisitor visitor) { boolean visitChildren = visitor.visit(this); if (visitChildren) { // visit children in normal left to right reading order - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { acceptChildren(visitor, this.annotations); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ProvidesDirective.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ProvidesDirective.java new file mode 100644 index 0000000000..64214dcfbc --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ProvidesDirective.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Provides directive AST node type (added in JLS9 API). + *
      + * ProvidesDirective:
      + *     provides Name with Name {, Name } ;
      + * 
      + * + * @since 3.14 + * + * @noextend This class is not intended to be subclassed by clients. + * @noinstantiate This class is not intended to be instantiated by clients. + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public class ProvidesDirective extends ModuleDirective { + + /** + * The "name" structural property of this node type (child type: {@link Name}). + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + new ChildPropertyDescriptor(ProvidesDirective.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "implementations" structural property of this node type (element type: {@link Name}). + */ + public static final ChildListPropertyDescriptor IMPLEMENTATIONS_PROPERTY = + new ChildListPropertyDescriptor(ProvidesDirective.class, "implementations", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_9_0; + + static { + List properyList = new ArrayList(3); + createPropertyList(ProvidesDirective.class, properyList); + addProperty(NAME_PROPERTY, properyList); + addProperty(IMPLEMENTATIONS_PROPERTY, properyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * AST.JLS* constants + + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_9_0; + } + + /** + * The interface name; lazily initialized; defaults to a unspecified, + * legal Java identifier. + */ + private Name name = null; + + /** + * The implementations names + * (element type: {@link Name}). + * Defaults to an empty list. + */ + private ASTNode.NodeList implementations = + new ASTNode.NodeList(IMPLEMENTATIONS_PROPERTY); + + /** + * Creates a new AST node for an provides directive owned by the + * given AST. The provides directive initially is + * for an unspecified, but legal, Java type name. + *

      + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + *

      + * + * @param ast the AST that is to own this node + */ + ProvidesDirective(AST ast) { + super(ast); + } + + @Override + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + @Override + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == NAME_PROPERTY) { + if (get) { + return getName(); + } else { + setName((Name) child); + return null; + } + } + + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + @Override + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == IMPLEMENTATIONS_PROPERTY) { + return implementations(); + } + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + @Override + final int getNodeType0() { + return PROVIDES_DIRECTIVE; + } + + @Override + ASTNode clone0(AST target) { + ProvidesDirective result = new ProvidesDirective(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setName((Name) getName().clone(target)); + result.implementations().addAll(ASTNode.copySubtrees(target, implementations())); + return result; + } + + @Override + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + @Override + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + acceptChild(visitor, getName()); + acceptChildren(visitor, this.implementations); + } + visitor.endVisit(this); + } + + + /** + * Returns the name of the service in this directive. + * + * @return the services name + */ + public Name getName() { + if (this.name == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.name == null) { + preLazyInit(); + this.name = this.ast.newQualifiedName( + new SimpleName(this.ast), new SimpleName(this.ast)); + postLazyInit(this.name, NAME_PROPERTY); + } + } + } + return this.name; + } + + /** + * Sets the name of the service. + * + * @param name the new service name + * @exception IllegalArgumentException if: + *
        + *
      • the node belongs to a different AST
      • + *
      • the node already has a parent
      • + *
      + */ + public void setName(Name name) { + if (name == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.name; + preReplaceChild(oldChild, name, NAME_PROPERTY); + this.name = name; + postReplaceChild(oldChild, name, NAME_PROPERTY); + } + + /** + * Returns the live ordered list of implementations for the interface in this provides directive. + * + * @return the live list of implementations for the interface + * (element type: {@link Name}) + */ + public List implementations() { + return this.implementations; + } + + @Override + int memSize() { + return BASE_NODE_SIZE + 2 * 4; + } + + @Override + int treeSize() { + return + memSize() + + (this.name == null ? 0 : getName().treeSize()) + + this.implementations.listSize(); + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java index 9ea8dcc78f..37a32840fb 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java @@ -231,7 +231,7 @@ ASTNode clone0(AST target) { QualifiedType result = new QualifiedType(target); result.setSourceRange(getStartPosition(), getLength()); result.setQualifier((Type) ((ASTNode) getQualifier()).clone(target)); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.annotations().addAll( ASTNode.copySubtrees(target, annotations())); } @@ -255,7 +255,7 @@ void accept0(ASTVisitor visitor) { if (visitChildren) { // visit children in normal left to right reading order acceptChild(visitor, getQualifier()); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { acceptChildren(visitor, this.annotations); } acceptChild(visitor, getName()); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RequiresDirective.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RequiresDirective.java new file mode 100644 index 0000000000..3a6ea47a99 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RequiresDirective.java @@ -0,0 +1,248 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Requires directive AST node type (added in JLS9 API). + *
      + * RequiresDirective:
      + *     requires { ModuleModifier } Name ;
      + * 
      + * + * @since 3.14 + * @noinstantiate This class is not intended to be instantiated by clients. + * @noextend This class is not intended to be subclassed by clients. + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public class RequiresDirective extends ModuleDirective { + + /** + * The "modifiers" structural property of this node type (element type: {@link ModuleModifier}). + */ + public static final ChildListPropertyDescriptor MODIFIERS_PROPERTY = + new ChildListPropertyDescriptor(RequiresDirective.class, "modifiers", ModuleModifier.class, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The module structural property of this node type (child type: {@link Name}). + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + new ChildPropertyDescriptor(RequiresDirective.class, "name", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_9_0; + + static { + List propertyList = new ArrayList(3); + createPropertyList(RequiresDirective.class, propertyList); + addProperty(MODIFIERS_PROPERTY, propertyList); + addProperty(NAME_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(propertyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * AST.JLS* constants + + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_9_0; + } + + /** + * The extended modifiers (element type: {@link ModuleModifier}). + * defaults to an empty list + */ + private ASTNode.NodeList modifiers = new ASTNode.NodeList(MODIFIERS_PROPERTY); + + /** + * The referenced module name; lazily initialized; defaults to a unspecified, + * legal Java identifier. + */ + private Name name = null; + + /** + * Creates a new AST node for an requires directive owned by the + * given AST. The requires directive initially is a regular (no modifiers) + * requires for an unspecified, but legal, Java module name. + *

      + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + *

      + * + * @param ast the AST that is to own this node + */ + RequiresDirective(AST ast) { + super(ast); + } + + @Override + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + @Override + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == NAME_PROPERTY) { + if (get) { + return getName(); + } else { + setName((Name) child); + return null; + } + } + + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + @Override + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == MODIFIERS_PROPERTY) { + return modifiers(); + } + + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + @Override + final int getNodeType0() { + return REQUIRES_DIRECTIVE; + } + + @Override + ASTNode clone0(AST target) { + RequiresDirective result = new RequiresDirective(target); + result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers())); + result.setName((Name) getName().clone(target)); + return result; + } + + @Override + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + @Override + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + acceptChildren(visitor, this.modifiers); + acceptChild(visitor, getName()); + } + visitor.endVisit(this); + } + + /** + * Returns the live ordered list of modifiers + * of this declaration. + *

      + * Note that the not all modifiers are legal. + *

      + * + * @return the live list of module modifiers + * (element type: {@link ModuleModifier}) + */ + public List modifiers() { + return this.modifiers; + } + + /** + * Returns the module modifiers explicitly specified on this declaration. + *

      + * This method is a convenience method that + * computes these flags from modifiers(). + *

      + * + * @return the bit-wise or of ModuleModifier constants + * @see ModuleModifier + */ + public int getModifiers() { + // do not cache - performance could be improved by caching computed flags + // but this would require tracking changes to this.modifiers + int computedModifierFlags = ModuleModifier.NONE; + for (Iterator it = modifiers().iterator(); it.hasNext(); ) { + Object x = it.next(); + if (x instanceof ModuleModifier) { + computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue(); + } + } + return computedModifierFlags; + } + + /** + * Returns the module name referenced by this declaration. + * + * @return the module referenced + */ + public Name getName() { + if (this.name == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.name == null) { + preLazyInit(); + this.name =this.ast.newQualifiedName( + new SimpleName(this.ast), new SimpleName(this.ast)); + postLazyInit(this.name, NAME_PROPERTY); + } + } + } + return this.name; + } + + /** + * Sets the module name in requires directive to the given name. + * + * @param name the new module name + * @exception IllegalArgumentException if: + *
        + *
      • the node belongs to a different AST
      • + *
      • the node already has a parent
      • + *
      + */ + public void setName(Name name) { + if (name == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.name; + preReplaceChild(oldChild, name, NAME_PROPERTY); + this.name = name; + postReplaceChild(oldChild, name, NAME_PROPERTY); + } + + @Override + int memSize() { + return BASE_NODE_SIZE + 2 * 4; + } + + @Override + int treeSize() { + return + memSize() + + (this.modifiers == null ? 0 : this.modifiers.listSize()) + + (this.name == null ? 0 : getName().treeSize()); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java index 33d123dc2e..77370b7f58 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java @@ -174,7 +174,7 @@ final int getNodeType0() { ASTNode clone0(AST target) { SimpleType result = new SimpleType(target); result.setSourceRange(getStartPosition(), getLength()); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.annotations().addAll( ASTNode.copySubtrees(target, annotations())); } @@ -197,7 +197,7 @@ void accept0(ASTVisitor visitor) { boolean visitChildren = visitor.visit(this); if (visitChildren) { // visit children in normal left to right reading order - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { acceptChildren(visitor, this.annotations); } acceptChild(visitor, getName()); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java index 99ca7a157c..187ad5fa24 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java @@ -171,7 +171,7 @@ public class SingleVariableDeclaration extends VariableDeclaration { public static List propertyDescriptors(int apiLevel) { if (apiLevel == AST.JLS2_INTERNAL) { return PROPERTY_DESCRIPTORS_2_0; - } else if (apiLevel < AST.JLS8) { + } else if (apiLevel < AST.JLS8_INTERNAL) { return PROPERTY_DESCRIPTORS_3_0; } else { return PROPERTY_DESCRIPTORS_8_0; @@ -231,7 +231,7 @@ public static List propertyDescriptors(int apiLevel) { super(ast); if (ast.apiLevel >= AST.JLS3_INTERNAL) { this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY); - if (ast.apiLevel >= AST.JLS8) { + if (ast.apiLevel >= AST.JLS8_INTERNAL) { this.varargsAnnotations = new ASTNode.NodeList(VARARGS_ANNOTATIONS_PROPERTY); } } @@ -385,12 +385,12 @@ ASTNode clone0(AST target) { result.setVarargs(isVarargs()); } result.setType((Type) getType().clone(target)); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.varargsAnnotations().addAll( ASTNode.copySubtrees(target, varargsAnnotations())); } result.setName((SimpleName) getName().clone(target)); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.extraDimensions().addAll( ASTNode.copySubtrees(target, this.extraDimensions())); } else { @@ -420,11 +420,11 @@ void accept0(ASTVisitor visitor) { acceptChildren(visitor, this.modifiers); } acceptChild(visitor, getType()); - if (this.ast.apiLevel >= AST.JLS8 && isVarargs()) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL && isVarargs()) { acceptChildren(visitor, this.varargsAnnotations); } acceptChild(visitor, getName()); - if (this.ast.apiLevel >= AST.JLS8){ + if (this.ast.apiLevel >= AST.JLS8_INTERNAL){ acceptChildren(visitor, this.extraDimensions); } acceptChild(visitor, getInitializer()); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java index e6ce04fbb3..a96d518e03 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -28,19 +28,31 @@ * Not all node arrangements will represent legal Java constructs. In particular, * at least one resource, catch clause, or finally block must be present.

      * + *

      A resource is either a {@link VariableDeclarationExpression} or (since JLS9) a {@link Name}.

      + * * @since 2.0 * @noinstantiate This class is not intended to be instantiated by clients. + * @noextend This class is not intended to be subclassed by clients. */ @SuppressWarnings({"rawtypes", "unchecked"}) public class TryStatement extends Statement { + /** * The "resources" structural property of this node type (element type: {@link VariableDeclarationExpression}) (added in JLS4 API). + * @deprecated In the JLS9 API, this property is replaced by {@link #RESOURCES2_PROPERTY}. * @since 3.7.1 */ public static final ChildListPropertyDescriptor RESOURCES_PROPERTY = new ChildListPropertyDescriptor(TryStatement.class, "resources", VariableDeclarationExpression.class, CYCLE_RISK); //$NON-NLS-1$ + /** + * The "resources" structural property of this node type (element type: {@link Expression}) (added in JLS9 API). + * @since 3.14 + */ + public static final ChildListPropertyDescriptor RESOURCES2_PROPERTY = + new ChildListPropertyDescriptor(TryStatement.class, "resources", Expression.class, CYCLE_RISK); //$NON-NLS-1$ + /** * The "body" structural property of this node type (child type: {@link Block}). * @since 3.0 @@ -77,6 +89,14 @@ public class TryStatement extends Statement { */ private static final List PROPERTY_DESCRIPTORS_4_0; + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + * @since 3.14 + */ + private static final List PROPERTY_DESCRIPTORS_9_0; + static { List propertyList = new ArrayList(4); createPropertyList(TryStatement.class, propertyList); @@ -92,6 +112,14 @@ public class TryStatement extends Statement { addProperty(CATCH_CLAUSES_PROPERTY, propertyList); addProperty(FINALLY_PROPERTY, propertyList); PROPERTY_DESCRIPTORS_4_0 = reapPropertyList(propertyList); + + propertyList = new ArrayList(5); + createPropertyList(TryStatement.class, propertyList); + addProperty(RESOURCES2_PROPERTY, propertyList); + addProperty(BODY_PROPERTY, propertyList); + addProperty(CATCH_CLAUSES_PROPERTY, propertyList); + addProperty(FINALLY_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(propertyList); } /** @@ -109,15 +137,20 @@ public static List propertyDescriptors(int apiLevel) { case AST.JLS2_INTERNAL : case AST.JLS3_INTERNAL : return PROPERTY_DESCRIPTORS; - default : + case AST.JLS4_INTERNAL : + case AST.JLS8_INTERNAL : return PROPERTY_DESCRIPTORS_4_0; + default : + return PROPERTY_DESCRIPTORS_9_0; } } /** - * The resource expressions (element type: {@link VariableDeclarationExpression}). - * Null in JLS2 and JLS3. Added in JLS4; defaults to an empty list - * (see constructor). + * The resource expressions (element type: {@link Expression}). + * Null in JLS2 and JLS3. Added in JLS4. + * In the deprecated JLS4 and JLS8 APIs, this used to be + * (element type: {@link VariableDeclarationExpression}). + * Defaults to an empty list (see constructor). * @since 3.7 */ private ASTNode.NodeList resources = null; @@ -153,7 +186,9 @@ public static List propertyDescriptors(int apiLevel) { */ TryStatement(AST ast) { super(ast); - if (ast.apiLevel >= AST.JLS4_INTERNAL) { + if (ast.apiLevel >= AST.JLS9_INTERNAL) { + this.resources = new ASTNode.NodeList(RESOURCES2_PROPERTY); + } else if (ast.apiLevel >= AST.JLS4_INTERNAL) { this.resources = new ASTNode.NodeList(RESOURCES_PROPERTY); } } @@ -193,7 +228,7 @@ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, bool * Method declared on ASTNode. */ final List internalGetChildListProperty(ChildListPropertyDescriptor property) { - if (property == RESOURCES_PROPERTY) { + if (property == RESOURCES_PROPERTY || property == RESOURCES2_PROPERTY) { return resources(); } if (property == CATCH_CLAUSES_PROPERTY) { @@ -336,9 +371,12 @@ public void setFinally(Block block) { /** * Returns the live ordered list of resources for this try statement (added in JLS4 API). + * + *

      A resource is either a {@link VariableDeclarationExpression} or (since JLS9) a {@link Name}.

      * - * @return the live list of resources - * (element type: {@link VariableDeclarationExpression}) + * @return the live list of resources (element type: {@link Expression}). + * In the deprecated JLS4 and JLS8 APIs, this used to be + * (element type: {@link VariableDeclarationExpression}). * @exception UnsupportedOperationException if this operation is used * in a JLS2 or JLS3 AST * @since 3.7.1 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java index 60e4f29163..9b569e0afe 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java @@ -130,7 +130,7 @@ public static List propertyDescriptors(int apiLevel) { TypeParameter(AST ast) { super(ast); unsupportedIn2(); - if (ast.apiLevel >= AST.JLS8) { + if (ast.apiLevel >= AST.JLS8_INTERNAL) { this.modifiers = new ASTNode.NodeList(MODIFIERS_PROPERTY); } } @@ -185,7 +185,7 @@ final int getNodeType0() { ASTNode clone0(AST target) { TypeParameter result = new TypeParameter(target); result.setSourceRange(getStartPosition(), getLength()); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.modifiers().addAll( ASTNode.copySubtrees(target, modifiers())); } @@ -210,7 +210,7 @@ void accept0(ASTVisitor visitor) { boolean visitChildren = visitor.visit(this); if (visitChildren) { // visit children in normal left to right reading order - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { acceptChildren(visitor, this.modifiers); } acceptChild(visitor, getName()); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/UsesDirective.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/UsesDirective.java new file mode 100644 index 0000000000..d91f5022b0 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/UsesDirective.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Uses directive AST node type (added in JLS9 API). + *
      + * UsesDirective:
      + *     uses Name ;
      + * 
      + * + * @since 3.14 + * + * @noextend This class is not intended to be subclassed by clients. + * @noinstantiate This class is not intended to be instantiated by clients. + */ +@SuppressWarnings("rawtypes") +public class UsesDirective extends ModuleDirective { + + /** + * The "name" structural property of this node type (child type: {@link Name}). + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + new ChildPropertyDescriptor(UsesDirective.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_9_0; + + static { + List properyList = new ArrayList(2); + createPropertyList(UsesDirective.class, properyList); + addProperty(NAME_PROPERTY, properyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * AST.JLS* constants + + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_9_0; + } + + /** + * The module name; lazily initialized; defaults to a unspecified, + * legal Java identifier. + */ + private Name name = null; + + /** + * Creates a new AST node for an uses directive owned by the + * given AST. The uses directive initially is + * for an unspecified, but legal, Java type name. + *

      + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + *

      + * + * @param ast the AST that is to own this node + */ + UsesDirective(AST ast) { + super(ast); + } + + @Override + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + @Override + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == NAME_PROPERTY) { + if (get) { + return getName(); + } else { + setName((Name) child); + return null; + } + } + + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + @Override + final int getNodeType0() { + return USES_DIRECTIVE; + } + + @Override + ASTNode clone0(AST target) { + UsesDirective result = new UsesDirective(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setName((Name) getName().clone(target)); + return result; + } + + @Override + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + @Override + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + acceptChild(visitor, getName()); + } + visitor.endVisit(this); + } + + + /** + * Returns the name of the service in this directive. + * + * @return the name of the service + */ + public Name getName() { + if (this.name == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.name == null) { + preLazyInit(); + this.name = this.ast.newQualifiedName( + new SimpleName(this.ast), new SimpleName(this.ast)); + postLazyInit(this.name, NAME_PROPERTY); + } + } + } + return this.name; + } + + /** + * Sets the name of the service in this directive. + * + * @param name the new name of the service + * @exception IllegalArgumentException if: + *
        + *
      • the node belongs to a different AST
      • + *
      • the node already has a parent
      • + *
      + */ + public void setName(Name name) { + if (name == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.name; + preReplaceChild(oldChild, name, NAME_PROPERTY); + this.name = name; + postReplaceChild(oldChild, name, NAME_PROPERTY); + } + + @Override + int memSize() { + return BASE_NODE_SIZE + 1 * 4; + } + + @Override + int treeSize() { + return + memSize() + + (this.name == null ? 0 : getName().treeSize()); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java index 2a40ccb58b..3195f7e458 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java @@ -196,7 +196,7 @@ public final ChildPropertyDescriptor getInitializerProperty() { */ VariableDeclaration(AST ast) { super(ast); - if (ast.apiLevel >= AST.JLS8) { + if (ast.apiLevel >= AST.JLS8_INTERNAL) { this.extraDimensions = new ASTNode.NodeList(getExtraDimensions2Property()); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java index 0405c65fbe..bd714100f7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java @@ -105,7 +105,7 @@ public class VariableDeclarationFragment extends VariableDeclaration { * @since 3.0 */ public static List propertyDescriptors(int apiLevel) { - if (apiLevel >= AST.JLS8) { + if (apiLevel >= AST.JLS8_INTERNAL) { return PROPERTY_DESCRIPTORS_8_0; } else { return PROPERTY_DESCRIPTORS; @@ -230,7 +230,7 @@ ASTNode clone0(AST target) { VariableDeclarationFragment result = new VariableDeclarationFragment(target); result.setSourceRange(getStartPosition(), getLength()); result.setName((SimpleName) getName().clone(target)); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.extraDimensions().addAll( ASTNode.copySubtrees(target, extraDimensions())); } else { @@ -257,7 +257,7 @@ void accept0(ASTVisitor visitor) { if (visitChildren) { // visit children in normal left to right reading order acceptChild(visitor, getName()); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { acceptChildren(visitor, this.extraDimensions); } acceptChild(visitor, getInitializer()); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java index ab4572d947..18ba40d3a8 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java @@ -199,7 +199,7 @@ final int getNodeType0() { ASTNode clone0(AST target) { WildcardType result = new WildcardType(target); result.setSourceRange(getStartPosition(), getLength()); - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { result.annotations().addAll( ASTNode.copySubtrees(target, annotations())); } @@ -222,7 +222,7 @@ void accept0(ASTVisitor visitor) { boolean visitChildren = visitor.visit(this); if (visitChildren) { // visit children in normal left to right reading order - if (this.ast.apiLevel >= AST.JLS8) { + if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { acceptChildren(visitor, this.annotations); } acceptChild(visitor, getBound()); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java index 503283c0aa..52a6946df2 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java @@ -312,6 +312,9 @@ public IAnnotationBinding[] removeRedundantTypeAnnotations(IAnnotationBinding[] private static final char STATIC_PREFIX= 's'; private static final char NORMAL_PREFIX= 'n'; + /** @deprecated using deprecated code */ + private static final int JLS8_INTERNAL = AST.JLS8; + private final ImportRewriteContext defaultContext; private final ICompilationUnit compilationUnit; @@ -1308,7 +1311,7 @@ public final TextEdit rewriteImports(IProgressMonitor monitor) throws CoreExcept CompilationUnit usedAstRoot= this.astRoot; if (usedAstRoot == null) { - ASTParser parser= ASTParser.newParser(AST.JLS8); + ASTParser parser= ASTParser.newParser(AST.JLS9); parser.setSource(this.compilationUnit); parser.setFocalPosition(0); // reduced AST parser.setResolveBindings(false); @@ -1325,7 +1328,7 @@ public final TextEdit rewriteImports(IProgressMonitor monitor) throws CoreExcept String qualifiedName = addedImport.substring(1); computer.addImport(isStatic, qualifiedName); } - + for (String removedImport : this.removedImports) { boolean isStatic = STATIC_PREFIX == removedImport.charAt(0); String qualifiedName = removedImport.substring(1); @@ -1532,7 +1535,7 @@ private Type createBaseType(AST ast, ImportRewriteContext context, ITypeBinding private Type getArrayType(Type elementType, AST ast, ImportRewriteContext context, ITypeBinding normalizedBinding, TypeLocation location) { int noDimensions = normalizedBinding.getDimensions(); ArrayType arrayType = ast.newArrayType(elementType, noDimensions); - if (ast.apiLevel() >= AST.JLS8) { + if (ast.apiLevel() >= JLS8_INTERNAL) { for (int i = 0; i < noDimensions; i++) { IAnnotationBinding[] typeAnnotations = normalizedBinding.getTypeAnnotations(); if (typeAnnotations.length > 0) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java index 2b079e4564..5a5caadebb 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -63,6 +63,16 @@ public class NaiveASTFlattener extends ASTVisitor { */ private static final int JLS4 = AST.JLS4; + /** + * Internal synonym for {@link AST#JLS8}. Use to alleviate + * deprecation warnings. + * @deprecated + * @since 3.14 + */ + private static final int JLS8 = AST.JLS8; + + private static final int JLS9 = AST.JLS9; + /** * The string buffer into which the serialized representation of the AST is * written. @@ -199,11 +209,24 @@ void printModifiers(List ext) { } } + private void printTypes(List types, String prefix) { + if (types.size() > 0) { + this.buffer.append(" " + prefix + " ");//$NON-NLS-1$ //$NON-NLS-2$ + Type type = types.get(0); + type.accept(this); + for (int i = 1, l = types.size(); i < l; ++i) { + this.buffer.append(","); //$NON-NLS-1$ + type = types.get(0); + type.accept(this); + } + } + } + /** * reference node helper function that is common to all * the difference reference nodes. - * - * @param typeArguments list of type arguments + * + * @param typeArguments list of type arguments */ private void visitReferenceTypeArguments(List typeArguments) { this.buffer.append("::");//$NON-NLS-1$ @@ -221,7 +244,7 @@ private void visitReferenceTypeArguments(List typeArguments) { } private void visitTypeAnnotations(AnnotatableType node) { - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8) { visitAnnotationsList(node.annotations()); } } @@ -367,7 +390,7 @@ public boolean visit(ArrayInitializer node) { * @see ASTVisitor#visit(ArrayType) */ public boolean visit(ArrayType node) { - if (node.getAST().apiLevel() < AST.JLS8) { + if (node.getAST().apiLevel() < JLS8) { visitComponentType(node); this.buffer.append("[]");//$NON-NLS-1$ } else { @@ -534,6 +557,11 @@ public boolean visit(ClassInstanceCreation node) { * @see ASTVisitor#visit(CompilationUnit) */ public boolean visit(CompilationUnit node) { + if (node.getAST().apiLevel() >= JLS9) { + if (node.getModule() != null) { + node.getModule().accept(this); + } + } if (node.getPackage() != null) { node.getPackage().accept(this); } @@ -736,9 +764,14 @@ public boolean visit(EnumDeclaration node) { return false; } + @Override + public boolean visit(ExportsDirective node) { + return visit(node, "exports"); //$NON-NLS-1$ + } + /* * @see ASTVisitor#visit(ExpressionMethodReference) - * + * * @since 3.10 */ public boolean visit(ExpressionMethodReference node) { @@ -1048,7 +1081,7 @@ public boolean visit(MethodDeclaration node) { } node.getName().accept(this); this.buffer.append("(");//$NON-NLS-1$ - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8) { Type receiverType = node.getReceiverType(); if (receiverType != null) { receiverType.accept(this); @@ -1073,7 +1106,7 @@ public boolean visit(MethodDeclaration node) { } this.buffer.append(")");//$NON-NLS-1$ int size = node.getExtraDimensions(); - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8) { List dimensions = node.extraDimensions(); for (int i = 0; i < size; i++) { visit((Dimension) dimensions.get(i)); @@ -1083,7 +1116,7 @@ public boolean visit(MethodDeclaration node) { this.buffer.append("[]"); //$NON-NLS-1$ } } - if (node.getAST().apiLevel() < AST.JLS8) { + if (node.getAST().apiLevel() < JLS8) { if (!thrownExceptions(node).isEmpty()) { this.buffer.append(" throws ");//$NON-NLS-1$ for (Iterator it = thrownExceptions(node).iterator(); it.hasNext(); ) { @@ -1199,6 +1232,46 @@ public boolean visit(Modifier node) { return false; } + @Override + public boolean visit(ModuleDeclaration node) { + if (node.getJavadoc() != null) { + node.getJavadoc().accept(this); + } + printModifiers(node.annotations()); + if (node.isOpen()) + this.buffer.append("open "); //$NON-NLS-1$ + this.buffer.append("module"); //$NON-NLS-1$ + this.buffer.append(" "); //$NON-NLS-1$ + node.getName().accept(this); + this.buffer.append(" {\n"); //$NON-NLS-1$ + this.indent++; + for (ModuleDirective stmt : (List)node.moduleStatements()) { + stmt.accept(this); + } + this.indent--; + this.buffer.append("}"); //$NON-NLS-1$ + return false; + } + + /* + * @see ASTVisitor#visit(ModuleModifier) + * @since 3.14 + */ + public boolean visit(ModuleModifier node) { + this.buffer.append(node.getKeyword().toString()); + return false; + } + + private boolean visit(ModulePackageAccess node, String keyword) { + printIndent(); + this.buffer.append(keyword); + this.buffer.append(" ");//$NON-NLS-1$ + node.getName().accept(this); + printTypes(node.modules(), "to"); //$NON-NLS-1$ + this.buffer.append(";\n");//$NON-NLS-1$ + return false; + } + /* * @see ASTVisitor#visit(NameQualifiedType) * @since 3.10 @@ -1246,6 +1319,11 @@ public boolean visit(NumberLiteral node) { return false; } + @Override + public boolean visit(OpensDirective node) { + return visit(node, "opens"); //$NON-NLS-1$ + } + /* * @see ASTVisitor#visit(PackageDeclaration) */ @@ -1322,6 +1400,17 @@ public boolean visit(PrimitiveType node) { return false; } + @Override + public boolean visit(ProvidesDirective node) { + printIndent(); + this.buffer.append("provides");//$NON-NLS-1$ + this.buffer.append(" ");//$NON-NLS-1$ + node.getName().accept(this); + printTypes(node.implementations(), "with"); //$NON-NLS-1$ + this.buffer.append(";\n");//$NON-NLS-1$ + return false; + } + /* * @see ASTVisitor#visit(QualifiedName) */ @@ -1344,6 +1433,17 @@ public boolean visit(QualifiedType node) { return false; } + @Override + public boolean visit(RequiresDirective node) { + printIndent(); + this.buffer.append("requires");//$NON-NLS-1$ + this.buffer.append(" ");//$NON-NLS-1$ + printModifiers(node.modifiers()); + node.getName().accept(this); + this.buffer.append(";\n");//$NON-NLS-1$ + return false; + } + /* * @see ASTVisitor#visit(ReturnStatement) */ @@ -1402,7 +1502,7 @@ public boolean visit(SingleVariableDeclaration node) { node.getType().accept(this); if (node.getAST().apiLevel() >= JLS3) { if (node.isVarargs()) { - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8) { List annotations = node.varargsAnnotations(); if (annotations.size() > 0) { this.buffer.append(' '); @@ -1415,7 +1515,7 @@ public boolean visit(SingleVariableDeclaration node) { this.buffer.append(" ");//$NON-NLS-1$ node.getName().accept(this); int size = node.getExtraDimensions(); - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8) { List dimensions = node.extraDimensions(); for (int i = 0; i < size; i++) { visit((Dimension) dimensions.get(i)); @@ -1673,7 +1773,7 @@ public boolean visit(TryStatement node) { if (!resources.isEmpty()) { this.buffer.append('('); for (Iterator it = resources.iterator(); it.hasNext(); ) { - VariableDeclarationExpression variable = (VariableDeclarationExpression) it.next(); + Expression variable = (Expression) it.next(); variable.accept(this); if (it.hasNext()) { this.buffer.append(';'); @@ -1811,7 +1911,7 @@ public boolean visit(TypeMethodReference node) { * @since 3.1 */ public boolean visit(TypeParameter node) { - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8) { printModifiers(node.modifiers()); } node.getName().accept(this); @@ -1843,6 +1943,16 @@ public boolean visit(UnionType node) { return false; } + @Override + public boolean visit(UsesDirective node) { + printIndent(); + this.buffer.append("uses");//$NON-NLS-1$ + this.buffer.append(" ");//$NON-NLS-1$ + node.getName().accept(this); + this.buffer.append(";\n");//$NON-NLS-1$ + return false; + } + /* * @see ASTVisitor#visit(VariableDeclarationExpression) */ @@ -1871,7 +1981,7 @@ public boolean visit(VariableDeclarationExpression node) { public boolean visit(VariableDeclarationFragment node) { node.getName().accept(this); int size = node.getExtraDimensions(); - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8) { List dimensions = node.extraDimensions(); for (int i = 0; i < size; i++) { visit((Dimension) dimensions.get(i)); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java index 4f21b8ecf4..061f53e469 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -112,6 +112,9 @@ public final class ASTRewriteAnalyzer extends ASTVisitor { /** @deprecated using deprecated code */ private static final SimplePropertyDescriptor INTERNAL_VDS_MODIFIERS_PROPERTY = VariableDeclarationStatement.MODIFIERS_PROPERTY; + /** @deprecated using deprecated code */ + private static final ChildListPropertyDescriptor INTERNAL_TRY_STATEMENT_RESOURCES_PROPERTY = TryStatement.RESOURCES_PROPERTY; + /** @deprecated using deprecated code */ private static final int JLS2_INTERNAL = AST.JLS2; @@ -121,6 +124,11 @@ public final class ASTRewriteAnalyzer extends ASTVisitor { /** @deprecated using deprecated code */ private static final int JLS4_INTERNAL = AST.JLS4; + /** @deprecated using deprecated code */ + private static final int JLS8_INTERNAL = AST.JLS8; + + private static final int JLS9_INTERNAL = AST.JLS9; + TextEdit currentEdit; final RewriteEventStore eventStore; // used from inner classes @@ -1318,13 +1326,10 @@ private void rewriteExtraDimensions(int oldDim, int newDim, int pos, TextEditGro } } - /* - * Next token is a left brace. Returns the offset after the brace. For incomplete code, return the start offset. - */ - private int getPosAfterLeftBrace(int pos) { + private int getPosAfterToken(int pos, int token) { try { int nextToken= getScanner().readNext(pos, true); - if (nextToken == TerminalTokens.TokenNameLBRACE) { + if (nextToken == token) { return getScanner().getCurrentEndOffset(); } } catch (CoreException e) { @@ -1332,6 +1337,12 @@ private int getPosAfterLeftBrace(int pos) { } return pos; } + /* + * Next token is a left brace. Returns the offset after the brace. For incomplete code, return the start offset. + */ + private int getPosAfterLeftBrace(int pos) { + return getPosAfterToken(pos, TerminalTokens.TokenNameLBRACE); + } /* * Next token is try keyword. Returns the offset after 'try' keyword. For incomplete code, return the start offset. @@ -1682,6 +1693,10 @@ public boolean visit(CompilationUnit node) { return doVisitUnchangedChildren(node); } + if (node.getAST().apiLevel() >= JLS9_INTERNAL && node.getModule() != null) { + rewriteNode(node, CompilationUnit.MODULE_PROPERTY, 0, ASTRewriteFormatter.NONE); + return false; + } int startPos= rewriteNode(node, CompilationUnit.PACKAGE_PROPERTY, 0, ASTRewriteFormatter.NONE); if (getChangeKind(node, CompilationUnit.PACKAGE_PROPERTY) == RewriteEvent.INSERTED) { @@ -1851,7 +1866,7 @@ private void rewriteReturnType(MethodDeclaration node, boolean isConstructor, bo private int rewriteMethodReceiver(MethodDeclaration method, int offset) throws CoreException { offset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, offset); - if (method.getAST().apiLevel() < AST.JLS8) { + if (method.getAST().apiLevel() < JLS8_INTERNAL) { return offset; } @@ -2034,9 +2049,9 @@ public boolean visit(MethodDeclaration node) { pos= rewriteNodeList(node, MethodDeclaration.PARAMETERS_PROPERTY, pos, Util.EMPTY_STRING, ", "); //$NON-NLS-1$ pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos); - ChildListPropertyDescriptor exceptionsProperty = apiLevel < AST.JLS8 ? INTERNAL_METHOD_THROWN_EXCEPTIONS_PROPERTY : MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY; + ChildListPropertyDescriptor exceptionsProperty = apiLevel < JLS8_INTERNAL ? INTERNAL_METHOD_THROWN_EXCEPTIONS_PROPERTY : MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY; - if (apiLevel < AST.JLS8) { + if (apiLevel < JLS8_INTERNAL) { int extraDims= rewriteExtraDimensions(node, INTERNAL_METHOD_EXTRA_DIMENSIONS_PROPERTY, pos); boolean hasExceptionChanges= isChanged(node, exceptionsProperty); @@ -2063,6 +2078,43 @@ public boolean visit(MethodDeclaration node) { return false; } + @Override + public boolean visit(ModuleDeclaration node) { + if (!hasChildrenChanges(node)) { + return doVisitUnchangedChildren(node); + } + int pos= rewriteJavadoc(node, ModuleDeclaration.JAVADOC_PROPERTY); + pos= rewriteModifiers2(node, ModuleDeclaration.ANNOTATIONS_PROPERTY, pos); + + RewriteEvent event= getEvent(node, ModuleDeclaration.OPEN_PROPERTY); + if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) { + boolean fakeInModule = getScanner().getScanner().fakeInModule; + try { + boolean wasOpen= ((Boolean) event.getOriginalValue()).booleanValue(); + if (wasOpen) { + this.tokenScanner.getScanner().fakeInModule = true; + int endPos= getScanner().getTokenStartOffset(TerminalTokens.TokenNamemodule, pos); + doTextRemove(pos, endPos - pos, getEditGroup(event)); + } else { + doTextInsert(pos, "open ", getEditGroup(event)); //$NON-NLS-1$ + } + } catch (CoreException e) { + handleException(e); + } finally { + this.tokenScanner.getScanner().fakeInModule = fakeInModule; + } + } + + pos= rewriteRequiredNode(node, ModuleDeclaration.NAME_PROPERTY); + int startPos = getPosAfterLeftBrace(pos); + int startIndent= getIndent(node.getStartPosition()) + 1; + boolean fakeInModule = this.tokenScanner.getScanner().fakeInModule; + this.tokenScanner.getScanner().fakeInModule = true; + rewriteParagraphList(node, ModuleDeclaration.MODULE_DIRECTIVES_PROPERTY, startPos, startIndent, 0, 1); + this.tokenScanner.getScanner().fakeInModule = fakeInModule; + return false; + } + /* (non-Javadoc) * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Block) */ @@ -2102,6 +2154,16 @@ public boolean visit(ReturnStatement node) { return false; } + @Override + public boolean visit(RequiresDirective node) { + if (!hasChildrenChanges(node)) { + return doVisitUnchangedChildren(node); + } + int pos = getPosAfterToken(node.getStartPosition(), TerminalTokens.TokenNamerequires); + rewriteNodeList(node, RequiresDirective.MODIFIERS_PROPERTY, pos, String.valueOf(' '), String.valueOf(' '), String.valueOf(' ')); + rewriteRequiredNode(node, RequiresDirective.NAME_PROPERTY); + return false; + } /* (non-Javadoc) * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(AnonymousClassDeclaration) @@ -2141,7 +2203,7 @@ public boolean visit(ArrayCreation node) { ArrayType arrayType= (ArrayType) getOriginalValue(node, ArrayCreation.TYPE_PROPERTY); ArrayType replacingType= arrayType; int nOldBrackets= getDimensions(arrayType); // number of total brackets - boolean astLevelGTE8 = node.getAST().apiLevel() >= AST.JLS8; + boolean astLevelGTE8 = node.getAST().apiLevel() >= JLS8_INTERNAL; boolean typeReplaced = false; TextEditGroup editGroup= null; @@ -2314,7 +2376,7 @@ protected int retrieveRightBracketEndPosition(int offset, int count, boolean isL } private Type getElementType(ArrayType parent) { - if (parent.getAST().apiLevel() >= AST.JLS8) { + if (parent.getAST().apiLevel() >= JLS8_INTERNAL) { return (Type) getOriginalValue(parent, ArrayType.ELEMENT_TYPE_PROPERTY); } Type t = (Type) getOriginalValue(parent, INTERNAL_ARRAY_COMPONENT_TYPE_PROPERTY); @@ -2325,7 +2387,7 @@ private Type getElementType(ArrayType parent) { } private int getDimensions(ArrayType parent) { - if (parent.getAST().apiLevel() >= AST.JLS8) { + if (parent.getAST().apiLevel() >= JLS8_INTERNAL) { return ((List) getOriginalValue(parent, ArrayType.DIMENSIONS_PROPERTY)).size(); } Type t = (Type) getOriginalValue(parent, INTERNAL_ARRAY_COMPONENT_TYPE_PROPERTY); @@ -2361,7 +2423,7 @@ public boolean visit(ArrayType node) { if (!hasChildrenChanges(node)) { return doVisitUnchangedChildren(node); } - if (node.getAST().apiLevel() < AST.JLS8) { + if (node.getAST().apiLevel() < JLS8_INTERNAL) { rewriteRequiredNode(node, INTERNAL_ARRAY_COMPONENT_TYPE_PROPERTY); } else { int pos = rewriteRequiredNode(node, ArrayType.ELEMENT_TYPE_PROPERTY); @@ -2640,6 +2702,16 @@ public boolean visit(EmptyStatement node) { return false; } + @Override + public boolean visit(ExportsDirective node) { + if (!hasChildrenChanges(node)) { + return doVisitUnchangedChildren(node); + } + int pos = rewriteRequiredNode(node, ExportsDirective.NAME_PROPERTY); + rewriteNodeList(node, ExportsDirective.MODULES_PROPERTY, pos, "to ", ", "); //$NON-NLS-1$ //$NON-NLS-2$ + + return false; + } /* (non-Javadoc) * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ExpressionStatement) */ @@ -3204,7 +3276,7 @@ public boolean visit(PrimitiveType node) { if (!hasChildrenChanges(node)) { return doVisitUnchangedChildren(node); } - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { rewriteTypeAnnotations(node, PrimitiveType.ANNOTATIONS_PROPERTY, node.getStartPosition()); } PrimitiveType.Code newCode= (PrimitiveType.Code) getNewValue(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY); @@ -3213,6 +3285,15 @@ public boolean visit(PrimitiveType node) { return false; } + @Override + public boolean visit(ProvidesDirective node) { + if (!hasChildrenChanges(node)) { + return doVisitUnchangedChildren(node); + } + int pos = rewriteRequiredNode(node, ProvidesDirective.NAME_PROPERTY); + pos= rewriteNodeList(node, ProvidesDirective.IMPLEMENTATIONS_PROPERTY, pos, " with ", ", "); //$NON-NLS-1$ //$NON-NLS-2$ + return false; + } /* (non-Javadoc) * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(QualifiedName) */ @@ -3246,7 +3327,7 @@ public boolean visit(SimpleType node) { if (!hasChildrenChanges(node)) { return doVisitUnchangedChildren(node); } - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { rewriteTypeAnnotations(node, SimpleType.ANNOTATIONS_PROPERTY, node.getStartPosition()); } rewriteRequiredNode(node, SimpleType.NAME_PROPERTY); @@ -3272,7 +3353,7 @@ public boolean visit(SingleVariableDeclaration node) { if (isChanged(node, SingleVariableDeclaration.VARARGS_PROPERTY)) { TextEditGroup editGroup = getEditGroup(node, SingleVariableDeclaration.VARARGS_PROPERTY); if (getNewValue(node, SingleVariableDeclaration.VARARGS_PROPERTY).equals(Boolean.TRUE)) { - if (apiLevel >= AST.JLS8) { + if (apiLevel >= JLS8_INTERNAL) { pos= rewriteVarargsAnnotations(node, SingleVariableDeclaration.VARARGS_ANNOTATIONS_PROPERTY, pos); } int indent= getIndent(node.getStartPosition()); @@ -3282,7 +3363,7 @@ public boolean visit(SingleVariableDeclaration node) { } else { try { int ellipsisEnd; - int noOfAnnotations = apiLevel >= AST.JLS8 ? node.varargsAnnotations().size() : 0; + int noOfAnnotations = apiLevel >= JLS8_INTERNAL ? node.varargsAnnotations().size() : 0; if (noOfAnnotations > 0) { Annotation annotation= (Annotation) node.varargsAnnotations().get(noOfAnnotations - 1); int annotationEndPosition= annotation.getStartPosition() + annotation.getLength(); @@ -3296,7 +3377,7 @@ public boolean visit(SingleVariableDeclaration node) { } } } else { - if (apiLevel >= AST.JLS8 && node.isVarargs()) { + if (apiLevel >= JLS8_INTERNAL && node.isVarargs()) { pos = rewriteVarargsAnnotations(node, SingleVariableDeclaration.VARARGS_ANNOTATIONS_PROPERTY, pos); } } @@ -3308,7 +3389,7 @@ public boolean visit(SingleVariableDeclaration node) { } pos= rewriteRequiredNode(node, SingleVariableDeclaration.NAME_PROPERTY); - if (apiLevel < AST.JLS8) { + if (apiLevel < JLS8_INTERNAL) { int extraDims= rewriteExtraDimensions(node, INTERNAL_VARIABLE_EXTRA_DIMENSIONS_PROPERTY, pos); if (extraDims > 0) { @@ -3613,14 +3694,16 @@ public boolean visit(TryStatement node) { return doVisitUnchangedChildren(node); } int pos= node.getStartPosition(); - if (node.getAST().apiLevel() >= JLS4_INTERNAL) { - if (isChanged(node, TryStatement.RESOURCES_PROPERTY)) { + int level = node.getAST().apiLevel(); + if (level >= JLS4_INTERNAL) { + StructuralPropertyDescriptor desc = level < JLS9_INTERNAL ? INTERNAL_TRY_STATEMENT_RESOURCES_PROPERTY : TryStatement.RESOURCES2_PROPERTY; + if (isChanged(node, desc)) { int indent= getIndent(node.getStartPosition()); String prefix= this.formatter.TRY_RESOURCES.getPrefix(indent); String newParen = this.formatter.TRY_RESOURCES_PAREN.getPrefix(indent) + "("; //$NON-NLS-1$ - pos= rewriteNodeList(node, TryStatement.RESOURCES_PROPERTY, getPosAfterTry(pos), newParen, ")", ";" + prefix); //$NON-NLS-1$ //$NON-NLS-2$ + pos= rewriteNodeList(node, desc, getPosAfterTry(pos), newParen, ")", ";" + prefix); //$NON-NLS-1$ //$NON-NLS-2$ } else { - pos= doVisit(node, TryStatement.RESOURCES_PROPERTY, pos); + pos= doVisit(node, desc, pos); } } @@ -3676,7 +3759,16 @@ public boolean visit(UnionType node) { rewriteNodeList(node, UnionType.TYPES_PROPERTY, node.getStartPosition(), Util.EMPTY_STRING, " | "); //$NON-NLS-1$ return false; } - + + @Override + public boolean visit(UsesDirective node) { + if (!hasChildrenChanges(node)) { + return doVisitUnchangedChildren(node); + } + rewriteRequiredNode(node,UsesDirective.NAME_PROPERTY); + return false; + } + /* (non-Javadoc) * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(VariableDeclarationExpression) */ @@ -3707,7 +3799,7 @@ public boolean visit(VariableDeclarationFragment node) { int pos= rewriteRequiredNode(node, VariableDeclarationFragment.NAME_PROPERTY); - if (node.getAST().apiLevel() < AST.JLS8) { + if (node.getAST().apiLevel() < JLS8_INTERNAL) { int extraDims= rewriteExtraDimensions(node, INTERNAL_FRAGMENT_EXTRA_DIMENSIONS_PROPERTY, pos); if (extraDims > 0) { int kind= getChangeKind(node, VariableDeclarationFragment.INITIALIZER_PROPERTY); @@ -4143,6 +4235,18 @@ public boolean visit(Modifier node) { doTextReplace(node.getStartPosition(), node.getLength(), newText, group); return false; } + /* (non-Javadoc) + * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ModuleModifier) + */ + public boolean visit(ModuleModifier node) { + if (!hasChildrenChanges(node)) { + return doVisitUnchangedChildren(node); + } + String newText= getNewValue(node, ModuleModifier.KEYWORD_PROPERTY).toString(); // type ModuleModifier.ModuleModifierKeyword + TextEditGroup group = getEditGroup(node, ModuleModifier.KEYWORD_PROPERTY); + doTextReplace(node.getStartPosition(), node.getLength(), newText, group); + return false; + } /* (non-Javadoc) * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NormalAnnotation) */ @@ -4210,7 +4314,7 @@ public boolean visit(QualifiedType node) { return doVisitUnchangedChildren(node); } int pos = rewriteRequiredNode(node, QualifiedType.QUALIFIER_PROPERTY); - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { try { pos = getScanner().getTokenEndOffset(TerminalTokens.TokenNameDOT, pos); rewriteTypeAnnotations(node, QualifiedType.ANNOTATIONS_PROPERTY, pos); @@ -4267,7 +4371,7 @@ public boolean visit(TypeParameter node) { return doVisitUnchangedChildren(node); } int pos; - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { pos = rewriteModifiers2(node, TypeParameter.MODIFIERS_PROPERTY, node.getStartPosition()); } pos= rewriteRequiredNode(node, TypeParameter.NAME_PROPERTY); @@ -4281,7 +4385,7 @@ public boolean visit(WildcardType node) { if (!hasChildrenChanges(node)) { return doVisitUnchangedChildren(node); } - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { rewriteTypeAnnotations(node, WildcardType.ANNOTATIONS_PROPERTY, node.getStartPosition()); } try { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java index 33a4b20760..e795889f37 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -69,6 +69,9 @@ public class ASTRewriteFlattener extends ASTVisitor { /** @deprecated using deprecated code */ private static final SimplePropertyDescriptor INTERNAL_VDS_MODIFIERS_PROPERTY = VariableDeclarationStatement.MODIFIERS_PROPERTY; + /** @deprecated using deprecated code */ + private static final ChildListPropertyDescriptor INTERNAL_TRY_STATEMENT_RESOURCES_PROPERTY = TryStatement.RESOURCES_PROPERTY; + /** @deprecated using deprecated code */ private static final int JLS2_INTERNAL = AST.JLS2; @@ -78,6 +81,11 @@ public class ASTRewriteFlattener extends ASTVisitor { /** @deprecated using deprecated code */ private static final int JLS4_INTERNAL = AST.JLS4; + /** @deprecated using deprecated code */ + private static final int JLS8_INTERNAL = AST.JLS8; + + private static final int JLS9_INTERNAL = AST.JLS9; + public static String asString(ASTNode node, RewriteEventStore store) { ASTRewriteFlattener flattener= new ASTRewriteFlattener(store); @@ -152,6 +160,7 @@ public static void printModifiers(int modifiers, StringBuffer buf) { } } + protected List getChildList(ASTNode parent, StructuralPropertyDescriptor childProperty) { return (List) getAttribute(parent, childProperty); } @@ -197,7 +206,7 @@ protected void visitList(ASTNode parent, StructuralPropertyDescriptor childPrope } private void visitExtraDimensions(ASTNode node, SimplePropertyDescriptor dimensions, ChildListPropertyDescriptor dimensionsInfo) { - if (node.getAST().apiLevel() < AST.JLS8) { + if (node.getAST().apiLevel() < JLS8_INTERNAL) { int extraDimensions= getIntAttribute(node, dimensions); for (int i = 0; i < extraDimensions; i++) { this.result.append("[]"); //$NON-NLS-1$ @@ -238,7 +247,7 @@ public boolean visit(ArrayCreation node) { // get the element type and count dimensions Type elementType; int dimensions; - boolean astLevelGTE8 = node.getAST().apiLevel() >= AST.JLS8; + boolean astLevelGTE8 = node.getAST().apiLevel() >= JLS8_INTERNAL; if (astLevelGTE8) { elementType = (Type) getChildNode(arrayType, ArrayType.ELEMENT_TYPE_PROPERTY); dimensions = getChildList(arrayType, ArrayType.DIMENSIONS_PROPERTY).size(); @@ -297,7 +306,7 @@ public boolean visit(ArrayInitializer node) { * @see ASTVisitor#visit(ArrayType) */ public boolean visit(ArrayType node) { - if (node.getAST().apiLevel() < AST.JLS8) { + if (node.getAST().apiLevel() < JLS8_INTERNAL) { getChildNode(node, INTERNAL_ARRAY_COMPONENT_TYPE_PROPERTY).accept(this); this.result.append("[]"); //$NON-NLS-1$ } else { @@ -428,10 +437,13 @@ public boolean visit(ClassInstanceCreation node) { return false; } - /* - * @see ASTVisitor#visit(CompilationUnit) - */ + @Override public boolean visit(CompilationUnit node) { + ASTNode module= getChildNode(node, CompilationUnit.MODULE_PROPERTY); + if (module != null) { + module.accept(this); + } + ASTNode pack= getChildNode(node, CompilationUnit.PACKAGE_PROPERTY); if (pack != null) { pack.accept(this); @@ -517,6 +529,19 @@ public boolean visit(EmptyStatement node) { return false; } + @Override + public boolean visit(ExportsDirective node) { + this.result.append("exports "); //$NON-NLS-1$ + getChildNode(node, ExportsDirective.NAME_PROPERTY).accept(this); + List modules = node.modules(); + if (modules.size() > 0) { + this.result.append(" to "); //$NON-NLS-1$ + visitList(node, ExportsDirective.MODULES_PROPERTY, Util.COMMA_SEPARATOR, Util.EMPTY_STRING, Util.EMPTY_STRING); + } + this.result.append(';'); + return false; + } + /* * @see ASTVisitor#visit(ExpressionStatement) */ @@ -737,7 +762,7 @@ public boolean visit(MethodDeclaration node) { getChildNode(node, MethodDeclaration.NAME_PROPERTY).accept(this); this.result.append('('); // receiver parameter - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { ASTNode receiverType = getChildNode(node, MethodDeclaration.RECEIVER_TYPE_PROPERTY); if (receiverType != null) { receiverType.accept(this); @@ -758,7 +783,7 @@ public boolean visit(MethodDeclaration node) { this.result.append(')'); visitExtraDimensions(node, INTERNAL_METHOD_EXTRA_DIMENSIONS_PROPERTY, MethodDeclaration.EXTRA_DIMENSIONS2_PROPERTY); - ChildListPropertyDescriptor exceptionsProperty = node.getAST().apiLevel() < AST.JLS8 ? + ChildListPropertyDescriptor exceptionsProperty = node.getAST().apiLevel() < JLS8_INTERNAL ? INTERNAL_METHOD_THROWN_EXCEPTIONS_PROPERTY : MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY; visitList(node, exceptionsProperty, String.valueOf(','), " throws ", Util.EMPTY_STRING); //$NON-NLS-1$ ASTNode body= getChildNode(node, MethodDeclaration.BODY_PROPERTY); @@ -770,6 +795,24 @@ public boolean visit(MethodDeclaration node) { return false; } + @Override + public boolean visit(ModuleDeclaration node) { + ASTNode javadoc= getChildNode(node, ModuleDeclaration.JAVADOC_PROPERTY); + if (javadoc != null) { + javadoc.accept(this); + } + visitList(node, ModuleDeclaration.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); + if (getBooleanAttribute(node, ModuleDeclaration.OPEN_PROPERTY)) { + this.result.append("open ");//$NON-NLS-1$ + } + this.result.append("module "); //$NON-NLS-1$ + getChildNode(node, ModuleDeclaration.NAME_PROPERTY).accept(this); + this.result.append('{'); + visitList(node, ModuleDeclaration.MODULE_DIRECTIVES_PROPERTY, null); + this.result.append('}'); + return false; + } + /* * @see ASTVisitor#visit(MethodInvocation) */ @@ -851,11 +894,21 @@ public boolean visit(PrefixExpression node) { return false; } + @Override + public boolean visit(ProvidesDirective node) { + this.result.append("provides "); //$NON-NLS-1$ + getChildNode(node, ProvidesDirective.NAME_PROPERTY).accept(this); + this.result.append(" with "); //$NON-NLS-1$ + visitList(node, ProvidesDirective.IMPLEMENTATIONS_PROPERTY, Util.EMPTY_STRING, Util.COMMA_SEPARATOR, Util.EMPTY_STRING); + this.result.append(';'); + return false; + } + /* * @see ASTVisitor#visit(PrimitiveType) */ public boolean visit(PrimitiveType node) { - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { visitList(node, PrimitiveType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); } this.result.append(getAttribute(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY).toString()); @@ -872,6 +925,15 @@ public boolean visit(QualifiedName node) { return false; } + @Override + public boolean visit(RequiresDirective node) { + this.result.append("requires "); //$NON-NLS-1$ + visitList(node, RequiresDirective.MODIFIERS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); + getChildNode(node, RequiresDirective.NAME_PROPERTY).accept(this); + this.result.append(';'); + return false; + } + /* * @see ASTVisitor#visit(ReturnStatement) */ @@ -898,7 +960,7 @@ public boolean visit(SimpleName node) { * @see ASTVisitor#visit(SimpleType) */ public boolean visit(SimpleType node) { - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { visitList(node, SimpleType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); } node.getName().accept(this); @@ -915,7 +977,7 @@ public boolean visit(SingleVariableDeclaration node) { visitList(node, SingleVariableDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); } getChildNode(node, SingleVariableDeclaration.TYPE_PROPERTY).accept(this); - if (node.getAST().apiLevel() >= AST.JLS8 && node.isVarargs()) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL && node.isVarargs()) { visitList(node, SingleVariableDeclaration.VARARGS_ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); } if (node.getAST().apiLevel() >= JLS3_INTERNAL) { @@ -1061,8 +1123,10 @@ public boolean visit(ThrowStatement node) { */ public boolean visit(TryStatement node) { this.result.append("try "); //$NON-NLS-1$ - if (node.getAST().apiLevel() >= JLS4_INTERNAL) { - visitList(node, TryStatement.RESOURCES_PROPERTY, String.valueOf(';'), String.valueOf('('), String.valueOf(')')); + int level = node.getAST().apiLevel(); + if (level >= JLS4_INTERNAL) { + StructuralPropertyDescriptor desc = level < JLS9_INTERNAL ? INTERNAL_TRY_STATEMENT_RESOURCES_PROPERTY : TryStatement.RESOURCES2_PROPERTY; + visitList(node, desc, String.valueOf(';'), String.valueOf('('), String.valueOf(')')); } getChildNode(node, TryStatement.BODY_PROPERTY).accept(this); this.result.append(' '); @@ -1146,7 +1210,15 @@ public boolean visit(UnionType node) { visitList(node, UnionType.TYPES_PROPERTY, " | ", Util.EMPTY_STRING, Util.EMPTY_STRING); //$NON-NLS-1$ return false; } - + + @Override + public boolean visit(UsesDirective node) { + this.result.append("uses "); //$NON-NLS-1$ + getChildNode(node, UsesDirective.NAME_PROPERTY).accept(this); + this.result.append(';'); + return false; + } + /* * @see ASTVisitor#visit(VariableDeclarationExpression) */ @@ -1426,6 +1498,15 @@ public boolean visit(Modifier node) { return false; } + /* + * @see ASTVisitor#visit(ModuleModifier) + * @since 3.14 + */ + public boolean visit(ModuleModifier node) { + this.result.append(getAttribute(node, ModuleModifier.KEYWORD_PROPERTY).toString()); + return false; + } + /* * @see ASTVisitor#visit(NormalAnnotation) * @since 3.0 @@ -1446,7 +1527,7 @@ public boolean visit(NormalAnnotation node) { public boolean visit(NameQualifiedType node) { getChildNode(node, NameQualifiedType.QUALIFIER_PROPERTY).accept(this); this.result.append('.'); - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { visitList(node, NameQualifiedType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); } getChildNode(node, NameQualifiedType.NAME_PROPERTY).accept(this); @@ -1472,7 +1553,7 @@ public boolean visit(ParameterizedType node) { public boolean visit(QualifiedType node) { getChildNode(node, QualifiedType.QUALIFIER_PROPERTY).accept(this); this.result.append('.'); - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { visitList(node, QualifiedType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); } getChildNode(node, QualifiedType.NAME_PROPERTY).accept(this); @@ -1521,7 +1602,7 @@ public boolean visit(TypeMethodReference node) { * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter) */ public boolean visit(TypeParameter node) { - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { visitList(node, TypeParameter.MODIFIERS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); } getChildNode(node, TypeParameter.NAME_PROPERTY).accept(this); @@ -1533,7 +1614,7 @@ public boolean visit(TypeParameter node) { * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType) */ public boolean visit(WildcardType node) { - if (node.getAST().apiLevel() >= AST.JLS8) { + if (node.getAST().apiLevel() >= JLS8_INTERNAL) { visitList(node, WildcardType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); } this.result.append('?'); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java index efb8893f74..3d08841fa3 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -294,6 +294,9 @@ private TextEdit formatNode(ASTNode node, String str, int indentationLevel) { case ASTNode.COMPILATION_UNIT: code= CodeFormatter.K_COMPILATION_UNIT; break; + case ASTNode.MODULE_DECLARATION: + code= CodeFormatter.K_MODULE_INFO; + break; case ASTNode.VARIABLE_DECLARATION_EXPRESSION: suffix= ";"; //$NON-NLS-1$ code= CodeFormatter.K_STATEMENTS; @@ -335,6 +338,9 @@ private TextEdit formatNode(ASTNode node, String str, int indentationLevel) { suffix= " class x {}"; //$NON-NLS-1$ code= CodeFormatter.K_COMPILATION_UNIT; break; + case ASTNode.MODULE_MODIFIER: + code= CodeFormatter.K_MODULE_INFO; + break; case ASTNode.TYPE_PARAMETER: prefix= "class X<"; //$NON-NLS-1$ suffix= "> {}"; //$NON-NLS-1$ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java index 3e7d5540ae..0c32521f00 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java @@ -51,7 +51,7 @@ public CodeSnippetClassFile( * @param creatingProblemType boolean */ this.referenceBinding = aType; - initByteArrays(); + initByteArrays(aType.methods().length + aType.fields().length); // generate the magic numbers inside the header this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 24); this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 16); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java index 24b0b5eb06..56d9142842 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at diff --git a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java index 20c5ed909a..59834c8060 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -449,7 +449,7 @@ public Binding getBinding(char[][] compoundName, int mask, InvocationSite invoca PackageBinding packageBinding = (PackageBinding) binding; while (currentIndex < length) { - binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); + binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], null); invocationSite.setFieldIndex(currentIndex); if (binding == null) { if (currentIndex == length) // must be a type if its the last name, otherwise we have no idea if its a package or type diff --git a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java index b95eccd395..6985ef4d85 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -199,6 +199,11 @@ public ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWal return walker; } @Override +public char[] getModule() { + // TODO Java 9 Auto-generated method stub + return null; +} +@Override public ExternalAnnotationStatus getExternalAnnotationStatus() { return ExternalAnnotationStatus.NOT_EEA_CONFIGURED; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java index c8391d0151..1fdfb58d1b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java @@ -321,6 +321,10 @@ public void acceptTypeParameter(char[] declaringTypePackageName, char[] declarin public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selectorEnd, char[] typeParameterName,boolean isDeclaration, int start, int end) { originalRequestor.acceptMethodTypeParameter(declaringTypePackageName, declaringTypeName, selector, selectorStart, selectorEnd, typeParameterName, isDeclaration, start, end); } + @Override + public void acceptModule(char[] moduleName, char[] uniqueKey, int start, int end) { + originalRequestor.acceptModule(moduleName, uniqueKey, start, end); + } }; } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java index b38d05b4b4..bb5ce146ee 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -160,6 +160,11 @@ public char[][] getPackageName() { public boolean ignoreOptionalProblems() { return false; } + @Override + public char[] getModuleName() { + // TODO Java 9 Auto-generated method stub + return null; + } }; CompletionEngine engine = new CompletionEngine(environment, mapper.getCompletionRequestor(requestor), options, project, owner, monitor); @@ -607,6 +612,10 @@ public char[][] getPackageName() { public boolean ignoreOptionalProblems() { return false; } + @Override + public char[] getModuleName() { + return null; + } }; SelectionEngine engine = new SelectionEngine(environment, mapper.getSelectionRequestor(requestor), options, owner); engine.select(sourceUnit, mapper.startPosOffset + selectionSourceStart, mapper.startPosOffset + selectionSourceEnd); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java index fe2da22922..3ef4235492 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -145,6 +145,11 @@ public char[][] getPackageName() { public boolean ignoreOptionalProblems() { return false; } + @Override + public char[] getModuleName() { + // TODO Java 9 Auto-generated method stub + return null; + } }}); if (compilerRequestor.hasErrors) { return null; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java index 75a8ff915a..ab3ce6c7d0 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -37,6 +37,8 @@ public abstract class CodeFormatter { /** * Kind used to format an expression *

      + * This kind is not applicable to module descriptions. + *

      * Note that using this constant, the comments encountered while formatting * the expression may be shifted to match the correct indentation but are not * formatted. @@ -51,6 +53,8 @@ public abstract class CodeFormatter { /** * Kind used to format a set of statements *

      + * This kind is not applicable to module descriptions. + *

      * Note that using this constant, the comments encountered while formatting * the statements may be shifted to match the correct indentation but are not * formatted. @@ -65,6 +69,8 @@ public abstract class CodeFormatter { /** * Kind used to format a set of class body declarations *

      + * This kind is not applicable to module descriptions. + *

      * Note that using this constant, the comments encountered while formatting * the body declarations may be shifted to match the correct indentation but * are not formatted. @@ -79,8 +85,9 @@ public abstract class CodeFormatter { /** * Kind used to format a compilation unit *

      - * Note that using this constant, the comments are only indented while - * formatting the compilation unit. + * Note: since 3.14, if the formatted compilation unit is a + * module description (i.e. it's named module-info.java), the + * {@link #K_MODULE_INFO} kind must be used instead. *

      * Since 3.4, if the corresponding comment option is set to * true then it is also possible to format the comments on the fly @@ -108,6 +115,17 @@ public abstract class CodeFormatter { */ public static final int K_JAVA_DOC = 0x40; + /** + * Kind used to format a module description (a module-info.java file). + *

      + * If the corresponding comment option is set to true then it is + * also possible to format the comments on the fly by adding the + * {@link #F_INCLUDE_COMMENTS} flag to this kind of format. + *

      + * @since 3.14 + */ + public static final int K_MODULE_INFO = 0x80; + /** * Flag used to include the comments during the formatting of the code * snippet. @@ -119,6 +137,7 @@ public abstract class CodeFormatter { *
    • {@link #K_CLASS_BODY_DECLARATIONS} (since 3.6)
    • *
    • {@link #K_EXPRESSION} (since 3.6)
    • *
    • {@link #K_STATEMENTS} (since 3.6)
    • + *
    • {@link #K_MODULE_INFO} (since 3.14)
    • *
    *

    * Note also that it has an effect only when one or several format comments @@ -201,17 +220,17 @@ public abstract class CodeFormatter { *

  • {@link #K_EXPRESSION}
  • *
  • {@link #K_STATEMENTS}
  • *
  • {@link #K_CLASS_BODY_DECLARATIONS}
  • - *
  • {@link #K_COMPILATION_UNIT}
    - * Since 3.4, the comments can be formatted on the fly while - * using this kind of code snippet
    - * (see {@link #F_INCLUDE_COMMENTS} for more detailed explanation on - * this flag) - *
  • + *
  • {@link #K_COMPILATION_UNIT}
  • + *
  • {@link #K_MODULE_INFO}
  • *
  • {@link #K_UNKNOWN}
  • *
  • {@link #K_SINGLE_LINE_COMMENT}
  • *
  • {@link #K_MULTI_LINE_COMMENT}
  • *
  • {@link #K_JAVA_DOC}
  • *
+ * Since 3.4 for {@link #K_COMPILATION_UNIT} and since 3.6 for other + * kinds unrelated to comments, the {@link #F_INCLUDE_COMMENTS} flag can be + * used to format comments on the fly (see the flag documentation for more + * detailed explanation). * @param source the source to format * @param offset the given offset to start recording the edits (inclusive). * @param length the given length to stop recording the edits (exclusive). @@ -244,17 +263,17 @@ public abstract class CodeFormatter { *
  • {@link #K_EXPRESSION}
  • *
  • {@link #K_STATEMENTS}
  • *
  • {@link #K_CLASS_BODY_DECLARATIONS}
  • - *
  • {@link #K_COMPILATION_UNIT}
    - * Since 3.4, the comments can be formatted on the fly while - * using this kind of code snippet
    - * (see {@link #F_INCLUDE_COMMENTS} for more detailed explanation on - * this flag) - *
  • + *
  • {@link #K_COMPILATION_UNIT}
  • + *
  • {@link #K_MODULE_INFO}
  • *
  • {@link #K_UNKNOWN}
  • *
  • {@link #K_SINGLE_LINE_COMMENT}
  • *
  • {@link #K_MULTI_LINE_COMMENT}
  • *
  • {@link #K_JAVA_DOC}
  • * + * Since 3.4 for {@link #K_COMPILATION_UNIT} and since 3.6 for other + * kinds unrelated to comments, the {@link #F_INCLUDE_COMMENTS} flag can be + * used to format comments on the fly (see the flag documentation for more + * detailed explanation). * @param source the source to format * @param regions a set of regions in source to format * @param indentationLevel the initial indentation level, used diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatterApplication.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatterApplication.java index d9527fc600..863e4b194b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatterApplication.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatterApplication.java @@ -27,6 +27,7 @@ import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; import org.eclipse.jdt.core.ToolFactory; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.core.util.Util; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; @@ -221,7 +222,9 @@ private void formatFile(File file, CodeFormatter codeFormatter) { String contents = new String(org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(file, null)); // format the file (the meat and potatoes) doc.set(contents); - TextEdit edit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS, contents, 0, contents.length(), 0, null); + int kind = (file.getName().equals(IModule.MODULE_INFO_JAVA)? CodeFormatter.K_MODULE_INFO + : CodeFormatter.K_COMPILATION_UNIT) | CodeFormatter.F_INCLUDE_COMMENTS; + TextEdit edit = codeFormatter.format(kind, contents, 0, contents.length(), 0, null); if (edit != null) { edit.apply(doc); } else { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java index e182aea285..21941253c4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java @@ -234,6 +234,17 @@ public class DefaultCodeFormatterConstants { * @since 3.6 */ public static final String FORMATTER_ALIGNMENT_FOR_METHOD_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.alignment_for_method_declaration"; //$NON-NLS-1$ + /** + *
    +	 * FORMATTER / Option for alignment of module statements
    +	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_module_statements"
    +	 *     - possible values:   values returned by createAlignmentValue(boolean, int, int) call
    +	 *     - default:           createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
    +	 * 
    + * @see #createAlignmentValue(boolean, int, int) + * @since 3.14 + */ + public static final String FORMATTER_ALIGNMENT_FOR_MODULE_STATEMENTS = JavaCore.PLUGIN_ID + ".formatter.alignment_for_module_statements"; //$NON-NLS-1$ /** *
     	 * FORMATTER / Option for alignment of multiple fields
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
    index 8200ee861c..b196404f1e 100644
    --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
    +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
    @@ -60,10 +60,10 @@ public class CommentsPreparator extends ASTVisitor {
     		String breakBeforeTags = "(dd|dt|li|td|th|h1|h2|h3|h4|h5|h6|q)"; //$NON-NLS-1$
     		String breakAfterTags = "(br)"; //$NON-NLS-1$
     		String noFormatTags = "(code|tt)"; //$NON-NLS-1$
    -		String otherTags = "([^<>&&\\S]++)"; //$NON-NLS-1$
    +		String otherTags = "([\\S&&[^<>]]++)"; //$NON-NLS-1$
     		String ws = "(?>[ \\t]++|[\\r\\n]++[ \\t]*+\\*?)"; // whitespace or line break with optional asterisk //$NON-NLS-1$
    -		String attributeValue = "(?>\"[^\"]*\")|(?>\'[^\']*\')|[^/>\"\'&&\\S]++"; //$NON-NLS-1$
    -		String attribute = "(?>" + ws + "+[^=&&\\S]+" + ws + "*(=)" + ws + "*(?>" + attributeValue  + "))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
    +		String attributeValue = "(?>\"[^\"]*\")|(?>\'[^\']*\')|[\\S&&[^/>\"\']]++"; //$NON-NLS-1$
    +		String attribute = "(?>" + ws + "+[\\S&&[^=]]+" + ws + "*(=)" + ws + "*(?>" + attributeValue  + "))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
     		HTML_TAG_PATTERN = Pattern.compile("<(/)?+(?:" //$NON-NLS-1$
     				+ formatCodeTags + '|' + separateLineTags + '|' + breakBeforeTags + '|' + breakAfterTags + '|' + noFormatTags + '|' + otherTags + ')'
     				+ "(" + attribute + "*)" + ws + "*/?>", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
    index e469e88697..683d70d384 100644
    --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
    +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
    @@ -1,5 +1,5 @@
     /*******************************************************************************
    - * Copyright (c) 2000, 2015 IBM Corporation and others.
    + * Copyright (c) 2000, 2017 IBM Corporation and others.
      * All rights reserved. This program and the accompanying materials
      * are made available under the terms of the Eclipse Public License v1.0
      * which accompanies this distribution, and is available at
    @@ -24,10 +24,15 @@
     import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE;
     
     import java.util.ArrayList;
    +import java.util.HashMap;
     import java.util.Arrays;
     import java.util.List;
     import java.util.Map;
     
    +import org.eclipse.core.resources.IFile;
    +import org.eclipse.core.resources.ResourcesPlugin;
    +import org.eclipse.core.runtime.Path;
    +import org.eclipse.jdt.core.ICompilationUnit;
     import org.eclipse.jdt.core.JavaCore;
     import org.eclipse.jdt.core.compiler.IProblem;
     import org.eclipse.jdt.core.compiler.InvalidInputException;
    @@ -41,8 +46,10 @@
     import org.eclipse.jdt.core.formatter.CodeFormatter;
     import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
     import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
    +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
     import org.eclipse.jdt.internal.compiler.parser.Scanner;
     import org.eclipse.jdt.internal.compiler.util.Util;
    +import org.eclipse.jdt.internal.core.PackageFragment;
     import org.eclipse.jdt.internal.formatter.linewrap.CommentWrapExecutor;
     import org.eclipse.jdt.internal.formatter.linewrap.WrapPreparator;
     import org.eclipse.jface.text.IRegion;
    @@ -67,8 +74,18 @@ public class DefaultCodeFormatter extends CodeFormatter {
     		| K_STATEMENTS
     		| K_CLASS_BODY_DECLARATIONS
     		| K_COMPILATION_UNIT
    +		| K_MODULE_INFO
     		| K_COMMENTS_MASK;
     
    +	private static final Map FORMAT_TO_PARSER_KIND = new HashMap<>();
    +	static {
    +		FORMAT_TO_PARSER_KIND.put(K_COMPILATION_UNIT, ASTParser.K_COMPILATION_UNIT);
    +		FORMAT_TO_PARSER_KIND.put(K_MODULE_INFO, ASTParser.K_COMPILATION_UNIT);
    +		FORMAT_TO_PARSER_KIND.put(K_CLASS_BODY_DECLARATIONS, ASTParser.K_CLASS_BODY_DECLARATIONS);
    +		FORMAT_TO_PARSER_KIND.put(K_STATEMENTS, ASTParser.K_STATEMENTS);
    +		FORMAT_TO_PARSER_KIND.put(K_EXPRESSION, ASTParser.K_EXPRESSION);
    +	}
    +
     	private DefaultCodeFormatterOptions originalOptions;
     	private DefaultCodeFormatterOptions workingOptions;
     
    @@ -76,7 +93,7 @@ public class DefaultCodeFormatter extends CodeFormatter {
     	private String sourceLevel;
     
     	private String sourceString;
    -	private char[] sourceArray;
    +	char[] sourceArray;
     	private List formatRegions;
     
     	private ASTNode astRoot;
    @@ -170,7 +187,7 @@ public TextEdit format(int kind, String source, IRegion[] regions, int indentati
     		return result;
     	}
     
    -	private boolean init(String source) {
    +	private boolean init(String source, int kind) {
     
     		// this is convenient for debugging (see Token.toString())
     		// Token.source = source;
    @@ -180,7 +197,7 @@ private boolean init(String source) {
     		this.tokens.clear();
     		this.tokenManager = new TokenManager(this.tokens, source, this.workingOptions);
     
    -		tokenizeSource();
    +		tokenizeSource(kind);
     		return !this.tokens.isEmpty();
     	}
     
    @@ -190,7 +207,7 @@ List prepareFormattedCode(String source) {
     	}
     
     	private List prepareFormattedCode(String source, int kind) {
    -		if (!init(source))
    +		if (!init(source, kind))
     			return null;
     
     		this.astRoot = parseSourceCode(kind);
    @@ -222,7 +239,7 @@ private void findHeader() {
     
     	private TextEdit formatComments(String source, int kind) {
     		MultiTextEdit result = new MultiTextEdit();
    -		if (!init(source))
    +		if (!init(source, kind))
     			return result;
     
     		CommentsPreparator commentsPreparator = new CommentsPreparator(this.tokenManager, this.workingOptions,
    @@ -230,12 +247,9 @@ private TextEdit formatComments(String source, int kind) {
     		CommentWrapExecutor commentWrapper = new CommentWrapExecutor(this.tokenManager, this.workingOptions);
     		switch (kind) {
     			case K_JAVA_DOC:
    -				ASTParser parser = ASTParser.newParser(AST.JLS8);
     				for (Token token : this.tokens) {
     					if (token.tokenType == TokenNameCOMMENT_JAVADOC) {
    -						parser.setSourceRange(token.originalStart, token.countChars());
    -						CompilationUnit cu = (CompilationUnit) parseSourceCode(parser, ASTParser.K_COMPILATION_UNIT,
    -								true);
    +						CompilationUnit cu = (CompilationUnit) parseSourceCode(ASTParser.K_COMPILATION_UNIT);
     						Javadoc javadoc = (Javadoc) cu.getCommentList().get(0);
     						javadoc.accept(commentsPreparator);
     						int startPosition = this.tokenManager.findSourcePositionInLine(token.originalStart);
    @@ -290,59 +304,67 @@ private TextEdit formatComments(String source, int kind) {
     	}
     
     	private ASTNode parseSourceCode(int kind) {
    -		ASTParser parser = ASTParser.newParser(AST.JLS8);
    +		kind = kind & K_MASK;
    +		if (kind != K_UNKNOWN) {
    +			ASTNode astNode = createParser(kind).createAST(null);
    +			if (kind == K_COMPILATION_UNIT || kind == K_MODULE_INFO)
    +				return astNode;
    +			return hasErrors(astNode) ? null : astNode;
    +		}
    +
    +		int[] kindsToTry = { K_COMPILATION_UNIT, K_EXPRESSION, K_CLASS_BODY_DECLARATIONS, K_STATEMENTS, K_MODULE_INFO };
    +		for (int kindToTry : kindsToTry) {
    +			ASTNode astNode = createParser(kindToTry).createAST(null);
    +			if (!hasErrors(astNode)) {
    +				if (kindToTry == K_MODULE_INFO) 
    +					tokenizeSource(kindToTry); // run scanner again to get module specific tokens
    +				return astNode;
    +			}
    +		}
    +		return null;
    +	}
    +
    +	private ASTParser createParser(int kind) {
    +		ASTParser parser = ASTParser.newParser(AST.JLS9);
    +
    +		if (kind == K_MODULE_INFO) {
    +			Path fakeModuleInfoPath = new Path("project/" + TypeConstants.MODULE_INFO_FILE_NAME_STRING); //$NON-NLS-1$
    +			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(fakeModuleInfoPath);
    +			ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file);
    +			parser.setSource(new org.eclipse.jdt.internal.core.CompilationUnit((PackageFragment) unit.getParent(),
    +					unit.getElementName(), unit.getOwner()) {
    +				@Override
    +				public char[] getContents() {
    +					return DefaultCodeFormatter.this.sourceArray;
    +				}
    +			});
    +		} else {
    +			parser.setSource(this.sourceArray);
    +		}
    +		parser.setKind(FORMAT_TO_PARSER_KIND.get(kind));
    +
     		Map parserOptions = JavaCore.getOptions();
     		parserOptions.put(CompilerOptions.OPTION_Source, this.sourceLevel);
     		parserOptions.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.ENABLED);
     		parser.setCompilerOptions(parserOptions);
    -
    -		switch (kind & K_MASK) {
    -			case K_COMPILATION_UNIT:
    -				return parseSourceCode(parser, ASTParser.K_COMPILATION_UNIT, true);
    -			case K_CLASS_BODY_DECLARATIONS:
    -				return parseSourceCode(parser, ASTParser.K_CLASS_BODY_DECLARATIONS, false);
    -			case K_STATEMENTS:
    -				return parseSourceCode(parser, ASTParser.K_STATEMENTS, false);
    -			case K_EXPRESSION:
    -				return parseSourceCode(parser, ASTParser.K_EXPRESSION, false);
    -			case K_UNKNOWN:
    -				int[] parserModes = { ASTParser.K_COMPILATION_UNIT, ASTParser.K_EXPRESSION,
    -						ASTParser.K_CLASS_BODY_DECLARATIONS, ASTParser.K_STATEMENTS };
    -				for (int parserMode : parserModes) {
    -					ASTNode astNode = parseSourceCode(parser, parserMode, false);
    -					if (astNode != null)
    -						return astNode;
    -					parser.setCompilerOptions(parserOptions); // parser loses compiler options after every use
    -				}
    -				return null;
    -			default:
    -				throw new IllegalArgumentException();
    -		}
    +		return parser;
     	}
     
    -	private ASTNode parseSourceCode(ASTParser parser, int parserMode, boolean ignoreErrors) {
    -		parser.setKind(parserMode);
    -		parser.setSource(this.sourceArray);
    -		ASTNode astNode = parser.createAST(null);
    -		if (ignoreErrors)
    -			return astNode;
    -
    -		boolean hasErrors = false;
    +	private boolean hasErrors(ASTNode astNode) {
     		CompilationUnit root = (CompilationUnit) astNode.getRoot();
     		for (IProblem problem : root.getProblems()) {
    -			if (problem.isError()) {
    -				hasErrors = true;
    -				break;
    -			}
    +			if (problem.isError())
    +				return true;
     		}
    -		return hasErrors ? null : astNode;
    +		return false;
     	}
     
    -	private void tokenizeSource() {
    +	private void tokenizeSource(int kind) {
     		this.tokens.clear();
     		Scanner scanner = new Scanner(true, false, false/* nls */, CompilerOptions.versionToJdkLevel(this.sourceLevel),
     				null/* taskTags */, null/* taskPriorities */, false/* taskCaseSensitive */);
     		scanner.setSource(this.sourceArray);
    +		scanner.fakeInModule = (kind & K_MODULE_INFO) != 0;
     		while (true) {
     			try {
     				int tokenType = scanner.getNextToken();
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
    index 8b2028fac0..c38b76dbe4 100644
    --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
    +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
    @@ -124,6 +124,7 @@ public static DefaultCodeFormatterOptions getJavaConventionsSettings() {
     	public int alignment_for_expressions_in_array_initializer;
     	public int alignment_for_expressions_in_for_loop_header;
     	public int alignment_for_method_declaration;
    +	public int alignment_for_module_statements;
     	// TODO following option cannot be set in preferences dialog (but it's used by old.CodeFormatter)
     	public int alignment_for_multiple_fields;
     	public int alignment_for_parameterized_type_references;
    @@ -460,6 +461,7 @@ public Map getMap() {
     		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER, getAlignment(this.alignment_for_expressions_in_array_initializer));
     		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_FOR_LOOP_HEADER, getAlignment(this.alignment_for_expressions_in_for_loop_header));
     		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_METHOD_DECLARATION, getAlignment(this.alignment_for_method_declaration));
    +		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MODULE_STATEMENTS, getAlignment(this.alignment_for_module_statements));
     		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS, getAlignment(this.alignment_for_multiple_fields));
     		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERIZED_TYPE_REFERENCES, getAlignment(this.alignment_for_parameterized_type_references));
     		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_CONSTRUCTOR_DECLARATION, getAlignment(this.alignment_for_parameters_in_constructor_declaration));
    @@ -897,6 +899,10 @@ public void set(Map settings) {
     				this.alignment_for_method_declaration = Alignment.M_COMPACT_SPLIT;
     			}
     		}
    +		final Object alignmentForModuleStatementsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MODULE_STATEMENTS);
    +		if (alignmentForModuleStatementsOption != null)
    +			this.alignment_for_module_statements = toInt(alignmentForModuleStatementsOption, Alignment.M_COMPACT_SPLIT);
    +
     		final Object alignmentForMultipleFieldsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS);
     		if (alignmentForMultipleFieldsOption != null) {
     			try {
    @@ -2430,6 +2436,7 @@ public void setDefaultSettings() {
     		this.alignment_for_expressions_in_array_initializer = Alignment.M_COMPACT_SPLIT;
     		this.alignment_for_expressions_in_for_loop_header = Alignment.M_NO_ALIGNMENT;
     		this.alignment_for_method_declaration = Alignment.M_NO_ALIGNMENT;
    +		this.alignment_for_module_statements = Alignment.M_COMPACT_SPLIT;
     		this.alignment_for_multiple_fields = Alignment.M_COMPACT_SPLIT;
     		this.alignment_for_parameterized_type_references = Alignment.M_NO_ALIGNMENT;
     		this.alignment_for_parameters_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
    @@ -2740,6 +2747,7 @@ public void setJavaConventionsSettings() {
     		this.alignment_for_expressions_in_array_initializer = Alignment.M_COMPACT_SPLIT;
     		this.alignment_for_expressions_in_for_loop_header = Alignment.M_NO_ALIGNMENT;
     		this.alignment_for_method_declaration = Alignment.M_NO_ALIGNMENT;
    +		this.alignment_for_module_statements = Alignment.M_COMPACT_SPLIT;
     		this.alignment_for_multiple_fields = Alignment.M_COMPACT_SPLIT;
     		this.alignment_for_parameterized_type_references = Alignment.M_NO_ALIGNMENT;
     		this.alignment_for_parameters_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
    index fb3402926b..9124dcb404 100644
    --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
    +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
    @@ -60,6 +60,8 @@
     import org.eclipse.jdt.core.dom.MethodDeclaration;
     import org.eclipse.jdt.core.dom.MethodInvocation;
     import org.eclipse.jdt.core.dom.Modifier;
    +import org.eclipse.jdt.core.dom.ModuleDeclaration;
    +import org.eclipse.jdt.core.dom.ModuleDirective;
     import org.eclipse.jdt.core.dom.NormalAnnotation;
     import org.eclipse.jdt.core.dom.PackageDeclaration;
     import org.eclipse.jdt.core.dom.ReturnStatement;
    @@ -674,6 +676,28 @@ public boolean visit(SuperConstructorInvocation node) {
     		return true;
     	}
     
    +	@Override
    +	public boolean visit(ModuleDeclaration node) {
    +		// using settings for type declaration and fields for now, add new settings if necessary
    +		breakLineBefore(node);
    +		handleBracedCode(node, node.getName(), this.options.brace_position_for_type_declaration,
    +				this.options.indent_body_declarations_compare_to_type_header,
    +				this.options.insert_new_line_in_empty_type_declaration);
    +
    +		List statements = node.moduleStatements();
    +		ModuleDirective previous = null;
    +		for (ModuleDirective statement : statements) {
    +			int blankLines = previous == null ? this.options.blank_lines_before_first_class_body_declaration
    +					: previous.getClass().equals(statement.getClass()) ? this.options.blank_lines_before_field
    +							: this.options.blank_lines_before_new_chunk;
    +			putBlankLinesBefore(statement, blankLines);
    +			previous = statement;
    +		}
    +
    +		this.declarationModifierVisited = false;
    +		return true;
    +	}
    +
     	private void breakLineBefore(ASTNode node) {
     		this.tm.firstTokenIn(node, -1).breakBefore();
     	}
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
    index 1b94472e11..865091be6c 100644
    --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
    +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
    @@ -40,6 +40,7 @@
     import org.eclipse.jdt.core.dom.EnhancedForStatement;
     import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
     import org.eclipse.jdt.core.dom.EnumDeclaration;
    +import org.eclipse.jdt.core.dom.ExportsDirective;
     import org.eclipse.jdt.core.dom.Expression;
     import org.eclipse.jdt.core.dom.ExpressionMethodReference;
     import org.eclipse.jdt.core.dom.ExpressionStatement;
    @@ -56,12 +57,16 @@
     import org.eclipse.jdt.core.dom.MemberValuePair;
     import org.eclipse.jdt.core.dom.MethodDeclaration;
     import org.eclipse.jdt.core.dom.MethodInvocation;
    +import org.eclipse.jdt.core.dom.ModuleDeclaration;
    +import org.eclipse.jdt.core.dom.Name;
     import org.eclipse.jdt.core.dom.NormalAnnotation;
    +import org.eclipse.jdt.core.dom.OpensDirective;
     import org.eclipse.jdt.core.dom.PackageDeclaration;
     import org.eclipse.jdt.core.dom.ParameterizedType;
     import org.eclipse.jdt.core.dom.ParenthesizedExpression;
     import org.eclipse.jdt.core.dom.PostfixExpression;
     import org.eclipse.jdt.core.dom.PrefixExpression;
    +import org.eclipse.jdt.core.dom.ProvidesDirective;
     import org.eclipse.jdt.core.dom.PrefixExpression.Operator;
     import org.eclipse.jdt.core.dom.ReturnStatement;
     import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
    @@ -363,7 +368,7 @@ public boolean visit(SynchronizedStatement node) {
     
     	@Override
     	public boolean visit(TryStatement node) {
    -		List resources = node.resources();
    +		List resources = node.resources();
     		if (!resources.isEmpty()) {
     			handleToken(node, TokenNameLPAREN, this.options.insert_space_before_opening_paren_in_try,
     					this.options.insert_space_after_opening_paren_in_try);
    @@ -951,6 +956,37 @@ public boolean visit(InstanceofExpression node) {
     		return true;
     	}
     
    +	@Override
    +	public boolean visit(ModuleDeclaration node) {
    +		handleToken(node.getName(), TokenNameLBRACE,
    +				this.options.insert_space_before_opening_brace_in_type_declaration, false);
    +		return true;
    +	}
    +
    +	@Override
    +	public boolean visit(ExportsDirective node) {
    +		handleModuleStatementCommas(node.modules());
    +		return true;
    +	}
    +	
    +	@Override
    +	public boolean visit(OpensDirective node) {
    +		handleModuleStatementCommas(node.modules());
    +		return true;
    +	}
    +
    +	@Override
    +	public boolean visit(ProvidesDirective node) {
    +		handleModuleStatementCommas(node.implementations());
    +		return true;
    +	}
    +
    +	private void handleModuleStatementCommas(List names) {
    +		// using settings for fields for now, add new settings if necessary
    +		handleCommas(names, this.options.insert_space_before_comma_in_multiple_field_declarations,
    +				this.options.insert_space_after_comma_in_multiple_field_declarations);
    +	}
    +
     	private void handleCommas(List nodes, boolean spaceBefore, boolean spaceAfter) {
     		if (spaceBefore || spaceAfter) {
     			for (int i = 1; i < nodes.size(); i++) {
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
    index b45e6d402f..404b1a4675 100644
    --- a/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
    +++ b/jdt-patch/e47/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
    @@ -34,6 +34,8 @@
     import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamesuper;
     import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamethis;
     import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamethrows;
    +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameto;
    +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewith;
     
     import java.util.ArrayList;
     import java.util.Collections;
    @@ -55,6 +57,7 @@
     import org.eclipse.jdt.core.dom.CreationReference;
     import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
     import org.eclipse.jdt.core.dom.EnumDeclaration;
    +import org.eclipse.jdt.core.dom.ExportsDirective;
     import org.eclipse.jdt.core.dom.Expression;
     import org.eclipse.jdt.core.dom.ExpressionMethodReference;
     import org.eclipse.jdt.core.dom.FieldAccess;
    @@ -67,8 +70,11 @@
     import org.eclipse.jdt.core.dom.LambdaExpression;
     import org.eclipse.jdt.core.dom.MethodDeclaration;
     import org.eclipse.jdt.core.dom.MethodInvocation;
    +import org.eclipse.jdt.core.dom.Name;
     import org.eclipse.jdt.core.dom.NormalAnnotation;
    +import org.eclipse.jdt.core.dom.OpensDirective;
     import org.eclipse.jdt.core.dom.ParameterizedType;
    +import org.eclipse.jdt.core.dom.ProvidesDirective;
     import org.eclipse.jdt.core.dom.QualifiedName;
     import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
     import org.eclipse.jdt.core.dom.Statement;
    @@ -779,6 +785,34 @@ private void handleTypeArguments(List typeArguments) {
     		handleWrap(this.options.alignment_for_type_arguments);
     	}
     
    +	@Override
    +	public boolean visit(ExportsDirective node) {
    +		handleModuleStatement(node.modules(), TokenNameto);
    +		return true;
    +	}
    +
    +	@Override
    +	public boolean visit(OpensDirective node) {
    +		handleModuleStatement(node.modules(), TokenNameto);
    +		return true;
    +	}
    +
    +	@Override
    +	public boolean visit(ProvidesDirective node) {
    +		handleModuleStatement(node.implementations(), TokenNamewith);
    +		return true;
    +	}
    +
    +	private void handleModuleStatement(List names, int joiningTokenType) {
    +		if (names.isEmpty())
    +			return;
    +		int joiningTokenIndex = this.tm.firstIndexBefore(names.get(0), joiningTokenType);
    +		this.wrapParentIndex = this.tm.firstIndexBefore(names.get(0), TokenNameIdentifier);
    +		this.wrapIndexes.add(joiningTokenIndex);
    +		prepareElementsList(names, TokenNameCOMMA, -1);
    +		handleWrap(this.options.alignment_for_module_statements, PREFERRED);
    +	}
    +
     	/**
     	 * Makes sure all new lines within given node will have wrap policy so that
     	 * wrap executor will fix their indentation if necessary.
    @@ -1030,7 +1064,7 @@ protected boolean token(Token token, int index) {
     		int endingBreaks = getLineBreaksToPreserve(last, null, false);
     		if (endingBreaks > 0) {
     			last.putLineBreaksAfter(endingBreaks);
    -		} else if ((this.kind & CodeFormatter.K_COMPILATION_UNIT) != 0
    +		} else if ((this.kind & (CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.K_MODULE_INFO)) != 0
     				&& this.options.insert_new_line_at_end_of_file_if_missing) {
     			last.breakAfter();
     		}
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/grammar/java.g b/jdt-patch/e47/org.eclipse.jdt.core/grammar/java.g
    index 7b7ffdeb5d..41761de113 100644
    --- a/jdt-patch/e47/org.eclipse.jdt.core/grammar/java.g
    +++ b/jdt-patch/e47/org.eclipse.jdt.core/grammar/java.g
    @@ -48,7 +48,7 @@ $Terminals
     	interface long native new null package private
     	protected public return short static strictfp super switch
     	synchronized this throw throws transient true try void
    -	volatile while
    +	volatile while module open requires transitive exports opens to uses provides with
     
     	IntegerLiteral
     	LongLiteral
    @@ -418,6 +418,120 @@ InternalCompilationUnit ::= $empty
     /.$putCase consumeEmptyInternalCompilationUnit(); $break ./
     /:$readableName CompilationUnit:/
     
    +--Java9 features
    +InternalCompilationUnit ::= ImportDeclarations ReduceImports ModuleDeclaration
    +/:$compliance 9:/
    +/.$putCase consumeInternalCompilationUnitWithModuleDeclaration(); $break ./
    +InternalCompilationUnit ::= ModuleDeclaration
    +/:$compliance 9:/
    +/.$putCase consumeInternalCompilationUnitWithModuleDeclaration(); $break ./
    +ModuleDeclaration ::= ModuleHeader ModuleBody
    +/:$compliance 9:/
    +/.$putCase consumeModuleDeclaration(); $break ./
    +
    +-- to work around shift/reduce conflicts, we allow Modifiersopt in order to support annotations
    +-- in a module declaration, and then report errors if any modifiers other than annotations are
    +-- encountered
    +ModuleHeader ::= Modifiersopt ModuleModifieropt 'module' UnannotatableName
    +/:$compliance 9:/
    +/.$putCase consumeModuleHeader(); $break ./
    +ModuleModifieropt ::= $empty
    +ModuleModifieropt ::= ModuleModifier
    +/:$compliance 9:/
    +/.$putCase consumeModuleModifiers(); $break ./
    +ModuleModifier -> 'open'
    +
    +ModuleBody ::= '{' ModuleStatementsOpt '}'
    +/:$compliance 9:/
    +/:$no_statements_recovery:/
    +ModuleStatementsOpt ::= $empty
    +/:$compliance 9:/
    +/.$putCase consumeEmptyModuleStatementsOpt(); $break ./
    +ModuleStatementsOpt -> ModuleStatements
    +/:$compliance 9:/
    +ModuleStatements ::= ModuleStatement
    +ModuleStatements ::= ModuleStatements ModuleStatement
    +/:$compliance 9:/
    +/.$putCase consumeModuleStatements(); $break ./
    +
    +ModuleStatement ::= RequiresStatement
    +/:$compliance 9:/
    +ModuleStatement ::= ExportsStatement
    +/:$compliance 9:/
    +ModuleStatement ::= OpensStatement
    +/:$compliance 9:/
    +ModuleStatement ::= UsesStatement
    +/:$compliance 9:/
    +ModuleStatement ::= ProvidesStatement
    +/:$compliance 9:/
    +
    +RequiresStatement ::=  SingleRequiresModuleName ';'
    +/:$compliance 9:/
    +/.$putCase consumeRequiresStatement(); $break ./
    +SingleRequiresModuleName ::= 'requires' RequiresModifiersopt UnannotatableName
    +/:$compliance 9:/
    +/.$putCase consumeSingleRequiresModuleName(); $break ./
    +RequiresModifiersopt ::= RequiresModifiers
    +/:$compliance 9:/
    +/.$putCase consumeModifiers(); $break ./
    +RequiresModifiersopt ::= $empty
    +/:$compliance 9:/
    +/.$putCase consumeDefaultModifiers(); $break ./
    +RequiresModifiers -> RequiresModifier
    +RequiresModifiers ::= RequiresModifiers RequiresModifier
    +/:$compliance 9:/
    +/.$putCase consumeModifiers2(); $break ./
    +RequiresModifier -> 'transitive'
    +RequiresModifier -> 'static'
    +ExportsStatement ::=  ExportsHeader TargetModuleListopt ';'
    +/:$compliance 9:/
    +/.$putCase consumeExportsStatement(); $break ./
    +ExportsHeader ::= 'exports' SinglePkgName
    +/:$compliance 9:/
    +/.$putCase consumeExportsHeader(); $break ./
    +TargetModuleListopt ::= $empty
    +TargetModuleListopt ::= 'to' TargetModuleNameList
    +/:$compliance 9:/
    +/.$putCase consumeTargetModuleList(); $break ./
    +TargetModuleName ::= UnannotatableName
    +/:$compliance 9:/
    +/.$putCase consumeSingleTargetModuleName(); $break ./
    +TargetModuleNameList -> TargetModuleName
    +TargetModuleNameList ::= TargetModuleNameList ',' TargetModuleName
    +/:$compliance 9:/
    +/.$putCase consumeTargetModuleNameList(); $break ./
    +SinglePkgName ::= UnannotatableName
    +/:$compliance 9:/
    +/.$putCase consumeSinglePkgName(); $break ./
    +OpensStatement ::=  OpensHeader TargetModuleListopt ';'
    +/:$compliance 9:/
    +/.$putCase consumeOpensStatement(); $break ./
    +OpensHeader ::= 'opens' SinglePkgName
    +/:$compliance 9:/
    +/.$putCase consumeOpensHeader(); $break ./
    +UsesStatement ::=  UsesHeader ';'
    +/:$compliance 9:/
    +/.$putCase consumeUsesStatement(); $break ./
    +UsesHeader ::= 'uses' Name
    +/.$putCase consumeUsesHeader(); $break ./
    +ProvidesStatement ::= ProvidesInterface WithClause ';'
    +/:$compliance 9:/
    +/.$putCase consumeProvidesStatement(); $break ./
    +ProvidesInterface ::= 'provides' Name
    +/:$compliance 9:/
    +/.$putCase consumeProvidesInterface(); $break ./
    +ServiceImplName ::= Name
    +/:$compliance 9:/
    +/.$putCase consumeSingleServiceImplName(); $break ./
    +ServiceImplNameList -> ServiceImplName
    +ServiceImplNameList ::= ServiceImplNameList ',' ServiceImplName
    +/:$compliance 9:/
    +/.$putCase consumeServiceImplNameList(); $break ./
    +
    +WithClause ::= 'with' ServiceImplNameList
    +/:$compliance 9:/
    +/.$putCase consumeWithClause(); $break ./
    +
     ReduceImports ::= $empty
     /.$putCase consumeReduceImports(); $break ./
     /:$readableName ReduceImports:/
    @@ -437,6 +551,12 @@ Header -> RecoveryMethodHeader
     Header -> FieldDeclaration
     Header -> AllocationHeader
     Header -> ArrayCreationHeader
    +Header -> ModuleHeader
    +Header -> RequiresStatement
    +Header -> ExportsStatement
    +Header -> UsesStatement
    +Header -> ProvidesStatement
    +Header -> OpensStatement
     /:$readableName Header:/
     
     Header1 -> Header
    @@ -1284,6 +1404,16 @@ Resource ::= Modifiers Type PushRealModifiers VariableDeclaratorId EnterVariable
     /:$readableName Resource:/
     /:$compliance 1.7:/
     
    +Resource ::= Name
    +/.$putCase consumeResourceAsLocalVariable(); $break ./
    +/:$readableName Resource:/
    +/:$compliance 1.9:/
    +
    +Resource ::= FieldAccess
    +/.$putCase consumeResourceAsFieldAccess(); $break ./
    +/:$readableName Resource:/
    +/:$compliance 1.9:/
    +
     TryBlock ::= Block ExitTryBlock
     /:$readableName Block:/
     
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/jdtCompilerAdapter.jar b/jdt-patch/e47/org.eclipse.jdt.core/jdtCompilerAdapter.jar
    index b4dc0a2e3207ba624b4033d9d9284a25d50c2350..f5a110881e3f8f63d8bb1ce4da098aa06d90c0da 100644
    GIT binary patch
    delta 769
    zcmdm6xVMlmz?+$ci-CcIf#GkSk@rMCWfm}PI#caEkk5bwSb*&OqI7+P4v>n8U({GY
    z^kg|kEeOMhQ6IvnXEcT|wlUg47)OmWd6-#57&tgM7(kjfFXgsm21{+WV98{MuzoPw
    zFbSbsuFEi4&|G|Sow>wjdHzaSh)PfW3Kj@!j?O|RK1L=HW`tKJ+n5-G{W7`O#Lgex
    zJdkG~K!D+`;}IYe;x&XB=sI{{8W?~&CYeH)5g7NKSD^o?VJ0{1QO0c|jv||K0
    zRx`jGw`r2drcK^$swIzZp9-=H#}$+Jn#xR8FcVh*shghBcitE%p9sVvaCHm}OB!D>
    zPM&BXp#`!S5zJzDi?yCJF)&q(hH%9f
    YbcDqMyjg)t7#R40uo`H(jtPhd0M3Dn8U({GY
    z^kg|kEeOMhQ6IvnXEcT|wlUg47^_%SCm%2u+U&>6$^;hKyoxoG9m2|GvSfy^!uhw!
    zLRh_q3z>MBSwt8(I5-$Uwrm#EtzZGmP5!}{$;Zef!i;eIWE&G>u6n0c0Ls~|%>V!Z
    
    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
    index b1a8f42a49..3dfe18f19d 100644
    --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
    +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
    @@ -1,5 +1,5 @@
     /*******************************************************************************
    - * Copyright (c) 2004, 2011 IBM Corporation and others.
    + * Copyright (c) 2004, 2016 IBM Corporation and others.
      * All rights reserved. This program and the accompanying materials
      * are made available under the terms of the Eclipse Public License v1.0
      * which accompanies this distribution, and is available at
    @@ -871,6 +871,30 @@ public class CompletionProposal {
     	 */
     	public static final int ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION = 27;
     
    +	/**
    +	 * Completion is a declaration of a module.
    +	 * This kind of completion might occur in a module-info.java file
    +	 * after the keyword  "module"  as shown below:
    +	 * "module co^" and complete it to
    +	 * "module com.greetings".
    +	 *
    +	 * @see #getKind()
    +	 * @since 3.14
    +	 */
    +	public static final int MODULE_DECLARATION = 28;
    +
    +	/**
    +	/**
    +	 * Completion is a reference to a module.
    +	 * This kind of completion might occur in a context like
    +	 * "requires com.g^" and complete it to
    +	 * "requires com.greetings" or in
    +	 *  "to com.g^" to "to com.greetings
    +	 *
    +	 * @see #getKind()
    +	 * @since 3.14
    +	 */
    +	public static final int MODULE_REF = 29;
     	/**
     	 * First valid completion kind.
     	 *
    @@ -883,7 +907,7 @@ public class CompletionProposal {
     	 *
     	 * @since 3.1
     	 */
    -	protected static final int LAST_KIND = ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION;
    +	protected static final int LAST_KIND = MODULE_REF;
     
     	/**
     	 * Creates a basic completion proposal. All instance
    @@ -1155,7 +1179,7 @@ public void setRelevance(int rating) {
     	}
     
     	/**
    -	 * Returns the type signature or package name of the relevant
    +	 * Returns the type signature or package name or module name (1.9) of the relevant
     	 * declaration in the context, or null if none.
     	 * 

    * This field is available for the following kinds of @@ -1180,6 +1204,8 @@ public void setRelevance(int rating) { *

  • METHOD_DECLARATION - type signature * of the type that declares the method that is being * implemented or overridden
  • + *
  • MODULE_REF - + * name of the module that is referenced
  • *
  • PACKAGE_REF - dot-based package * name of the package that is referenced
  • *
  • TYPE_IMPORT - dot-based package @@ -1194,7 +1220,7 @@ public void setRelevance(int rating) { * returned. *

    * - * @return a type signature or a package name (depending + * @return a type signature or a package name or module name (1.9) (depending * on the kind of completion), or null if none * @see Signature */ @@ -1230,7 +1256,7 @@ public char[] getDeclarationKey() { } /** - * Sets the type or package signature of the relevant + * Sets the type or package or module(1.9) signature of the relevant * declaration in the context, or null if none. *

    * If not set, defaults to none. @@ -1240,7 +1266,7 @@ public char[] getDeclarationKey() { * its properties; this method is not intended to be used by other clients. *

    * - * @param signature the type or package signature, or + * @param signature the type or package or module(1.9) signature, or * null if none */ public void setDeclarationSignature(char[] signature) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java index bdb0d5ba7a..a580135c7a 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -172,6 +172,14 @@ public final class Flags { */ public static final int AccAnnotationDefault = ClassFileConstants.AccAnnotationDefault; + /** + * Module declaration property flag. + * Used to flag a compilation unit or a class file that contains a module declaration. + * + * @since 3.14 + */ + public static final int AccModule = ClassFileConstants.AccModule; + /** * Not instantiable. */ @@ -406,6 +414,18 @@ public static boolean isAnnnotationDefault(int flags) { return (flags & AccAnnotationDefault) != 0; } + /** + * Returns whether the given integer has the AccModule + * bit set. + * + * @return true if the AccModule flag is included + * @see #AccModule + * @since 3.14 + */ + public static boolean isModule(int flags) { + return (flags & AccModule) != 0; + } + /** * Returns a standard string describing the given modifier flags. * Only modifier flags are included in the output; deprecated, diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java index 9c51ec3b07..f8df966ef7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,8 +13,12 @@ import org.eclipse.core.runtime.IProgressMonitor; /** - * Represents an entire binary type (single .class file). - * A class file has a single child of type IType. + * Represents a single .class file, holding the binary form + * of either a type or a module: + *
      + *
    • A class file of type {@link IOrdinaryClassFile} has a single child of type IType,
    • + *
    • a class file of type {@link IModularClassFile} has a single child of type IModuleDescription.
    • + *
    * Class file elements need to be opened before they can be navigated. * If a class file cannot be parsed, its structure remains unknown. Use * IJavaElement.isStructureKnown to determine whether this is the @@ -94,7 +98,10 @@ public interface IClassFile extends ITypeRoot { * This is a handle-only method. The type may or may not exist. * * @return the type contained in this class file + * @throws UnsupportedOperationException when invoked on an instance representing a modular class file. + * @deprecated should only be used as {@link IOrdinaryClassFile#getType()}. */ +@Deprecated IType getType(); /** * Returns a working copy on the source associated with this class file using the given diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java index 9bab66c543..15a16354f2 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for @@ -114,6 +114,89 @@ public interface IClasspathAttribute { */ String OPTIONAL = "optional"; //$NON-NLS-1$ + /** + * Constant for the name of the module attribute. The possible values + * for this attribute are "true" or "false". + * When not present, "false" is assumed. + * If the value of this attribute is "true", the classpath + * entry is considered to be on the module path and will be treated as a + * regular named module or as an automatic module. + * + * @since 3.14 + */ + String MODULE = "module"; //$NON-NLS-1$ + + /** + * Constant for the name of the add-exports attribute. + * + *

    The value of this attribute must adhere to the syntax of javac's + * {@code --add-exports} command line option: {@code /=(,)*}. + * Multiple such options are packed as a ':' separated list into a single classpath attribute. + * The given exports will be added at compile time.

    + *

    Classpath entries with this attribute should also have a {@link #MODULE} attribute + * with value "true".

    + * + * @since 3.14 + */ + String ADD_EXPORTS = "add-exports"; //$NON-NLS-1$ + + /** + * Constant for the name of the add-reads attribute. + * + *

    The value of this attribute must adhere to the syntax of javac's + * {@code --add-reads} command line option: {@code =}. + * The given reads edge will be added at compile time.

    + * + * @since 3.14 + */ + String ADD_READS = "add-reads"; //$NON-NLS-1$ + + /** + * Constant for the name of the patch-module attribute. + * + *

    The value of this attribute must be the name of a module defined in the + * classpath entry, to which this attribute is attached.

    + * + *

    This attribute is supported for classpath entries of kind + * {@link IClasspathEntry#CPE_CONTAINER}, {@link IClasspathEntry#CPE_LIBRARY} + * and {@link IClasspathEntry#CPE_PROJECT}. + * A classpath entry having this attribute must also have the + * {@link #MODULE} attribute with value "true".

    + * + * @since 3.14 + */ + String PATCH_MODULE = "patch-module"; //$NON-NLS-1$ + + /** + * Constant for the name of the limit-modules attribute. + * + *

    The value of this attribute must be a comma-separated list of names of modules + * defined in the classpath entry, to which this attribute is attached. + * The set of modules observable through this entry will be limited to + * the transitive closure of modules in this list.

    + * + *

    This attribute is supported for classpath entries of kind + * {@link IClasspathEntry#CPE_CONTAINER}. + * A classpath entry having this attribute must also have the + * {@link #MODULE} attribute with value "true".

    + * + * @since 3.14 + */ + String LIMIT_MODULES = "limit-modules"; //$NON-NLS-1$ + + /** + * Constant of the name of the module-main-class attribute. + * The classpath entry holding this attribute must refer to a source folder + * containing the implementation of a module. + * + *

    The value of this attribute must be the name of a class defined in this module. + * It will be used for generating the ModuleMainClass attribute + * in module-info.class.

    + * + * @since 3.14 + */ + String MODULE_MAIN_CLASS = "module-main-class"; //$NON-NLS-1$ + /** * Constant for the name of the external annotation path attribute. * diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java index 8c882fda5d..8ae34ae3cd 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java index 62b9372363..65f83063d8 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -131,6 +131,14 @@ public interface IJavaElement extends IAdaptable { */ int ANNOTATION = 16; + /** + * Constant represents a module descriptor. + * A Java element with this type can be safely cast to {@link IModuleDescription}. + * + * @since 3.14 + */ + int JAVA_MODULE = 17; + /** * Returns whether this Java element exists in the model. *

    diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java index b891c7a94e..2fe8e7c7c1 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -406,6 +406,20 @@ IPackageFragmentRoot findPackageFragmentRoot(IPath path) */ IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException; + /** + * Finds the first module with the given name found following this project's module path. + * If the returned module descriptor is part of a compilation unit, its owner is the given owner. + * @param moduleName the given module name + * @param owner the owner of the returned module descriptor's compilation unit + * + * @exception JavaModelException if this project does not exist or if an + * exception occurs while accessing its corresponding resource + * @return the first module found following this project's module path + * with the given name or null if none is found + * @since 3.14 + */ + IModuleDescription findModule(String moduleName, WorkingCopyOwner owner) throws JavaModelException; + /** * Returns all of the existing package fragment roots that exist * on the classpath, in the order they are defined by the classpath. @@ -575,6 +589,23 @@ IPackageFragmentRoot findPackageFragmentRoot(IPath path) */ IProject getProject(); + /** + * Returns the IModuleDescription this project represents or + * null if the Java project doesn't represent any named module. A Java + * project is said to represent a module if any of its source package + * fragment roots (see {@link IPackageFragmentRoot#K_SOURCE}) contains a + * valid Java module descriptor, or if one of its classpath entries + * has a valid {@link IClasspathAttribute#PATCH_MODULE} attribute. + * In the latter case the corresponding module description of the + * location referenced by that classpath entry is returned. + * + * @return the IModule this project represents. + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + * @since 3.14 + */ + IModuleDescription getModuleDescription() throws JavaModelException; + /** * Returns the raw classpath for the project, as a list of classpath * entries. This corresponds to the exact set of entries which were assigned diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModularClassFile.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModularClassFile.java new file mode 100644 index 0000000000..61e0f56dfa --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModularClassFile.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core; + +/** + * Represents the class file of a module description ("module-info.class"). + * + * @since 3.14 + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IModularClassFile extends IClassFile { + /** + * Returns the module description contained in this type root. + * An error-free {@link IModularClassFile} should always have a module. + * + * @throws JavaModelException + * @return the module description contained in the type root. + */ + @Override + IModuleDescription getModule() throws JavaModelException; +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModuleDescription.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModuleDescription.java new file mode 100644 index 0000000000..19da276ad0 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModuleDescription.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core; + +/** + * Represents a Java module descriptor. The module description could either come from source or binary. + * A simple module looks like the following: + *

    + * module my.module {
    + * 		exports my.pack1;
    + * 		exports my.pack2;
    + * 		requires java.sql;
    + * }
    + * 
    + * + * @noimplement This interface is not intended to be implemented by clients. + * @since 3.14 + */ +public interface IModuleDescription extends IMember { + // empty block +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOrdinaryClassFile.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOrdinaryClassFile.java new file mode 100644 index 0000000000..a32a3931fc --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOrdinaryClassFile.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core; + +/** + * Ordinary form of a {@link IClassFile} which holds exactly one IType. + * + * @since 3.14 + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IOrdinaryClassFile extends IClassFile { + /** + * Returns the type contained in this class file. + * This is a handle-only method. The type may or may not exist. + * + *

    This method supersedes the corresponding super method. + * This method will never throw {@link UnsupportedOperationException}.

    + * + * @return the type contained in this class file + */ + @Override + IType getType(); +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java index cea9e2be2e..f203a17823 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -75,22 +75,89 @@ public interface IPackageFragment extends IParent, IJavaElement, IOpenable, ISou * in this package (for example, "Object.class"). * The ".class" suffix is required. * This is a handle-only method. The class file may or may not be present. + *

    + * This method can handle ordinary class files or modular class files + * denoted by the name "module-info.class". + *

    * @param name the given name * @return the class file with the specified name in this package */ IClassFile getClassFile(String name); + /** + * Returns the class file with the specified name + * in this package (for example, "Object.class"). + * The ".class" suffix is required. + * This is a handle-only method. The class file may or may not be present. + *

    + * This method is not applicable to the files "module-info.class" + * as introduced in Java 9. For those please use {@link #getModularClassFile()}. + *

    + * @param name the given name + * @return the class file with the specified name in this package + * @since 3.14 + */ + IOrdinaryClassFile getOrdinaryClassFile(String name); + + /** + * Returns the class file for "module-info.class" in this package. + * This is a handle-only method. The class file may or may not be present. + * If the class file is present, then it is guaranteed to contain an {@link IModuleDescription}. + * + * @since 3.14 + * @return the class file representing "module-info.class" in this package. + */ + IModularClassFile getModularClassFile(); + /** * Returns all of the class files in this package fragment. * *

    Note: it is possible that a package fragment contains only * compilation units (in other words, its kind is K_SOURCE), in - * which case this method returns an empty collection. + * which case this method returns an empty collection.

    + * + *

    Note: the returned list may contain ordinary class files as well as + * a modular class file (for "module-info.class").

    * * @exception JavaModelException if this element does not exist or if an * exception occurs while accessing its corresponding resource. * @return all of the class files in this package fragment + * @since 3.14 */ + IClassFile[] getAllClassFiles() throws JavaModelException; + + /** + * Returns all of the ordinary class files in this package fragment. + * + *

    Note: this list never includes a modular class file + * (see {@link #getModularClassFile()}).

    + * + *

    Note: it is possible that a package fragment contains only + * compilation units (in other words, its kind is K_SOURCE), in + * which case this method returns an empty collection.

    + * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return all of the ordinary class files in this package fragment + * @deprecated Clients are advised to specifically use either {@link #getOrdinaryClassFiles()} + * or {@link #getAllClassFiles()} to express their intent. + */ + @Deprecated IClassFile[] getClassFiles() throws JavaModelException; + /** + * Returns all of the ordinary class files in this package fragment, + * i.e., not including the modular class file "module-info.class". + * + *

    Note: it is possible that a package fragment contains only + * compilation units (in other words, its kind is K_SOURCE), in + * which case this method returns an empty collection.

    + * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return all of the ordinary class files in this package fragment + * @since 3.14 + */ + IOrdinaryClassFile[] getOrdinaryClassFiles() throws JavaModelException; + /** * Returns the compilation unit with the specified name * in this package (for example, "Object.java"). diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java index c1ed588f26..79a64d0789 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -446,4 +446,17 @@ IPackageFragment createPackageFragment( * @since 2.1 */ void move(IPath destination, int updateResourceFlags, int updateModelFlags, IClasspathEntry sibling, IProgressMonitor monitor) throws JavaModelException; + + /** + * Returns the IModuleDescription that this package fragment root contains + * or null if the root doesn't contain any named module. If present the module + * descriptor is found as a child of the package fragment representing the default package. + * + * Note that only one of the source package fragment roots in a Java Project can legally + * contain a module descriptor. + * + * @return the IModuleDescription this root contains. + * @since 3.14 + */ + public IModuleDescription getModuleDescription(); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java index 97ebff6de3..1ed8d9ad30 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 IBM Corporation and others. + * Copyright (c) 2006, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -33,7 +33,18 @@ public interface ITypeRoot extends IJavaElement, IParent, IOpenable, ISourceRefe * @return the found primary type of this Java type root, or null if no such a type exists */ IType findPrimaryType(); - +/** + * Returns the module description contained in this type root or null if there is no module + * in this type root. + *

    Only subtype {@link IModularClassFile} promises to return non-null.

    + * + * @throws JavaModelException + * @since 3.14 + * @return the module description contained in the type root or null. + */ +default IModuleDescription getModule() throws JavaModelException { + return null; +} /** * Returns the smallest element within this Java type root that * includes the given source position (that is, a method, field, etc.), or diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java index 79c9b6930e..7be61f7f62 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,6 +11,7 @@ package org.eclipse.jdt.core; import java.util.StringTokenizer; +import java.util.regex.Pattern; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; @@ -38,7 +39,9 @@ public final class JavaConventions { private static final char DOT= '.'; - private static final String PACKAGE_INFO = new String(TypeConstants.PACKAGE_INFO_NAME); + private static final Pattern DOT_DOT = Pattern.compile("(\\.)(\\1)+"); //$NON-NLS-1$ + private static final Pattern TERMINAL_DIGIT = Pattern.compile("\\d$"); //$NON-NLS-1$ + private static final Pattern PREFIX_JAVA = Pattern.compile("java$"); //$NON-NLS-1$ private static final Scanner SCANNER = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/); private JavaConventions() { @@ -157,7 +160,8 @@ public static IStatus validateCompilationUnitName(String name, String sourceLeve // JSR-175 metadata strongly recommends "package-info.java" as the // file in which to store package annotations and // the package-level spec (replaces package.html) - if (!identifier.equals(PACKAGE_INFO)) { + if (!CharOperation.equals(identifier.toCharArray(), TypeConstants.PACKAGE_INFO_NAME) + && !CharOperation.equals(identifier.toCharArray(), TypeConstants.MODULE_INFO_NAME)) { IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel); if (!status.isOK()) { return status; @@ -229,7 +233,8 @@ public static IStatus validateClassFileName(String name, String sourceLevel, Str // JSR-175 metadata strongly recommends "package-info.java" as the // file in which to store package annotations and // the package-level spec (replaces package.html) - if (!identifier.equals(PACKAGE_INFO)) { + if (!CharOperation.equals(identifier.toCharArray(), TypeConstants.PACKAGE_INFO_NAME) + && !CharOperation.equals(identifier.toCharArray(), TypeConstants.MODULE_INFO_NAME)) { IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel); if (!status.isOK()) { return status; @@ -408,6 +413,7 @@ public static IStatus validateJavaTypeName(String name) { * @see JavaCore#VERSION_1_6 * @see JavaCore#VERSION_1_7 * @see JavaCore#VERSION_1_8 + * @see JavaCore#VERSION_9 */ public static IStatus validateJavaTypeName(String name, String sourceLevel, String complianceLevel) { if (name == null) { @@ -541,11 +547,8 @@ public static IStatus validatePackageName(String name, String sourceLevel, Strin if (CharOperation.isWhitespace(name.charAt(0)) || CharOperation.isWhitespace(name.charAt(name.length() - 1))) { return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_package_nameWithBlanks, null); } - int dot = 0; - while (dot != -1 && dot < length-1) { - if ((dot = name.indexOf(DOT, dot+1)) != -1 && dot < length-1 && name.charAt(dot+1) == DOT) { - return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_package_consecutiveDotsName, null); - } + if (DOT_DOT.matcher(name).find()) { + return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_package_consecutiveDotsName, null); } IWorkspace workspace = ResourcesPlugin.getWorkspace(); StringTokenizer st = new StringTokenizer(name, "."); //$NON-NLS-1$ @@ -575,6 +578,76 @@ public static IStatus validatePackageName(String name, String sourceLevel, Strin return JavaModelStatus.VERIFIED_OK; } + /** + * Validate the given module name for the given source and compliance levels. + *

    + * The syntax of a module name corresponds to ModuleName as + * defined by ModuleDeclaration (JLS 7.6). For example, "java.base". + *

    + * Note that the given name must not be empty. Also each segment of the module + * name (separated by ".") must be a valid Java identifier as per JLS 3.8. + * + * @param name name of a module + * @param sourceLevel the source level + * @param complianceLevel the compliance level + * @return a status object with code IStatus.OK if + * the given name is valid as a module name, otherwise a status + * object indicating what is wrong with the name + * @since 3.14 + */ + public static IStatus validateModuleName(String name, String sourceLevel, String complianceLevel) { + + if (name == null) { + return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_nullName, null); + } + int length; + if ((length = name.length()) == 0) { + return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_emptyName, null); + } + + if (name.charAt(0) == DOT || name.charAt(length-1) == DOT) { + return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_dotName, null); + } + if (CharOperation.isWhitespace(name.charAt(0)) || CharOperation.isWhitespace(name.charAt(name.length() - 1))) { + return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_nameWithBlanks, null); + } + if (DOT_DOT.matcher(name).find()) { + return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_consecutiveDotsName, null); + } + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + StringTokenizer st = new StringTokenizer(name, "."); //$NON-NLS-1$ + boolean firstToken = true; + IStatus warningStatus = null; + while (st.hasMoreTokens()) { + String segment = st.nextToken(); + segment = segment.trim(); // grammar allows spaces + char[] scannedID = scannedIdentifier(segment, sourceLevel, complianceLevel); + if (scannedID == null) { + return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_illegalIdentifier, segment), null); + } + if (firstToken && PREFIX_JAVA.matcher(segment).find()) { + warningStatus = new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_module_javaName), null); + } + if (TERMINAL_DIGIT.matcher(segment).find()) { + warningStatus = new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.convention_module_terminalDigits, null); + } + IStatus status = workspace.validateName(new String(scannedID), IResource.FOLDER); + if (!status.isOK()) { + return status; + } + if (firstToken && scannedID.length > 0 && ScannerHelper.isUpperCase(scannedID[0])) { + if (warningStatus == null) { + warningStatus = new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.convention_module_uppercaseName, null); + } + } + firstToken = false; + } + if (warningStatus != null) { + return warningStatus; + } + return JavaModelStatus.VERIFIED_OK; + } + /** * Validate a given classpath and output location for a project, using the following rules: *

      diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java index db6d24bba3..0261b28ce9 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java @@ -149,6 +149,7 @@ import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.core.search.SearchPattern; import org.eclipse.jdt.core.search.TypeNameRequestor; +import org.eclipse.jdt.core.util.IAttributeNamesConstants; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; @@ -169,11 +170,13 @@ import org.eclipse.jdt.internal.core.SetContainerOperation; import org.eclipse.jdt.internal.core.SetVariablesOperation; import org.eclipse.jdt.internal.core.builder.JavaBuilder; +import org.eclipse.jdt.internal.core.builder.ModuleInfoBuilder; import org.eclipse.jdt.internal.core.builder.State; import org.eclipse.jdt.internal.core.nd.indexer.Indexer; import org.eclipse.jdt.internal.core.search.indexing.IndexManager; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; +import org.eclipse.jdt.internal.core.util.ModuleUtil; import org.eclipse.jdt.internal.core.util.Util; import org.osgi.framework.BundleContext; @@ -240,6 +243,11 @@ public final class JavaCore extends Plugin { */ public static final String USER_LIBRARY_CONTAINER_ID= "org.eclipse.jdt.USER_LIBRARY"; //$NON-NLS-1$ + /** + * @since 3.13 + */ + public static final String MODULE_PATH_CONTAINER_ID = "org.eclipse.jdt.MODULE_PATH"; //$NON-NLS-1$ + // Begin configurable option IDs { /** @@ -313,7 +321,7 @@ public final class JavaCore extends Plugin { *

      "cldc1.1" requires the source version to be "1.3" and the compliance version to be "1.4" or lower.

      *
      *
      Option id:
      "org.eclipse.jdt.core.compiler.codegen.targetPlatform"
      - *
      Possible values:
      { "1.1", "cldc1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8" }
      + *
      Possible values:
      { "1.1", "cldc1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "9" }
      *
      Default:
      "1.2"
      *
      * @category CompilerOptionID @@ -405,6 +413,19 @@ public final class JavaCore extends Plugin { * @category CompilerOptionID */ public static final String COMPILER_PB_DEPRECATION = PLUGIN_ID + ".compiler.problem.deprecation"; //$NON-NLS-1$ + /** + * Compiler option ID: Reporting Terminal Deprecation. + *

      When enabled, the compiler will signal use of terminally deprecated API either as an + * error or a warning.

      + *
      + *
      Option id:
      "org.eclipse.jdt.core.compiler.problem.terminalDeprecation"
      + *
      Possible values:
      { "error", "warning", "info", "ignore" }
      + *
      Default:
      "warning"
      + *
      + * @since 3.14 + * @category CompilerOptionID + */ + public static final String COMPILER_PB_TERMINAL_DEPRECATION = PLUGIN_ID + ".compiler.problem.terminalDeprecation"; //$NON-NLS-1$ /** * Compiler option ID: Reporting Deprecation Inside Deprecated Code. *

      When enabled, the compiler will signal use of deprecated API inside deprecated code.

      @@ -1570,6 +1591,30 @@ public final class JavaCore extends Plugin { */ public static final String COMPILER_PB_UNLIKELY_EQUALS_ARGUMENT_TYPE = PLUGIN_ID + ".compiler.problem.unlikelyEqualsArgumentType"; //$NON-NLS-1$ + /** + * Compiler option ID: Reporting when public API uses a non-API type. + *

      + * This option is relevant only when compiling code in a named module (at compliance 9 or greater). + *

      + * When enabled, the compiler will issue an error or warning when public API mentions a type that is not + * accessible to clients. Here, public API refers to signatures of public fields and methods declared + * by a public type in an exported package. + * In these positions types are complained against that are either not public or not in an exported package. + * Export qualification is not taken into account. + * If a type in one of these positions is declared in another module that is required by the current module, + * but without the {@code transitive} modifier, this is reported as a problem, too. + *

      + *
      Option id:
      "org.eclipse.jdt.core.compiler.problem.APILeak"
      + *
      Possible values:
      + *
      { "error", "warning", "info", "ignore" }
      + *
      Default:
      "warning"
      + *
      + * + * @since 3.14 + * @category CompilerOptionID + */ + public static final String COMPILER_PB_API_LEAKS = PLUGIN_ID + ".compiler.problem.APILeak"; //$NON-NLS-1$ + /** * Compiler option ID: Annotation-based Null Analysis. *

      This option controls whether the compiler will use null annotations for @@ -1975,7 +2020,7 @@ public final class JavaCore extends Plugin { * set to the same version as the source level.

      *
      *
      Option id:
      "org.eclipse.jdt.core.compiler.source"
      - *
      Possible values:
      { "1.3", "1.4", "1.5", "1.6", "1.7", "1.8" }
      + *
      Possible values:
      { "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "9" }
      *
      Default:
      "1.3"
      *
      * @since 2.0 @@ -1993,7 +2038,7 @@ public final class JavaCore extends Plugin { * should match the compliance setting.

      *
      *
      Option id:
      "org.eclipse.jdt.core.compiler.compliance"
      - *
      Possible values:
      { "1.3", "1.4", "1.5", "1.6", "1.7", "1.8" }
      + *
      Possible values:
      { "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "9" }
      *
      Default:
      "1.4"
      *
      * @since 2.0 @@ -2892,6 +2937,12 @@ public final class JavaCore extends Plugin { * @category OptionValue */ public static final String VERSION_1_8 = "1.8"; //$NON-NLS-1$ + /** + * Configurable option value: {@value}. + * @since 3.14 + * @category OptionValue + */ + public static final String VERSION_9 = "9"; //$NON-NLS-1$ /** * Configurable option value: {@value}. * @since 3.4 @@ -4473,8 +4524,8 @@ public static boolean isReferencedBy(IJavaElement element, IMarker marker) throw if (element.equals(markerElement)) return true; // external elements may still be equal with different handleIDs. // cycle through enclosing types in case marker is associated with a classfile (15568) - if (markerElement instanceof IClassFile){ - IType enclosingType = ((IClassFile)markerElement).getType().getDeclaringType(); + if (markerElement instanceof IOrdinaryClassFile){ + IType enclosingType = ((IOrdinaryClassFile)markerElement).getType().getDeclaringType(); if (enclosingType != null){ markerElement = enclosingType.getClassFile(); // retry with immediate enclosing classfile continue; @@ -4516,8 +4567,8 @@ public static boolean isReferencedBy(IJavaElement element, IMarkerDelta markerDe if (element.equals(markerElement)) return true; // external elements may still be equal with different handleIDs. // cycle through enclosing types in case marker is associated with a classfile (15568) - if (markerElement instanceof IClassFile){ - IType enclosingType = ((IClassFile)markerElement).getType().getDeclaringType(); + if (markerElement instanceof IOrdinaryClassFile){ + IType enclosingType = ((IOrdinaryClassFile)markerElement).getType().getDeclaringType(); if (enclosingType != null){ markerElement = enclosingType.getClassFile(); // retry with immediate enclosing classfile continue; @@ -5846,6 +5897,14 @@ public static void setComplianceOptions(String compliance, Map options) { options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.ERROR); options.put(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE, JavaCore.ENABLED); break; + case ClassFileConstants.MAJOR_VERSION_9: + options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_9); + options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_9); + options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_9); + options.put(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR); + options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.ERROR); + options.put(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE, JavaCore.ENABLED); + break; } } @@ -5888,6 +5947,61 @@ public static void setOptions(Hashtable newOptions) { public static int compareJavaVersions(String first, String second) { return Long.compare(CompilerOptions.versionToJdkLevel(first), CompilerOptions.versionToJdkLevel(second)); } + /** + * Returns an array of module names referenced by this project indirectly. + * This is a helper method that can be used to construct a Java module + * description of an existing project. The referenced modules can either be + * system modules or user modules found in project build path in the form of + * libraries. + * The prerequisites for this to be effective are: + *
        + *
      • the project is already in compliance level 9 or above. + *
      • the system library on the build path of the project is a modularized Java Runtime. + *
      + * + * @param project + * the project whose referenced modules to be computed + * @return an array of String containing module names + * @throws CoreException + * @since 3.14 + */ + public static String[] getReferencedModules(IJavaProject project) throws CoreException { + return ModuleUtil.getReferencedModules(project); + } + + /** + * Compile the given module description in the context of its enclosing Java project + * and add class file attributes using the given map of attribute values. + *

      In this map, the following keys are supported

      + *
      + *
      {@link IAttributeNamesConstants#MODULE_MAIN_CLASS}
      + *
      The associated value will be used for the ModuleMainClass attribute.
      + *
      {@link IAttributeNamesConstants#MODULE_PACKAGES}
      + *
      If the associated value is an empty string, then the compiler will generate a + * ModulePackages attribute with a list of packages that is computed from + *
        + *
      • all exports directives + *
      • all opens directives + *
      • the implementation classes of all provides directives. + *
      + * If the associated value is not empty, it must be a comma-separated list of package names, + * which will be added to the computed list. + *
      + *

      No other keys are supported in this version, but more keys may be added in the future.

      + * + * @param module handle for the module-info.java file to be compiled. + * @param classFileAttributes map of attribute names and values to be used during class file generation + * @return the compiled byte code + * + * @throws JavaModelException + * @throws IllegalArgumentException if the map of classFileAttributes contains an unsupported key. + * @since 3.14 + */ + public static byte[] compileWithAttributes(IModuleDescription module, Map classFileAttributes) + throws JavaModelException, IllegalArgumentException + { + return new ModuleInfoBuilder().compileWithAttributes(module, classFileAttributes); + } /* (non-Javadoc) * Shutdown the JavaCore plug-in. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java index bb6d6c4521..d84f691561 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -71,6 +71,15 @@ public JavaModelException(CoreException exception) { public JavaModelException(IJavaModelStatus status) { super(status); } + +/** + * Creates a Java model exception for the given status object. + * + * @since 3.14 + */ +public JavaModelException(IStatus status) { + super(status); +} /** * Returns the underlying Throwable that caused the failure. * diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java index 38eca3b072..2da3be49d1 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2013 IBM Corporation and others. + * Copyright (c) 2005, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -88,20 +88,9 @@ public ReconcileContext(ReconcileWorkingCopyOperation operation, CompilationUnit * with JLS4 level. */ public org.eclipse.jdt.core.dom.CompilationUnit getAST3() throws JavaModelException { - if (this.operation.astLevel != AST.JLS3 || !this.operation.resolveBindings) { - // create AST (optionally resolving bindings) - ASTParser parser = ASTParser.newParser(AST.JLS3); - parser.setCompilerOptions(this.workingCopy.getJavaProject().getOptions(true)); - if (JavaProject.hasJavaNature(this.workingCopy.getJavaProject().getProject())) - parser.setResolveBindings(true); - parser.setStatementsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0); - parser.setBindingsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0); - parser.setSource(this.workingCopy); - parser.setIgnoreMethodBodies((this.operation.reconcileFlags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0); - return (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(this.operation.progressMonitor); - } - return this.operation.makeConsistent(this.workingCopy); + return getAST(AST.JLS3); } + /** * Returns a resolved AST with {@link AST#JLS4 JLS4} level. * It is created from the current state of the working copy. @@ -128,20 +117,9 @@ public org.eclipse.jdt.core.dom.CompilationUnit getAST3() throws JavaModelExcept * @since 3.7.1 */ public org.eclipse.jdt.core.dom.CompilationUnit getAST4() throws JavaModelException { - if (this.operation.astLevel != AST.JLS4 || !this.operation.resolveBindings) { - // create AST (optionally resolving bindings) - ASTParser parser = ASTParser.newParser(AST.JLS4); - parser.setCompilerOptions(this.workingCopy.getJavaProject().getOptions(true)); - if (JavaProject.hasJavaNature(this.workingCopy.getJavaProject().getProject())) - parser.setResolveBindings(true); - parser.setStatementsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0); - parser.setBindingsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0); - parser.setSource(this.workingCopy); - parser.setIgnoreMethodBodies((this.operation.reconcileFlags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0); - return (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(this.operation.progressMonitor); - } - return this.operation.makeConsistent(this.workingCopy); + return getAST(AST.JLS4); } + /** * Returns a resolved AST with {@link AST#JLS8 JLS8} level. * It is created from the current state of the working copy. @@ -163,12 +141,43 @@ public org.eclipse.jdt.core.dom.CompilationUnit getAST4() throws JavaModelExcept *
        *
      • The working copy does not exist (ELEMENT_DOES_NOT_EXIST)
      • *
      + * @deprecated JLS8 has been deprecated. This method has been replaced by {@link #getAST(int)} which returns an AST + * with the given level. * @since 3.10 */ public org.eclipse.jdt.core.dom.CompilationUnit getAST8() throws JavaModelException { - if (this.operation.astLevel != AST.JLS8 || !this.operation.resolveBindings) { + return getAST(AST.JLS8); +} + +/** + * Returns a resolved AST with the given AST level. + * It is created from the current state of the working copy. + * Creates one if none exists yet. + * Returns null if the current state of the working copy + * doesn't allow the AST to be created (e.g. if the working copy's content + * cannot be parsed). + *

      + * If the AST level requested during reconciling is not the latest available AST level + * or if binding resolutions was not requested, then a different AST is created. + * Note that this AST does not become the current AST and it is only valid for + * the requestor. + *

      + * + * @param level the API level; one of the .JLS* level constants + * declared on {@link AST} + * @return the AST created from the current state of the working copy, + * or null if none could be created + * @exception JavaModelException if the contents of the working copy + * cannot be accessed. Reasons include: + *
        + *
      • The working copy does not exist (ELEMENT_DOES_NOT_EXIST)
      • + *
      + * @since 3.14 + */ +public org.eclipse.jdt.core.dom.CompilationUnit getAST(int level) throws JavaModelException { + if (this.operation.astLevel != level || !this.operation.resolveBindings) { // create AST (optionally resolving bindings) - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(level); parser.setCompilerOptions(this.workingCopy.getJavaProject().getOptions(true)); if (JavaProject.hasJavaNature(this.workingCopy.getJavaProject().getProject())) parser.setResolveBindings(true); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/provisional/JavaModelAccess.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/provisional/JavaModelAccess.java new file mode 100644 index 0000000000..2d0d86d88a --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/provisional/JavaModelAccess.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.provisional; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.core.IClasspathAttribute; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference; +import org.eclipse.jdt.internal.core.AbstractModule; +import org.eclipse.jdt.internal.core.JavaProject; + +/** + * Provisional API for use by JDT/UI, which may possibly be removed in a future version. + * See Bug 522391. + */ +public class JavaModelAccess { + + /** + * In a Java 9 project, a classpath entry can be filtered using a {@link IClasspathAttribute#LIMIT_MODULES} attribute, + * otherwise a default set of roots is used as defined in JEP 261. + * In both cases {@link IJavaProject#findPackageFragmentRoots(IClasspathEntry)} will not contain all roots physically + * present in the container. + * This provisional API can be used to bypass any filter and get really all roots to which the given entry is resolved. + * + * @param javaProject the Java project to search in + * @param entry a classpath entry of the Java project + * @return the unfiltered array of package fragment roots to which the classpath entry resolves + */ + public static IPackageFragmentRoot[] getUnfilteredPackageFragmentRoots(IJavaProject javaProject, IClasspathEntry entry) { + try { + JavaProject internalProject = (JavaProject) javaProject; // cast should be safe since IJavaProject is @noimplement + IClasspathEntry[] resolvedEntries = internalProject.resolveClasspath(new IClasspathEntry[]{ entry }); + return internalProject.computePackageFragmentRoots(resolvedEntries, false /* not exported roots */, false /* don't filter! */, null /* no reverse map */); + } catch (JavaModelException e) { + // according to comment in JavaProject.findPackageFragmentRoots() we assume that this is caused by the project no longer existing + return new IPackageFragmentRoot[] {}; + } + } + + /** + * Answer the names of all modules directly required from the given module. + * @param module the module whose "requires" directives are queried + * @return a non-null array of module names + */ + public static String[] getRequiredModules(IModuleDescription module) throws JavaModelException { + IModuleReference[] references = ((AbstractModule) module).getRequiredModules(); + return Arrays.stream(references).map(ref -> String.valueOf(ref.name())).toArray(String[]::new); + } + + /** + * Filter the given set of system roots by the rules for root modules from JEP 261. + * @param allSystemRoots all physically available system modules, represented by their package fragment roots + * @return the list of names of default root modules + */ + public static List defaultRootModules(Iterable allSystemRoots) { + return JavaProject.defaultRootModules(allSystemRoots); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java index c301b3bea2..c1f5ec1c3b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -52,6 +52,7 @@ private static void checkASTLevel(int level) { case AST.JLS3 : case AST.JLS4 : case AST.JLS8 : + case AST.JLS9 : break; default : throw new IllegalArgumentException(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java index f6682a57a6..eca76e5f2b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -169,4 +169,22 @@ public interface IAttributeNamesConstants { * @since 3.10 */ char[] METHOD_PARAMETERS = "MethodParameters".toCharArray(); //$NON-NLS-1$ + + /** + * "Module" attribute (added in Java SE 9). + * @since 3.14 + */ + char[] MODULE = "Module".toCharArray(); //$NON-NLS-1$ + + /** + * "ModulePackages" attribute (added in Java SE 9). + * @since 3.14 + */ + char[] MODULE_PACKAGES = "ModulePackages".toCharArray(); //$NON-NLS-1$ + + /** + * "ModuleMainClass" attribute (added in Java SE 9). + * @since 3.14 + */ + char[] MODULE_MAIN_CLASS = "ModuleMainClass".toCharArray(); //$NON-NLS-1$ } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java index 3ce95da7c7..deaffd4197 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -74,9 +74,9 @@ public interface IClassFileReader { int ALL_BUT_METHOD_BODIES = ALL & ~METHOD_BODIES; /** - * Answer back the access flag of the .class file. + * Answer back the access flags of the .class file. * - * @return the access flag of the .class file + * @return the access flags of the .class file */ int getAccessFlags(); @@ -157,9 +157,9 @@ public interface IClassFileReader { int getSuperclassIndex(); /** - * Answer true if this .class file represents an class, false otherwise. + * Answer true if this .class file represents a class, false otherwise. * - * @return true if this .class file represents an class, false otherwise + * @return true if this .class file represents a class, false otherwise */ boolean isClass(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java index 9f57bb10f9..ab750ce47c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -36,11 +36,15 @@ public interface IConstantPool { /** * Answer back the entry at the given index in the constant pool. - * + * *

      The return value can be an instance of {@link IConstantPoolEntry2} if the value returned * by {@link #getEntryKind(int)} is either {@link IConstantPoolConstant#CONSTANT_MethodHandle}, * {@link IConstantPoolConstant#CONSTANT_MethodType} or {@link IConstantPoolConstant#CONSTANT_InvokeDynamic}.

      * + *

      The return value can be an instance of {@link IConstantPoolEntry3} if the value returned + * by {@link #getEntryKind(int)} is either {@link IConstantPoolConstant#CONSTANT_Module} + * or {@link IConstantPoolConstant#CONSTANT_Package}.

      + * * @param index the index of the entry in the constant pool * @return the entry at the given index in the constant pool */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java index ff6ed22c2d..c5f0401474 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -42,6 +42,15 @@ public interface IConstantPoolConstant { */ int CONSTANT_InvokeDynamic = 18; + /** + * @since 3.14 + */ + int CONSTANT_Module = 19; + /** + * @since 3.14 + */ + int CONSTANT_Package = 20; + int CONSTANT_Methodref_SIZE = 5; int CONSTANT_Class_SIZE = 3; int CONSTANT_Double_SIZE = 9; @@ -66,6 +75,15 @@ public interface IConstantPoolConstant { */ int CONSTANT_InvokeDynamic_SIZE = 5; + /** + * @since 3.14 + */ + int CONSTANT_Module_SIZE = 3; + + /** + * @since 3.14 + */ + int CONSTANT_Package_SIZE = 3; /** * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3). * @since 3.8 diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java index 343765b396..4ed570a0d7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,8 +14,11 @@ * Description of a constant pool entry as described in the JVM specifications. * Its contents is initialized according to its kind. * - * This interface may be implemented by clients. + * This interface may be implemented by clients. Because of that questionable choice, + * clients may have to cast to {@link IConstantPoolEntry3} to get access to the relevant content. * + * @see IConstantPoolEntry2 + * @see IConstantPoolEntry3 * @since 2.0 */ public interface IConstantPoolEntry { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry3.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry3.java new file mode 100644 index 0000000000..d38f7409d1 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry3.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of a constant pool entry as described in the JVM specifications. + * Its contents is initialized according to its kind. + * + * @noimplement This interface is not intended to be implemented by clients. + * @since 3.14 + */ +public interface IConstantPoolEntry3 extends IConstantPoolEntry2 { + /** + * Returns the index for a CONSTANT_Module type entry. + * The value is unspecified otherwise. + * + * @return the index for a CONSTANT_Module type entry + * @see IConstantPoolConstant#CONSTANT_Module + * @see #getModuleName() + */ + int getModuleIndex(); + + /** + * Returns the name of a CONSTANT_Module type entry. + * Returns null otherwise. + * + * @return the name of a CONSTANT_Module type entry + * @see IConstantPoolConstant#CONSTANT_Module + * @see #getModuleIndex() + */ + char[] getModuleName(); + + /** + * Returns the index for a CONSTANT_Package type entry. + * The value is unspecified otherwise. + * + * @return the index for a CONSTANT_Package type entry + * @see IConstantPoolConstant#CONSTANT_Package + * @see #getPackageName() + */ + int getPackageIndex(); + + /** + * Returns the name of a CONSTANT_Package type entry. + * Returns null otherwise. + * + * @return the name of a CONSTANT_Package type entry + * @see IConstantPoolConstant#CONSTANT_Package + * @see #getPackageIndex() + */ + char[] getPackageName(); +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModifierConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModifierConstants.java index 6af1f116e7..9f45a2b380 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModifierConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModifierConstants.java @@ -1,11 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * * Contributors: * IBM Corporation - initial API and implementation * Jesper Steen Moeller - Contribution for bug 406973 - [compiler] Parse MethodParameters attribute @@ -63,9 +62,32 @@ public interface IModifierConstants { */ int ACC_ENUM = 0x4000; + /** + * Indicates a module (added in Java SE 9). + * @since 3.14 + */ + int ACC_MODULE = 0x8000; + /** * Indicates a mandated parameter, such as this$1 (added in Java SE 8). * @since 3.10 */ int ACC_MANDATED = 0x8000; + /** + * Indicates an open module in module-info file (added in Java SE 9). + * @since 3.14 + */ + int ACC_OPEN = 0x0020; + + /** + * Indicates a transitive requires in module-info file (added in Java SE 9). + * @since 3.14 + */ + int ACC_TRANSITIVE = 0x0020; + + /** + * Indicates a static requires in module-info file (added in Java SE 9). + * @since 3.14 + */ + int ACC_STATIC_PHASE = 0x0040; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModuleAttribute.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModuleAttribute.java new file mode 100644 index 0000000000..ca1b5d5701 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModuleAttribute.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of a module's attributes as described in the JVM specifications. + * + * @noimplement This interface is not intended to be implemented by clients. + * @since 3.14 + */ +public interface IModuleAttribute extends IClassFileAttribute { + + /** + * Answer back the module name index. + * + * @return the module name index + */ + int getModuleNameIndex(); + + /** + * Answer back the module name. + * + * @return the module name + */ + char[] getModuleName(); + + /** + * Answer back the module flags. + * + * @return the module flags + */ + int getModuleFlags(); + + /** + * Answer back the module version index. + * + * @return the module version index + */ + int getModuleVersionIndex(); + + /** + * Answer back the module version string. + * + * @return the module version string + */ + public char[] getModuleVersionValue(); + + /** + * Answer back the requires count. + * + * @return the requires counts + */ + int getRequiresCount(); + + /** + * Answer back the array of requires infos of the .class file, + * an empty array if none. + * + * @return the array of requires infos of the .class file, an empty array if none + */ + IRequiresInfo[] getRequiresInfo(); + + /** + * Answer back the exports count. + * + * @return the exports counts + */ + int getExportsCount(); + + /** + * Answer back the array of exports infos of the .class file, + * an empty array if none. + * + * @return the array of exports infos of the .class file, an empty array if none + */ + IPackageVisibilityInfo[] getExportsInfo(); + + /** + * Answer back the opens count. + * + * @return the opens counts + */ + int getOpensCount(); + + /** + * Answer back the array of opens infos of the .class file, + * an empty array if none. + * + * @return the array of opens infos of the .class file, an empty array if none + */ + IPackageVisibilityInfo[] getOpensInfo(); + + /** + * Answer back the uses count. + * + * @return the uses counts + */ + int getUsesCount(); + + /** + * Answer back the array of uses indices of the .class file, + * an empty array if none. + * + * @return the array of uses indices of the .class file, an empty array if none + */ + int[] getUsesIndices(); + + /** + * Answer back the array of uses class names of the .class file, + * an empty array if none. + * + * @return the array of uses class names of the .class file, an empty array if none + */ + char[][] getUsesClassNames(); + + /** + * Answer back the provides count. + * + * @return the provides counts + */ + int getProvidesCount(); + + /** + * Answer back the array of provides infos of the .class file, + * an empty array if none. + * + * @return the array of provides infos of the .class file, an empty array if none + */ + IProvidesInfo[] getProvidesInfo(); +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModuleMainClassAttribute.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModuleMainClassAttribute.java new file mode 100644 index 0000000000..f37a4c81f3 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModuleMainClassAttribute.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of a Module Main Class Attribute as described in the JVMS9 4.7.27 + * + * This interface may be implemented by clients. + * + * @since 3.14 + */ +public interface IModuleMainClassAttribute extends IClassFileAttribute { + + /** + * Answer back the main class index. + * + * @return the main class index + */ + int getMainClassIndex(); + + /** + * Answer back the name of main class. + * + * @return the name of main class + */ + char[] getMainClassName(); +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModulePackagesAttribute.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModulePackagesAttribute.java new file mode 100644 index 0000000000..976ff18855 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModulePackagesAttribute.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of a Module Packages as described in the JVMS9 4.7.26 + * + * This interface may be implemented by clients. + * + * @since 3.14 + */ +public interface IModulePackagesAttribute extends IClassFileAttribute { + + /** + * Answer back the number of packages exported or opened. + * + * @return the number of packages exported or opened + */ + int getPackagesCount(); + + /** + * Answer back the array of package indices. + * + * @return the array of package indices. + */ + int[] getPackageIndices(); + + /** + * Answer back the names of packages. Answers an empty collection if none. + * + * @return the names of packages + */ + char[][] getPackageNames(); +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPackageVisibilityInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPackageVisibilityInfo.java new file mode 100644 index 0000000000..b510218085 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPackageVisibilityInfo.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of an exports/opens info as described in the JVM specifications 4.7.25 + * + * @noimplement This interface is not intended to be implemented by clients. + * @since 3.14 + */ +public interface IPackageVisibilityInfo { + + /** + * Answer back the exports/opens index. + * + * @return the exports/opens index + */ + int getIndex(); + + /** + * Answer back the exports/opens package. + * + * @return the exports/opens package + */ + char[] getPackageName(); + + /** + * Answer back the exports/opens flags. + * + * @return the exports/opens flags + */ + int getFlags(); + + /** + * Answer back the number of targets, zero if none. + * + * @return the number of targets, zero if none. + */ + int getTargetsCount(); + + /** + * Answer back the array of target module indices. + * + * @return the array of target module indices. + */ + int[] getTargetModuleIndices(); + + /** + * Answer back the array of target module names. + * + * @return the array of target module names. + */ + char[][] getTargetModuleNames(); +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IProvidesInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IProvidesInfo.java new file mode 100644 index 0000000000..b134fd2941 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IProvidesInfo.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of a provides info as described in JVMS9 4.7.25. + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + * @since 3.14 + */ +public interface IProvidesInfo { + + /** + * Answer back the provides index. + * + * @return the provides index + */ + int getIndex(); + + /** + * Answer back the service class/interface + * + * @return the service class/interface + */ + char[] getServiceName(); + + /** + * Answer back the number of implementations. + * + * @return the number of implementations. + */ + int getImplementationsCount(); + + /** + * Answer back the array of implementation indices. + * + * @return the array of implementation indices. + */ + int[] getImplementationIndices(); + + /** + * Answer back the array of implementation names. + * + * @return the array of implementation names. + */ + char[][] getImplementationNames(); + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRequiresInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRequiresInfo.java new file mode 100644 index 0000000000..4ab6e27dfd --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRequiresInfo.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of a requires info as described in JVMS9 4.7.25 + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + * @since 3.14 + */ +public interface IRequiresInfo { + + /** + * Answer back the requires index. + * + * @return the requires index + */ + int getRequiresIndex(); + + /** + * Answer back the requires module name. + * + * @return the requires module name + */ + char[] getRequiresModuleName(); + + /** + * Answer back the requires flags. + * + * @return the requires flags + */ + int getRequiresFlags(); + + /** + * Answer back the requires version index. + * + * @return the requires version index + */ + int getRequiresVersionIndex(); + + /** + * Answer back the requires version string. + * + * @return the requires version string + */ + public char[] getRequiresVersionValue(); + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java index 42fd7d64fd..727eb32d1e 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,6 +18,7 @@ import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.ImportReference; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; /* @@ -27,7 +28,8 @@ * * The structural investigation includes: - package statement - import * statements - top-level types: package member, member types (member types of - * member types...) - fields - methods + * member types...) - fields - methods. From Java 9 onwards it includes the + * module name in a module declaration * * If reference information is requested, then all source constructs are * investigated and type, field & method references are provided as well. @@ -46,6 +48,33 @@ @SuppressWarnings("rawtypes") public interface ISourceElementRequestor { + public static class ModuleInfo { + public int declarationStart; + public int modifiers; + public char[] name; + public int nameSourceStart; + public int nameSourceEnd; + public char[] moduleName; + public RequiresInfo[] requires; + public PackageExportInfo[] exports; + public ServicesInfo[] services; + public PackageExportInfo[] opens; + public char[][] usedServices; + public Annotation[] annotations; + public ModuleDeclaration node; + } + public static class RequiresInfo { + public char[] moduleName; + public int modifiers; + } + public static class PackageExportInfo { + public char[] pkgName; + public char[][] targets; + } + public static class ServicesInfo { + public char[] serviceName; + public char[][] implNames; + } public static class TypeInfo { public boolean typeAnnotated; public int declarationStart; @@ -200,4 +229,11 @@ public static class FieldInfo { void exitMethod(int declarationEnd, Expression defaultValue); void exitType(int declarationEnd); + + default void enterModule(ModuleInfo info) { + // do nothing + } + default void exitModule(int declarationEnd) { + // do nothing + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java index 54d7a09c28..d5811508ae 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2015 IBM Corporation and others. + * Copyright (c) 2008, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -31,12 +31,15 @@ import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.Initializer; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.OpensStatement; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -427,7 +430,8 @@ public void notifySourceElementRequestor( length = (currentPackage == null ? 0 : 1) + (imports == null ? 0 : imports.length) - + (types == null ? 0 : types.length); + + (types == null ? 0 : types.length) + + (parsedUnit.moduleDeclaration == null ? 0 : 1); nodes = new ASTNode[length]; int index = 0; if (currentPackage != null) { @@ -443,6 +447,9 @@ public void notifySourceElementRequestor( nodes[index++] = types[i]; } } + + if (parsedUnit.moduleDeclaration != null) + nodes[index++] = parsedUnit.moduleDeclaration; // notify the nodes in the syntactical order if (length > 0) { @@ -456,8 +463,10 @@ public void notifySourceElementRequestor( } else { notifySourceElementRequestor(importRef, false); } - } else { // instanceof TypeDeclaration + } else if (node instanceof TypeDeclaration) { notifySourceElementRequestor((TypeDeclaration)node, true, null, currentPackage); + } else if (node instanceof ModuleDeclaration) { + notifySourceElementRequestor(parsedUnit.moduleDeclaration); } } } @@ -576,6 +585,31 @@ protected void notifySourceElementRequestor( importReference.modifiers); } } +protected void notifySourceElementRequestor(ModuleDeclaration moduleDeclaration) { + boolean isInRange = + this.initialPosition <= moduleDeclaration.declarationSourceStart + && this.eofPosition >= moduleDeclaration.declarationSourceEnd; + ISourceElementRequestor.ModuleInfo info = new ISourceElementRequestor.ModuleInfo(); + if (isInRange) { + + int currentModifiers = moduleDeclaration.modifiers; + + // remember deprecation so as to not lose it below + boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0 || hasDeprecatedAnnotation(moduleDeclaration.annotations); + + info.declarationStart = moduleDeclaration.declarationSourceStart; + info.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag; + info.name = TypeConstants.MODULE_INFO_NAME; + info.nameSourceStart = moduleDeclaration.sourceStart; + info.nameSourceEnd = moduleDeclaration.sourceEnd; + info.moduleName = moduleDeclaration.moduleName; + info.annotations = moduleDeclaration.annotations; + info.node = moduleDeclaration; + fillModuleInfo(moduleDeclaration, info); + this.requestor.enterModule(info); + this.requestor.exitModule(moduleDeclaration.declarationSourceEnd); + } +} protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType, ImportReference currentPackage) { if (CharOperation.equals(TypeConstants.PACKAGE_INFO_NAME, typeDeclaration.name)) return; @@ -711,6 +745,74 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo this.nestedTypeIndex--; } } +private void fillModuleInfo(ModuleDeclaration mod, ISourceElementRequestor.ModuleInfo modInfo) { + if (mod.requiresCount > 0) { + ISourceElementRequestor.RequiresInfo reqs[] = new ISourceElementRequestor.RequiresInfo[mod.requiresCount]; + for (int i = 0; i < mod.requiresCount; i++) { + ISourceElementRequestor.RequiresInfo req = new ISourceElementRequestor.RequiresInfo(); + req.moduleName = CharOperation.concatWith(mod.requires[i].module.tokens, '.'); + req.modifiers = mod.requires[i].modifiers; + reqs[i] = req; + } + modInfo.requires = reqs; + } + if (mod.exportsCount > 0) { + ISourceElementRequestor.PackageExportInfo exps[] = new ISourceElementRequestor.PackageExportInfo[mod.exportsCount]; + for (int i = 0; i < mod.exportsCount; i++) { + ISourceElementRequestor.PackageExportInfo exp = new ISourceElementRequestor.PackageExportInfo(); + ExportsStatement exportsStatement = mod.exports[i]; + exp.pkgName = exportsStatement.pkgName; + if (exportsStatement.targets == null) { + exp.targets = CharOperation.NO_CHAR_CHAR; + } else { + exp.targets = new char[exportsStatement.targets.length][]; + for(int j = 0; j < exp.targets.length; j++) { + exp.targets[j] = CharOperation.concatWith(exportsStatement.targets[j].tokens, '.'); + } + } + exps[i] = exp; + } + modInfo.exports = exps; + } + if (mod.servicesCount > 0) { + ISourceElementRequestor.ServicesInfo[] services = new ISourceElementRequestor.ServicesInfo[mod.servicesCount]; + for (int i = 0; i < services.length; i++) { + ISourceElementRequestor.ServicesInfo ser = new ISourceElementRequestor.ServicesInfo(); + ser.serviceName = CharOperation.concatWith(mod.services[i].serviceInterface.getParameterizedTypeName(), '.'); + ser.implNames = new char[mod.services[i].implementations.length][]; + for (int j = 0; j < ser.implNames.length; j++) { + ser.implNames[j] = CharOperation.concatWith(mod.services[i].implementations[j].getParameterizedTypeName(), '.'); + } + services[i] = ser; + } + modInfo.services = services; + } + if (mod.usesCount > 0) { + char[][] uses = new char[mod.usesCount][]; + for (int i = 0; i < uses.length; i++) { + uses[i] = CharOperation.concatWith(mod.uses[i].serviceInterface.getParameterizedTypeName(), '.'); + } + modInfo.usedServices = uses; + } + if (mod.opensCount > 0) { + ISourceElementRequestor.PackageExportInfo opens[] = new ISourceElementRequestor.PackageExportInfo[mod.opensCount]; + for (int i = 0; i < mod.opensCount; i++) { + ISourceElementRequestor.PackageExportInfo op = new ISourceElementRequestor.PackageExportInfo(); + OpensStatement openStmt = mod.opens[i]; + op.pkgName = openStmt.pkgName; + if (openStmt.targets == null) { + op.targets = CharOperation.NO_CHAR_CHAR; + } else { + op.targets = new char[openStmt.targets.length][]; + for(int j = 0; j < op.targets.length; j++) { + op.targets[j] = CharOperation.concatWith(openStmt.targets[j].tokens, '.'); + } + } + opens[i] = op; + } + modInfo.opens = opens; + } +} /* * Sort the given ast nodes by their positions. */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java index 03d11d25b7..218dd5ddf6 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java @@ -1,11 +1,11 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -537,6 +537,12 @@ protected void consumeNormalAnnotation(boolean isTypeAnnotation) { this.requestor.acceptAnnotationTypeReference(annotation.type.getTypeName(), annotation.sourceStart, annotation.sourceEnd); } } +protected void consumeProvidesStatement() { + super.consumeProvidesStatement(); + ProvidesStatement service = (ProvidesStatement) this.astStack[this.astPtr]; + TypeReference ref = service.serviceInterface; + this.requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd); +} protected void consumeSingleMemberAnnotation(boolean isTypeAnnotation) { super.consumeSingleMemberAnnotation(isTypeAnnotation); SingleMemberAnnotation member = (SingleMemberAnnotation) (isTypeAnnotation ? this.typeAnnotationStack[this.typeAnnotationPtr] : this.expressionStack[this.expressionPtr]); @@ -719,6 +725,19 @@ protected void consumeTypeImportOnDemandDeclarationName() { this.requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd); } } +protected void consumeUsesStatement() { + super.consumeUsesStatement(); + UsesStatement ref = (UsesStatement) this.astStack[this.astPtr]; + this.requestor.acceptTypeReference(ref.serviceInterface.getTypeName(), ref.sourceStart, ref.sourceEnd); +} +protected void consumeWithClause() { + super.consumeWithClause(); + ProvidesStatement service = (ProvidesStatement) this.astStack[this.astPtr]; + for (int i = 0; i < service.implementations.length; i++) { + TypeReference ref = service.implementations[i]; + this.requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd); + } +} public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) { MethodDeclaration methodDeclaration = super.convertToMethodDeclaration(c, compilationResult); int selectorSourceEnd = this.sourceEnds.removeKey(c); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java index a507dfbc70..4b1add03a7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,8 +14,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; -import org.codehaus.jdt.groovy.integration.LanguageSupportFactory; - /** * Converter from source element type to parsed compilation unit. * @@ -29,6 +27,7 @@ * */ +import org.codehaus.jdt.groovy.integration.LanguageSupportFactory; import org.eclipse.jdt.core.IAnnotatable; import org.eclipse.jdt.core.IAnnotation; import org.eclipse.jdt.core.IImportDeclaration; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractClassFile.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractClassFile.java new file mode 100644 index 0000000000..d2e9a4fc83 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractClassFile.java @@ -0,0 +1,462 @@ +/******************************************************************************* + * Copyright (c) 2000, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for + * Bug 458577 - IClassFile.getWorkingCopy() may lead to NPE in BecomeWorkingCopyOperation + * Bug 440477 - [null] Infrastructure for feeding external annotations into compilation + * Bug 462768 - [null] NPE when using linked folder for external annotations + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import java.io.File; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.util.SuffixConstants; +import org.eclipse.jdt.internal.core.util.Util; + +/** + * Common parts of ClassFile (containing a BinaryType) and ModularClassFile (containing a BinaryModule). + * Prior to Java 9, most of this content was directly in ClassFile. + */ +public abstract class AbstractClassFile extends Openable implements IClassFile, SuffixConstants { + + protected String name; + + protected AbstractClassFile(PackageFragment parent, String nameWithoutExtension) { + super(parent); + this.name = nameWithoutExtension; + } + + /* + * @see IClassFile#becomeWorkingCopy(IProblemRequestor, WorkingCopyOwner, IProgressMonitor) + */ + public ICompilationUnit becomeWorkingCopy(IProblemRequestor problemRequestor, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + CompilationUnit workingCopy = new ClassFileWorkingCopy(this, owner == null ? DefaultWorkingCopyOwner.PRIMARY : owner); + JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = manager.getPerWorkingCopyInfo(workingCopy, false/*don't create*/, true /*record usage*/, null/*no problem requestor needed*/); + if (perWorkingCopyInfo == null) { + // close cu and its children + close(); + + BecomeWorkingCopyOperation operation = new BecomeWorkingCopyOperation(workingCopy, problemRequestor); + operation.runOperation(monitor); + + return workingCopy; + } + return perWorkingCopyInfo.workingCopy; + } + + /** + * @see ICodeAssist#codeComplete(int, ICompletionRequestor) + * @deprecated + */ + @Deprecated + public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException { + codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY); + } + /** + * @see ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner) + * @deprecated + */ + @Deprecated + public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException { + if (requestor == null) { + throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$ + } + codeComplete(offset, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), owner); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor) + */ + public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException { + codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY); + } + /* (non-Javadoc) + * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.core.runtime.IProgressMonitor) + */ + public void codeComplete(int offset, CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException { + codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY, monitor); + } + /* (non-Javadoc) + * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner) + */ + public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException { + codeComplete(offset, requestor, owner, null); + } + public abstract void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException; + + /** + * @see ICodeAssist#codeSelect(int, int) + */ + public IJavaElement[] codeSelect(int offset, int length) throws JavaModelException { + return codeSelect(offset, length, DefaultWorkingCopyOwner.PRIMARY); + } + public abstract IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner owner) throws JavaModelException; + + /** + * Returns a new element info for this element. + */ + @Override + protected Object createElementInfo() { + return new ClassFileInfo(); + } + @Override + public boolean equals(Object o) { + if (!(o instanceof AbstractClassFile)) return false; + AbstractClassFile other = (AbstractClassFile) o; + return this.name.equals(other.name) && this.parent.equals(other.parent); + } + + /** + * Finds the deepest IJavaElement in the hierarchy of + * elt's children (including elt itself) + * which has a source range that encloses position + * according to mapper. + */ + protected IJavaElement findElement(IJavaElement elt, int position, SourceMapper mapper) { + SourceRange range = mapper.getSourceRange(elt); + if (range == null || position < range.getOffset() || range.getOffset() + range.getLength() - 1 < position) { + return null; + } + if (elt instanceof IParent) { + try { + IJavaElement[] children = ((IParent) elt).getChildren(); + for (int i = 0; i < children.length; i++) { + IJavaElement match = findElement(children[i], position, mapper); + if (match != null) { + return match; + } + } + } catch (JavaModelException npe) { + // elt doesn't exist: return the element + } + } + return elt; + } + + public byte[] getBytes() throws JavaModelException { + JavaElement pkg = (JavaElement) getParent(); + if (pkg instanceof JarPackageFragment) { + JarPackageFragmentRoot root = (JarPackageFragmentRoot) pkg.getParent(); + try { + String entryName = Util.concatWith(((PackageFragment) pkg).names, getElementName(), '/'); + entryName = root.getClassFilePath(entryName); + return getClassFileContent(root, entryName); + // Java 9 - The below exception is not thrown in new scheme of things. Could cause issues? + // throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this)); + } catch (IOException ioe) { + throw new JavaModelException(ioe, IJavaModelStatusConstants.IO_EXCEPTION); + } catch (CoreException e) { + if (e instanceof JavaModelException) { + throw (JavaModelException)e; + } else { + throw new JavaModelException(e); + } + } + } else { + IFile file = (IFile) resource(); + return Util.getResourceContentsAsByteArray(file); + } + } + protected byte[] getClassFileContent(JarPackageFragmentRoot root, String className) throws CoreException, IOException { + byte[] contents = null; + String rootPath = root.getPath().toOSString(); + if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) { + try { + contents = org.eclipse.jdt.internal.compiler.util.JRTUtil.getClassfileContent( + new File(rootPath), + className, + root.getElementName()); + } catch (ClassFormatException e) { + e.printStackTrace(); + } + } else { + ZipFile zip = root.getJar(); + try { + ZipEntry ze = zip.getEntry(className); + if (ze != null) { + contents = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip); + } + } finally { + JavaModelManager.getJavaModelManager().closeZipFile(zip); + } + } + return contents; + } + + @Override + public IBuffer getBuffer() throws JavaModelException { + IStatus status = validateClassFile(); + if (status.isOK()) { + return super.getBuffer(); + } else { + switch (status.getCode()) { + case IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH: // don't throw a JavaModelException to be able to open .class file outside the classpath (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=138507 ) + case IJavaModelStatusConstants.INVALID_ELEMENT_TYPES: // don't throw a JavaModelException to be able to open .class file in proj==src case without source (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=221904 ) + return null; + default: + throw new JavaModelException(status); + } + } + } + /** + * @see IMember#getTypeRoot() + */ + public ITypeRoot getTypeRoot() { + return this; + } + + /** + * A class file has a corresponding resource unless it is contained + * in a jar. + * + * @see IJavaElement + */ + @Override + public IResource getCorrespondingResource() throws JavaModelException { + IPackageFragmentRoot root= (IPackageFragmentRoot)getParent().getParent(); + if (root.isArchive()) { + return null; + } else { + return getUnderlyingResource(); + } + } + public IJavaElement getElementAtConsideringSibling(int position) throws JavaModelException { + IPackageFragment fragment = (IPackageFragment)getParent(); + PackageFragmentRoot root = (PackageFragmentRoot) fragment.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + SourceMapper mapper = root.getSourceMapper(); + if (mapper == null) { + return null; + } else { + int index = this.name.indexOf('$'); + int prefixLength = index < 0 ? this.name.length() : index; + + IType type = null; + int start = -1; + int end = Integer.MAX_VALUE; + IJavaElement[] children = fragment.getChildren(); + for (int i = 0; i < children.length; i++) { + if (children[i] instanceof IOrdinaryClassFile) { + IOrdinaryClassFile classFile = (IOrdinaryClassFile) children[i]; + String childName = classFile.getElementName(); + + int childIndex = childName.indexOf('$'); + int childPrefixLength = childIndex < 0 ? childName.indexOf('.') : childIndex; + if (prefixLength == childPrefixLength && this.name.regionMatches(0, childName, 0, prefixLength)) { + + // ensure this class file's buffer is open so that source ranges are computed + classFile.getBuffer(); + + SourceRange range = mapper.getSourceRange(classFile.getType()); + if (range == SourceMapper.UNKNOWN_RANGE) continue; + int newStart = range.getOffset(); + int newEnd = newStart + range.getLength() - 1; + if(newStart > start && newEnd < end + && newStart <= position && newEnd >= position) { + type = classFile.getType(); + start = newStart; + end = newEnd; + } + } + } + } + if(type != null) { + return findElement(type, position, mapper); + } + return null; + } + } + @Override + public String getElementName() { + return this.name + SuffixConstants.SUFFIX_STRING_class; + } + /** + * @see IJavaElement + */ + public int getElementType() { + return CLASS_FILE; + } + + /* + * @see IJavaElement + */ + public IPath getPath() { + PackageFragmentRoot root = getPackageFragmentRoot(); + if (root.isArchive()) { + return root.getPath(); + } else { + return getParent().getPath().append(getElementName()); + } + } + + /* + * @see IJavaElement + */ + @Override + public IResource resource(PackageFragmentRoot root) { + return ((IContainer) ((Openable) this.parent).resource(root)).getFile(new Path(getElementName())); + } + /** + * @see ISourceReference + */ + public String getSource() throws JavaModelException { + IBuffer buffer = getBuffer(); + if (buffer == null) { + return null; + } + return buffer.getContents(); + } + /** + * @see ISourceReference + */ + public ISourceRange getSourceRange() throws JavaModelException { + IBuffer buffer = getBuffer(); + if (buffer != null) { + String contents = buffer.getContents(); + if (contents == null) return null; + return new SourceRange(0, contents.length()); + } else { + return null; + } + } + /** + * @see IClassFile + * @deprecated + */ + @Deprecated + public IJavaElement getWorkingCopy(IProgressMonitor monitor, org.eclipse.jdt.core.IBufferFactory factory) throws JavaModelException { + return getWorkingCopy(BufferFactoryWrapper.create(factory), monitor); + } + /** + * @see Openable + */ + @Override + protected boolean hasBuffer() { + return true; + } + @Override + public int hashCode() { + return Util.combineHashCodes(this.name.hashCode(), this.parent.hashCode()); + } + /** + * Returns true - class files are always read only. + */ + @Override + public boolean isReadOnly() { + return true; + } + private IStatus validateClassFile() { + IPackageFragmentRoot root = getPackageFragmentRoot(); + try { + if (root.getKind() != IPackageFragmentRoot.K_BINARY) + return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, root); + } catch (JavaModelException e) { + return e.getJavaModelStatus(); + } + IJavaProject project = getJavaProject(); + return JavaConventions.validateClassFileName(getElementName(), project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true)); + } + + + /** + * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor) + * @deprecated - should use codeComplete(int, ICompletionRequestor) instead + */ + @Deprecated + public void codeComplete(int offset, final org.eclipse.jdt.core.ICodeCompletionRequestor requestor) throws JavaModelException { + + if (requestor == null){ + codeComplete(offset, (ICompletionRequestor)null); + return; + } + codeComplete( + offset, + new ICompletionRequestor(){ + public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName, char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) { + // ignore + } + public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) { + requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd); + } + public void acceptError(IProblem error) { + // was disabled in 1.0 + } + public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) { + requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd); + } + public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) { + requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd); + } + public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){ + requestor.acceptKeyword(keywordName, completionStart, completionEnd); + } + public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){ + requestor.acceptLabel(labelName, completionStart, completionEnd); + } + public void acceptLocalVariable(char[] localVarName,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){ + // ignore + } + public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){ + // skip parameter names + requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd); + } + public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){ + // ignore + } + public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){ + requestor.acceptModifier(modifierName, completionStart, completionEnd); + } + public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){ + requestor.acceptPackage(packageName, completionName, completionStart, completionEnd); + } + public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){ + requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd); + } + public void acceptVariableName(char[] typePackageName,char[] typeName,char[] varName,char[] completionName,int completionStart,int completionEnd, int relevance){ + // ignore + } + }); + } + + @Override + protected IStatus validateExistence(IResource underlyingResource) { + // check whether the class file can be opened + IStatus status = validateClassFile(); + if (!status.isOK()) + return status; + if (underlyingResource != null) { + if (!underlyingResource.isAccessible()) + return newDoesNotExistStatus(); + PackageFragmentRoot root; + if ((underlyingResource instanceof IFolder) && (root = getPackageFragmentRoot()).isArchive()) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=204652 + return root.newDoesNotExistStatus(); + } + } + return JavaModelStatus.VERIFIED_OK; + } + + public ISourceRange getNameRange() { + return null; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java new file mode 100644 index 0000000000..2ec7f06d70 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference; +import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport; +import org.eclipse.jdt.internal.compiler.env.IModule.IService; + +public abstract class AbstractModule extends NamedMember implements IModuleDescription { + protected AbstractModule(JavaElement parent, String name) { + super(parent, name); + } + public IModuleReference[] getRequiredModules() throws JavaModelException { + ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo(); + return info.requires(); + } + public IPackageExport[] getExportedPackages() throws JavaModelException { + ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo(); + return info.exports(); + } + public IService[] getProvidedServices() throws JavaModelException { + ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo(); + return info.provides(); + } + public char[][] getUsedServices() throws JavaModelException { + ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo(); + return info.uses(); + } + public IPackageExport[] getOpenedPackages() throws JavaModelException { + ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo(); + return info.opens(); + } + public String getKey(boolean forceOpen) throws JavaModelException { + return getKey(this, forceOpen); + } + public String toString(String lineDelimiter) { + StringBuffer buffer = new StringBuffer(); + try { + toStringContent(buffer, lineDelimiter); + } catch (JavaModelException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return buffer.toString(); + } + protected void toStringContent(StringBuffer buffer, String lineDelimiter) throws JavaModelException { + IPackageExport[] exports = getExportedPackages(); + IModuleReference[] requires = getRequiredModules(); + buffer.append("module "); //$NON-NLS-1$ + buffer.append(this.name).append(' '); + buffer.append('{').append(lineDelimiter); + if (exports != null) { + for(int i = 0; i < exports.length; i++) { + buffer.append("\texports "); //$NON-NLS-1$ + buffer.append(exports[i].toString()); + buffer.append(lineDelimiter); + } + } + buffer.append(lineDelimiter); + if (requires != null) { + for(int i = 0; i < requires.length; i++) { + buffer.append("\trequires "); //$NON-NLS-1$ + if (requires[i].isTransitive()) { + buffer.append(" public "); //$NON-NLS-1$ + } + buffer.append(requires[i].name()); + buffer.append(';').append(lineDelimiter); + } + } + buffer.append(lineDelimiter).append('}').toString(); + } + + /** + * @see JavaElement#getHandleMemento() + */ + protected char getHandleMementoDelimiter() { + return JavaElement.JEM_MODULE; + } + @Override + public int getElementType() { + return JAVA_MODULE; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java index 11cdaa3500..d27fff13fb 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,6 +18,9 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModularClassFile; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.util.Util; @@ -38,14 +41,19 @@ public class BasicCompilationUnit implements ICompilationUnit { protected char[][] packageName; protected char[] mainTypeName; + protected char[] moduleName; protected String encoding; -public BasicCompilationUnit(char[] contents, char[][] packageName, String fileName) { +private BasicCompilationUnit(char[] contents, char[][] packageName, String fileName) { this.contents = contents; this.fileName = fileName.toCharArray(); this.packageName = packageName; } +/** + * @deprecated Should pass a javaElement via {@link BasicCompilationUnit#BasicCompilationUnit(char[], char[][], String, IJavaElement)}. + */ +@Deprecated public BasicCompilationUnit(char[] contents, char[][] packageName, String fileName, String encoding) { this(contents, packageName, fileName); this.encoding = encoding; @@ -53,7 +61,7 @@ public BasicCompilationUnit(char[] contents, char[][] packageName, String fileNa public BasicCompilationUnit(char[] contents, char[][] packageName, String fileName, IJavaElement javaElement) { this(contents, packageName, fileName); - initEncoding(javaElement); + initAttributes(javaElement); } /* @@ -64,26 +72,49 @@ public BasicCompilationUnit(char[] contents, char[][] packageName, String fileNa * a corresponding source file resource. * If we have a compilation unit, then get encoding from its resource directly... */ -private void initEncoding(IJavaElement javaElement) { +private void initAttributes(IJavaElement javaElement) { if (javaElement != null) { try { - IJavaProject javaProject = javaElement.getJavaProject(); - switch (javaElement.getElementType()) { - case IJavaElement.COMPILATION_UNIT: - IFile file = (IFile) javaElement.getResource(); - if (file != null) { - this.encoding = file.getCharset(); - break; + IModuleDescription module = null; + + search: while (javaElement != null) { + switch (javaElement.getElementType()) { + case IJavaElement.JAVA_PROJECT: + module = ((IJavaProject) javaElement).getModuleDescription(); + break search; + case IJavaElement.PACKAGE_FRAGMENT_ROOT: + module = ((IPackageFragmentRoot) javaElement).getModuleDescription(); + break search; + case IJavaElement.CLASS_FILE: + if (javaElement instanceof IModularClassFile) { + module = ((IModularClassFile) javaElement).getModule(); + break search; + } + break; + case IJavaElement.COMPILATION_UNIT: + IFile file = (IFile) javaElement.getResource(); + if (file != null) { + this.encoding = file.getCharset(); + } + module = ((org.eclipse.jdt.core.ICompilationUnit) javaElement).getModule(); + if (module != null) + break search; + break; + default: + break; } - // if no file, then get project encoding - // $FALL-THROUGH$ - default: - IProject project = (IProject) javaProject.getResource(); + javaElement = javaElement.getParent(); + } + + if (module != null) { + this.moduleName = module.getElementName().toCharArray(); + } + if (this.encoding == null) { + IProject project = javaElement.getJavaProject().getProject(); if (project != null) { this.encoding = project.getDefaultCharset(); } - break; - } + } } catch (CoreException e1) { this.encoding = null; } @@ -115,7 +146,7 @@ public char[] getMainTypeName() { int start = CharOperation.lastIndexOf('/', this.fileName) + 1; if (start == 0 || start < CharOperation.lastIndexOf('\\', this.fileName)) start = CharOperation.lastIndexOf('\\', this.fileName) + 1; - int separator = CharOperation.indexOf('|', this.fileName) + 1; + int separator = CharOperation.lastIndexOf('|', this.fileName) + 1; if (separator > start) // case of a .class file in a default package in a jar start = separator; @@ -139,4 +170,9 @@ public boolean ignoreOptionalProblems() { public String toString(){ return "CompilationUnit: "+new String(this.fileName); //$NON-NLS-1$ } + +@Override +public char[] getModuleName() { + return this.moduleName; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java index 79b615f1e6..bc73c591a2 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java @@ -251,8 +251,8 @@ public String[] getParameterNames() throws JavaModelException { if(paramNames == null) { IBinaryType info = (IBinaryType) ((BinaryType) getDeclaringType()).getElementInfo(); char[] source = mapper.findSource(type, info); - if (source != null){ - mapper.mapSource(type, source, info); + if (source != null) { + mapper.mapSource((NamedMember) type, source, info); } paramNames = mapper.getMethodParameterNames(this); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java new file mode 100644 index 0000000000..7977c999bf --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import java.net.URL; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.ISourceRange; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; + +public class BinaryModule extends AbstractModule { + public BinaryModule(JavaElement parent, String name) { + super(parent, name); + } + /* + * @see IParent#getChildren() + */ + public IJavaElement[] getChildren() throws JavaModelException { + return NO_ELEMENTS; + } + @Override + public boolean isBinary() { + return true; + } + @Override + public int getFlags() throws JavaModelException { + ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo(); + return info.getModifiers(); + } + public String getKey(boolean forceOpen) throws JavaModelException { + return getKey(this, forceOpen); + } + @Override + public ISourceRange getSourceRange() throws JavaModelException { + SourceMapper mapper= getSourceMapper(); + if (mapper != null) { + // ensure the class file's buffer is open so that source ranges are computed + ((ModularClassFile)getClassFile()).getBuffer(); + + return mapper.getSourceRange(this); + } else { + return SourceMapper.UNKNOWN_RANGE; + } + } + public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException { + JavadocContents javadocContents = getJavadocContents(monitor); + if (javadocContents == null) return null; + return javadocContents.getModuleDoc(); + } + public JavadocContents getJavadocContents(IProgressMonitor monitor) throws JavaModelException { + PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(getJavaProject().getProject()); + JavadocContents cachedJavadoc = null; + synchronized (projectInfo.javadocCache) { + cachedJavadoc = (JavadocContents) projectInfo.javadocCache.get(this); + } + + if (cachedJavadoc != null && cachedJavadoc != BinaryType.EMPTY_JAVADOC) { + return cachedJavadoc; + } + URL baseLocation= getJavadocBaseLocation(); + if (baseLocation == null) { + return null; + } + StringBuffer pathBuffer = new StringBuffer(baseLocation.toExternalForm()); + + if (!(pathBuffer.charAt(pathBuffer.length() - 1) == '/')) { + pathBuffer.append('/'); + } + pathBuffer.append(getElementName()).append(JavadocConstants.MODULE_FILE_SUFFIX); + if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException(); + String contents = getURLContents(baseLocation, String.valueOf(pathBuffer)); + JavadocContents javadocContents = new JavadocContents(contents); + synchronized (projectInfo.javadocCache) { + projectInfo.javadocCache.put(this, javadocContents); + } + return javadocContents; + } + public String toString(String lineDelimiter) { + StringBuffer buffer = new StringBuffer(); + try { + toStringContent(buffer, lineDelimiter); + } catch (JavaModelException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return buffer.toString(); + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java index c315276e3c..23e57159f6 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -249,7 +249,7 @@ public IType getDeclaringType() { return null; } - return getPackageFragment().getClassFile(new String(enclosingTypeName) + SUFFIX_STRING_class).getType(); + return getPackageFragment().getOrdinaryClassFile(new String(enclosingTypeName) + SUFFIX_STRING_class).getType(); } catch (JavaModelException npe) { return null; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java index 3236b322f5..5ff925c374 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java @@ -45,15 +45,13 @@ public NameEnvironmentAnswer findType(char[] name, char[][] packageName) { return super.findType(name, packageName); } - public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes) { - return findType(typeName, packageName); - } - public NameEnvironmentAnswer findType(char[][] compoundTypeName) { checkCanceled(); return super.findType(compoundTypeName); } - + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes, char[] moduleName) { + return findType(typeName, packageName, moduleName); + } public void findTypes(char[] prefix, boolean findMembers, boolean camelCaseMatch, int searchFor, ISearchRequestor storage, IProgressMonitor progressMonitor) { checkCanceled(); super.findTypes(prefix, findMembers, camelCaseMatch, searchFor, storage, progressMonitor); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java index 328c91a78a..d6683efb50 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,13 +18,9 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.codehaus.jdt.groovy.integration.LanguageSupportFactory; -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; @@ -35,11 +31,13 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.*; -import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator; import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider; import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IDependent; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.nd.java.JavaNames; import org.eclipse.jdt.internal.core.nd.java.model.BinaryTypeDescriptor; @@ -53,9 +51,8 @@ */ @SuppressWarnings({"rawtypes"}) -public class ClassFile extends Openable implements IClassFile, SuffixConstants { +public class ClassFile extends AbstractClassFile implements IOrdinaryClassFile { - protected String name; protected BinaryType binaryType = null; private IPath externalAnnotationBase; @@ -64,27 +61,7 @@ public class ClassFile extends Openable implements IClassFile, SuffixConstants { * Creates a handle to a class file. */ protected ClassFile(PackageFragment parent, String nameWithoutExtension) { - super(parent); - this.name = nameWithoutExtension; -} - -/* - * @see IClassFile#becomeWorkingCopy(IProblemRequestor, WorkingCopyOwner, IProgressMonitor) - */ -public ICompilationUnit becomeWorkingCopy(IProblemRequestor problemRequestor, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { - JavaModelManager manager = JavaModelManager.getJavaModelManager(); - CompilationUnit workingCopy = new ClassFileWorkingCopy(this, owner == null ? DefaultWorkingCopyOwner.PRIMARY : owner); - JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = manager.getPerWorkingCopyInfo(workingCopy, false/*don't create*/, true /*record usage*/, null/*no problem requestor needed*/); - if (perWorkingCopyInfo == null) { - // close cu and its children - close(); - - BecomeWorkingCopyOperation operation = new BecomeWorkingCopyOperation(workingCopy, problemRequestor); - operation.runOperation(monitor); - - return workingCopy; - } - return perWorkingCopyInfo.workingCopy; + super(parent, nameWithoutExtension); } /** @@ -104,55 +81,15 @@ protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, info.setChildren(new IJavaElement[] {}); return false; } - + // Make the type IType type = getType(); info.setChildren(new IJavaElement[] {type}); newElements.put(type, typeInfo); - // Read children ((ClassFileInfo) info).readBinaryChildren(this, (HashMap) newElements, typeInfo); - return true; } -/** - * @see ICodeAssist#codeComplete(int, ICompletionRequestor) - * @deprecated - */ -@Deprecated -public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException { - codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY); -} -/** - * @see ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner) - * @deprecated - */ -@Deprecated -public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException { - if (requestor == null) { - throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$ - } - codeComplete(offset, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), owner); -} - -/* (non-Javadoc) - * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor) - */ -public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException { - codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY); -} -/* (non-Javadoc) - * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.core.runtime.IProgressMonitor) - */ -public void codeComplete(int offset, CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException { - codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY, monitor); -} -/* (non-Javadoc) - * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner) - */ -public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException { - codeComplete(offset, requestor, owner, null); -} /* (non-Javadoc) * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner, org.eclipse.core.runtime.IProgressMonitor) */ @@ -170,12 +107,6 @@ public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyO } } -/** - * @see ICodeAssist#codeSelect(int, int) - */ -public IJavaElement[] codeSelect(int offset, int length) throws JavaModelException { - return codeSelect(offset, length, DefaultWorkingCopyOwner.PRIMARY); -} /** * @see ICodeAssist#codeSelect(int, int, WorkingCopyOwner) */ @@ -191,7 +122,7 @@ public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner owner) if (LanguageSupportFactory.isInterestingBinary(type, typeInfo)) { return LanguageSupportFactory.binaryCodeSelect(this, offset, length, owner); } - BasicCompilationUnit cu = new BasicCompilationUnit(contents, null, type.sourceFileName(typeInfo)); + BasicCompilationUnit cu = new BasicCompilationUnit(contents, null, type.sourceFileName(typeInfo), type); // GROOVY end return super.codeSelect(cu, offset, length, owner); } else { @@ -199,19 +130,6 @@ public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner owner) return new IJavaElement[] {}; } } -/** - * Returns a new element info for this element. - */ -@Override -protected Object createElementInfo() { - return new ClassFileInfo(); -} -@Override -public boolean equals(Object o) { - if (!(o instanceof ClassFile)) return false; - ClassFile other = (ClassFile) o; - return this.name.equals(other.name) && this.parent.equals(other.parent); -} public boolean existsUsingJarTypeCache() { if (getPackageFragmentRoot().isArchive()) { JavaModelManager manager = JavaModelManager.getJavaModelManager(); @@ -248,32 +166,6 @@ else if (info != null) return exists(); } -/** - * Finds the deepest IJavaElement in the hierarchy of - * elt's children (including elt itself) - * which has a source range that encloses position - * according to mapper. - */ -protected IJavaElement findElement(IJavaElement elt, int position, SourceMapper mapper) { - SourceRange range = mapper.getSourceRange(elt); - if (range == null || position < range.getOffset() || range.getOffset() + range.getLength() - 1 < position) { - return null; - } - if (elt instanceof IParent) { - try { - IJavaElement[] children = ((IParent) elt).getChildren(); - for (int i = 0; i < children.length; i++) { - IJavaElement match = findElement(children[i], position, mapper); - if (match != null) { - return match; - } - } - } catch (JavaModelException npe) { - // elt doesn't exist: return the element - } - } - return elt; -} /** * @see ITypeRoot#findPrimaryType() */ @@ -324,36 +216,6 @@ public IBinaryType getBinaryTypeInfo() throws JavaModelException { } } -public byte[] getBytes() throws JavaModelException { - JavaElement pkg = (JavaElement) getParent(); - if (pkg instanceof JarPackageFragment) { - JarPackageFragmentRoot root = (JarPackageFragmentRoot) pkg.getParent(); - ZipFile zip = null; - try { - zip = root.getJar(); - String entryName = Util.concatWith(((PackageFragment) pkg).names, getElementName(), '/'); - ZipEntry ze = zip.getEntry(entryName); - if (ze != null) { - return org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip); - } - throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this)); - } catch (IOException ioe) { - throw new JavaModelException(ioe, IJavaModelStatusConstants.IO_EXCEPTION); - } catch (CoreException e) { - if (e instanceof JavaModelException) { - throw (JavaModelException)e; - } else { - throw new JavaModelException(e); - } - } finally { - JavaModelManager.getJavaModelManager().closeZipFile(zip); - } - } else { - IFile file = (IFile) resource(); - return Util.getResourceContentsAsByteArray(file); - } -} - public String getName() { return this.name; } @@ -364,33 +226,52 @@ private IBinaryType getJarBinaryTypeInfo() throws CoreException, IOException, Cl if (descriptor == null) { return null; } - - IBinaryType result = BinaryTypeFactory.readType(descriptor, null); - + IBinaryType result = null; + IPackageFragmentRoot root = getPackageFragmentRoot(); + if (getPackageFragmentRoot() instanceof JarPackageFragmentRoot) { + if (root instanceof JrtPackageFragmentRoot || this.name.equals(IModule.MODULE_INFO)) { + PackageFragment pkg = (PackageFragment) getParent(); + JarPackageFragmentRoot jarRoot = (JarPackageFragmentRoot) getPackageFragmentRoot(); + String entryName = jarRoot.getClassFilePath(Util.concatWith(pkg.names, getElementName(), '/')); + byte[] contents = getClassFileContent(jarRoot, entryName); + if (contents != null) { + String fileName; + String rootPath = root.getPath().toOSString(); + if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) { + fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + + root.getElementName() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName; + } else { + fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName; + } + result = new ClassFileReader(contents, fileName.toCharArray(), false); + } + } else { + result = BinaryTypeFactory.readType(descriptor, null); + } + } else { + result = BinaryTypeFactory.readType(descriptor, null); + } + if (result == null) { return null; } // TODO(sxenos): setup the external annotation provider if the IBinaryType came from the index - PackageFragment pkg = (PackageFragment) getParent(); - IJavaElement grandparent = pkg.getParent(); - if (grandparent instanceof JarPackageFragmentRoot) { - JarPackageFragmentRoot root = (JarPackageFragmentRoot) grandparent; - - if (root.getKind() == IPackageFragmentRoot.K_BINARY) { - JavaProject javaProject = (JavaProject) getAncestor(IJavaElement.JAVA_PROJECT); - IClasspathEntry entry = javaProject.getClasspathEntryFor(getPath()); - if (entry != null) { - String entryName = new String(CharArrayUtils.concat( - JavaNames.fieldDescriptorToBinaryName(descriptor.fieldDescriptor), SuffixConstants.SUFFIX_CLASS)); - IProject project = javaProject.getProject(); - IPath externalAnnotationPath = ClasspathEntry.getExternalAnnotationPath(entry, project, false); // unresolved for use in ExternalAnnotationTracker - if (externalAnnotationPath != null) { - result = setupExternalAnnotationProvider(project, externalAnnotationPath, result, + if (root.getKind() == IPackageFragmentRoot.K_BINARY) { + JavaProject javaProject = (JavaProject) getAncestor(IJavaElement.JAVA_PROJECT); + IClasspathEntry entry = javaProject.getClasspathEntryFor(getPath()); + if (entry != null) { + PackageFragment pkg = (PackageFragment) getParent(); + String entryName = Util.concatWith(pkg.names, getElementName(), '/'); + entryName = new String(CharArrayUtils.concat( + JavaNames.fieldDescriptorToBinaryName(descriptor.fieldDescriptor), SuffixConstants.SUFFIX_CLASS)); + IProject project = javaProject.getProject(); + IPath externalAnnotationPath = ClasspathEntry.getExternalAnnotationPath(entry, project, false); // unresolved for use in ExternalAnnotationTracker + if (externalAnnotationPath != null) { + result = setupExternalAnnotationProvider(project, externalAnnotationPath, result, entryName.substring(0, entryName.length() - SuffixConstants.SUFFIX_CLASS.length)); - } else if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { - result = new ExternalAnnotationDecorator(result, true); - } + } else if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { + result = new ExternalAnnotationDecorator(result, true); } } } @@ -465,21 +346,6 @@ public void close() throws JavaModelException { } super.close(); } -@Override -public IBuffer getBuffer() throws JavaModelException { - IStatus status = validateClassFile(); - if (status.isOK()) { - return super.getBuffer(); - } else { - switch (status.getCode()) { - case IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH: // don't throw a JavaModelException to be able to open .class file outside the classpath (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=138507 ) - case IJavaModelStatusConstants.INVALID_ELEMENT_TYPES: // don't throw a JavaModelException to be able to open .class file in proj==src case without source (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=221904 ) - return null; - default: - throw new JavaModelException((IJavaModelStatus) status); - } - } -} /** * @see IMember */ @@ -487,27 +353,6 @@ public IBuffer getBuffer() throws JavaModelException { public IClassFile getClassFile() { return this; } -/** - * @see IMember#getTypeRoot() - */ -public ITypeRoot getTypeRoot() { - return this; -} -/** - * A class file has a corresponding resource unless it is contained - * in a jar. - * - * @see IJavaElement - */ -@Override -public IResource getCorrespondingResource() throws JavaModelException { - IPackageFragmentRoot root= (IPackageFragmentRoot)getParent().getParent(); - if (root.isArchive()) { - return null; - } else { - return getUnderlyingResource(); - } -} /** * @see IClassFile */ @@ -528,59 +373,7 @@ public IJavaElement getElementAt(int position) throws JavaModelException { return findElement(type, position, mapper); } } -public IJavaElement getElementAtConsideringSibling(int position) throws JavaModelException { - IPackageFragment fragment = (IPackageFragment)getParent(); - PackageFragmentRoot root = (PackageFragmentRoot) fragment.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); - SourceMapper mapper = root.getSourceMapper(); - if (mapper == null) { - return null; - } else { - int index = this.name.indexOf('$'); - int prefixLength = index < 0 ? this.name.length() : index; - - IType type = null; - int start = -1; - int end = Integer.MAX_VALUE; - IJavaElement[] children = fragment.getChildren(); - for (int i = 0; i < children.length; i++) { - String childName = children[i].getElementName(); - - int childIndex = childName.indexOf('$'); - int childPrefixLength = childIndex < 0 ? childName.indexOf('.') : childIndex; - if (prefixLength == childPrefixLength && this.name.regionMatches(0, childName, 0, prefixLength)) { - IClassFile classFile = (IClassFile) children[i]; - // ensure this class file's buffer is open so that source ranges are computed - classFile.getBuffer(); - - SourceRange range = mapper.getSourceRange(classFile.getType()); - if (range == SourceMapper.UNKNOWN_RANGE) continue; - int newStart = range.getOffset(); - int newEnd = newStart + range.getLength() - 1; - if(newStart > start && newEnd < end - && newStart <= position && newEnd >= position) { - type = classFile.getType(); - start = newStart; - end = newEnd; - } - } - } - if(type != null) { - return findElement(type, position, mapper); - } - return null; - } -} -@Override -public String getElementName() { - return this.name + SuffixConstants.SUFFIX_STRING_class; -} -/** - * @see IJavaElement - */ -public int getElementType() { - return CLASS_FILE; -} /* * @see JavaElement */ @@ -602,47 +395,6 @@ public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, protected char getHandleMementoDelimiter() { return JavaElement.JEM_CLASSFILE; } -/* - * @see IJavaElement - */ -public IPath getPath() { - PackageFragmentRoot root = getPackageFragmentRoot(); - if (root.isArchive()) { - return root.getPath(); - } else { - return getParent().getPath().append(getElementName()); - } -} -/* - * @see IJavaElement - */ -@Override -public IResource resource(PackageFragmentRoot root) { - return ((IContainer) ((Openable) this.parent).resource(root)).getFile(new Path(getElementName())); -} -/** - * @see ISourceReference - */ -public String getSource() throws JavaModelException { - IBuffer buffer = getBuffer(); - if (buffer == null) { - return null; - } - return buffer.getContents(); -} -/** - * @see ISourceReference - */ -public ISourceRange getSourceRange() throws JavaModelException { - IBuffer buffer = getBuffer(); - if (buffer != null) { - String contents = buffer.getContents(); - if (contents == null) return null; - return new SourceRange(0, contents.length()); - } else { - return null; - } -} /* * Returns the name of the toplevel type of this class file. */ @@ -685,25 +437,6 @@ public ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor op.runOperation(monitor); return workingCopy; } -/** - * @see IClassFile - * @deprecated - */ -@Deprecated -public IJavaElement getWorkingCopy(IProgressMonitor monitor, org.eclipse.jdt.core.IBufferFactory factory) throws JavaModelException { - return getWorkingCopy(BufferFactoryWrapper.create(factory), monitor); -} -/** - * @see Openable - */ -@Override -protected boolean hasBuffer() { - return true; -} -@Override -public int hashCode() { - return Util.combineHashCodes(this.name.hashCode(), this.parent.hashCode()); -} /** * @see IClassFile */ @@ -716,24 +449,6 @@ public boolean isClass() throws JavaModelException { public boolean isInterface() throws JavaModelException { return getType().isInterface(); } -/** - * Returns true - class files are always read only. - */ -@Override -public boolean isReadOnly() { - return true; -} -private IStatus validateClassFile() { - IPackageFragmentRoot root = getPackageFragmentRoot(); - try { - if (root.getKind() != IPackageFragmentRoot.K_BINARY) - return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, root); - } catch (JavaModelException e) { - return e.getJavaModelStatus(); - } - IJavaProject project = getJavaProject(); - return JavaConventions.validateClassFileName(getElementName(), project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true)); -} /** * Opens and returns buffer on the source code associated with this class file. * Maps the source code to the children elements of this class file. @@ -775,7 +490,7 @@ private IBuffer mapSource(SourceMapper mapper, IBinaryType info, IClassFile buff buffer.addBufferChangedListener(this); // do the source mapping - mapper.mapSource(getOuterMostEnclosingType(), contents, info); + mapper.mapSource((NamedMember) getOuterMostEnclosingType(), contents, info); return buffer; } else { @@ -878,84 +593,4 @@ public static char[] translatedName(char[] name) { } return className; } - -/** - * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor) - * @deprecated - should use codeComplete(int, ICompletionRequestor) instead - */ -@Deprecated -public void codeComplete(int offset, final org.eclipse.jdt.core.ICodeCompletionRequestor requestor) throws JavaModelException { - - if (requestor == null){ - codeComplete(offset, (ICompletionRequestor)null); - return; - } - codeComplete( - offset, - new ICompletionRequestor(){ - public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName, char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) { - // ignore - } - public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) { - requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd); - } - public void acceptError(IProblem error) { - // was disabled in 1.0 - } - public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) { - requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd); - } - public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) { - requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd); - } - public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){ - requestor.acceptKeyword(keywordName, completionStart, completionEnd); - } - public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){ - requestor.acceptLabel(labelName, completionStart, completionEnd); - } - public void acceptLocalVariable(char[] localVarName,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){ - // ignore - } - public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){ - // skip parameter names - requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd); - } - public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){ - // ignore - } - public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){ - requestor.acceptModifier(modifierName, completionStart, completionEnd); - } - public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){ - requestor.acceptPackage(packageName, completionName, completionStart, completionEnd); - } - public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){ - requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd); - } - public void acceptVariableName(char[] typePackageName,char[] typeName,char[] varName,char[] completionName,int completionStart,int completionEnd, int relevance){ - // ignore - } - }); -} - -@Override -protected IStatus validateExistence(IResource underlyingResource) { - // check whether the class file can be opened - IStatus status = validateClassFile(); - if (!status.isOK()) - return status; - if (underlyingResource != null) { - if (!underlyingResource.isAccessible()) - return newDoesNotExistStatus(); - PackageFragmentRoot root; - if ((underlyingResource instanceof IFolder) && (root = getPackageFragmentRoot()).isArchive()) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=204652 - return root.newDoesNotExistStatus(); - } - } - return JavaModelStatus.VERIFIED_OK; -} -public ISourceRange getNameRange() { - return null; -} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java index 094ddcaf5d..3647282e4d 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java @@ -19,6 +19,7 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair; import org.eclipse.jdt.internal.compiler.env.IBinaryField; import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; +import org.eclipse.jdt.internal.compiler.env.IBinaryModule; import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.lookup.TagBits; @@ -152,6 +153,9 @@ private IMemberValuePair[] getTargetElementTypes(long tagBits) { if ((tagBits & TagBits.AnnotationForTypeParameter) != 0) { values.add(elementType + new String(TypeConstants.TYPE_PARAMETER_TARGET)); } + if ((tagBits & TagBits.AnnotationForModule) != 0) { + values.add(elementType + new String(TypeConstants.UPPER_MODULE)); + } final Object value; if (values.size() == 0) { if ((tagBits & TagBits.AnnotationTarget) != 0) @@ -404,13 +408,6 @@ private void generateTypeParameterInfos(BinaryMember parent, char[] signature, H newElements.put(typeParameter, info); } } -/** - * Returns true iff the readBinaryChildren has already - * been called. - */ -boolean hasReadBinaryChildren() { - return this.binaryChildren != null; -} /** * Creates the handles for BinaryMembers defined in this * ClassFile and adds them to the @@ -438,6 +435,21 @@ protected void readBinaryChildren(ClassFile classFile, HashMap newElements, IBin typeParameterHandles.toArray(this.typeParameters); } } +protected BinaryModule readBinaryModule(AbstractClassFile classFile, HashMap newElements, IBinaryModule modDecl) { + this.binaryChildren = JavaElement.NO_ELEMENTS; + this.typeParameters = TypeParameter.NO_TYPE_PARAMETERS; + if (modDecl != null) {//may not be a valid class file + // TODO: The following needs fix once we can get ModuleDeclaration from IndexBinaryType + char[] modName = modDecl.name(); + BinaryModule handle = new BinaryModule(classFile, new String(modName)); + ModuleDescriptionInfo moduleInfo = ModuleDescriptionInfo.createModule(modDecl); + setModule(handle); + newElements.put(handle, moduleInfo); + this.binaryChildren = new JavaElement[] { handle }; + return handle; + } + return null; +} /** * Removes the binary children handles and remove their infos from * the JavaModelManager's cache. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java index 4c085ce633..8de2b943f6 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -23,6 +23,7 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.util.ClassFileBytesDisassembler; import org.eclipse.jdt.core.util.IClassFileReader; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.core.util.Disassembler; import org.eclipse.jdt.internal.core.util.Util; @@ -31,12 +32,18 @@ */ public class ClassFileWorkingCopy extends CompilationUnit { - public ClassFile classFile; + public AbstractClassFile classFile; -public ClassFileWorkingCopy(ClassFile classFile, WorkingCopyOwner owner) { - super((PackageFragment) classFile.getParent(), ((BinaryType) classFile.getType()).getSourceFileName(null/*no info available*/), owner); +public ClassFileWorkingCopy(AbstractClassFile classFile, WorkingCopyOwner owner) { + super((PackageFragment) classFile.getParent(), sourceFileName(classFile), owner); this.classFile = classFile; } +private static String sourceFileName(AbstractClassFile classFile) { + if (classFile instanceof ModularClassFile) + return TypeConstants.MODULE_INFO_FILE_NAME_STRING; + else + return ((BinaryType) ((ClassFile) classFile).getType()).getSourceFileName(null/*no info available*/); +} public void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException { throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this)); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java index 7d1df251b4..a34937d703 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -136,6 +136,10 @@ private int classpathContains(IClasspathEntry[] list, IClasspathEntry entry) { continue; // null and not-null } } + if (((ClasspathEntry) entry).isModular() != + ((ClasspathEntry) other).isModular()) { + continue nextEntry; + } return i; } } @@ -339,6 +343,7 @@ public int generateDelta(JavaElementDelta delta, boolean addClasspathChange) { rootIDs, null, // inside original project false, // don't retrieve exported roots + true, // filter module roots null); /*no reverse map*/ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=335986 // When a package fragment's corresponding resource is removed from the project, diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java index c69d88fb8f..25e61b23a8 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Terry Parker - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425 @@ -64,6 +64,7 @@ import org.eclipse.jdt.internal.compiler.env.AccessRule; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.ManifestAnalyzer; import org.eclipse.jdt.internal.core.nd.IReader; import org.eclipse.jdt.internal.core.nd.java.JavaIndex; @@ -1000,7 +1001,7 @@ private static char[] getManifestContents(IPath jarPath) throws CoreException, I JavaModelManager manager = JavaModelManager.getJavaModelManager(); try { zip = manager.getZipFile(jarPath); - ZipEntry manifest = zip.getEntry("META-INF/MANIFEST.MF"); //$NON-NLS-1$ + ZipEntry manifest = zip.getEntry(TypeConstants.META_INF_MANIFEST_MF); if (manifest == null) { return null; } @@ -1363,14 +1364,7 @@ public static IPath getExternalAnnotationPath(IClasspathEntry entry, IProject pr * @return the attached external annotation path, or null. */ static String getRawExternalAnnotationPath(IClasspathEntry entry) { - IClasspathAttribute[] extraAttributes = entry.getExtraAttributes(); - for (int i = 0, length = extraAttributes.length; i < length; i++) { - IClasspathAttribute attribute = extraAttributes[i]; - if (IClasspathAttribute.EXTERNAL_ANNOTATION_PATH.equals(attribute.getName())) { - return attribute.getValue(); - } - } - return null; + return getExtraAttribute(entry, IClasspathAttribute.EXTERNAL_ANNOTATION_PATH); } private static void invalidExternalAnnotationPath(IProject project) { @@ -1408,6 +1402,17 @@ private IJavaModelStatus validateExternalAnnotationPath(IJavaProject javaProject new String[] { annotationPath.toString(), project.getName(), this.path.toString()})); } + public static String getExtraAttribute(IClasspathEntry entry, String attributeName) { + IClasspathAttribute[] extraAttributes = entry.getExtraAttributes(); + for (int i = 0, length = extraAttributes.length; i < length; i++) { + IClasspathAttribute attribute = extraAttributes[i]; + if (attributeName.equals(attribute.getName())) { + return attribute.getValue(); + } + } + return null; + } + public IClasspathEntry getReferencingEntry() { return this.referencingEntry; } @@ -1434,6 +1439,14 @@ public boolean isOptional() { } return false; } + public boolean isModular() { + for (int i = 0, length = this.extraAttributes.length; i < length; i++) { + IClasspathAttribute attribute = this.extraAttributes[i]; + if (IClasspathAttribute.MODULE.equals(attribute.getName()) && "true".equals(attribute.getValue())) //$NON-NLS-1$ + return true; + } + return false; + } public String getSourceAttachmentEncoding() { for (int i = 0, length = this.extraAttributes.length; i < length; i++) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java index dee42d2e86..797193f23a 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -26,6 +26,7 @@ import org.eclipse.jdt.internal.compiler.SourceElementParser; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; @@ -747,6 +748,11 @@ public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, String typeName = memento.nextToken(); JavaElement type = (JavaElement)getType(typeName); return type.getHandleFromMemento(memento, workingCopyOwner); + case JEM_MODULE: + if (!memento.hasMoreTokens()) return this; + String modName = memento.nextToken(); + JavaElement mod = new SourceModule(this, modName); + return mod.getHandleFromMemento(memento, workingCopyOwner); } return null; } @@ -1367,4 +1373,29 @@ protected IStatus validateExistence(IResource underlyingResource) { public ISourceRange getNameRange() { return null; } + + +@Override +public IModuleDescription getModule() throws JavaModelException { + if (TypeConstants.MODULE_INFO_FILE_NAME_STRING.equals(getElementName())) + return ((CompilationUnitElementInfo) getElementInfo()).getModule(); + return null; +} + +@Override +public char[] getModuleName() { + try { + IModuleDescription module = getModule(); + if (module == null) { + JavaProject project = (JavaProject) getAncestor(IJavaElement.JAVA_PROJECT); + module = project.getModuleDescription(); + } + if (module != null) + return module.getElementName().toCharArray(); + } catch (JavaModelException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java index f72671f0d8..05e00310f7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java @@ -1,11 +1,11 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -27,6 +27,7 @@ import org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.jdt.internal.compiler.env.ISourceType; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; @@ -105,6 +106,10 @@ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, Acc final long savedComplianceLevel = this.options.complianceLevel; final long savedSourceLevel = this.options.sourceLevel; + LookupEnvironment environment = packageBinding.environment; + if (environment == null) + environment = this.lookupEnvironment; + try { IJavaProject project = ((SourceTypeElementInfo) sourceTypes[0]).getHandle().getJavaProject(); this.options.complianceLevel = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_COMPLIANCE, true)); @@ -117,12 +122,12 @@ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, Acc SourceTypeConverter.FIELD_AND_METHOD // need field and methods | SourceTypeConverter.MEMBER_TYPE // need member types | SourceTypeConverter.FIELD_INITIALIZATION, // need field initialization - this.lookupEnvironment.problemReporter, + environment.problemReporter, result); if (unit != null) { - this.lookupEnvironment.buildTypeBindings(unit, accessRestriction); - this.lookupEnvironment.completeTypeBindings(unit); + environment.buildTypeBindings(unit, accessRestriction); + environment.completeTypeBindings(unit); } } finally { this.options.complianceLevel = savedComplianceLevel; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java index 34b4ca9600..4f3c72d740 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -23,6 +23,7 @@ import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMemberValuePair; import org.eclipse.jdt.core.ITypeParameter; +import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; @@ -253,6 +254,10 @@ protected SourceType createTypeHandle(JavaElement parent, TypeInfo typeInfo) { String nameString= new String(typeInfo.name); return new SourceType(parent, nameString); } +protected SourceModule createModuleHandle(JavaElement parent, ModuleInfo modInfo) { + String nameString= new String(modInfo.moduleName); + return new org.eclipse.jdt.internal.core.SourceModule(parent, nameString); +} protected TypeParameter createTypeParameter(JavaElement parent, String name) { return new TypeParameter(parent, name); } @@ -491,7 +496,17 @@ private LocalVariable[] acceptMethodParameters(Argument[] arguments, JavaElement } return result; } +public void enterModule(ModuleInfo info) { + + Object parentInfo = this.infoStack.peek(); + JavaElement parentHandle= (JavaElement) this.handleStack.peek(); + JavaElement handle = createModuleHandle(parentHandle, info); + + this.infoStack.push(info); + this.handleStack.push(handle); + addToChildren(parentInfo, handle); +} /** * @see ISourceElementRequestor */ @@ -499,9 +514,9 @@ public void enterType(TypeInfo typeInfo) { Object parentInfo = this.infoStack.peek(); JavaElement parentHandle= (JavaElement) this.handleStack.peek(); - SourceType handle = createTypeHandle(parentHandle, typeInfo); //NB: occurenceCount is computed in resolveDuplicates - resolveDuplicates(handle); - + JavaElement handle = createTypeHandle(parentHandle, typeInfo); + //NB: occurenceCount is computed in resolveDuplicates + resolveDuplicates((SourceType) handle); this.infoStack.push(typeInfo); this.handleStack.push(handle); @@ -509,6 +524,17 @@ public void enterType(TypeInfo typeInfo) { ((TypeInfo) parentInfo).childrenCategories.put(handle, typeInfo.categories); addToChildren(parentInfo, handle); } +private org.eclipse.jdt.internal.core.ModuleDescriptionInfo createModuleInfo(ModuleInfo modInfo, org.eclipse.jdt.internal.core.SourceModule handle) { + org.eclipse.jdt.internal.core.ModuleDescriptionInfo info = org.eclipse.jdt.internal.core.ModuleDescriptionInfo.createModule(modInfo.node); + info.setHandle(handle); + info.setSourceRangeStart(modInfo.declarationStart); + info.setFlags(modInfo.modifiers); + info.setNameSourceStart(modInfo.nameSourceStart); + info.setNameSourceEnd(modInfo.nameSourceEnd); + this.newElements.put(handle, info); + + return info; +} private SourceTypeElementInfo createTypeInfo(TypeInfo typeInfo, SourceType handle) { SourceTypeElementInfo info = typeInfo.anonymousMember ? @@ -702,16 +728,34 @@ public void exitMethod(int declarationEnd, Expression defaultValue) { this.handleStack.pop(); this.infoStack.pop(); } +public void exitModule(int declarationEnd) { + ModuleInfo moduleInfo = (ModuleInfo) this.infoStack.peek(); + SourceModule handle = (SourceModule) this.handleStack.peek(); + JavaProject proj = (JavaProject) handle.getAncestor(IJavaElement.JAVA_PROJECT); + if (proj != null) { + try { + org.eclipse.jdt.internal.core.SourceModule moduleDecl = handle; + org.eclipse.jdt.internal.core.ModuleDescriptionInfo info = createModuleInfo(moduleInfo, moduleDecl); + info.setSourceRangeEnd(declarationEnd); + info.children = getChildren(info); + this.unitInfo.setModule(moduleDecl); + proj.setModuleDescription(moduleDecl); + } catch (JavaModelException e) { + // Unexpected while creating + } + } + this.handleStack.pop(); + this.infoStack.pop(); +} /** * @see ISourceElementRequestor */ public void exitType(int declarationEnd) { - SourceType handle = (SourceType) this.handleStack.peek(); TypeInfo typeInfo = (TypeInfo) this.infoStack.peek(); + SourceType handle = (SourceType) this.handleStack.peek(); SourceTypeElementInfo info = createTypeInfo(typeInfo, handle); info.setSourceRangeEnd(declarationEnd); info.children = getChildren(typeInfo); - this.handleStack.pop(); this.infoStack.pop(); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java index 828ba35ccc..a01c1978ec 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -89,7 +89,7 @@ public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElemen initializeASTParser(); } private void initializeASTParser() { - this.parser = ASTParser.newParser(AST.JLS8); + this.parser = ASTParser.newParser(AST.JLS9); } /** * Returns the children of source which are affected by this operation. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java index cbb38dbdbd..199fbfa004 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -261,7 +261,7 @@ protected CompilationUnit parse(ICompilationUnit cu) throws JavaModelException { // ensure cu is consistent (noop if already consistent) cu.makeConsistent(this.progressMonitor); // create an AST for the compilation unit - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(AST.JLS9); parser.setSource(cu); return (CompilationUnit) parser.createAST(this.progressMonitor); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java index d1e230e235..48a4e2544c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -78,7 +78,7 @@ protected StructuralPropertyDescriptor getChildPropertyDescriptor(ASTNode parent protected ASTNode generateElementAST(ASTRewrite rewriter, ICompilationUnit cu) throws JavaModelException { if (this.createdNode == null) { this.source = removeIndentAndNewLines(this.source, cu); - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(AST.JLS9); parser.setSource(this.source.toCharArray()); parser.setProject(getCompilationUnit().getJavaProject()); parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS); @@ -165,7 +165,7 @@ protected String generateSyntaxIncorrectAST() { buff.append(lineSeparator + " public class A {" + lineSeparator); //$NON-NLS-1$ buff.append(this.source); buff.append(lineSeparator).append('}'); - ASTParser parser = ASTParser.newParser(AST.JLS8); + ASTParser parser = ASTParser.newParser(AST.JLS9); parser.setSource(buff.toString().toCharArray()); CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null); TypeDeclaration typeDeclaration = (TypeDeclaration) compilationUnit.types().iterator().next(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java index 593a89073f..0bc605c956 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -81,7 +81,7 @@ private void deleteElement(IJavaElement elementToRemove, ICompilationUnit cu) th } private void initASTParser() { - this.parser = ASTParser.newParser(AST.JLS8); + this.parser = ASTParser.newParser(AST.JLS9); } /** diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java index 34a9211201..699151ce6f 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -34,6 +34,7 @@ import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.SourceElementParser; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; import org.eclipse.jdt.internal.core.builder.JavaBuilder; import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy; @@ -495,7 +496,7 @@ private void checkProjectsAndClasspathChanges(IResourceDelta delta) { this.manager.removePerProjectInfo(javaProject, true /* remove external jar files indexes and timestamps*/); // remove container cache for this project this.manager.containerRemove(javaProject); - + JavaModelManager.getModulePathManager().removeEntry(javaProject); this.state.rootsAreStale = true; break; } @@ -552,6 +553,28 @@ private void checkProjectsAndClasspathChanges(IResourceDelta delta) { javaProject = (JavaProject)JavaCore.create(file.getProject()); javaProject.resetResolvedClasspath(); this.state.rootsAreStale = true; + } else if (file.getName().toLowerCase().contains(new String(TypeConstants.MODULE_INFO_FILE_NAME))) { + switch(kind) { + case IResourceDelta.CHANGED : + int flags = delta.getFlags(); + if ((flags & IResourceDelta.CONTENT) == 0) + break; + javaProject = (JavaProject)JavaCore.create(file.getProject()); + this.manager.removePerProjectInfo(javaProject, false); + this.state.rootsAreStale = true; + break; + //$FALL-THROUGH$ + case IResourceDelta.ADDED : + case IResourceDelta.REMOVED : + javaProject = (JavaProject)JavaCore.create(file.getProject()); + try { + // Make sure module description is read + javaProject.close(); + } catch (JavaModelException e) { + // do nothing + } + break; + } } break; @@ -797,7 +820,10 @@ private Openable createElement(IResource resource, int elementType, RootInfo roo // create class file handle // fileName validation has been done in elementType(IResourceDelta, int, boolean) String fileName = path.lastSegment(); - element = pkgFragment.getClassFile(fileName); + if (TypeConstants.MODULE_INFO_CLASS_NAME_STRING.equals(fileName)) + element = pkgFragment.getModularClassFile(); + else + element = pkgFragment.getClassFile(fileName); } } } @@ -1120,6 +1146,7 @@ private void deleting(IProject project) { javaProject.computePackageFragmentRoots( javaProject.getResolvedClasspath(), false, + true, // respect limit modules null /*no reverse map*/)); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java index f0540458be..8a0ddadff4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java @@ -13,6 +13,7 @@ import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IInitializer; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; @@ -30,6 +31,7 @@ public interface IJavaElementRequestor { public void acceptMethod(IMethod method); public void acceptPackageFragment(IPackageFragment packageFragment); public void acceptType(IType type); +public void acceptModule(IModuleDescription module); /** * Returns true if this IJavaElementRequestor does * not want to receive any more results. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JModPackageFragmentRoot.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JModPackageFragmentRoot.java new file mode 100644 index 0000000000..51cb2bd3b9 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JModPackageFragmentRoot.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.core.builder.ClasspathJMod; +import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject; + +/** + * A package fragment root that corresponds to a JMod file. + * + *

      NOTE: The only visible entries from a Jmod package fragment root + * are .class files. The sub folder "classes" where the .class files are nested under + * is hidden from clients. THe package fragments appear to be directly under the + * package fragment roots. + *

      NOTE: A JMod package fragment root may or may not have an associated resource. + * + * @see org.eclipse.jdt.core.IPackageFragmentRoot + * @see org.eclipse.jdt.internal.core.JarPackageFragmentRootInfo + */ +public class JModPackageFragmentRoot extends JarPackageFragmentRoot { + + /** + * Constructs a package fragment root which is the root of the Java package directory hierarchy + * based on a JMOD file that is not contained in a IJavaProject and + * does not have an associated IResource. + */ + protected JModPackageFragmentRoot(IPath externalPath, JavaProject project) { + super(externalPath, project); + } + /** + * Constructs a package fragment root which is the root of the Java package directory hierarchy + * based on a JMOD file. + */ + protected JModPackageFragmentRoot(IResource resource, JavaProject project) { + super(resource, project); + } + + /** + * @see PackageFragmentRoot#getClassFilePath(String) + */ + public String getClassFilePath(String entryName) { + char[] name = CharOperation.append(ClasspathJMod.CLASSES_FOLDER, entryName.toCharArray()); + return new String(name); + } + protected void initRawPackageInfo(HashtableOfArrayToObject rawPackageInfo, String entryName, boolean isDirectory, String compliance) { + char[] name = entryName.toCharArray(); + if (CharOperation.prefixEquals(ClasspathJMod.CLASSES_FOLDER, name)) { + name = CharOperation.subarray(name, ClasspathJMod.CLASSES_FOLDER.length, name.length); + } + super.initRawPackageInfo(rawPackageInfo, new String(name), isDirectory, compliance); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java index cb048920e0..8861b89341 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java index 21af1eb87b..5ce6a8a853 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,6 +11,7 @@ package org.eclipse.jdt.internal.core; import java.io.ByteArrayInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; @@ -18,9 +19,12 @@ import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IJarEntryResource; import org.eclipse.jdt.core.IJavaModelStatusConstants; +import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.Util; /** @@ -30,7 +34,6 @@ */ public class JarEntryFile extends JarEntryResource { private static final IJarEntryResource[] NO_CHILDREN = new IJarEntryResource[0]; - public JarEntryFile(String simpleName) { super(simpleName); } @@ -42,24 +45,38 @@ public JarEntryResource clone(Object newParent) { } public InputStream getContents() throws CoreException { - ZipFile zipFile = null; - try { - zipFile = getZipFile(); - if (JavaModelManager.ZIP_ACCESS_VERBOSE) { - System.out.println("(" + Thread.currentThread() + ") [JarEntryFile.getContents()] Creating ZipFile on " +zipFile.getName()); //$NON-NLS-1$ //$NON-NLS-2$ + IPackageFragmentRoot root = getPackageFragmentRoot(); + if (Util.isJrt(root.getPath().toOSString())) { + try { + IPath rootPath = root.getPath(); + Object target = JavaModel.getTarget(rootPath, false); + if (target != null && target instanceof File) { + return JRTUtil.getContentFromJrt((File) target, getEntryName(), root.getElementName()); + } + } catch (IOException e) { + throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); } - String entryName = getEntryName(); - ZipEntry zipEntry = zipFile.getEntry(entryName); - if (zipEntry == null){ - throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, entryName)); + return null; + } else { + ZipFile zipFile = null; + try { + zipFile = getZipFile(); + if (JavaModelManager.ZIP_ACCESS_VERBOSE) { + System.out.println("(" + Thread.currentThread() + ") [JarEntryFile.getContents()] Creating ZipFile on " +zipFile.getName()); //$NON-NLS-1$ //$NON-NLS-2$ + } + String entryName = getEntryName(); + ZipEntry zipEntry = zipFile.getEntry(entryName); + if (zipEntry == null){ + throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, entryName)); + } + byte[] contents = Util.getZipEntryByteContent(zipEntry, zipFile); + return new ByteArrayInputStream(contents); + } catch (IOException e){ + throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); + } finally { + // avoid leaking ZipFiles + JavaModelManager.getJavaModelManager().closeZipFile(zipFile); } - byte[] contents = Util.getZipEntryByteContent(zipEntry, zipFile); - return new ByteArrayInputStream(contents); - } catch (IOException e){ - throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); - } finally { - // avoid leaking ZipFiles - JavaModelManager.getJavaModelManager().closeZipFile(zipFile); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java index 57a2775865..4f0fcdf2fb 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java index b3e35e5a45..07bc54488b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -27,6 +27,7 @@ import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModelStatusConstants; import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.core.util.Util; /** @@ -73,7 +74,10 @@ private IJavaElement[] computeChildren(ArrayList namesWithoutExtension) { IJavaElement[] children = new IJavaElement[size]; for (int i = 0; i < size; i++) { String nameWithoutExtension = (String) namesWithoutExtension.get(i); - children[i] = new ClassFile(this, nameWithoutExtension); + if (TypeConstants.MODULE_INFO_NAME_STRING.equals(nameWithoutExtension)) + children[i] = new ModularClassFile(this); + else + children[i] = new ClassFile(this, nameWithoutExtension); } return children; } @@ -173,7 +177,7 @@ protected Object createElementInfo() { /** * @see org.eclipse.jdt.core.IPackageFragment */ -public IClassFile[] getClassFiles() throws JavaModelException { +public IClassFile[] getAllClassFiles() throws JavaModelException { ArrayList list = getChildrenOfType(CLASS_FILE); IClassFile[] array= new IClassFile[list.size()]; list.toArray(array); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java index f9675fdb0b..0bcb245b1b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,9 +10,11 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core; +import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; +import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; @@ -27,6 +29,7 @@ import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.core.nd.IReader; import org.eclipse.jdt.internal.core.nd.java.JavaIndex; import org.eclipse.jdt.internal.core.nd.java.NdResourceFile; @@ -48,7 +51,7 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public class JarPackageFragmentRoot extends PackageFragmentRoot { - private final static ArrayList EMPTY_LIST = new ArrayList(); + protected final static ArrayList EMPTY_LIST = new ArrayList(); /** * The path to the jar file @@ -81,7 +84,7 @@ protected JarPackageFragmentRoot(IResource resource, JavaProject project) { * by the path of class files contained in the jar of this package fragment root. */ protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException { - HashtableOfArrayToObject rawPackageInfo = new HashtableOfArrayToObject(); + final HashtableOfArrayToObject rawPackageInfo = new HashtableOfArrayToObject(); IJavaElement[] children; try { // always create the default package @@ -132,7 +135,6 @@ protected boolean computeChildren(OpenableElementInfo info, IResource underlying JavaModelManager.getJavaModelManager().closeZipFile(jar); } } - // loop through all of referenced packages, creating package fragments if necessary // and cache the entry names in the rawPackageInfo table children = new IJavaElement[rawPackageInfo.size()]; @@ -158,6 +160,19 @@ protected boolean computeChildren(OpenableElementInfo info, IResource underlying ((JarPackageFragmentRootInfo) info).rawPackageInfo = rawPackageInfo; return true; } + protected IJavaElement[] createChildren(final HashtableOfArrayToObject rawPackageInfo) { + IJavaElement[] children; + // loop through all of referenced packages, creating package fragments if necessary + // and cache the entry names in the rawPackageInfo table + children = new IJavaElement[rawPackageInfo.size()]; + int index = 0; + for (int i = 0, length = rawPackageInfo.keyTable.length; i < length; i++) { + String[] pkgName = (String[]) rawPackageInfo.keyTable[i]; + if (pkgName == null) continue; + children[index++] = getPackageFragment(pkgName); + } + return children; + } /** * Returns a new element info for this element. */ @@ -225,6 +240,9 @@ public Object[] getNonJavaResources() throws JavaModelException { public PackageFragment getPackageFragment(String[] pkgName) { return new JarPackageFragment(this, pkgName); } + public PackageFragment getPackageFragment(String[] pkgName, String mod) { + return new JarPackageFragment(this, pkgName); // Overridden in JImageModuleFragmentBridge + } public IPath internalPath() { if (isExternal()) { return this.jarPath; @@ -255,8 +273,17 @@ public IResource getUnderlyingResource() throws JavaModelException { public int hashCode() { return this.jarPath.hashCode(); } - private void initRawPackageInfo(HashtableOfArrayToObject rawPackageInfo, String entryName, boolean isDirectory, String compliance) { - int lastSeparator = isDirectory ? entryName.length()-1 : entryName.lastIndexOf('/'); + protected void initRawPackageInfo(HashtableOfArrayToObject rawPackageInfo, String entryName, boolean isDirectory, String compliance) { + int lastSeparator; + if (isDirectory) { + if (entryName.charAt(entryName.length() - 1) == '/') { + lastSeparator = entryName.length() - 1; + } else { + lastSeparator = entryName.length(); + } + } else { + lastSeparator = entryName.lastIndexOf('/'); + } String[] pkgName = Util.splitOn('/', entryName, 0, lastSeparator); String[] existing = null; int length = pkgName.length; @@ -316,7 +343,6 @@ public boolean isExternal() { public boolean isReadOnly() { return true; } - /** * Returns whether the corresponding resource or associated file exists */ @@ -349,4 +375,28 @@ public URL getIndexPath() { return null; } + @Override + public Manifest getManifest() { + ZipFile jar = null; + try { + jar = getJar(); + ZipEntry mfEntry = jar.getEntry(TypeConstants.META_INF_MANIFEST_MF); + if (mfEntry != null) + return new Manifest(jar.getInputStream(mfEntry)); + } catch (CoreException | IOException e) { + // must do without manifest + } finally { + JavaModelManager.getJavaModelManager().closeZipFile(jar); + } + return null; + } + +// @Override +// public boolean isModule() { +// try { +// return ((PackageFragmentRootInfo) getElementInfo()).isModule(resource(), this); +// } catch (JavaModelException e) { +// return false; +// } +// } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java index 8def7e8c1e..519defa6b4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -87,6 +87,7 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement public static final char JEM_INITIALIZER = '|'; public static final char JEM_COMPILATIONUNIT = '{'; public static final char JEM_CLASSFILE = '('; + public static final char JEM_MODULAR_CLASSFILE = '\''; public static final char JEM_TYPE = '['; public static final char JEM_PACKAGEDECLARATION = '%'; public static final char JEM_IMPORTDECLARATION = '#'; @@ -97,6 +98,7 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement public static final char JEM_LAMBDA_EXPRESSION = ')'; public static final char JEM_LAMBDA_METHOD = '&'; public static final char JEM_STRING = '"'; + public static final char JEM_MODULE = '`'; /** * Before ')', '&' and '"' became the newest additions as delimiters, the former two @@ -121,6 +123,7 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement */ protected JavaElement parent; + protected static final String[] NO_STRINGS = new String[0]; protected static final JavaElement[] NO_ELEMENTS = new JavaElement[0]; protected static final Object NO_INFO = new Object(); @@ -201,6 +204,7 @@ protected void escapeMementoName(StringBuffer buffer, String mementoName) { case JEM_INITIALIZER: case JEM_COMPILATIONUNIT: case JEM_CLASSFILE: + case JEM_MODULAR_CLASSFILE: case JEM_TYPE: case JEM_PACKAGEDECLARATION: case JEM_IMPORTDECLARATION: diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java index 86b94bff82..06b2b6265b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IInitializer; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; @@ -66,6 +67,12 @@ public class JavaElementRequestor implements IJavaElementRequestor { */ protected ArrayList types= null; + /** + * A collection of the resulting modules, or null + * if no module results have been received + */ + protected ArrayList modules = null; + /** * Empty arrays used for efficiency */ @@ -74,6 +81,7 @@ public class JavaElementRequestor implements IJavaElementRequestor { protected static final IType[] EMPTY_TYPE_ARRAY= new IType[0]; protected static final IPackageFragment[] EMPTY_PACKAGE_FRAGMENT_ARRAY= new IPackageFragment[0]; protected static final IMethod[] EMPTY_METHOD_ARRAY= new IMethod[0]; + protected static final IModuleDescription[] EMPTY_MODULE_ARRAY= new IModuleDescription[0]; /** * @see IJavaElementRequestor */ @@ -128,6 +136,16 @@ public void acceptType(IType type) { } this.types.add(type); } +/** + * @see IJavaElementRequestor + */ +public void acceptModule(IModuleDescription module) { + if (this.modules == null) { + this.modules= new ArrayList(); + } + this.modules.add(module); +} + /** * @see IJavaElementRequestor */ @@ -200,6 +218,18 @@ public IType[] getTypes() { this.types.toArray(results); return results; } +/** + * @see IJavaElementRequestor + */ +public IModuleDescription[] getModules() { + if (this.modules == null) { + return EMPTY_MODULE_ARRAY; + } + int size = this.modules.size(); + IModuleDescription[] results = new IModuleDescription[size]; + this.modules.toArray(results); + return results; +} /** * @see IJavaElementRequestor */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java index 8e8a746c52..2338341c32 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -27,6 +27,7 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.*; +import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; @@ -361,6 +362,17 @@ public static boolean isFile(Object target) { return false; } +public static boolean isJimage(File file) { + return JavaModelManager.isJrt(file.getPath()); +} +public static boolean isJmod(File file) { + IPath path = Path.fromOSString(file.getPath()); + if (path.getFileExtension().equalsIgnoreCase(SuffixConstants.EXTENSION_jmod)) { + return true; + } + return false; +} + /** * Returns whether the provided path is an external file, checking and updating the * JavaModelManager's external file cache. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java index dc34b7389a..dc5f6ae078 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java @@ -126,7 +126,10 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; +import org.eclipse.jdt.internal.compiler.util.ObjectVector; import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache; import org.eclipse.jdt.internal.core.builder.JavaBuilder; import org.eclipse.jdt.internal.core.dom.SourceRangeVerifier; @@ -412,7 +415,7 @@ public void setCache(IPath path, ZipFile zipFile) { public static class CompilationParticipants { - private final static int MAX_SOURCE_LEVEL = 8; // 1.1 to 1.8 + private final static int MAX_SOURCE_LEVEL = 9; // 1.1 to 1.8 and 9 /* * The registered compilation participants (a table from int (source level) to Object[]) @@ -538,6 +541,8 @@ else if (TRUE.equals(configElement.getAttribute("createsProblems"))) //$NON-NLS- * ... * 1.6 -> 5 * 1.7 -> 6 + * 1.8 -> 7 + * 9 -> 8 * null -> 0 */ private int indexForSourceLevel(String sourceLevel) { @@ -558,6 +563,8 @@ private int indexForSourceLevel(String sourceLevel) { return 6; case ClassFileConstants.MAJOR_VERSION_1_8: return 7; + case ClassFileConstants.MAJOR_VERSION_9: + return 8; default: // all other cases including ClassFileConstants.MAJOR_VERSION_1_1 return 0; @@ -1061,6 +1068,9 @@ public static IClassFile createClassFileFrom(IFile file, IJavaProject project ) PackageFragmentRoot root = (PackageFragmentRoot) project.getPackageFragmentRoot(file.getParent()); pkg = root.getPackageFragment(CharOperation.NO_STRINGS); } + String fileName = file.getName(); + if (TypeConstants.MODULE_INFO_CLASS_NAME_STRING.equals(fileName)) + return pkg.getModularClassFile(); return pkg.getClassFile(file.getName()); } @@ -1247,6 +1257,7 @@ public static class PerProjectInfo { public Map rootPathToRawEntries; // reverse map from a package fragment root's path to the raw entry public Map rootPathToResolvedEntries; // map from a package fragment root's path to the resolved entry public IPath outputLocation; + public Map jrtRoots; // A map between a JRT file system (as a string) and the package fragment roots found in it. public IEclipsePreferences preferences; public Hashtable options; @@ -1366,6 +1377,11 @@ public synchronized ClasspathChange setResolvedClasspath(IClasspathEntry[] newRe return setClasspath(this.rawClasspath, referencedEntries, this.outputLocation, this.rawClasspathStatus, newResolvedClasspath, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, addClasspathChange); } + public synchronized void setJrtPackageRoots(IPath jrtPath, ObjectVector roots) { + if (this.jrtRoots == null) this.jrtRoots = new HashMap<>(); + this.jrtRoots.put(jrtPath, roots); + } + /** * Reads the classpath and caches the entries. Returns a two-dimensional array, where the number of elements in the row is fixed to 2. * The first element is an array of raw classpath entries and the second element is an array of referenced entries that may have been stored @@ -1550,6 +1566,7 @@ public String toString() { public static boolean CP_RESOLVE_VERBOSE_ADVANCED = false; public static boolean CP_RESOLVE_VERBOSE_FAILURE = false; public static boolean ZIP_ACCESS_VERBOSE = false; + public static boolean JRT_ACCESS_VERBOSE = false; /** * A cache of opened zip files per thread. @@ -1558,7 +1575,8 @@ public String toString() { private ThreadLocal zipFiles = new ThreadLocal(); private UserLibraryManager userLibraryManager; - + + private ModuleSourcePathManager modulePathManager; /* * A set of IPaths for jars that are known to not contain a chaining (through MANIFEST.MF) to another library */ @@ -2726,6 +2744,17 @@ public static UserLibraryManager getUserLibraryManager() { return MANAGER.userLibraryManager; } + public static ModuleSourcePathManager getModulePathManager() { + if (MANAGER.modulePathManager == null) { + ModuleSourcePathManager modulePathManager = new ModuleSourcePathManager(); + synchronized(MANAGER) { + if (MANAGER.modulePathManager == null) { // ensure another library manager was not set while creating the instance above + MANAGER.modulePathManager = modulePathManager; + } + } + } + return MANAGER.modulePathManager; + } /* * Returns all the working copies which have the given owner. * Adds the working copies of the primary owner if specified. @@ -2770,7 +2799,19 @@ public JavaWorkspaceScope getWorkspaceScope() { return this.workspaceScope; } + public static boolean isJrt(IPath path) { + return path.toString().endsWith(JRTUtil.JRT_FS_JAR); + } + + public static boolean isJrt(String path) { + return isJrt(new Path(path)); + } + public void verifyArchiveContent(IPath path) throws CoreException { + // TODO: we haven't finalized what path the JRT is represented by. Don't attempt to validate it. + if (isJrt(path)) { + return; + } throwExceptionIfArchiveInvalid(path); // Check if we can determine the archive's validity by examining the index if (JavaIndex.isEnabled()) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java index bf64ae66c2..d4438386b4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,7 +16,10 @@ import java.io.*; import java.net.URI; +import java.nio.file.FileVisitResult; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; @@ -24,6 +27,9 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.jar.Manifest; import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; @@ -50,6 +56,7 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentDescription; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IScopeContext; @@ -62,6 +69,7 @@ import org.eclipse.jdt.core.IJavaModelStatus; import org.eclipse.jdt.core.IJavaModelStatusConstants; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IRegion; @@ -73,6 +81,13 @@ import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.eval.IEvaluationContext; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference; +import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.ObjectVector; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; @@ -461,8 +476,25 @@ protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, IClasspathEntry[] resolvedClasspath = getResolvedClasspath(); // compute the pkg fragment roots - info.setChildren(computePackageFragmentRoots(resolvedClasspath, false, null /*no reverse map*/)); - + IPackageFragmentRoot[] roots = computePackageFragmentRoots(resolvedClasspath, false, true, null /*no reverse map*/); + info.setChildren(roots); + IModuleDescription module = null; + IModuleDescription current = null; + for (IPackageFragmentRoot root : roots) { + if (root.getKind() != IPackageFragmentRoot.K_SOURCE) + continue; + module = root.getModuleDescription(); + if (module != null) { + if (current != null) { + throw new JavaModelException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, + Messages.bind(Messages.classpath_duplicateEntryPath, TypeConstants.MODULE_INFO_FILE_NAME_STRING, getElementName()))); + } + current = module; + JavaModelManager.getModulePathManager().addEntry(module, this); + //break; continue looking, there may be other roots containing module-info + info.setModule(module); + } + } return true; } @@ -553,6 +585,7 @@ public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry resolv computePackageFragmentRoots( new IClasspathEntry[]{ resolvedEntry }, false, // don't retrieve exported roots + true, // respect limit-modules null /* no reverse map */ ); } catch (JavaModelException e) { @@ -569,6 +602,9 @@ public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry resolv * @param rootIDs HashSet * @param referringEntry the CP entry (project) referring to this entry, or null if initial project * @param retrieveExportedRoots boolean + * @param filterModuleRoots if true, roots corresponding to modules will be filtered if applicable: + * if a limit-modules attribute exists, this is used, otherwise system modules will be filtered + * according to the rules of root modules per JEP 261. * @throws JavaModelException */ public void computePackageFragmentRoots( @@ -577,6 +613,7 @@ public void computePackageFragmentRoots( HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, + boolean filterModuleRoots, Map rootToResolvedEntries) throws JavaModelException { String rootID = ((ClasspathEntry)resolvedEntry).rootID(); @@ -616,7 +653,36 @@ public void computePackageFragmentRoots( } else if (target instanceof File) { // external target if (JavaModel.isFile(target)) { - root = new JarPackageFragmentRoot(entryPath, this); + if (JavaModel.isJimage((File) target)) { + PerProjectInfo info = getPerProjectInfo(); + ObjectVector imageRoots; + if (info.jrtRoots == null || !info.jrtRoots.containsKey(entryPath)) { + imageRoots = new ObjectVector(); + loadModulesInJimage(entryPath, imageRoots, rootToResolvedEntries, resolvedEntry, referringEntry); + info.setJrtPackageRoots(entryPath, imageRoots); // unfiltered + rootIDs.add(rootID); + } else { + imageRoots = info.jrtRoots.get(entryPath); + } + if (filterModuleRoots) { + List rootModules = null; + String limitModules = ClasspathEntry.getExtraAttribute(resolvedEntry, IClasspathAttribute.LIMIT_MODULES); + if (limitModules != null) { + rootModules = Arrays.asList(limitModules.split(",")); //$NON-NLS-1$ + } else if (isUnNamedModule()) { + rootModules = defaultRootModules((Iterable) imageRoots); + } + if (rootModules != null) { + imageRoots = filterLimitedModules(entryPath, imageRoots, rootModules); + } + } + accumulatedRoots.addAll(imageRoots); + } else if (JavaModel.isJmod((File) target)) { + root = new JModPackageFragmentRoot(entryPath, this); + } + else { + root = new JarPackageFragmentRoot(entryPath, this); + } } else if (((File) target).isDirectory()) { root = new ExternalPackageFragmentRoot(entryPath, this); } @@ -641,6 +707,7 @@ public void computePackageFragmentRoots( rootIDs, rootToResolvedEntries == null ? resolvedEntry : ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry), // only combine if need to build the reverse map retrieveExportedRoots, + filterModuleRoots, rootToResolvedEntries); } break; @@ -653,6 +720,166 @@ public void computePackageFragmentRoots( } } + /** Implements selection of root modules per JEP 261. */ + public static List defaultRootModules(Iterable allSystemRoots) { + return internalDefaultRootModules(allSystemRoots, + IPackageFragmentRoot::getElementName, + r -> (r instanceof JrtPackageFragmentRoot) ? ((JrtPackageFragmentRoot) r).getModule() : null); + } + + public static List internalDefaultRootModules(Iterable allSystemModules, Function getModuleName, Function getModule) { + List result = new ArrayList<>(); + boolean hasJavaDotSE = false; + for (T mod : allSystemModules) { + String moduleName = getModuleName.apply(mod); + if ("java.se".equals(moduleName)) { //$NON-NLS-1$ + result.add(moduleName); + hasJavaDotSE = true; + break; + } + } + for (T mod : allSystemModules) { + String moduleName = getModuleName.apply(mod); + boolean isJavaDotStart = moduleName.startsWith("java."); //$NON-NLS-1$ + boolean isPotentialRoot = !isJavaDotStart; // always include non-java.* + if (!hasJavaDotSE) + isPotentialRoot |= isJavaDotStart; // no java.se => add all java.* + + if (isPotentialRoot) { + IModule module = getModule.apply(mod); + if (module != null) { + for (IPackageExport packageExport : module.exports()) { + if (!packageExport.isQualified()) { + result.add(moduleName); + break; + } + } + } + } + } + return result; + } + + private ObjectVector filterLimitedModules(IPath jrtPath, ObjectVector imageRoots, List rootModuleNames) { + Set limitModulesSet = new HashSet<>(rootModuleNames); + ModuleLookup lookup = new ModuleLookup(jrtPath.toFile()); + // collect all module roots: + for (int i = 0; i < imageRoots.size(); i++) { + lookup.recordRoot((JrtPackageFragmentRoot) imageRoots.elementAt(i)); + } + // for those contained in limitModules, add the transitive closure: + for (int i = 0; i < imageRoots.size(); i++) { + String moduleName = ((JrtPackageFragmentRoot) imageRoots.elementAt(i)).moduleName; + if (limitModulesSet.contains(moduleName)) + lookup.addTransitive(moduleName); + } + // map the result back to package fragment roots: + ObjectVector result = new ObjectVector(lookup.resultModuleSet.size()); + for (IModule mod : lookup.resultModuleSet) { + result.add(lookup.getRoot(mod)); + } + return result; + } + + /** Helper for computing the transitive closure of a set of modules. */ + private static class ModuleLookup { + File jrtFile; + Map modNames2Roots = new HashMap<>(); + Map modules = new HashMap<>(); + Set resultModuleSet = new HashSet<>(); + + public ModuleLookup(File jrtFile) { + this.jrtFile = jrtFile; + } + + void recordRoot(JrtPackageFragmentRoot root) { + this.modNames2Roots.put(root.moduleName, root); + } + void addTransitive(String moduleName) { + IModule module = getModule(moduleName); + if (module != null && this.resultModuleSet.add(module)) { + for (IModuleReference reqRef : module.requires()) + addTransitive(String.valueOf(reqRef.name())); + } + } + private IModule getModule(String moduleName) { + IModule result = this.modules.get(moduleName); + if (result == null) { + JrtPackageFragmentRoot root = this.modNames2Roots.get(moduleName); + if (root != null) { + try { + ClassFileReader classFile = JRTUtil.getClassfile(this.jrtFile, TypeConstants.MODULE_INFO_CLASS_NAME_STRING, root.moduleName); + result = classFile.getModuleDeclaration(); + this.modules.put(moduleName, result); + } catch (IOException | ClassFormatException e) { + JavaCore.getJavaCore().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Failed to read module-info.class", e)); //$NON-NLS-1$ + } + } + } + return result; + } + JrtPackageFragmentRoot getRoot(IModule module) { + return this.modNames2Roots.get(String.valueOf(module.name())); + } + } + + /** + * This bogus package fragment root acts as placeholder plus bridge for the + * real one until the module name becomes available. It is useful in certain + * scenarios like creating package roots from delta processors, search etc. + */ + class JImageModuleFragmentBridge extends JarPackageFragmentRoot { + + protected JImageModuleFragmentBridge(IPath externalJarPath) { + super(externalJarPath, JavaProject.this); + } + public PackageFragment getPackageFragment(String[] pkgName) { + return getPackageFragment(pkgName, null); + } + public PackageFragment getPackageFragment(String[] pkgName, String mod) { + PackageFragmentRoot realRoot = new JrtPackageFragmentRoot(this.jarPath, + mod == null ? JRTUtil.JAVA_BASE : mod, + JavaProject.this); + return new JarPackageFragment(realRoot, pkgName); + } + protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException { + // Do nothing, idea is to avoid this being read in JarPackageFragmentRoot as a Jar. + return true; + } + public boolean isModule() { + return true; + } + } + + private void loadModulesInJimage(final IPath imagePath, final ObjectVector roots, final Map rootToResolvedEntries, + final IClasspathEntry resolvedEntry, final IClasspathEntry referringEntry) { + try { + org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imagePath.toFile(), + new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor() { + @Override + public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException { + return FileVisitResult.SKIP_SIBLINGS; + } + + @Override + public FileVisitResult visitFile(java.nio.file.Path path, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException { + return FileVisitResult.SKIP_SIBLINGS; + } + + @Override + public FileVisitResult visitModule(java.nio.file.Path mod) throws IOException { + JrtPackageFragmentRoot root = new JrtPackageFragmentRoot(imagePath, mod.toString(), JavaProject.this); + roots.add(root); + if (rootToResolvedEntries != null) + rootToResolvedEntries.put(root, ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry)); + return FileVisitResult.SKIP_SUBTREE; + } + }, JRTUtil.NOTIFY_MODULES); + } catch (IOException e) { + Util.log(IStatus.ERROR, "Error reading modules from " + imagePath.toOSString()); //$NON-NLS-1$ + } + } + /** * Returns (local/all) the package fragment roots identified by the given project's classpath. * Note: this follows project classpath references to find required project contributions, @@ -660,12 +887,16 @@ public void computePackageFragmentRoots( * Only works with resolved entries * @param resolvedClasspath IClasspathEntry[] * @param retrieveExportedRoots boolean + * @param filterModuleRoots if true, roots corresponding to modules will be filtered if applicable: + * if a limit-modules attribute exists, this is used, otherwise system modules will be filtered + * according to the rules of root modules per JEP 261. * @return IPackageFragmentRoot[] * @throws JavaModelException */ public IPackageFragmentRoot[] computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots, + boolean filterModuleRoots, Map rootToResolvedEntries) throws JavaModelException { ObjectVector accumulatedRoots = new ObjectVector(); @@ -675,6 +906,7 @@ public IPackageFragmentRoot[] computePackageFragmentRoots( new HashSet(5), // rootIDs null, // inside original project retrieveExportedRoots, + filterModuleRoots, rootToResolvedEntries); IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots.size()]; accumulatedRoots.copyInto(rootArray); @@ -691,6 +923,9 @@ public IPackageFragmentRoot[] computePackageFragmentRoots( * @param rootIDs HashSet * @param referringEntry project entry referring to this CP or null if initial project * @param retrieveExportedRoots boolean + * @param filterModuleRoots if true, roots corresponding to modules will be filtered if applicable: + * if a limit-modules attribute exists, this is used, otherwise system modules will be filtered + * according to the rules of root modules per JEP 261. * @throws JavaModelException */ public void computePackageFragmentRoots( @@ -699,6 +934,7 @@ public void computePackageFragmentRoots( HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, + boolean filterModuleRoots, Map rootToResolvedEntries) throws JavaModelException { if (referringEntry == null){ @@ -711,6 +947,7 @@ public void computePackageFragmentRoots( rootIDs, referringEntry, retrieveExportedRoots, + filterModuleRoots, rootToResolvedEntries); } } @@ -1231,7 +1468,7 @@ public IPackageFragmentRoot findPackageFragmentRoot0(IPath path) } for (int i= 0; i < allRoots.length; i++) { IPackageFragmentRoot classpathRoot= allRoots[i]; - if (classpathRoot.getPath().equals(path)) { + if (classpathRoot.getPath() != null && classpathRoot.getPath().equals(path)) { return classpathRoot; } } @@ -1249,6 +1486,7 @@ public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) { computePackageFragmentRoots( resolveClasspath(new IClasspathEntry[] {entry}), false, // don't retrieve exported roots + true, // respect limit-modules null); /*no reverse map*/ } } @@ -1366,6 +1604,21 @@ public IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgre return findType(fullyQualifiedName, lookup, true, progressMonitor); } + public IModuleDescription findModule(String moduleName, WorkingCopyOwner owner) throws JavaModelException { + NameLookup lookup = newNameLookup(owner); + return findModule(moduleName, lookup); + } + + /* + * Internal findModule with instantiated name lookup + */ + IModuleDescription findModule(String moduleName, NameLookup lookup) throws JavaModelException { + NameLookup.Answer answer = lookup.findModule(moduleName.toCharArray()); + if (answer != null) + return answer.module; + return null; + } + /** * Remove all markers denoting classpath problems */ //TODO (philippe) should improve to use a bitmask instead of booleans (CYCLE, FORMAT, VALID) @@ -1427,7 +1680,7 @@ public IPackageFragmentRoot[] getAllPackageFragmentRoots() public IPackageFragmentRoot[] getAllPackageFragmentRoots(Map rootToResolvedEntries) throws JavaModelException { - return computePackageFragmentRoots(getResolvedClasspath(), true/*retrieveExportedRoots*/, rootToResolvedEntries); + return computePackageFragmentRoots(getResolvedClasspath(), true/*retrieveExportedRoots*/, true/*respectLimitModules*/, rootToResolvedEntries); } /** @@ -1588,6 +1841,7 @@ public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) { * @see JavaElement */ public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) { + String mod = null; switch (token.charAt(0)) { case JEM_PACKAGEFRAGMENTROOT: String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH; @@ -1597,11 +1851,22 @@ public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, // https://bugs.eclipse.org/bugs/show_bug.cgi?id=331821 if (token == MementoTokenizer.PACKAGEFRAGMENT || token == MementoTokenizer.COUNT) { break; + } else if (token == MementoTokenizer.PACKAGEFRAGMENTROOT) { + if (memento.hasMoreTokens()) { + token = memento.nextToken(); + if (token != null) { + mod = token; + + } + } + continue; } rootPath += token; } - JavaElement root = (JavaElement)getPackageFragmentRoot(new Path(rootPath)); - if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) { + JavaElement root = (mod == null) ? + (JavaElement)getPackageFragmentRoot(new Path(rootPath)) : + new JrtPackageFragmentRoot(new Path(rootPath), mod, this); + if (token != null && (token.charAt(0) == JEM_PACKAGEFRAGMENT)) { return root.getHandleFromMemento(token, memento, owner); } else { return root.getHandleFromMemento(memento, owner); @@ -1833,6 +2098,15 @@ public IPackageFragmentRoot getPackageFragmentRoot0(IPath externalLibraryPath) { IFolder linkedFolder = JavaModelManager.getExternalManager().getFolder(externalLibraryPath); if (linkedFolder != null) return new ExternalPackageFragmentRoot(linkedFolder, externalLibraryPath, this); + if (JavaModelManager.isJrt(externalLibraryPath)) { + return this.new JImageModuleFragmentBridge(externalLibraryPath); + } + Object target = JavaModel.getTarget(externalLibraryPath, true/*check existency*/); + if (target instanceof File && JavaModel.isFile(target)) { + if (JavaModel.isJmod((File) target)) { + return new JModPackageFragmentRoot(externalLibraryPath, this); + } + } return new JarPackageFragmentRoot(externalLibraryPath, this); } @@ -3238,4 +3512,72 @@ protected IStatus validateExistence(IResource underlyingResource) { } return JavaModelStatus.VERIFIED_OK; } + + public IModuleDescription getModuleDescription() throws JavaModelException { + JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo(); + IModuleDescription module = info.getModule(); + if (module != null) + return module; + for(IClasspathEntry entry : getRawClasspath()) { + String mainModule = ClasspathEntry.getExtraAttribute(entry, IClasspathAttribute.PATCH_MODULE); + if (mainModule != null) { + switch (entry.getEntryKind()) { + case IClasspathEntry.CPE_PROJECT: + IJavaProject referencedProject = getJavaModel().getJavaProject(entry.getPath().toString()); + module = referencedProject.getModuleDescription(); + if (module != null && module.getElementName().equals(mainModule)) + return module; + break; + case IClasspathEntry.CPE_LIBRARY: + case IClasspathEntry.CPE_CONTAINER: + for (IPackageFragmentRoot root : findPackageFragmentRoots(entry)) { + module = root.getModuleDescription(); + if (module != null && module.getElementName().equals(mainModule)) + return module; + } + } + } + } + return null; + } + + public void setModuleDescription(IModuleDescription module) throws JavaModelException { + JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo(); + IModuleDescription current = info.getModule(); + if (current != null) { + IPackageFragmentRoot root = (IPackageFragmentRoot) current.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + IPackageFragmentRoot newRoot = (IPackageFragmentRoot) module.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + if (!root.equals(newRoot)) + throw new JavaModelException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, + Messages.bind(Messages.classpath_duplicateEntryPath, TypeConstants.MODULE_INFO_FILE_NAME_STRING, getElementName()))); + } + info.setModule(module); + } + + private boolean isUnNamedModule() throws JavaModelException { + JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo(); + IModuleDescription module = info.getModule(); + if (module != null) + return false; + for(IClasspathEntry entry : getRawClasspath()) { + String mainModule = ClasspathEntry.getExtraAttribute(entry, IClasspathAttribute.PATCH_MODULE); + if (mainModule != null) + return false; + + } + return true; + } + + public Manifest getManifest() { + IFile file = getProject().getFile(new Path(TypeConstants.META_INF_MANIFEST_MF)); + if (file.exists()) { + try (InputStream contents = file.getContents()) { + return new Manifest(contents); + } catch (IOException | CoreException e) { + // unusable manifest + } + } + return null; + } + } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java index 21de2b3d24..115c060339 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java @@ -255,7 +255,7 @@ private void initializePackageNames(IPackageFragmentRoot root, HashSetOfArray fr return; } for (int j = 0, length = frags.length; j < length; j++) { - fragmentsCache.add(((PackageFragment) frags[j]).names); + if (frags[j] instanceof PackageFragment) fragmentsCache.add(((PackageFragment) frags[j]).names); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java index e52d2e190d..33a8347b67 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2016 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -35,6 +35,9 @@ public interface JavadocConstants { String PACKAGE_FILE_NAME = "package-summary.html"; //$NON-NLS-1$ char[] PACKAGE_DESCRIPTION_START = "name=\"package_description\"".toCharArray(); //$NON-NLS-1$ char[] PACKAGE_DESCRIPTION_START2 = "name=\"package.description\"".toCharArray(); //$NON-NLS-1$ + char[] PACKAGE_DESCRIPTION_START3 = "

      ".toCharArray(); //$NON-NLS-1$ + String MODULE_FILE_SUFFIX = "-summary.html"; //$NON-NLS-1$ + char[] MODULE_DESCRIPTION_START = "".toCharArray(); //$NON-NLS-1$ char[] H2_PREFIX = "() { + @Override + public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs) throws IOException { + initRawPackageInfo(rawPackageInfo, dir.toString(), true, compliance); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path path, Path mod, BasicFileAttributes attrs) throws IOException { + initRawPackageInfo(rawPackageInfo, path.toString(), false, compliance); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitModule(Path mod) throws IOException { + if (!JrtPackageFragmentRoot.this.moduleName.equals(mod.toString())) { + return FileVisitResult.SKIP_SUBTREE; + } + return FileVisitResult.CONTINUE; + } + }, JRTUtil.NOTIFY_ALL); + } catch (IOException e) { + Util.log(IStatus.ERROR, "Error reading modules" + toStringWithAncestors()); //$NON-NLS-1$ + } + + info.setChildren(createChildren(rawPackageInfo)); + ((JarPackageFragmentRootInfo) info).rawPackageInfo = rawPackageInfo; + return true; + } + SourceMapper createSourceMapper(IPath sourcePath, IPath rootPath) throws JavaModelException { + IClasspathEntry entry = ((JavaProject) getParent()).getClasspathEntryFor(getPath()); + String encoding = (entry== null) ? null : ((ClasspathEntry) entry).getSourceAttachmentEncoding(); + IModule mod = getModule(); + String modName = mod == null ? null : new String(mod.name()); + SourceMapper mapper = new SourceMapper( + sourcePath, + rootPath == null ? modName : rootPath.toOSString(), + getJavaProject().getOptions(true),// cannot use workspace options if external jar is 1.5 jar and workspace options are 1.4 options + encoding); + return mapper; + } + public boolean equals(Object o) { + if (this == o) + return true; + if (o instanceof JrtPackageFragmentRoot) { + JrtPackageFragmentRoot other= (JrtPackageFragmentRoot) o; + return this.moduleName.equals(other.moduleName) && + this.jarPath.equals(other.jarPath); + } + return false; + } + public String getElementName() { + return this.moduleName; + } + public PackageFragment getPackageFragment(String[] pkgName) { + // NOTE: Do we need a different kind of package fragment? + return new JarPackageFragment(this, pkgName); + } + public int hashCode() { + return this.jarPath.hashCode() + this.moduleName.hashCode(); + } + protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo) { + buffer.append(tabString(tab)); + buffer.append(""); //$NON-NLS-1$ //$NON-NLS-2$ + if (info == null) { + buffer.append(" (not open)"); //$NON-NLS-1$ + } + } + + @Override + public IModule getModule() { + IModuleDescription desc = getModuleDescription(); + if (desc != null) { + try { + return (ModuleDescriptionInfo)((JavaElement) desc).getElementInfo(); + } catch (JavaModelException e) { + e.printStackTrace(); + } + } + return null; + } + + @Override + public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String requestedModuleName) { + if (requestedModuleName != null && !requestedModuleName.equals(this.moduleName)) + return null; + if (getPackageFragment(qualifiedPackageName).exists()) { + return new char[][] { requestedModuleName.toCharArray() }; + } + return null; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModularClassFile.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModularClassFile.java new file mode 100644 index 0000000000..0d01505c4b --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModularClassFile.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.env.IBinaryModule; +import org.eclipse.jdt.internal.compiler.env.IDependent; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.core.nd.java.model.BinaryModuleDescriptor; +import org.eclipse.jdt.internal.core.nd.java.model.BinaryModuleFactory; +import org.eclipse.jdt.internal.core.util.MementoTokenizer; +import org.eclipse.jdt.internal.core.util.Util; + +/** + * A handle to a modular class file. + */ +public class ModularClassFile extends AbstractClassFile implements IModularClassFile { + + private BinaryModule binaryModule; + + protected ModularClassFile(PackageFragment parent) { + super(parent, TypeConstants.MODULE_INFO_NAME_STRING); + } + + /** + * Creates the single child element for this class file adding the resulting + * new handle (of type {@link IBinaryModule}) and info object to the newElements table. + * Returns true if successful, or false if an error is encountered parsing the class file. + * + * @see Openable + * @see Signature + */ + @Override + protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException { + IBinaryModule moduleInfo = getBinaryModuleInfo(); + if (moduleInfo == null) { + // The structure of a class file is unknown if a class file format errors occurred + //during the creation of the diet class file representative of this ClassFile. + info.setChildren(JavaElement.NO_ELEMENTS); + return false; + } + + // Read the module + BinaryModule module = ((ClassFileInfo) info).readBinaryModule(this, (HashMap) newElements, moduleInfo); + if (module != null) { + this.binaryModule = module; + info.setChildren(new IJavaElement[] {module}); + ((PackageFragmentRootInfo) getPackageFragmentRoot().getElementInfo()).setModule(module); + } + return true; + } + + @Override + public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { + String source = getSource(); + if (source != null) { + BasicCompilationUnit cu = + new BasicCompilationUnit( + getSource().toCharArray(), + null, + TypeConstants.MODULE_INFO_FILE_NAME_STRING, + getJavaProject()); // use project to retrieve corresponding .java IFile + codeComplete(cu, cu, offset, requestor, owner, null/*extended context isn't computed*/, monitor); + } + } + + @Override + public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner owner) throws JavaModelException { + IBuffer buffer = getBuffer(); + char[] contents; + if (buffer != null && (contents = buffer.getCharacters()) != null) { + BasicCompilationUnit cu = new BasicCompilationUnit(contents, null, TypeConstants.MODULE_INFO_FILE_NAME_STRING, this); + return super.codeSelect(cu, offset, length, owner); + } else { + // has no associated source + return new IJavaElement[] {}; + } + } + + @Override + public IType findPrimaryType() { + return null; + } + + @Override + public boolean isClass() throws JavaModelException { + return false; + } + + @Override + public boolean isInterface() throws JavaModelException { + return false; + } + + @Override + public IType getType() { + throw new UnsupportedOperationException("IClassFile#getType() cannot be used on an IModularClassFile"); + } + + /** + * Returns the IBinaryModule specific for this IClassFile, based + * on its underlying resource, or null if unable to create + * the diet class file. + * There are two cases to consider:
        + *
      • a class file corresponding to an IFile resource
      • + *
      • a class file corresponding to a zip entry in a JAR
      • + *
      + * + * @exception JavaModelException when the IFile resource or JAR is not available + * or when this class file is not present in the JAR + */ + public IBinaryModule getBinaryModuleInfo() throws JavaModelException { + try { + IBinaryModule info = getJarBinaryModuleInfo(); + if (info == null) { + throw newNotPresentException(); + } + return info; + } catch (ClassFormatException cfe) { + //the structure remains unknown + if (JavaCore.getPlugin().isDebugging()) { + cfe.printStackTrace(System.err); + } + return null; + } catch (IOException ioe) { + throw new JavaModelException(ioe, IJavaModelStatusConstants.IO_EXCEPTION); + } catch (CoreException e) { + if (e instanceof JavaModelException) { + throw (JavaModelException)e; + } else { + throw new JavaModelException(e); + } + } + } + + private IBinaryModule getJarBinaryModuleInfo() throws CoreException, IOException, ClassFormatException { + BinaryModuleDescriptor descriptor = BinaryModuleFactory.createDescriptor(this); + + if (descriptor == null) { + return null; + } + IBinaryModule result = null; + IPackageFragmentRoot root = getPackageFragmentRoot(); + if (getPackageFragmentRoot() instanceof JarPackageFragmentRoot) { + if (root instanceof JrtPackageFragmentRoot || this.name.equals(IModule.MODULE_INFO)) { + PackageFragment pkg = (PackageFragment) getParent(); + JarPackageFragmentRoot jarRoot = (JarPackageFragmentRoot) getPackageFragmentRoot(); + String entryName = jarRoot.getClassFilePath(Util.concatWith(pkg.names, getElementName(), '/')); + byte[] contents = getClassFileContent(jarRoot, entryName); + if (contents != null) { + String fileName; + String rootPath = root.getPath().toOSString(); + if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) { + fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + + root.getElementName() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName; + } else { + fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName; + } + ClassFileReader classFileReader = new ClassFileReader(contents, fileName.toCharArray(), false); + return classFileReader.getModuleDeclaration(); + } + } else { + result = BinaryModuleFactory.readModule(descriptor, null); + } + } else { + result = BinaryModuleFactory.readModule(descriptor, null); + } + + return result; + } + + /** + * @see ITypeRoot + */ + public IJavaElement getElementAt(int position) throws JavaModelException { + IJavaElement parentElement = getParent(); + while (parentElement.getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT) { + parentElement = parentElement.getParent(); + } + PackageFragmentRoot root = (PackageFragmentRoot) parentElement; + SourceMapper mapper = root.getSourceMapper(); + if (mapper == null) { + return null; + } else { + // ensure this class file's buffer is open so that source ranges are computed + getBuffer(); + + IModuleDescription module = getModule(); + return findElement(module, position, mapper); + } + } + @Override + public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) { + switch (token.charAt(0)) { + case JEM_MODULE: + if (!memento.hasMoreTokens()) return this; + String modName = memento.nextToken(); + JavaElement mod = new BinaryModule(this, modName); + return mod.getHandleFromMemento(memento, owner); + } + return null; + } + /** + * @see JavaElement#getHandleMemento() + */ + @Override + protected char getHandleMementoDelimiter() { + return JavaElement.JEM_MODULAR_CLASSFILE; + } + @Override + protected void escapeMementoName(StringBuffer buffer, String mementoName) { + // nop, name is irrelevant + } + @Override + public ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { + CompilationUnit workingCopy = new ClassFileWorkingCopy(this, owner == null ? DefaultWorkingCopyOwner.PRIMARY : owner); + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = + manager.getPerWorkingCopyInfo(workingCopy, false/*don't create*/, true/*record usage*/, null/*not used since don't create*/); + if (perWorkingCopyInfo != null) { + return perWorkingCopyInfo.getWorkingCopy(); // return existing handle instead of the one created above + } + BecomeWorkingCopyOperation op = new BecomeWorkingCopyOperation(workingCopy, null); + op.runOperation(monitor); + System.out.println("<null
      is returned. + * + * @see Openable + */ + @Override + protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException { + SourceMapper mapper = getSourceMapper(); + if (mapper != null) { + return mapSource(mapper); + } + return null; + } + + /** Loads the buffer via SourceMapper, and maps it in SourceMapper */ + private IBuffer mapSource(SourceMapper mapper) throws JavaModelException { + char[] contents = mapper.findSource(getModule()); + if (contents != null) { + // create buffer + IBuffer buffer = BufferManager.createBuffer(this); + if (buffer == null) return null; + BufferManager bufManager = getBufferManager(); + bufManager.addBuffer(buffer); + + // set the buffer source + if (buffer.getCharacters() == null){ + buffer.setContents(contents); + } + + // listen to buffer changes + buffer.addBufferChangedListener(this); + + // do the source mapping + mapper.mapSource((NamedMember) getModule(), contents, null); + + return buffer; + } else { + // create buffer + IBuffer buffer = BufferManager.createNullBuffer(this); + if (buffer == null) return null; + BufferManager bufManager = getBufferManager(); + bufManager.addBuffer(buffer); + + // listen to buffer changes + buffer.addBufferChangedListener(this); + return buffer; + } + } + + @Override + public IModuleDescription getModule() throws JavaModelException { + if (this.binaryModule == null) { + openWhenClosed(createElementInfo(), false, null); + if (this.binaryModule == null) + throw newNotPresentException(); + } + return this.binaryModule; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Module.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Module.java new file mode 100644 index 0000000000..84f97f3c9b --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Module.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +//import org.eclipse.jdt.core.IType; +//import org.eclipse.jdt.core.JavaModelException; +//import org.eclipse.jdt.core.compiler.CharOperation; +//import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +//import org.eclipse.jdt.internal.compiler.env.IModuleDeclaration; + +//public class Module implements org.eclipse.jdt.internal.compiler.env.IModuleDeclaration { +// +// public ClassFile binaryDecl; +// public IModuleDeclaration declaration = null; +// public boolean isBinary = false; +// public SourceType sourceDecl; +// +// public Module(SourceType sourceDecl) { +// this.sourceDecl = sourceDecl; +// } +// public Module(ClassFile binaryDecl) { +// this.binaryDecl = binaryDecl; +// this.isBinary = true; +// } +// @Override +// public char[] name() { +// // +// IModuleDeclaration decl = getDeclaration(); +// return decl == null ? CharOperation.NO_CHAR : decl.name(); +// } +// @Override +// public IModuleDeclaration getDeclaration() { +// // +// if (this.declaration == null) { +// try { +// if (this.isBinary) { +// IType type = this.binaryDecl.getType(); +// this.declaration = ((ClassFileReader) (((BinaryType)type).getElementInfo())).getModuleDeclaration(); +// } else { +// this.declaration = (ModuleInfo) this.sourceDecl.getElementInfo(); +// } +// }catch (JavaModelException e) { +// // do nothing +// } +// } +// return this.declaration; +// } +// +// public String toString() { +// return new String(this.name()); +// +// } +//} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleDescriptionInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleDescriptionInfo.java new file mode 100644 index 0000000000..cb7b265524 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleDescriptionInfo.java @@ -0,0 +1,399 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ast.ExportsStatement; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleReference; +import org.eclipse.jdt.internal.compiler.ast.OpensStatement; +import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement; +import org.eclipse.jdt.internal.compiler.ast.RequiresStatement; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.ast.UsesStatement; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; + +public class ModuleDescriptionInfo extends AnnotatableInfo implements IModule { + + protected static final char[][] NO_USES = new char[0][0]; + protected static final ModuleReferenceInfo[] NO_REQUIRES = new ModuleReferenceInfo[0]; + protected static final PackageExportInfo[] NO_EXPORTS = new PackageExportInfo[0]; + protected static final ServiceInfo[] NO_PROVIDES = new ServiceInfo[0]; + protected static final PackageExportInfo[] NO_OPENS = new PackageExportInfo[0]; + + protected IJavaElement[] children = JavaElement.NO_ELEMENTS; + + ModuleReferenceInfo[] requires; + PackageExportInfo[] exports; + ServiceInfo[] services; + PackageExportInfo[] opens; + char[][] usedServices; + IModuleDescription handle; + char[] name; + boolean isOpen = false; + + static class ModuleReferenceInfo extends MemberElementInfo implements IModule.IModuleReference { + char[] name; + int modifiers; + public char[] name() { + return this.name; + } + public int getModifiers() { + return this.modifiers; + } + } + static class PackageExportInfo extends MemberElementInfo implements IModule.IPackageExport { + char[] pack; + char[][] target; + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(this.pack); + if (this.target != null) { + buffer.append(" to "); //$NON-NLS-1$ + for (char[] mod : this.target) { + buffer.append(mod); + } + } + buffer.append(';'); + return buffer.toString(); + } + + @Override + public char[] name() { + return this.pack; + } + + @Override + public char[][] targets() { + return this.target; + } + } + + static class ServiceInfo extends MemberElementInfo implements IModule.IService { + char[] serviceName; + char[][] implNames; + @Override + public char[] name() { + return this.serviceName; + } + @Override + public char[][] with() { + return this.implNames; + } + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(this.serviceName); + buffer.append(" with "); //$NON-NLS-1$ + for (int i = 0; i < this.implNames.length; i++) { + buffer.append(this.implNames[i]); + if (i < this.implNames.length - 1) + buffer.append(", "); //$NON-NLS-1$ + } + buffer.append(';'); + return buffer.toString(); + } + } + + public static ModuleDescriptionInfo createModule(IModule module) { + ModuleDescriptionInfo mod = new ModuleDescriptionInfo(); + mod.children = JavaElement.NO_ELEMENTS; + mod.name = module.name(); + mod.isOpen = module.isOpen(); + if (module.requires().length > 0) { + IModuleReference[] refs = module.requires(); + mod.requires = new ModuleReferenceInfo[refs.length]; + for (int i = 0; i < refs.length; i++) { + mod.requires[i] = new ModuleReferenceInfo(); + mod.requires[i].name = refs[i].name(); // Check why ModuleReference#tokens must be a char[][] and not a char[] or String; + mod.requires[i].modifiers = refs[i].getModifiers(); + } + } else { + mod.requires = NO_REQUIRES; + } + if (module.exports().length > 0) { + IPackageExport[] refs = module.exports(); + mod.exports = new PackageExportInfo[refs.length]; + for (int i = 0; i < refs.length; i++) { + PackageExportInfo exp = createPackageExport(refs[i]); + mod.exports[i] = exp; + } + } else { + mod.exports = NO_EXPORTS; + } + if (module.uses().length > 0) { + char[][] uses = module.uses(); + mod.usedServices = new char[uses.length][]; + for (int i = 0; i < uses.length; i++) { + mod.usedServices[i] = uses[i]; + } + } else { + mod.usedServices = NO_USES; + } + if (module.provides().length > 0) { + IService[] provides = module.provides(); + mod.services = new ServiceInfo[provides.length]; + for (int i = 0; i < provides.length; i++) { + mod.services[i] = createService(provides[i]); + } + } else { + mod.services = NO_PROVIDES; + } + if (module.opens().length > 0) { + IPackageExport[] opens = module.opens(); + mod.opens = new PackageExportInfo[opens.length]; + for (int i = 0; i < opens.length; i++) { + PackageExportInfo op = createOpensInfo(opens[i]); + mod.opens[i] = op; + } + } else { + mod.opens = NO_OPENS; + } + return mod; + } + private static PackageExportInfo createPackageExport(IModule.IPackageExport ref) { + PackageExportInfo exp = new PackageExportInfo(); + exp.pack = ref.name(); + char[][] targets = ref.targets(); + if (targets != null) { + exp.target = new char[targets.length][]; + for(int j = 0; j < targets.length; j++) { + exp.target[j] = targets[j]; + } + } + return exp; + } + private static PackageExportInfo createOpensInfo(IModule.IPackageExport opens) { + PackageExportInfo open = new PackageExportInfo(); + open.pack = opens.name(); + char[][] targets = opens.targets(); + if (targets != null) { + open.target = new char[targets.length][]; + for(int j = 0; j < targets.length; j++) { + open.target[j] = targets[j]; + } + } + return open; + } + + private static ServiceInfo createService(IModule.IService provides) { + ServiceInfo info = new ServiceInfo(); + info.serviceName = provides.name(); + char[][] implementations = provides.with(); + info.implNames = new char[implementations.length][]; + for(int i = 0; i < implementations.length; i++) { + info.implNames[i] = implementations[i]; + } + return info; + } + + public static ModuleDescriptionInfo createModule(ModuleDeclaration module) { + ModuleDescriptionInfo mod = new ModuleDescriptionInfo(); + mod.name = module.moduleName; + mod.isOpen = module.isOpen(); + if (module.requiresCount > 0) { + RequiresStatement[] refs = module.requires; + mod.requires = new ModuleReferenceInfo[refs.length+1]; + mod.requires[0] = getJavaBaseReference(); + for (int i = 0; i < refs.length; i++) { + mod.requires[i+1] = new ModuleReferenceInfo(); + mod.requires[i+1].name = CharOperation.concatWith(refs[i].module.tokens, '.'); // Check why ModuleReference#tokens must be a char[][] and not a char[] or String; + mod.requires[i+1].modifiers = refs[i].modifiers; + } + } else { + mod.requires = CharOperation.equals(module.moduleName, TypeConstants.JAVA_BASE) + ? NO_REQUIRES + : new ModuleReferenceInfo[] { getJavaBaseReference() }; + } + if (module.exportsCount > 0) { + ExportsStatement[] refs = module.exports; + mod.exports = new PackageExportInfo[refs.length]; + for (int i = 0; i < refs.length; i++) { + PackageExportInfo exp = createPackageExport(refs[i]); + mod.exports[i] = exp; + } + } else { + mod.exports = NO_EXPORTS; + } + if (module.usesCount > 0) { + UsesStatement[] uses = module.uses; + mod.usedServices = new char[uses.length][]; + for (int i = 0; i < uses.length; i++) { + mod.usedServices[i] = CharOperation.concatWith(uses[i].serviceInterface.getTypeName(), '.'); + } + } else { + mod.usedServices = NO_USES; + } + if (module.servicesCount > 0) { + ProvidesStatement[] provides = module.services; + mod.services = new ServiceInfo[provides.length]; + for (int i = 0; i < provides.length; i++) { + mod.services[i] = createService(provides[i]); + } + } else { + mod.services = NO_PROVIDES; + } + if (module.opensCount > 0) { + OpensStatement[] opens = module.opens; + mod.opens = new PackageExportInfo[opens.length]; + for (int i = 0; i < opens.length; i++) { + PackageExportInfo op = createOpensInfo(opens[i]); + mod.opens[i] = op; + } + } else { + mod.opens = NO_OPENS; + } + return mod; + } + + private static ModuleReferenceInfo getJavaBaseReference() { + ModuleReferenceInfo ref = new ModuleReferenceInfo(); + ref.name = TypeConstants.JAVA_BASE; + return ref; + } + + private static PackageExportInfo createPackageExport(ExportsStatement ref) { + PackageExportInfo exp = new PackageExportInfo(); + exp.pack = ref.pkgName; + ModuleReference[] imp = ref.targets; + if (imp != null) { + exp.target = new char[imp.length][]; + for(int j = 0; j < imp.length; j++) { + exp.target[j] = imp[j].moduleName; + } + } + return exp; + } + private static PackageExportInfo createOpensInfo(OpensStatement opens) { + PackageExportInfo open = new PackageExportInfo(); + open.pack = opens.pkgName; + ModuleReference[] imp = opens.targets; + if (imp != null) { + open.target = new char[imp.length][]; + for(int j = 0; j < imp.length; j++) { + open.target[j] = imp[j].moduleName; + } + } + return open; + } + + private static ServiceInfo createService(ProvidesStatement provides) { + ServiceInfo info = new ServiceInfo(); + info.serviceName = CharOperation.concatWith(provides.serviceInterface.getTypeName(), '.'); + TypeReference[] implementations = provides.implementations; + info.implNames = new char[implementations.length][]; + for(int i = 0; i < implementations.length; i++) { + info.implNames[i] = CharOperation.concatWith(implementations[i].getTypeName(), '.'); + } + return info; + } + + protected void setHandle(IModuleDescription handle) { + this.handle = handle; + } + + public IJavaElement[] getChildren() { + return this.children; + } + + @Override + public boolean isOpen() { + return this.isOpen; + } + + @Override + public char[] name() { + return this.name; + } + + @Override + public IModule.IModuleReference[] requires() { + return this.requires; + } + @Override + public IPackageExport[] exports() { + return this.exports; + } + + @Override + public char[][] uses() { + return this.usedServices; + } + + @Override + public IService[] provides() { + return this.services; + } + + @Override + public IPackageExport[] opens() { + return this.opens; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(getClass().getName()); + toStringContent(buffer); + return buffer.toString(); + } + protected void toStringContent(StringBuffer buffer) { + buffer.append("\n"); //$NON-NLS-1$ + if (this.isOpen()) + buffer.append("open "); //$NON-NLS-1$ + buffer.append("module "); //$NON-NLS-1$ + buffer.append(this.name).append(' '); + buffer.append('{').append('\n'); + if (this.requires != null && this.requires.length > 0) { + buffer.append('\n'); + for(int i = 0; i < this.requires.length; i++) { + buffer.append("\trequires "); //$NON-NLS-1$ + if (this.requires[i].isTransitive()) { + buffer.append("transitive "); //$NON-NLS-1$ + } + if (this.requires[i].isStatic()) { + buffer.append("static "); //$NON-NLS-1$ + } + buffer.append(this.requires[i].name); + buffer.append(';').append('\n'); + } + } + if (this.exports != null && this.exports.length > 0) { + buffer.append('\n'); + for(int i = 0; i < this.exports.length; i++) { + buffer.append("\texports "); //$NON-NLS-1$ + buffer.append(this.exports[i].toString()).append('\n'); + } + } + if (this.usedServices != null && this.usedServices.length > 0) { + buffer.append('\n'); + for(int i = 0; i < this.usedServices.length; i++) { + buffer.append("\tuses "); //$NON-NLS-1$ + buffer.append(this.usedServices[i]).append('\n'); + } + } + if (this.services != null && this.services.length > 0) { + buffer.append('\n'); + for(int i = 0; i < this.services.length; i++) { + buffer.append("\tprovides "); //$NON-NLS-1$ + buffer.append(this.services[i].toString()).append('\n'); + } + } + if (this.opens != null && this.opens.length > 0) { + buffer.append('\n'); + for(int i = 0; i < this.opens.length; i++) { + buffer.append("\topens "); //$NON-NLS-1$ + buffer.append(this.opens[i].toString()).append('\n'); + } + } + buffer.append('\n').append('}').toString(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainer.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainer.java new file mode 100644 index 0000000000..7165f326b0 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainer.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.IClasspathAttribute; +import org.eclipse.jdt.core.IClasspathContainer; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.compiler.env.IModulePathEntry; + +public class ModulePathContainer implements IClasspathContainer{ + + private IJavaProject project; + + public ModulePathContainer(IJavaProject project) { + this.project = project; + } + @Override + public IClasspathEntry[] getClasspathEntries() { + // + List entries = new ArrayList<>(); + ModuleSourcePathManager manager = JavaModelManager.getModulePathManager(); + try { + AbstractModule module = (AbstractModule) ((JavaProject)this.project).getModuleDescription(); + if (module == null) + return new IClasspathEntry[0]; + for (org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference ref : module.getRequiredModules()) { + IModulePathEntry entry = manager.getModuleRoot(new String(ref.name())); + JavaProject refRoot = null; + if (entry instanceof ProjectEntry) { + refRoot = ((ProjectEntry) entry).project; + } + if (refRoot == null) + continue; + IPath path = refRoot.getPath(); + IClasspathAttribute moduleAttribute = new ClasspathAttribute(IClasspathAttribute.MODULE, "true"); //$NON-NLS-1$ + entries.add(JavaCore.newProjectEntry(path, ClasspathEntry.NO_ACCESS_RULES, + false, + new IClasspathAttribute[] {moduleAttribute}, ref.isTransitive())); + } + } catch (JavaModelException e) { + // ignore + } + return entries.toArray(new IClasspathEntry[entries.size()]); + } + + @Override + public String getDescription() { + // + return "Module path"; //$NON-NLS-1$ + } + + @Override + public int getKind() { + // + return K_APPLICATION; + } + + @Override + public IPath getPath() { + // + return new Path(JavaCore.MODULE_PATH_CONTAINER_ID); + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainerInitializer.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainerInitializer.java new file mode 100644 index 0000000000..7e855988bc --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainerInitializer.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.ClasspathContainerInitializer; +import org.eclipse.jdt.core.IClasspathContainer; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.internal.core.util.Util; + +public class ModulePathContainerInitializer extends ClasspathContainerInitializer { + + @Override + public void initialize(IPath containerPath, IJavaProject project) throws CoreException { + // + if (isModulePathContainer(containerPath)) { + if (project instanceof JavaProject) { + // TODO: should project compliance level be checked here? + ModulePathContainer container = new ModulePathContainer(project); + JavaCore.setClasspathContainer(containerPath, new IJavaProject[] { project }, + new IClasspathContainer[] { container }, null); + } + } else if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { + verbose_not_a_module_project(project, containerPath); + } + } + private boolean isModulePathContainer(IPath path) { + return path != null && JavaCore.MODULE_PATH_CONTAINER_ID.equals(path.segment(0)); + } + private void verbose_not_a_module_project(IJavaProject project, IPath containerPath) { + Util.verbose( + "Module path INIT - FAILED (not a module project)\n" + //$NON-NLS-1$ + " project: " + project.getElementName() + '\n' + //$NON-NLS-1$ + " container path: " + containerPath); //$NON-NLS-1$ + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleSourcePathManager.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleSourcePathManager.java new file mode 100644 index 0000000000..a991c98de8 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleSourcePathManager.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModulePathEntry; + +public class ModuleSourcePathManager { + + private Map knownModules = new HashMap(11); + + private IModulePathEntry getModuleRoot0(String name) { + return this.knownModules.get(name); + } + public IModulePathEntry getModuleRoot(String name) { + IModulePathEntry root = getModuleRoot0(name); + if (root == null) { + try { + seekModule(name.toCharArray(),false, new JavaElementRequestor()); + } catch (JavaModelException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + root = this.knownModules.get(name); + return root; + } + public void addEntry(IModuleDescription module, JavaProject project) throws JavaModelException { + String moduleName = new String(module.getElementName().toCharArray()); + IModulePathEntry entry = getModuleRoot0(moduleName); + if (entry != null) { + // TODO : Should we signal error via JavaModelException + return; + } + this.knownModules.put(moduleName, new ProjectEntry(project)); + } + + public void removeEntry(JavaProject javaProject) { + Entry entry = this.knownModules.entrySet().stream() + .filter(e -> e.getValue().equalsProject(javaProject)) + .findFirst() + .orElse(null); + + String key = entry != null ? entry.getKey() : null; + if (key != null) { + this.knownModules.remove(key); + } + } + interface IPrefixMatcherCharArray { + boolean matches(char[] prefix, char[] name); + } + public void seekModule(char[] name, boolean prefixMatch, IJavaElementRequestor requestor) throws JavaModelException { + if (name == null) + return; + IPrefixMatcherCharArray prefixMatcher = prefixMatch ? CharOperation.equals(name, CharOperation.ALL_PREFIX) ? + (x, y) -> true : CharOperation::prefixEquals : CharOperation :: equals; + IJavaProject[] projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects(); + for (int i = 0; i < projects.length; i++) { + IJavaProject project = projects[i]; + if (!project.getProject().isAccessible()) + continue; + if (project instanceof JavaProject) { + IModuleDescription module = ((JavaProject) project).getModuleDescription(); + if (module != null) { + if (prefixMatcher.matches(name, module.getElementName().toCharArray())) { + //addEntry(module, (JavaProject) project); + requestor.acceptModule(module); + } + } + } + } + } + public IModule getModule(char[] name) { + IModulePathEntry root = getModuleRoot0(CharOperation.charToString(name)); + if (root != null) + try { + return root.getModule(); + } catch (Exception e1) { + // + return null; + } + JavaElementRequestor requestor = new JavaElementRequestor(); + try { + seekModule(name, false, requestor); + } catch (JavaModelException e) { + // + } + IModuleDescription[] modules = requestor.getModules(); + if (modules.length > 0) { + IModuleDescription module = modules[0]; + try { + return (ModuleDescriptionInfo) ((JavaElement) module).getElementInfo(); + } catch (JavaModelException e) { + e.printStackTrace(); + } + } + return null; + } +// public IModuleDeclaration[] getModules() { +// if (this.knownModules.size() == 0) { +// return new IModuleDeclaration[0]; +// } +// List modules = new ArrayList(); +// for (IModulePathEntry val : this.knownModules.values()) { +// try { +// modules.add(val.getModule()); +// } catch (Exception e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } +// return modules.toArray(new IModuleDeclaration[modules.size()]); +// } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java new file mode 100644 index 0000000000..16947f99d1 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.core.IClasspathAttribute; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaModelStatusConstants; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdatesByKind; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.core.util.Util; + +/** + * An instance of this class collects add-exports and add-reads options from + * a project's class path entries, and performs the corresponding updates when requested by the compiler. + *

      For patch-module and limit-modules see + * org.eclipse.jdt.internal.core.builder.ModuleEntryProcessor.

      + */ +public class ModuleUpdater { + + private JavaProject javaProoject; + + private Map moduleUpdates = new HashMap<>(); + + public ModuleUpdater(JavaProject javaProject) { + this.javaProoject = javaProject; + } + + /** + * Detects any ADD_EXPORTS or ADD_READS classpath attributes, parses the value, + * and collects the resulting module updates. + * @param entry a classpath entry of the current project. + * @throws JavaModelException + */ + public void computeModuleUpdates(IClasspathEntry entry) throws JavaModelException { + for (IClasspathAttribute attribute : entry.getExtraAttributes()) { + String attributeName = attribute.getName(); + String values = attribute.getValue(); // the attributes considered here may have multiple values separated by ':' + if (attributeName.equals(IClasspathAttribute.ADD_EXPORTS)) { + for (String value : values.split(":")) { // format: /=(,)* //$NON-NLS-1$ + int slash = value.indexOf('/'); + int equals = value.indexOf('='); + if (slash != -1 && equals != -1) { + String modName = value.substring(0, slash); + char[] packName = value.substring(slash+1, equals).toCharArray(); + char[][] targets = CharOperation.splitOn(',', value.substring(equals+1).toCharArray()); + addModuleUpdate(modName, m -> m.addExports(packName, targets), UpdateKind.PACKAGE); + } else { + Util.log(IStatus.WARNING, "Invalid argument to add-exports: "+value); //$NON-NLS-1$ + } + } + } else if (attributeName.equals(IClasspathAttribute.ADD_READS)) { + for (String value : values.split(":")) { // format: = //$NON-NLS-1$ + int equals = value.indexOf('='); + if (equals != -1) { + String srcMod = value.substring(0, equals); + char[] targetMod = value.substring(equals+1).toCharArray(); + addModuleUpdate(srcMod, m -> m.addReads(targetMod), UpdateKind.MODULE); + } else { + Util.log(IStatus.WARNING, "Invalid argument to add-reads: "+value); //$NON-NLS-1$ + } + } + } else if (attributeName.equals(IClasspathAttribute.MODULE_MAIN_CLASS)) { + IModuleDescription module = this.javaProoject.getModuleDescription(); + if (module == null) + throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST)); + addModuleUpdate(module.getElementName(), m -> m.setMainClassName(values.toCharArray()), UpdateKind.MODULE); + } + } + } + + public void addModuleUpdate(String moduleName, Consumer update, UpdateKind kind) { + UpdatesByKind updates = this.moduleUpdates.get(moduleName); + if (updates == null) { + this.moduleUpdates.put(moduleName, updates = new UpdatesByKind()); + } + updates.getList(kind, true).add(update); + } + + /** + * @see IModuleAwareNameEnvironment#applyModuleUpdates(IUpdatableModule, UpdateKind) + */ + public void applyModuleUpdates(IUpdatableModule compilerModule, UpdateKind kind) { + char[] name = compilerModule.name(); + if (name != ModuleBinding.UNNAMED) { // can't update the unnamed module + UpdatesByKind updates = this.moduleUpdates.get(String.valueOf(name)); + if (updates != null) { + for (Consumer update : updates.getList(kind, false)) + update.accept(compilerModule); + } + } + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java index 58ea8fe8d7..1ab7ef71f7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java @@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - contribution for bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment @@ -13,14 +13,21 @@ import java.io.File; import java.util.*; +import java.util.function.Function; +import java.util.jar.Manifest; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.IInitializer; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.IOrdinaryClassFile; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; @@ -31,7 +38,9 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; +import org.eclipse.jdt.internal.compiler.env.AutomaticModuleNaming; import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt; @@ -58,14 +67,42 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) public class NameLookup implements SuffixConstants { + + /** + * Handle for an automatic module. + * + *

      Note, that by definition this is mostly a fake, only {@link #getElementName()} provides a useful value.

      + */ + private static class AutoModule extends AbstractModule { + + public AutoModule(JavaElement parent, String name) { + super(parent, name); + } + + @Override + protected void toStringContent(StringBuffer buffer, String lineDelimiter) throws JavaModelException { + buffer.append("automatic module "); //$NON-NLS-1$ + buffer.append(this.name); + } + } + public static class Answer { public IType type; + public IModuleDescription module; AccessRestriction restriction; IClasspathEntry entry; Answer(IType type, AccessRestriction restriction, IClasspathEntry entry) { + this(type, restriction, entry, null); + } + Answer(IType type, AccessRestriction restriction, IClasspathEntry entry, IModuleDescription module) { this.type = type; this.restriction = restriction; this.entry = entry; + this.module = module; + } + Answer(IModuleDescription module) { + this.module = module; + this.restriction = null; } public boolean ignoreIfBetter() { return this.restriction != null && this.restriction.ignoreIfBetter(); @@ -81,6 +118,61 @@ public boolean isBetter(Answer otherAnswer) { return otherAnswer.restriction != null && this.restriction.getProblemId() < otherAnswer.restriction.getProblemId(); } + public String toString() { + StringBuilder builder = new StringBuilder(this.type.toString()); + builder.append("from ") //$NON-NLS-1$ + .append(this.module); + return builder.toString(); + } + } + + private class Selector implements IJavaElementRequestor { + public List pkgFragments; + + public Selector(String moduleName) { + this.pkgFragments = new ArrayList<>(); + } + + @Override + public void acceptField(IField field) { + // do nothing + } + + @Override + public void acceptInitializer(IInitializer initializer) { + // do nothing + } + + @Override + public void acceptMemberType(IType type) { + // do nothing + } + + @Override + public void acceptMethod(IMethod method) { + // do nothing + } + + @Override + public void acceptPackageFragment(IPackageFragment packageFragment) { + this.pkgFragments.add(packageFragment); + } + + @Override + public void acceptType(IType type) { + // do nothing + } + + @Override + public void acceptModule(IModuleDescription module) { + // do nothing + } + + @Override + public boolean isCanceled() { + // TODO Auto-generated method stub + return false; + } } // TODO (jerome) suppress the accept flags (qualified name is sufficient to find a type) @@ -135,7 +227,9 @@ public boolean isBetter(Answer otherAnswer) { * Reverse map from root path to corresponding resolved CP entry * (so as to be able to figure inclusion/exclusion rules) */ - protected Map rootToResolvedEntries; + protected Map rootToResolvedEntries; + + protected Map rootToModule; /** * A map from package handles to a map from type name to an IType or an IType[]. @@ -159,6 +253,7 @@ public NameLookup( Util.verbose(" -> working copy size: " + (workingCopies == null ? 0 : workingCopies.length)); //$NON-NLS-1$ start = System.currentTimeMillis(); } + this.rootToModule = new HashMap<>(); this.packageFragmentRoots = packageFragmentRoots; if (workingCopies == null) { this.packageFragments = packageFragments; @@ -615,6 +710,23 @@ private IType findSecondaryType(String packageName, String typeName, IJavaProjec return null; } + /** + * Find type in the given modules considering secondary types but without waiting for indexes. + * It means that secondary types may be not found under certain circumstances... + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118789" + */ + public Answer findType(String typeName, String packageName, boolean partialMatch, int acceptFlags, boolean checkRestrictions, IPackageFragmentRoot[] moduleContext) { + return findType(typeName, + packageName, + partialMatch, + acceptFlags, + true/* consider secondary types */, + false/* do NOT wait for indexes */, + checkRestrictions, + null, + moduleContext); + } + /** * Find type considering secondary types but without waiting for indexes. * It means that secondary types may be not found under certain circumstances... @@ -630,7 +742,6 @@ public Answer findType(String typeName, String packageName, boolean partialMatch checkRestrictions, null); } - /** * Find type. Considering secondary types and waiting for indexes depends on given corresponding parameters. */ @@ -643,6 +754,30 @@ public Answer findType( boolean waitForIndexes, boolean checkRestrictions, IProgressMonitor monitor) { + + return findType(typeName, + packageName, + partialMatch, + acceptFlags, + considerSecondaryTypes, + waitForIndexes, + checkRestrictions, + monitor, + null); // no module + } + /** + * Find type. Considering secondary types and waiting for indexes depends on given corresponding parameters. + */ + public Answer findType( + String typeName, + String packageName, + boolean partialMatch, + int acceptFlags, + boolean considerSecondaryTypes, + boolean waitForIndexes, + boolean checkRestrictions, + IProgressMonitor monitor, + IPackageFragmentRoot[] moduleContext) { if (packageName == null || packageName.length() == 0) { packageName= IPackageFragment.DEFAULT_PACKAGE_NAME; } else if (typeName.length() > 0 && ScannerHelper.isLowerCase(typeName.charAt(0))) { @@ -652,7 +787,7 @@ public Answer findType( // Look for concerned package fragments JavaElementRequestor elementRequestor = new JavaElementRequestor(); - seekPackageFragments(packageName, false, elementRequestor); + seekPackageFragments(packageName, false, elementRequestor, moduleContext); IPackageFragment[] packages= elementRequestor.getPackageFragments(); // Try to find type in package fragments list @@ -672,7 +807,8 @@ public Answer findType( accessRestriction = getViolatedRestriction(typeName, packageName, entry, accessRestriction); } } - Answer answer = new Answer(type, accessRestriction, entry); + Answer answer = new Answer(type, accessRestriction, entry, + getModuleDescription(root, this.rootToModule, this.rootToResolvedEntries::get)); if (!answer.ignoreIfBetter()) { if (answer.isBetter(suggestedAnswer)) return answer; @@ -731,6 +867,71 @@ else if (suggestedAnswer == null && considerSecondaryTypes) { return type == null ? null : new Answer(type, null, null); } + public static IModule getModuleDescriptionInfo(IModuleDescription moduleDesc) { + if (moduleDesc != null) { + try { + if (moduleDesc instanceof BinaryModule) { + return (ModuleDescriptionInfo)((BinaryModule) moduleDesc).getElementInfo(); + } else if (moduleDesc instanceof SourceModule) { + return (ModuleDescriptionInfo)((SourceModule) moduleDesc).getElementInfo(); + } else { + return IModule.createAutomatic(moduleDesc.getElementName().toCharArray()); + } + } catch (JavaModelException e) { + // TODO Auto-generated catch block + if (!e.isDoesNotExist()) + e.printStackTrace(); + } + } + return null; + } + + /** Internal utility, which is able to answer explicit and automatic modules. */ + static IModuleDescription getModuleDescription(IPackageFragmentRoot root, Map cache, Function rootToEntry) { + IModuleDescription module = cache.get(root); + if (module != null) + return module; + try { + if (root.getKind() == IPackageFragmentRoot.K_SOURCE) + module = root.getJavaProject().getModuleDescription(); // from any root in this project + else + module = root.getModuleDescription(); + } catch (JavaModelException e) { + return null; + } + if (module == null) { + // 2nd attempt: try automatic module: + IClasspathEntry classpathEntry = rootToEntry.apply(root); + if (classpathEntry instanceof ClasspathEntry) { + if (((ClasspathEntry) classpathEntry).isModular()) { + // modular but no module-info implies this is an automatic module + Manifest manifest = null; + switch (classpathEntry.getEntryKind()) { + case IClasspathEntry.CPE_LIBRARY: + manifest = ((PackageFragmentRoot) root).getManifest(); + break; + case IClasspathEntry.CPE_PROJECT: + JavaProject javaProject = (JavaProject) root.getJavaModel().getJavaProject(classpathEntry.getPath().lastSegment()); + manifest = javaProject.getManifest(); + break; + } + char[] moduleName = AutomaticModuleNaming.determineAutomaticModuleName(root.getElementName(), root.isArchive(), manifest); + module = new AutoModule((JavaElement) root, String.valueOf(moduleName)); + } + } + } + if (module != null) + cache.put(root, module); + return module; + } + + public IModule getModuleDescriptionInfo(PackageFragmentRoot root) { + IModuleDescription desc = getModuleDescription(root, this.rootToModule, this.rootToResolvedEntries::get); + if (desc != null) { + return getModuleDescriptionInfo(desc); + } + return null; + } private AccessRestriction getViolatedRestriction(String typeName, String packageName, ClasspathEntry entry, AccessRestriction accessRestriction) { AccessRuleSet accessRuleSet = entry.getAccessRuleSet(); if (accessRuleSet != null) { @@ -846,6 +1047,24 @@ public Answer findType(String name, boolean partialMatch, int acceptFlags, boole } return findType(className, packageName, partialMatch, acceptFlags, considerSecondaryTypes, waitForIndexes, checkRestrictions, monitor); } + public Answer findModule(char[] moduleName) { + JavaElementRequestor requestor = new JavaElementRequestor(); + seekModule(moduleName, false, requestor); + IModuleDescription[] modules = requestor.getModules(); + if (modules.length == 0) { + try { + // FIXME(SHMOD): only considers source modules?? (MODULEPATH container is only experimental) + JavaModelManager.getModulePathManager().seekModule(moduleName, false, requestor); + modules = requestor.getModules(); + } catch (JavaModelException e) { + // TODO Auto-generated catch block + } + } + if (modules.length > 0) { // TODO what to do?? + return new Answer(modules[0]); + } + return null; + } private IType getMemberType(IType type, String name, int dot) { while (dot != -1) { @@ -861,6 +1080,24 @@ public boolean isPackage(String[] pkgName) { return this.packageFragments.get(pkgName) != null; } + public boolean isPackage(String[] pkgName, IPackageFragmentRoot[] moduleContext) { + if (moduleContext == null) // includes the case where looking for module UNNAMED or ANY + return isPackage(pkgName); + + for (IPackageFragmentRoot moduleRoot : moduleContext) { + if (moduleRoot.getPackageFragment(String.join(".", pkgName)).exists()) //$NON-NLS-1$ + return true; + } + return false; + } + + private boolean moduleMatches(IPackageFragmentRoot root, IPackageFragmentRoot[] moduleContext) { + for (IPackageFragmentRoot moduleRoot : moduleContext) + if (moduleRoot.equals(root)) + return true; + return false; + } + /** * Returns true if the given element's name matches the * specified searchName, otherwise false. @@ -897,6 +1134,88 @@ protected boolean nameMatches(String searchName, ICompilationUnit cu, boolean pa } } + /** + * Notifies the given requestor of all package fragments with the + * given name. Checks the requestor at regular intervals to see if the + * requestor has canceled. The domain of + * the search is bounded by the IJavaProject + * this NameLookup was obtained from. + * + * @param partialMatch partial name matches qualify when true; + * only exact name matches qualify when false + */ + public void seekPackageFragments(String name, boolean partialMatch, IJavaElementRequestor requestor, IPackageFragmentRoot[] moduleContext) { + if (moduleContext == null) { + seekPackageFragments(name, partialMatch, requestor); + return; + } + if (partialMatch) { + seekModuleAwarePartialPackageFragments(name, requestor, moduleContext); + return; + } + for (IPackageFragmentRoot moduleRoot : moduleContext) { + IPackageFragment fragment = moduleRoot.getPackageFragment(name); + if (fragment.exists()) + requestor.acceptPackageFragment(fragment); + } + } + + /** + * Notifies the given requestor of all package fragments with the + * given name. Checks the requestor at regular intervals to see if the + * requestor has canceled. The domain of + * the search is bounded by the IJavaProject + * this NameLookup was obtained from. + * + * @param partialMatch partial name matches qualify when true; + * only exact name matches qualify when false + */ + public void seekTypes(String pkgName, String name, boolean partialMatch, IJavaElementRequestor requestor, + int acceptFlags, IPackageFragmentRoot[] moduleContext, String moduleName) { + Selector selector = new Selector(moduleName); + seekPackageFragments(pkgName, true /*partialMatch*/, selector, moduleContext); + if (selector.pkgFragments.size() == 0) return; + for (IPackageFragment pkg : selector.pkgFragments) { + seekTypes(name, pkg, partialMatch, acceptFlags, requestor); + } + } + + private void seekModuleAwarePartialPackageFragments(String name, IJavaElementRequestor requestor, IPackageFragmentRoot[] moduleContext) { + boolean allPrefixMatch = CharOperation.equals(name.toCharArray(), CharOperation.ALL_PREFIX); + Arrays.stream(this.packageFragments.keyTable) + .filter(k -> k != null) + .filter(k -> allPrefixMatch || Util.concatWith((String[])k, '.').startsWith(name)) + .forEach(k -> { + checkModulePackages(requestor, moduleContext, this.packageFragments.getIndex(k)); + }); + } + + private void checkModulePackages(IJavaElementRequestor requestor, IPackageFragmentRoot[] moduleContext, int pkgIndex) { + Object value = this.packageFragments.valueTable[pkgIndex]; + // reuse existing String[] + String[] pkgName = (String[]) this.packageFragments.keyTable[pkgIndex]; + if (value instanceof PackageFragmentRoot) { + PackageFragmentRoot root = (PackageFragmentRoot) value; + if (moduleMatches(root, moduleContext)) + requestor.acceptPackageFragment(root.getPackageFragment(pkgName)); + } else { + IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value; + if (roots != null) { + for (int i = 0, length = roots.length; i < length; i++) { + if (requestor.isCanceled()) + return; + PackageFragmentRoot root = (PackageFragmentRoot) roots[i]; + if (moduleMatches(root, moduleContext)) + requestor.acceptPackageFragment(root.getPackageFragment(pkgName)); + } + } + } + } + + @FunctionalInterface + interface IPrefixMatcherCharArray { // note the reversal in the order of params wrt to the string version. + boolean matches(char[] prefix, char[] name, boolean isCaseSensitive); + } /** * Notifies the given requestor of all package fragments with the * given name. Checks the requestor at regular intervals to see if the @@ -913,7 +1232,8 @@ public void seekPackageFragments(String name, boolean partialMatch, IJavaElement Util.verbose(" -> name: " + name); //$NON-NLS-1$ Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$ } -*/ if (partialMatch) { +*/ + if (partialMatch) { String[] splittedName = Util.splitOn('.', name, 0, name.length()); Object[][] keys = this.packageFragments.keyTable; for (int i = 0, length = keys.length; i < length; i++) { @@ -964,7 +1284,35 @@ public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, i seekTypes(name, pkg, partialMatch, acceptFlags, requestor, true); } - /** + public void seekModuleReferences(String name, IJavaElementRequestor requestor, IJavaProject javaProject) { + seekModule(name.toCharArray(), true /* prefix */, requestor); + } + public void seekModule(char[] name, boolean prefixMatch, IJavaElementRequestor requestor) { + + IPrefixMatcherCharArray prefixMatcher = prefixMatch + ? CharOperation.equals(name, CharOperation.ALL_PREFIX) + ? (x, y, isCaseSensitive) -> true + : CharOperation::prefixEquals + : CharOperation::equals; + + int count= this.packageFragmentRoots.length; + for (int i= 0; i < count; i++) { + if (requestor.isCanceled()) + return; + IPackageFragmentRoot root= this.packageFragmentRoots[i]; + IModuleDescription module = null; + if (root instanceof JrtPackageFragmentRoot) { + if (!prefixMatcher.matches(name, root.getElementName().toCharArray(), false)) { + continue; + } + } + module = getModuleDescription(root, this.rootToModule, this.rootToResolvedEntries::get); + if (module != null && prefixMatcher.matches(name, module.getElementName().toCharArray(), false)) { + requestor.acceptModule(module); + } + } + } +/** * Notifies the given requestor of all types (classes and interfaces) in the * given package fragment with the given (unqualified) name. * Checks the requestor at regular intervals to see if the requestor @@ -1080,11 +1428,13 @@ protected void seekTypesInBinaryPackage(String name, IPackageFragment pkg, boole // MatchName will never have the extension ".class" and the elementName always will. String elementName = classFile.getElementName(); if (elementName.regionMatches(true /*ignore case*/, 0, name, 0, matchLength)) { - IType type = ((ClassFile) classFile).getType(); - String typeName = type.getElementName(); - if (typeName.length() > 0 && !Character.isDigit(typeName.charAt(0))) { //not an anonymous type - if (nameMatches(unqualifiedName, type, true/*partial match*/) && acceptType(type, acceptFlags, false/*not a source type*/)) - requestor.acceptType(type); + if (classFile instanceof IOrdinaryClassFile) { + IType type = ((IOrdinaryClassFile) classFile).getType(); + String typeName = type.getElementName(); + if (typeName.length() > 0 && !Character.isDigit(typeName.charAt(0))) { //not an anonymous type + if (nameMatches(unqualifiedName, type, true/*partial match*/) && acceptType(type, acceptFlags, false/*not a source type*/)) + requestor.acceptType(type); + } } } } @@ -1312,4 +1662,24 @@ protected boolean seekTypesInWorkingCopies( return false; } + public boolean hasCompilationUnit(char[][] pkgName, IPackageFragmentRoot[] moduleContext) { + String packageName = CharOperation.toString(pkgName); + if (packageName == null || packageName.length() == 0) { + packageName= IPackageFragment.DEFAULT_PACKAGE_NAME; + } + + // Look for concerned package fragments + JavaElementRequestor elementRequestor = new JavaElementRequestor(); + seekPackageFragments(packageName, false, elementRequestor, moduleContext); + IPackageFragment[] packages= elementRequestor.getPackageFragments(); + for (IPackageFragment fragment : packages) { + try { + if (fragment.containsJavaResources()) + return true; + } catch (JavaModelException e) { + // silent + } + } + return false; + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java index 166182fa38..b8c361b797 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java @@ -16,6 +16,8 @@ import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IModularClassFile; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeParameter; @@ -159,6 +161,13 @@ protected String getKey(IType type, boolean forceOpen) throws JavaModelException key.append(';'); return key.toString(); } + protected String getKey(IModuleDescription module, boolean forceOpen) throws JavaModelException { + StringBuffer key = new StringBuffer(); + key.append('"'); + String modName = module.getElementName(); + key.append(modName); + return key.toString(); + } protected String getFullyQualifiedParameterizedName(String fullyQualifiedName, String uniqueKey) throws JavaModelException { String[] typeArguments = new BindingKey(uniqueKey).getTypeArguments(); @@ -200,6 +209,8 @@ public String getTypeQualifiedName(char enclosingTypeSeparator, boolean showPara } return this.name; case IJavaElement.CLASS_FILE: + if (this.parent instanceof IModularClassFile) + return null; String classFileName = this.parent.getElementName(); String typeName; if (classFileName.indexOf('$') == -1) { @@ -293,6 +304,10 @@ public void acceptTypeParameter(char[] declaringTypePackageName, char[] declarin public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selcetorEnd, char[] typeParameterName, boolean isDeclaration, int start, int end) { // ignore } + @Override + public void acceptModule(char[] moduleName, char[] uniqueKey, int start, int end) { + // ignore + } } TypeResolveRequestor requestor = new TypeResolveRequestor(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java index 5774763c4d..6f87a4b9a9 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java @@ -12,6 +12,9 @@ package org.eclipse.jdt.internal.core; import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IModuleDescription; + + /** Element info for IOpenable elements. */ public class OpenableElementInfo extends JavaElementInfo { @@ -22,7 +25,7 @@ public class OpenableElementInfo extends JavaElementInfo { * no children. */ protected volatile IJavaElement[] children = JavaElement.NO_ELEMENTS; - + protected IModuleDescription module; /** * Is the structure of this element known * @see IJavaElement#isStructureKnown() @@ -84,6 +87,12 @@ public void setChildren(IJavaElement[] children) { this.children = children; } + public void setModule(IModuleDescription module) { + this.module = module; + } + public IModuleDescription getModule() { + return this.module; + } /** * Sets whether the structure of this element known * @see IJavaElement#isStructureKnown() diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java index 19c58fd29f..0725cc75d5 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,6 +14,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import org.codehaus.jdt.groovy.integration.LanguageSupportFactory; @@ -30,6 +31,8 @@ import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModularClassFile; +import org.eclipse.jdt.core.IOrdinaryClassFile; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IParent; @@ -37,6 +40,7 @@ import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.WorkingCopyOwner; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; import org.eclipse.jdt.internal.core.util.MementoTokenizer; @@ -52,6 +56,7 @@ public class PackageFragment extends Openable implements IPackageFragment, Suffi * Constant empty list of class files */ protected static final IClassFile[] NO_CLASSFILES = new IClassFile[] {}; + protected static final IOrdinaryClassFile[] NO_ORDINARY_CLASSFILES = new IOrdinaryClassFile[] {}; /** * Constant empty list of compilation units */ @@ -185,13 +190,17 @@ public boolean exists() { return super.exists() && !Util.isExcluded(this) && isValidPackageName(); } /** - * @see IPackageFragment#getClassFile(String) - * @exception IllegalArgumentException if the name does not end with ".class" + * @see IPackageFragment#getOrdinaryClassFile(String) + * @exception IllegalArgumentException if the name does not end with ".class" or if the name is "module-info.class". */ -public IClassFile getClassFile(String classFileName) { +@Override +public IOrdinaryClassFile getOrdinaryClassFile(String classFileName) { if (!org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(classFileName)) { throw new IllegalArgumentException(Messages.bind(Messages.element_invalidClassFileName, classFileName)); } + if (TypeConstants.MODULE_INFO_CLASS_NAME_STRING.equals(classFileName)) { + throw new IllegalArgumentException(Messages.element_moduleInfoNotSupported); + } // don't hold on the .class file extension to save memory // also make sure to not use substring as the resulting String may hold on the underlying char[] which might be much bigger than necessary int length = classFileName.length() - 6; @@ -200,13 +209,52 @@ public IClassFile getClassFile(String classFileName) { return new ClassFile(this, new String(nameWithoutExtension)); } /** - * Returns a the collection of class files in this - a folder package fragment which has a root + * @see IPackageFragment#getClassFile(String) + * @exception IllegalArgumentException if the name does not end with ".class". + */ +@Override +public IClassFile getClassFile(String classFileName) { + if (TypeConstants.MODULE_INFO_CLASS_NAME_STRING.equals(classFileName)) + return getModularClassFile(); + return getOrdinaryClassFile(classFileName); +} +@Override +public IModularClassFile getModularClassFile() { + // don't hold on the .class file extension to save memory + // also make sure to not use substring as the resulting String may hold on the underlying char[] which might be much bigger than necessary + return new ModularClassFile(this); +} + +/** + * Returns a collection of ordinary class files in this - a folder package fragment which has a root * that has its kind set to IPackageFragmentRoot.K_Source does not * recognize class files. * - * @see IPackageFragment#getClassFiles() + * @see IPackageFragment#getOrdinaryClassFiles() */ -public IClassFile[] getClassFiles() throws JavaModelException { +@Override +public IOrdinaryClassFile[] getOrdinaryClassFiles() throws JavaModelException { + if (getKind() == IPackageFragmentRoot.K_SOURCE) { + return NO_ORDINARY_CLASSFILES; + } + + ArrayList list = getChildrenOfType(CLASS_FILE); + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + if (iterator.next() instanceof ModularClassFile) + iterator.remove(); + } + IOrdinaryClassFile[] array= new IOrdinaryClassFile[list.size()]; + list.toArray(array); + return array; +} +/** + * Returns a collection of all class files in this - a folder package fragment which has a root + * that has its kind set to IPackageFragmentRoot.K_Source does not + * recognize class files. + * + * @see IPackageFragment#getAllClassFiles() + */ +public IClassFile[] getAllClassFiles() throws JavaModelException { if (getKind() == IPackageFragmentRoot.K_SOURCE) { return NO_CLASSFILES; } @@ -216,6 +264,13 @@ public IClassFile[] getClassFiles() throws JavaModelException { list.toArray(array); return array; } + +@Deprecated +@Override +public IClassFile[] getClassFiles() throws JavaModelException { + return getOrdinaryClassFiles(); +} + /** * @see IPackageFragment#getCompilationUnit(String) * @exception IllegalArgumentException if the name does not end with ".java" @@ -281,7 +336,10 @@ public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, case JEM_CLASSFILE: if (!memento.hasMoreTokens()) return this; String classFileName = memento.nextToken(); - JavaElement classFile = (JavaElement)getClassFile(classFileName); + JavaElement classFile = (JavaElement) getClassFile(classFileName); + return classFile.getHandleFromMemento(memento, owner); + case JEM_MODULAR_CLASSFILE: + classFile = (JavaElement) getModularClassFile(); return classFile.getHandleFromMemento(memento, owner); case JEM_COMPILATIONUNIT: if (!memento.hasMoreTokens()) return this; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java index beba74d554..a0ce587a8c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,11 +13,13 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.Map; +import java.util.jar.Manifest; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; @@ -196,6 +198,12 @@ protected boolean computeChildren(OpenableElementInfo info, IResource underlying char[][] inclusionPatterns = fullInclusionPatternChars(); char[][] exclusionPatterns = fullExclusionPatternChars(); computeFolderChildren(rootFolder, !Util.isExcluded(rootFolder, inclusionPatterns, exclusionPatterns), CharOperation.NO_STRINGS, vChildren, inclusionPatterns, exclusionPatterns); +// char[] suffix = getKind() == K_SOURCE ? SuffixConstants.SUFFIX_java : SuffixConstants.SUFFIX_class; +// char[] moduleInfoName = CharOperation.concat(TypeConstants.MODULE_INFO_NAME, suffix); +// IResource module = rootFolder.findMember(String.valueOf(moduleInfoName), true); +// if (module != null && module.exists()) { +// vChildren.add(new ClassFile(getPackageFragment(CharOperation.NO_STRINGS), String.valueOf(TypeConstants.MODULE_INFO_NAME))); +// } IJavaElement[] children = new IJavaElement[vChildren.size()]; vChildren.toArray(children); info.setChildren(children); @@ -209,7 +217,7 @@ protected boolean computeChildren(OpenableElementInfo info, IResource underlying } /** - * Starting at this folder, create package fragments and add the fragments that are not exclused + * Starting at this folder, create package fragments and add the fragments that are not excluded * to the collection of children. * * @exception JavaModelException The resource associated with this package fragment does not exist @@ -439,7 +447,7 @@ public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, if (memento.hasMoreTokens()) { token = memento.nextToken(); char firstChar = token.charAt(0); - if (firstChar == JEM_CLASSFILE || firstChar == JEM_COMPILATIONUNIT || firstChar == JEM_COUNT) { + if (firstChar == JEM_CLASSFILE || firstChar == JEM_MODULAR_CLASSFILE || firstChar == JEM_COMPILATIONUNIT || firstChar == JEM_COUNT) { pkgName = CharOperation.NO_STRINGS; } else { pkgName = Util.splitOn('.', token, 0, token.length()); @@ -478,6 +486,10 @@ protected void getHandleMemento(StringBuffer buff) { ((JavaElement)getParent()).getHandleMemento(buff); buff.append(getHandleMementoDelimiter()); escapeMementoName(buff, path.toString()); + if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(path.toOSString())) { + buff.append(getHandleMementoDelimiter()); + escapeMementoName(buff, getElementName()); + } } /** * @see IPackageFragmentRoot @@ -517,6 +529,9 @@ public IPackageFragment getPackageFragment(String packageName) { public PackageFragment getPackageFragment(String[] pkgName) { return new PackageFragment(this, pkgName); } +public PackageFragment getPackageFragment(String[] pkgName, String mod) { + return new PackageFragment(this, pkgName); // Overridden in JImageModuleFragmentBridge +} /** * Returns the package name for the given folder * (which is a decendent of this root). @@ -823,5 +838,60 @@ protected void verifyAttachSource(IPath sourcePath) throws JavaModelException { throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, sourcePath)); } } - +/** + * Returns the relative path within an archive for the given class file name. In certain + * kind of archives, such as a JMOD file, class files are stored in a nested folder, as opposed + * to directly under the root. It is the responsibility of such package fragment roots to + * provide the custom behavior. + * + * @param classname + * @return the relative path for the class file within the archive + */ +public String getClassFilePath(String classname) { + return classname; +} +public IModuleDescription getModuleDescription() { + try { + IJavaElement[] pkgs = getChildren(); + for (int j = 0, length = pkgs.length; j < length; j++) { + // only look in the default package + if (pkgs[j].getElementName().length() == 0) { + OpenableElementInfo info = null; + if (getKind() == IPackageFragmentRoot.K_SOURCE) { + ICompilationUnit unit = ((PackageFragment) pkgs[j]) + .getCompilationUnit(TypeConstants.MODULE_INFO_FILE_NAME_STRING); + if (unit instanceof CompilationUnit && unit.exists()) { + info = (CompilationUnitElementInfo) ((CompilationUnit) unit) + .getElementInfo(); + if (info != null) + return info.getModule(); + } + } else { + IModularClassFile classFile = ((IPackageFragment)pkgs[j]).getModularClassFile(); + if (classFile.exists()) { + return classFile.getModule(); + } + } + break; + } + } + } catch (JavaModelException e) { + } + return null; +} +/** @see org.eclipse.jdt.internal.compiler.env.IModulePathEntry#hasCompilationUnit(String, String) */ +public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) { + IPackageFragment fragment = getPackageFragment(qualifiedPackageName.replace('/', '.')); + try { + if (fragment.exists()) + return fragment.containsJavaResources(); + } catch (JavaModelException e) { + // silent + } + return false; +} +/** Convenience lookup, though currently only JarPackageFragmentRoot is searched for a manifest. */ +public Manifest getManifest() { + return null; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java index 6f1ae49649..1570655163 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java @@ -41,6 +41,7 @@ class PackageFragmentRootInfo extends OpenableElementInfo { private boolean ignoreOptionalProblems; private boolean initialized; + /** * Create and initialize a new instance of the receiver */ @@ -157,6 +158,7 @@ synchronized Object[] getNonJavaResources(IJavaProject project, IResource underl } return resources; } + /** * Returns the kind of this root. */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectEntry.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectEntry.java new file mode 100644 index 0000000000..7c2576ea05 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectEntry.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModulePathEntry; + +/** + * Represents a project + * + */ +public class ProjectEntry implements IModulePathEntry { + + JavaProject project; + + public ProjectEntry(JavaProject project) { + // + this.project = project; + } + @Override + public IModule getModule() { + try { + IModuleDescription module = this.project.getModuleDescription(); + if (module != null) { + return (ModuleDescriptionInfo) ((JavaElement) module) .getElementInfo(); + } + } catch (JavaModelException e) { + // Proceed with null; + } + return null; + } + + @Override + public boolean equalsProject(IJavaProject otherProject) { + return this.project.equals(otherProject); + } + + @Override + public boolean isAutomaticModule() { + return false; + } + + @Override + public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) { + // TODO(SHMOD): verify (is unnamed handled correctly?) + IModule mod = getModule(); + if (mod == null) { + if (moduleName != null) + return null; + } else if (!String.valueOf(mod.name()).equals(moduleName)) { + return null; + } + try { + IJavaElement element = this.project.findElement(new Path(qualifiedPackageName.replace('.', '/'))); + if (element instanceof IPackageFragment) + return mod != null ? new char[][] { mod.name() } : CharOperation.NO_CHAR_CHAR; + } catch (JavaModelException e) { + return null; + } + return null; + } + @Override + public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) { + try { + for (IPackageFragmentRoot root : this.project.getPackageFragmentRoots()) { + if (root instanceof PackageFragmentRoot && ((PackageFragmentRoot) root).hasCompilationUnit(qualifiedPackageName, moduleName)) + return true; + } + } catch (JavaModelException e) { + // silent + } + return false; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java index c44cba3422..0f03104f77 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java @@ -11,6 +11,15 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; @@ -18,13 +27,20 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.search.*; import org.eclipse.jdt.internal.codeassist.ISearchRequestor; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; -import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; import org.eclipse.jdt.internal.compiler.env.ISourceType; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.core.NameLookup.Answer; import org.eclipse.jdt.internal.core.search.BasicSearchEngine; import org.eclipse.jdt.internal.core.search.IRestrictedAccessConstructorRequestor; import org.eclipse.jdt.internal.core.search.IRestrictedAccessTypeRequestor; @@ -37,7 +53,7 @@ * uses the Java model as a search tool. */ public class SearchableEnvironment - implements INameEnvironment, IJavaSearchConstants { + implements IModuleAwareNameEnvironment, IJavaSearchConstants { public NameLookup nameLookup; protected ICompilationUnit unitToSkip; @@ -48,6 +64,11 @@ public class SearchableEnvironment protected IJavaSearchScope searchScope; protected boolean checkAccessRestrictions; + // moduleName -> IPackageFragmentRoot[](lazily populated) + private Map knownModuleLocations; // null indicates: not using JPMS + + private ModuleUpdater moduleUpdater; + private Map rootToModule; /** * Creates a SearchableEnvironment on the given project @@ -59,6 +80,19 @@ public SearchableEnvironment(JavaProject project, org.eclipse.jdt.core.ICompilat || !JavaCore.IGNORE.equals(project.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true)); this.workingCopies = workingCopies; this.nameLookup = project.newNameLookup(workingCopies); + if (CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_COMPLIANCE, true)) >= ClassFileConstants.JDK9) { + for (IPackageFragmentRoot root : project.getPackageFragmentRoots()) { + if (root.getModuleDescription() != null) { + this.knownModuleLocations = new HashMap<>(); + break; + } + } + } + if (CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_COMPLIANCE, true)) >= ClassFileConstants.JDK9) { + this.moduleUpdater = new ModuleUpdater(project); + for (IClasspathEntry entry : project.getRawClasspath()) + this.moduleUpdater.computeModuleUpdates(entry); + } } /** @@ -91,13 +125,18 @@ private static int convertSearchFilterToModelFilter(int searchFilter) { * Returns the given type in the the given package if it exists, * otherwise null. */ - protected NameEnvironmentAnswer find(String typeName, String packageName) { + protected NameEnvironmentAnswer find(String typeName, String packageName, IPackageFragmentRoot[] moduleContext) { if (packageName == null) packageName = IPackageFragment.DEFAULT_PACKAGE_NAME; if (this.owner != null) { String source = this.owner.findSource(typeName, packageName); if (source != null) { - ICompilationUnit cu = new BasicCompilationUnit(source.toCharArray(), CharOperation.splitOn('.', packageName.toCharArray()), typeName + Util.defaultJavaExtension()); + IJavaElement moduleElement = (moduleContext != null && moduleContext.length > 0) ? moduleContext[0] : null; + ICompilationUnit cu = new BasicCompilationUnit( + source.toCharArray(), + CharOperation.splitOn('.', packageName.toCharArray()), + typeName + Util.defaultJavaExtension(), + moduleElement); return new NameEnvironmentAnswer(cu, null); } } @@ -107,12 +146,14 @@ protected NameEnvironmentAnswer find(String typeName, String packageName) { packageName, false/*exact match*/, NameLookup.ACCEPT_ALL, - this.checkAccessRestrictions); + this.checkAccessRestrictions, + moduleContext); if (answer != null) { // construct name env answer if (answer.type instanceof BinaryType) { // BinaryType try { - return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) answer.type).getElementInfo(), answer.restriction); + char[] moduleName = answer.module != null ? answer.module.getElementName().toCharArray() : null; + return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) answer.type).getElementInfo(), answer.restriction, moduleName); } catch (JavaModelException npe) { // fall back to using owner } @@ -137,7 +178,8 @@ protected NameEnvironmentAnswer find(String typeName, String packageName) { if (!otherType.equals(topLevelType) && index < length) // check that the index is in bounds (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62861) sourceTypes[index++] = otherType; } - return new NameEnvironmentAnswer(sourceTypes, answer.restriction, getExternalAnnotationPath(answer.entry)); + char[] moduleName = answer.module != null ? answer.module.getElementName().toCharArray() : null; + return new NameEnvironmentAnswer(sourceTypes, answer.restriction, getExternalAnnotationPath(answer.entry), moduleName); } catch (JavaModelException jme) { if (jme.isDoesNotExist() && String.valueOf(TypeConstants.PACKAGE_INFO_NAME).equals(typeName)) { // in case of package-info.java the type doesn't exist in the model, @@ -160,6 +202,17 @@ private String getExternalAnnotationPath(IClasspathEntry entry) { return path.toOSString(); } + /** + * Find the modules that start with the given prefix. + * A valid prefix is a qualified name separated by periods + * (ex. java.util). + * The packages found are passed to: + * ISearchRequestor.acceptModule(char[][] moduleName) + */ + public void findModules(char[] prefix, ISearchRequestor requestor, IJavaProject javaProject) { + this.nameLookup.seekModule(prefix, true, new SearchableEnvironmentRequestor(requestor)); + } + /** * Find the packages that start with the given prefix. * A valid prefix is a qualified name separated by periods @@ -174,6 +227,19 @@ public void findPackages(char[] prefix, ISearchRequestor requestor) { new SearchableEnvironmentRequestor(requestor)); } + /** + * Find the packages that start with the given prefix and belong to the given module. + * A valid prefix is a qualified name separated by periods + * (ex. java.util). + * The packages found are passed to: + * ISearchRequestor.acceptPackage(char[][] packageName) + */ + public void findPackages(char[] prefix, ISearchRequestor requestor, IPackageFragmentRoot[] moduleContext) { + this.nameLookup.seekPackageFragments( + new String(prefix), + true, + new SearchableEnvironmentRequestor(requestor), moduleContext); + } /** * Find the top-level types that are defined * in the current environment and whose simple name matches the given name. @@ -276,15 +342,41 @@ private void findExactTypes(String name, ISearchRequestor storage, int type) { } /** - * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[][]) + * Find a type in the given module or any module read by it. + * Does not check accessibility / unique visibility, but returns the first observable type found. + * @param compoundTypeName name of the sought type + * @param module start into the module graph + * @return the answer :) + */ + public NameEnvironmentAnswer findTypeInModules(char[][] compoundTypeName, ModuleBinding module) { + char[] nameForLookup = module.nameForLookup(); + NameEnvironmentAnswer answer = findType(compoundTypeName, nameForLookup); + if (answer != null) + return answer; + if (LookupStrategy.get(nameForLookup) == LookupStrategy.Named) { + for (ModuleBinding required : module.getAllRequiredModules()) { + answer = findType(compoundTypeName, required.nameForLookup()); + if (answer != null) + return answer; + } + } + return null; + } + + /** + * @see org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment#findType(char[][],char[]) */ - public NameEnvironmentAnswer findType(char[][] compoundTypeName) { + @Override + public NameEnvironmentAnswer findType(char[][] compoundTypeName, char[] moduleName) { if (compoundTypeName == null) return null; + boolean isNamedStrategy = LookupStrategy.get(moduleName) == LookupStrategy.Named; + IPackageFragmentRoot[] moduleLocations = isNamedStrategy ? findModuleContext(moduleName) : null; + int length = compoundTypeName.length; if (length <= 1) { if (length == 0) return null; - return find(new String(compoundTypeName[0]), null); + return find(new String(compoundTypeName[0]), null, moduleLocations); } int lengthM1 = length - 1; @@ -293,18 +385,23 @@ public NameEnvironmentAnswer findType(char[][] compoundTypeName) { return find( new String(compoundTypeName[lengthM1]), - CharOperation.toString(packageName)); + CharOperation.toString(packageName), + moduleLocations); } /** - * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[], char[][]) + * @see org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment#findType(char[],char[][],char[]) */ - public NameEnvironmentAnswer findType(char[] name, char[][] packageName) { + @Override + public NameEnvironmentAnswer findType(char[] name, char[][] packageName, char[] moduleName) { if (name == null) return null; + boolean isNamedStrategy = LookupStrategy.get(moduleName) == LookupStrategy.Named; + IPackageFragmentRoot[] moduleLocations = isNamedStrategy ? findModuleContext(moduleName) : null; return find( new String(name), - packageName == null || packageName.length == 0 ? null : CharOperation.toString(packageName)); + packageName == null || packageName.length == 0 ? null : CharOperation.toString(packageName), + moduleLocations); } /** @@ -695,22 +792,168 @@ private IJavaSearchScope getSearchScope() { } /** - * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#isPackage(char[][], char[]) + * @see org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment#getModulesDeclaringPackage(char[][], char[], char[]) */ - public boolean isPackage(char[][] parentPackageName, char[] subPackageName) { + @Override + public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) { String[] pkgName; if (parentPackageName == null) - pkgName = new String[] {new String(subPackageName)}; + pkgName = new String[] {new String(name)}; else { int length = parentPackageName.length; pkgName = new String[length+1]; for (int i = 0; i < length; i++) pkgName[i] = new String(parentPackageName[i]); - pkgName[length] = new String(subPackageName); + pkgName[length] = new String(name); + } + LookupStrategy strategy = LookupStrategy.get(moduleName); + switch (strategy) { + case Named: + if (this.knownModuleLocations != null) { + IPackageFragmentRoot[] moduleContext = findModuleContext(moduleName); + if (moduleContext != null) { + // (this.owner != null && this.owner.isPackage(pkgName)) // TODO(SHMOD) see old isPackage + if (this.nameLookup.isPackage(pkgName, moduleContext)) { + return new char[][] { moduleName }; + } + } + } + return null; + case Unnamed: + case Any: + // if in pre-9 mode we may still search the unnamed module + if (this.knownModuleLocations == null) { + if ((this.owner != null && this.owner.isPackage(pkgName)) + || this.nameLookup.isPackage(pkgName)) + return new char[][] { ModuleBinding.UNNAMED }; + return null; + } + //$FALL-THROUGH$ + case AnyNamed: + char[][] names = CharOperation.NO_CHAR_CHAR; + IPackageFragmentRoot[] packageRoots = this.nameLookup.packageFragmentRoots; + for (IPackageFragmentRoot packageRoot : packageRoots) { + IPackageFragmentRoot[] singleton = { packageRoot }; + if (strategy.matches(singleton, locs -> locs[0] instanceof JrtPackageFragmentRoot || getModuleDescription(locs) != null)) { + if (this.nameLookup.isPackage(pkgName, singleton)) { + IModuleDescription moduleDescription = getModuleDescription(singleton); + char[] aName = moduleDescription != null ? moduleDescription.getElementName().toCharArray() : ModuleBinding.UNNAMED; + names = CharOperation.arrayConcat(names, aName); + } + } + } + return names == CharOperation.NO_CHAR_CHAR ? null : names; + default: + throw new IllegalArgumentException("Unexpected LookupStrategy "+strategy); //$NON-NLS-1$ } - return - (this.owner != null && this.owner.isPackage(pkgName)) - || this.nameLookup.isPackage(pkgName); + } + @Override + public boolean hasCompilationUnit(char[][] pkgName, char[] moduleName, boolean checkCUs) { + LookupStrategy strategy = LookupStrategy.get(moduleName); + switch (strategy) { + case Named: + if (this.knownModuleLocations != null) { + IPackageFragmentRoot[] moduleContext = findModuleContext(moduleName); + if (moduleContext != null) { + // (this.owner != null && this.owner.isPackage(pkgName)) // TODO(SHMOD) see old isPackage + if (this.nameLookup.hasCompilationUnit(pkgName, moduleContext)) + return true; + } + } + return false; + case Unnamed: + case Any: + // if in pre-9 mode we may still search the unnamed module + if (this.knownModuleLocations == null) { + if (this.nameLookup.hasCompilationUnit(pkgName, null)) + return true; + } + //$FALL-THROUGH$ + case AnyNamed: + IPackageFragmentRoot[] packageRoots = this.nameLookup.packageFragmentRoots; + for (IPackageFragmentRoot packageRoot : packageRoots) { + IPackageFragmentRoot[] singleton = { packageRoot }; + if (strategy.matches(singleton, locs -> locs[0] instanceof JrtPackageFragmentRoot || getModuleDescription(locs) != null)) { + if (this.nameLookup.hasCompilationUnit(pkgName, singleton)) + return true; + } + } + return false; + default: + throw new IllegalArgumentException("Unexpected LookupStrategy "+strategy); //$NON-NLS-1$ + } + } + + private IModuleDescription getModuleDescription(IPackageFragmentRoot[] roots) { + if (this.rootToModule == null) { + this.rootToModule = new HashMap<>(); + } + Function rootToEntry = r -> { + try { + return ((JavaProject) r.getJavaProject()).getClasspathEntryFor(r.getPath()); + } catch (JavaModelException e) { + return null; + } + }; + for (IPackageFragmentRoot root : roots) { + IModuleDescription moduleDescription = NameLookup.getModuleDescription(root, this.rootToModule, rootToEntry); + if (moduleDescription != null) + return moduleDescription; + } + return null; + } + + private IPackageFragmentRoot[] findModuleContext(char[] moduleName) { + IPackageFragmentRoot[] moduleContext = null; + if (this.knownModuleLocations != null && moduleName != null && moduleName.length > 0) { + moduleContext = this.knownModuleLocations.get(String.valueOf(moduleName)); + if (moduleContext == null) { + Answer moduleAnswer = this.nameLookup.findModule(moduleName); + if (moduleAnswer != null) { + IProject currentProject = moduleAnswer.module.getJavaProject().getProject(); + IJavaElement current = moduleAnswer.module.getParent(); + while (moduleContext == null && current != null) { + switch (current.getElementType()) { + case IJavaElement.PACKAGE_FRAGMENT_ROOT: + if (!((IPackageFragmentRoot) current).isExternal()) { + current = current.getJavaProject(); + } else { + moduleContext = new IPackageFragmentRoot[] { (IPackageFragmentRoot) current }; // TODO: validate + break; + } + //$FALL-THROUGH$ + case IJavaElement.JAVA_PROJECT: + try { + moduleContext = getOwnedPackageFragmentRoots((IJavaProject) current); + } catch (JavaModelException e) { + // silent? + } + break; + default: + current = current.getParent(); + if (current != null) { + try { + // detect when an element refers to a resource owned by another project: + IResource resource = current.getUnderlyingResource(); + if (resource != null) { + IProject otherProject = resource.getProject(); + if (otherProject != null && !otherProject.equals(currentProject)) { + IJavaProject otherJavaProject = JavaCore.create(otherProject); + if (otherJavaProject.exists()) + moduleContext = getRootsForOutputLocation(otherJavaProject, resource); + } + } + } catch (JavaModelException e) { + Util.log(e, "Failed to find package fragment root for " + current); //$NON-NLS-1$ + } + } + } + } + this.knownModuleLocations.put(String.valueOf(moduleName), moduleContext); + } + } + } + return moduleContext; } /** @@ -735,4 +978,69 @@ protected String toStringCharChar(char[][] names) { public void cleanup() { // nothing to do } + + @Override + public org.eclipse.jdt.internal.compiler.env.IModule getModule(char[] name) { + NameLookup.Answer answer = this.nameLookup.findModule(name); + IModule module = null; + if (answer != null) { + module = NameLookup.getModuleDescriptionInfo(answer.module); + } + return module; + } + + @Override + public char[][] getAllAutomaticModules() { + return CharOperation.NO_CHAR_CHAR; + } + + @Override + public void applyModuleUpdates(IUpdatableModule module, UpdateKind kind) { + if (this.moduleUpdater != null) + this.moduleUpdater.applyModuleUpdates(module, kind); + } + + private IPackageFragmentRoot[] getRootsForOutputLocation(IJavaProject otherJavaProject, IResource outputLocation) throws JavaModelException { + IPath outputPath = outputLocation.getFullPath(); + List result = new ArrayList<>(); + if (outputPath.equals(otherJavaProject.getOutputLocation())) { + // collect roots reporting to the default output location: + for (IClasspathEntry classpathEntry : otherJavaProject.getRawClasspath()) { + if (classpathEntry.getOutputLocation() == null) { + for (IPackageFragmentRoot root : otherJavaProject.findPackageFragmentRoots(classpathEntry)) { + IResource rootResource = root.getResource(); + if (rootResource == null || !rootResource.getProject().equals(otherJavaProject.getProject())) + continue; // outside this project + result.add(root); + } + } + } + } + if (!result.isEmpty()) + return result.toArray(new IPackageFragmentRoot[result.size()]); + // search an entry that specifically (and exclusively) reports to the output location: + for (IClasspathEntry classpathEntry : otherJavaProject.getRawClasspath()) { + if (outputPath.equals(classpathEntry.getOutputLocation())) + return otherJavaProject.findPackageFragmentRoots(classpathEntry); + } + return null; + } + + public static IPackageFragmentRoot[] getOwnedPackageFragmentRoots(IJavaProject javaProject) throws JavaModelException { + IPackageFragmentRoot[] allRoots = javaProject.getPackageFragmentRoots(); + IPackageFragmentRoot[] sourceRoots = Arrays.copyOf(allRoots, allRoots.length); + int count = 0; + for (int i = 0; i < allRoots.length; i++) { + IPackageFragmentRoot root = allRoots[i]; + if (root.getKind() == IPackageFragmentRoot.K_BINARY) { + IResource resource = root.getResource(); + if (resource == null || !resource.getProject().equals(javaProject.getProject())) + continue; // outside this project + } + sourceRoots[count++] = root; + } + if (count < allRoots.length) + return Arrays.copyOf(sourceRoots, count); + return sourceRoots; + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java index 49bfd1844a..1a5ce90f91 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java @@ -13,6 +13,7 @@ import org.eclipse.jdt.core.IInitializer; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; @@ -85,6 +86,9 @@ public void acceptInitializer(IInitializer initializer) { public void acceptPackageFragment(IPackageFragment packageFragment) { this.requestor.acceptPackage(packageFragment.getElementName().toCharArray()); } +public void acceptModule(IModuleDescription module) { + this.requestor.acceptModule(module.getElementName().toCharArray()); +} /** * @see IJavaElementRequestor */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java index 305cfe6098..03388e0dbe 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,6 +19,7 @@ import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; @@ -43,6 +44,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; +import org.eclipse.jdt.internal.core.NameLookup.Answer; import org.eclipse.jdt.internal.core.util.HandleFactory; import org.eclipse.jdt.internal.core.util.Util; @@ -168,6 +170,11 @@ protected void acceptBinaryMethod( acceptBinaryMethod(type, method, uniqueKey, isConstructor); } } +@Override +public void acceptModule(char[] moduleName, char[] uniqueKey, int start, int end) { + IModuleDescription module = resolveModule(moduleName); + addElement(module); +} /** * Resolve the type. */ @@ -905,6 +912,13 @@ public IJavaElement[] getElements() { } return this.elements; } +protected IModuleDescription resolveModule(char[] moduleName) { + Answer answer = this.nameLookup.findModule(moduleName); + if (answer != null) { + return answer.module; + } + return null; +} /** * Resolve the type */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java index 4be663fb53..dde04c2c39 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java @@ -13,6 +13,7 @@ import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IInitializer; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; @@ -49,6 +50,12 @@ public void acceptMemberType(IType type) { public void acceptMethod(IMethod method) { // implements interface method } +/** + * @see IJavaElementRequestor + */ +public void acceptModule(IModuleDescription module) { + // implements interface method +} /** * @see IJavaElementRequestor */ diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java index cdf0b5717d..33f0607226 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,6 +14,8 @@ package org.eclipse.jdt.internal.core; import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -43,6 +45,7 @@ import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; @@ -61,17 +64,21 @@ import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter; /** - * A SourceMapper maps source code in a ZIP file to binary types in - * a JAR. The SourceMapper uses the fuzzy parser to identify source - * fragments in a .java file, and attempts to match the source code - * with children in a binary type. A SourceMapper is associated - * with a JarPackageFragment by an AttachSourceOperation. + * A SourceMapper maps source code in a ZIP file to binary types or + * binary modules in a JAR. The SourceMapper uses the fuzzy parser + * to identify source fragments in a .java file, and attempts to match + * the source code with children in a binary type. + * Since a module has no children in the Java Model no such matching + * happens in that case. + * A SourceMapper is associated with a JarPackageFragment by an AttachSourceOperation. * * @see org.eclipse.jdt.internal.core.JarPackageFragment */ @@ -149,9 +156,9 @@ public String toString() { protected ArrayList rootPaths; /** - * The binary type source is being mapped for + * The binary type or module source is being mapped for */ - protected BinaryType binaryType; + protected NamedMember binaryTypeOrModule; /** * The location of the zip file containing source. @@ -230,7 +237,7 @@ public String toString() { protected IJavaElement searchedElement; /** - * imports references + * imports references (keyed by binaryTypeOrModule) */ private HashMap importsTable; private HashMap importsCounterTable; @@ -244,6 +251,13 @@ public String toString() { int[] typeModifiers; int typeDepth; + /** + * Module information + */ + SourceRange moduleNameRange; + int moduleDeclarationStart; + int moduleModifiers; + /** * Anonymous counter in case we want to map the source of an anonymous class. */ @@ -283,6 +297,7 @@ public SourceMapper(IPath sourcePath, String rootPath, Map options, String encod // use no encoding } if (rootPath != null) { + this.rootPath = rootPath; this.rootPaths = new ArrayList(); this.rootPaths.add(rootPath); } @@ -305,13 +320,13 @@ public void acceptImport( char[][] tokens, boolean onDemand, int modifiers) { - char[][] imports = (char[][]) this.importsTable.get(this.binaryType); + char[][] imports = (char[][]) this.importsTable.get(this.binaryTypeOrModule); int importsCounter; if (imports == null) { imports = new char[5][]; importsCounter = 0; } else { - importsCounter = ((Integer) this.importsCounterTable.get(this.binaryType)).intValue(); + importsCounter = ((Integer) this.importsCounterTable.get(this.binaryTypeOrModule)).intValue(); } if (imports.length == importsCounter) { System.arraycopy( @@ -329,8 +344,8 @@ public void acceptImport( name[nameLength + 1] = '*'; } imports[importsCounter++] = name; - this.importsTable.put(this.binaryType, imports); - this.importsCounterTable.put(this.binaryType, Integer.valueOf(importsCounter)); + this.importsTable.put(this.binaryTypeOrModule, imports); + this.importsCounterTable.put(this.binaryTypeOrModule, Integer.valueOf(importsCounter)); } /** @@ -455,11 +470,67 @@ private int findMatchingGenericEnd(char[] sig, int start) { return -1; } - private synchronized void computeAllRootPaths(IType type) { + class JrtPackageNamesAdderVisitor implements JRTUtil.JrtFileVisitor { + + public final HashSet firstLevelPackageNames; + final IPackageFragmentRoot root; + public String sourceLevel = null; + public String complianceLevel = null; + public boolean containsADefaultPackage; + public boolean containsJavaSource; + + JrtPackageNamesAdderVisitor(HashSet firstLevelPackageNames, String sourceLevel, String complianceLevel, + boolean containsADefaultPackage, boolean containsJavaSource, IPackageFragmentRoot root) { + this.firstLevelPackageNames = firstLevelPackageNames; + this.root = root; + this.sourceLevel = sourceLevel; + this.complianceLevel = complianceLevel; + this.containsADefaultPackage = containsADefaultPackage; + this.containsJavaSource = containsJavaSource; + } + + @Override + public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(java.nio.file.Path file, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException { + String entryName = file.toString(); + if (Util.isClassFileName(entryName)) { + int index = entryName.indexOf('/'); + if (index != -1) { + String firstLevelPackageName = entryName.substring(0, index); + if (!this.firstLevelPackageNames.contains(firstLevelPackageName)) { + if (this.sourceLevel == null) { + IJavaProject project = this.root.getJavaProject(); + this.sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true); + this.complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true); + } + IStatus status = JavaConventions.validatePackageName(firstLevelPackageName, this.sourceLevel, this.complianceLevel); + if (status.isOK() || status.getSeverity() == IStatus.WARNING) { + this.firstLevelPackageNames.add(firstLevelPackageName); + } + } + } else { + this.containsADefaultPackage = true; + } + } else if (!this.containsJavaSource && org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(entryName)) { + this.containsJavaSource = true; + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitModule(java.nio.file.Path mod) throws IOException { + return FileVisitResult.CONTINUE; + } + } + private synchronized void computeAllRootPaths(IJavaElement typeOrModule) { if (this.areRootPathsComputed) { return; } - IPackageFragmentRoot root = (IPackageFragmentRoot) type.getPackageFragment().getParent(); + IPackageFragmentRoot root = (IPackageFragmentRoot) typeOrModule.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); IPath pkgFragmentRootPath = root.getPath(); final HashSet tempRoots = new HashSet(); long time = 0; @@ -473,7 +544,22 @@ private synchronized void computeAllRootPaths(IType type) { String sourceLevel = null; String complianceLevel = null; - if (root.isArchive()) { + if (Util.isJrt(pkgFragmentRootPath.toOSString())) { + try { + JrtPackageNamesAdderVisitor jrtPackageNamesAdderVisitor = new JrtPackageNamesAdderVisitor(firstLevelPackageNames, + sourceLevel, complianceLevel, containsADefaultPackage, containsJavaSource, root); + org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(root.getPath().toFile(), jrtPackageNamesAdderVisitor, JRTUtil.NOTIFY_FILES); + sourceLevel = jrtPackageNamesAdderVisitor.sourceLevel; + complianceLevel = jrtPackageNamesAdderVisitor.complianceLevel; + containsADefaultPackage = jrtPackageNamesAdderVisitor.containsADefaultPackage; + containsJavaSource = jrtPackageNamesAdderVisitor.containsJavaSource; + } catch (IOException e) { + // We are not reading any specific file, so, move on for now + if (VERBOSE) { + e.printStackTrace(); + } + } + } else if (root.isArchive()) { JavaModelManager manager = JavaModelManager.getJavaModelManager(); ZipFile zip = null; try { @@ -723,7 +809,7 @@ public void enterType(TypeInfo typeInfo) { if (typeInfo.name.length == 0) { this.anonymousCounter++; if (this.anonymousCounter == this.anonymousClassName) { - this.types[this.typeDepth] = getType(this.binaryType.getElementName()); + this.types[this.typeDepth] = getType(this.binaryTypeOrModule.getElementName()); } else { this.types[this.typeDepth] = getType(new String(typeInfo.name)); } @@ -758,6 +844,27 @@ public void enterType(TypeInfo typeInfo) { // categories addCategories(currentType, typeInfo.categories); } + + @Override + public void enterModule(ModuleInfo moduleInfo) { + this.moduleNameRange = + new SourceRange(moduleInfo.nameSourceStart, moduleInfo.nameSourceEnd - moduleInfo.nameSourceStart + 1); + this.moduleDeclarationStart = moduleInfo.declarationStart; + + + // module type modifiers + this.moduleModifiers = moduleInfo.modifiers; + } + + @Override + public void exitModule(int declarationEnd) { + setSourceRange( + this.binaryTypeOrModule, + new SourceRange( + this.moduleDeclarationStart, + declarationEnd - this.moduleDeclarationStart + 1), + this.moduleNameRange); + } /** * @see ISourceElementRequestor @@ -994,12 +1101,28 @@ public char[] findSource(IType type, IBinaryType info) { * folder) used to create the given type (e.g. "A.java" for x/y/A$Inner.class) */ public char[] findSource(IType type, String simpleSourceFileName) { + PackageFragment pkgFrag = (PackageFragment) type.getPackageFragment(); + String name = org.eclipse.jdt.internal.core.util.Util.concatWith(pkgFrag.names, simpleSourceFileName, '/'); + return internalFindSource((NamedMember) type, name); + } + + /** + * Locates and returns source code for the given (binary) module, in this + * SourceMapper's ZIP file, or returns null if source + * code cannot be found. + */ + public char[] findSource(IModuleDescription module) { + if (!module.isBinary()) { + return null; + } + return internalFindSource((NamedMember) module, TypeConstants.MODULE_INFO_FILE_NAME_STRING); + } + + private char[] internalFindSource(NamedMember typeOrModule, String name) { long time = 0; if (VERBOSE) { time = System.currentTimeMillis(); } - PackageFragment pkgFrag = (PackageFragment) type.getPackageFragment(); - String name = org.eclipse.jdt.internal.core.util.Util.concatWith(pkgFrag.names, simpleSourceFileName, '/'); char[] source = null; @@ -1009,10 +1132,13 @@ public char[] findSource(IType type, String simpleSourceFileName) { if (this.rootPath != null) { source = getSourceForRootPath(this.rootPath, name); + if (source == null) { + source = getSourceForRootPath("", name); //$NON-NLS-1$ + } } if (source == null) { - computeAllRootPaths(type); + computeAllRootPaths(typeOrModule); if (this.rootPaths != null) { loop: for (Iterator iterator = this.rootPaths.iterator(); iterator.hasNext(); ) { String currentRootPath = (String) iterator.next(); @@ -1031,7 +1157,7 @@ public char[] findSource(IType type, String simpleSourceFileName) { javaModelManager.flushZipFiles(this); // clean up cached zip files. } if (VERBOSE) { - System.out.println("spent " + (System.currentTimeMillis() - time) + "ms for " + type.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println("spent " + (System.currentTimeMillis() - time) + "ms for " + typeOrModule.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$ } return source; } @@ -1235,8 +1361,11 @@ public SourceRange getSourceRange(IJavaElement element) { * as well. */ protected IType getType(String typeName) { + if (!(this.binaryTypeOrModule instanceof IType)) + return null; + IType type = (IType) this.binaryTypeOrModule; if (typeName.length() == 0) { - IJavaElement classFile = this.binaryType.getParent(); + IJavaElement classFile = type.getParent(); String classFileName = classFile.getElementName(); StringBuffer newClassFileName = new StringBuffer(); int lastDollar = classFileName.lastIndexOf('$'); @@ -1245,10 +1374,10 @@ protected IType getType(String typeName) { newClassFileName.append(Integer.toString(this.anonymousCounter)); PackageFragment pkg = (PackageFragment) classFile.getParent(); return new BinaryType(new ClassFile(pkg, newClassFileName.toString()), typeName); - } else if (this.binaryType.getElementName().equals(typeName)) - return this.binaryType; + } else if (type.getElementName().equals(typeName)) + return type; else - return ((this.typeDepth <= 1) ? this.binaryType : this.types[this.typeDepth - 1]).getType(typeName); + return ((this.typeDepth <= 1) ? type : this.types[this.typeDepth - 1]).getType(typeName); } /** @@ -1366,10 +1495,10 @@ private int getUnqualifiedTypeSignature(String qualifiedTypeSig, int start, int } /** - * Maps the given source code to the given binary type and its children. + * Maps the given source code to the given binary type or module and its children. */ - public void mapSource(IType type, char[] contents, IBinaryType info) { - this.mapSource(type, contents, info, null); + public void mapSource(NamedMember typeOrModule, char[] contents, IBinaryType info) { + this.mapSource(typeOrModule, contents, info, null); } /** @@ -1378,18 +1507,18 @@ public void mapSource(IType type, char[] contents, IBinaryType info) { * given java element without storing it. */ public synchronized ISourceRange mapSource( - IType type, + NamedMember typeOrModule, char[] contents, - IBinaryType info, + IBinaryType info, // null for modules IJavaElement elementToFind) { - this.binaryType = (BinaryType) type; + this.binaryTypeOrModule = typeOrModule; // check whether it is already mapped - if (this.sourceRanges.get(type) != null) return (elementToFind != null) ? getNameRange(elementToFind) : null; + if (this.sourceRanges.get(typeOrModule) != null) return (elementToFind != null) ? getNameRange(elementToFind) : null; - this.importsTable.remove(this.binaryType); - this.importsCounterTable.remove(this.binaryType); + this.importsTable.remove(this.binaryTypeOrModule); + this.importsCounterTable.remove(this.binaryTypeOrModule); this.searchedElement = elementToFind; this.types = new IType[1]; this.typeDeclarationStarts = new int[1]; @@ -1410,42 +1539,50 @@ public synchronized ISourceRange mapSource( try { IProblemFactory factory = new DefaultProblemFactory(); SourceElementParser parser = null; + boolean doFullParse = false; this.anonymousClassName = 0; - if (info == null) { - try { - info = (IBinaryType) this.binaryType.getElementInfo(); - } catch(JavaModelException e) { - return null; + String sourceFileName; + if (this.binaryTypeOrModule instanceof BinaryType) { + if (info == null) { + try { + info = (IBinaryType) this.binaryTypeOrModule.getElementInfo(); + } catch(JavaModelException e) { + return null; + } } - } - boolean isAnonymousClass = info.isAnonymous(); - char[] fullName = info.getName(); - if (isAnonymousClass) { - String eltName = this.binaryType.getParent().getElementName(); - eltName = eltName.substring(eltName.lastIndexOf('$') + 1, eltName.length()); - try { - this.anonymousClassName = Integer.parseInt(eltName); - } catch(NumberFormatException e) { - // ignore + sourceFileName = ((BinaryType) this.binaryTypeOrModule).sourceFileName(info); + boolean isAnonymousClass = info.isAnonymous(); + + char[] fullName = info.getName(); + if (isAnonymousClass) { + String eltName = this.binaryTypeOrModule.getParent().getElementName(); + eltName = eltName.substring(eltName.lastIndexOf('$') + 1, eltName.length()); + try { + this.anonymousClassName = Integer.parseInt(eltName); + } catch(NumberFormatException e) { + // ignore + } } + doFullParse = hasToRetrieveSourceRangesForLocalClass(fullName); + } else { + sourceFileName = TypeConstants.MODULE_INFO_CLASS_NAME_STRING; } - boolean doFullParse = hasToRetrieveSourceRangesForLocalClass(fullName); // GROOVY edit //parser = new SourceElementParser(this, factory, new CompilerOptions(this.options), doFullParse, true/*optimize string literals*/); parser = LanguageSupportFactory.getSourceElementParser(this, factory, new CompilerOptions(this.options), doFullParse, true/*optimize string literals*/, true); // GROOVY end parser.javadocParser.checkDocComment = false; // disable javadoc parsing - IJavaElement javaElement = this.binaryType.getCompilationUnit(); - if (javaElement == null) javaElement = this.binaryType.getParent(); + IJavaElement javaElement = this.binaryTypeOrModule.getCompilationUnit(); + if (javaElement == null) javaElement = this.binaryTypeOrModule.getParent(); parser.parseCompilationUnit( - new BasicCompilationUnit(contents, null, this.binaryType.sourceFileName(info), javaElement), + new BasicCompilationUnit(contents, null, sourceFileName, javaElement), doFullParse, null/*no progress*/); // GROOVY add // if this is an interesting file in an interesting project, then filter out all binary members that do not have a direct mapping to the source org.eclipse.core.resources.IProject project = javaElement.getJavaProject().getProject(); - if (LanguageSupportFactory.isInterestingProject(project) && LanguageSupportFactory.isInterestingSourceFile(this.binaryType.getSourceFileName(info))) { - LanguageSupportFactory.filterNonSourceMembers(this.binaryType); + if (LanguageSupportFactory.isInterestingProject(project) && LanguageSupportFactory.isInterestingSourceFile(sourceFileName)) { + LanguageSupportFactory.filterNonSourceMembers((BinaryType) this.binaryTypeOrModule); } // GROOVY end if (elementToFind != null) { @@ -1458,7 +1595,7 @@ public synchronized ISourceRange mapSource( if (elementToFind != null) { this.sourceRanges = oldSourceRanges; } - this.binaryType = null; + this.binaryTypeOrModule = null; this.searchedElement = null; this.types = null; this.typeDeclarationStarts = null; @@ -1509,10 +1646,10 @@ protected void setSourceRange( /** * Return a char[][] array containing the imports of the attached source for the binary type */ - public char[][] getImports(BinaryType type) { - char[][] imports = (char[][]) this.importsTable.get(type); + public char[][] getImports(Member typeOrModule) { + char[][] imports = (char[][]) this.importsTable.get(typeOrModule); if (imports != null) { - int importsCounter = ((Integer) this.importsCounterTable.get(type)).intValue(); + int importsCounter = ((Integer) this.importsCounterTable.get(typeOrModule)).intValue(); if (imports.length != importsCounter) { System.arraycopy( imports, @@ -1521,7 +1658,7 @@ public char[][] getImports(BinaryType type) { 0, importsCounter); } - this.importsTable.put(type, imports); + this.importsTable.put(typeOrModule, imports); } return imports; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceModule.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceModule.java new file mode 100644 index 0000000000..acbce05039 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceModule.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import org.eclipse.jdt.core.JavaModelException; + +public class SourceModule extends AbstractModule { + public SourceModule(JavaElement parent, String name) { + super(parent, name); + } + @Override + public int getFlags() throws JavaModelException { + ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo(); + return info.getModifiers(); + } + public String toString(String lineDelimiter) { + StringBuffer buffer = new StringBuffer(); + try { + toStringContent(buffer, lineDelimiter); + } catch (JavaModelException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return buffer.toString(); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java index 332c4af123..c1cf20e1bd 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -241,7 +241,8 @@ public boolean visit(IResourceProxy proxy) throws CoreException { if (exclusionPatterns != null || inclusionPatterns != null) if (Util.isExcluded(resource.getFullPath(), inclusionPatterns, exclusionPatterns, false)) return false; - sourceFiles.add(new SourceFile((IFile) resource, sourceLocation)); + SourceFile unit = new SourceFile((IFile) resource, sourceLocation); + sourceFiles.add(unit); } return false; case IResource.FOLDER : @@ -382,8 +383,12 @@ protected void compile(SourceFile[] units, SourceFile[] additionalUnits, boolean additionalUnits[length + i] = (SourceFile) this.problemSourceFiles.get(i); } String[] initialTypeNames = new String[units.length]; - for (int i = 0, l = units.length; i < l; i++) - initialTypeNames[i] = units[i].initialTypeName; + for (int i = 0, l = units.length; i < l; i++) { + char[] moduleName = units[i].getModuleName(); + initialTypeNames[i] = (moduleName == null) + ? units[i].initialTypeName + : new StringBuilder(60).append(moduleName).append(':').append(units[i].initialTypeName).toString(); + } this.nameEnvironment.setNames(initialTypeNames, additionalUnits); this.notifier.checkCancel(); try { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java index 8c972d17e0..0fcb218e95 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java @@ -14,7 +14,6 @@ import org.codehaus.jdt.groovy.integration.LanguageSupportFactory; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; - import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.ClassFile; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java index fa1e11d102..74f3332b74 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,17 +13,23 @@ import java.io.IOException; import java.util.zip.ZipFile; -import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.*; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.util.Util; + public class ClasspathDirectory extends ClasspathLocation { IContainer binaryFolder; // includes .class files for a single directory @@ -34,13 +40,14 @@ public class ClasspathDirectory extends ClasspathLocation { ZipFile annotationZipFile; String externalAnnotationPath; -ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) { +ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath) { this.binaryFolder = binaryFolder; this.isOutputFolder = isOutputFolder || binaryFolder.getProjectRelativePath().isEmpty(); // if binaryFolder == project, then treat it as an outputFolder this.directoryCache = new SimpleLookupTable(5); this.accessRuleSet = accessRuleSet; if (externalAnnotationPath != null) this.externalAnnotationPath = externalAnnotationPath.toOSString(); + this.isOnModulePath = isOnModulePath; } public void cleanup() { @@ -54,6 +61,33 @@ public void cleanup() { this.directoryCache = null; } +IModule initializeModule() { + IResource[] members = null; + try { + members = this.binaryFolder.members(); + if (members != null) { + for (int i = 0, l = members.length; i < l; i++) { + IResource m = members[i]; + String name = m.getName(); + // Note: Look only inside the default package. + if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) { + if (name.equalsIgnoreCase(IModule.MODULE_INFO_CLASS)) { + try { + ClassFileReader cfr = Util.newClassFileReader(m); + return cfr.getModuleDeclaration(); + } catch (ClassFormatException | IOException e) { + // TODO Java 9 Auto-generated catch block + e.printStackTrace(); + } + } + } + } + } + } catch (CoreException e1) { + e1.printStackTrace(); + } + return null; +} String[] directoryList(String qualifiedPackageName) { String[] dirList = (String[]) this.directoryCache.get(qualifiedPackageName); if (dirList == this.missingPackageHolder) return null; // package exists in another classpath directory or jar @@ -67,9 +101,11 @@ String[] directoryList(String qualifiedPackageName) { int index = 0; for (int i = 0, l = members.length; i < l; i++) { IResource m = members[i]; - if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(m.getName())) + String name = m.getName(); + if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) { // add exclusion pattern check here if we want to hide .class files - dirList[index++] = m.getName(); + dirList[index++] = name; + } } if (index < dirList.length) System.arraycopy(dirList, 0, dirList = new String[index], 0, index); @@ -82,7 +118,6 @@ String[] directoryList(String qualifiedPackageName) { this.directoryCache.put(qualifiedPackageName, this.missingPackageHolder); return null; } - boolean doesFileExist(String fileName, String qualifiedPackageName, String qualifiedFullName) { String[] dirList = directoryList(qualifiedPackageName); if (dirList == null) return false; // most common case @@ -101,10 +136,12 @@ public boolean equals(Object o) { if (this.accessRuleSet != dir.accessRuleSet) if (this.accessRuleSet == null || !this.accessRuleSet.equals(dir.accessRuleSet)) return false; + if (this.module != dir.module) + if (this.module == null || !this.module.equals(dir.module)) + return false; return this.binaryFolder.equals(dir.binaryFolder); } - -public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName) { +public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { if (!doesFileExist(binaryFileName, qualifiedPackageName, qualifiedBinaryFileName)) return null; // most common case IBinaryType reader = null; @@ -118,6 +155,14 @@ public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPa return null; } if (reader != null) { + char[] modName = this.module == null ? null : this.module.name(); + if (reader instanceof ClassFileReader) { + ClassFileReader cfReader = (ClassFileReader) reader; + if (cfReader.moduleName == null) + cfReader.moduleName = modName; + else + modName = cfReader.moduleName; + } String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length); if (this.externalAnnotationPath != null) { try { @@ -132,8 +177,8 @@ public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPa } } if (this.accessRuleSet == null) - return new NameEnvironmentAnswer(reader, null); - return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray())); + return this.module == null ? new NameEnvironmentAnswer(reader, null) : new NameEnvironmentAnswer(reader, null, modName); + return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()), modName); } return null; } @@ -154,9 +199,25 @@ public boolean isOutputFolder() { return this.isOutputFolder; } -public boolean isPackage(String qualifiedPackageName) { +public boolean isPackage(String qualifiedPackageName, String moduleName) { + if (moduleName != null) { + if (this.module == null || !moduleName.equals(String.valueOf(this.module.name()))) + return false; + } return directoryList(qualifiedPackageName) != null; } +@Override +public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) { + String[] dirList = directoryList(qualifiedPackageName); + if (dirList != null) { + for (String entry : dirList) { + String entryLC = entry.toLowerCase(); + if (entryLC.endsWith(SuffixConstants.SUFFIX_STRING_class) || entryLC.endsWith(SuffixConstants.SUFFIX_STRING_java)) + return true; + } + } + return false; +} public void reset() { this.directoryCache = new SimpleLookupTable(5); @@ -173,5 +234,10 @@ public String debugPathString() { return this.binaryFolder.getFullPath().toString(); } +@Override +public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName) { + // + return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false); +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java new file mode 100644 index 0000000000..570a529c35 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.builder; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.zip.ZipEntry; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator; +import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; +import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.util.SimpleSet; +import org.eclipse.jdt.internal.compiler.util.SuffixConstants; + +public class ClasspathJMod extends ClasspathJar { + + public static char[] CLASSES = "classes".toCharArray(); //$NON-NLS-1$ + public static char[] CLASSES_FOLDER = "classes/".toCharArray(); //$NON-NLS-1$ + private static int MODULE_DESCRIPTOR_NAME_LENGTH = IModule.MODULE_INFO_CLASS.length(); + + ClasspathJMod(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) { + super(zipFilename, lastModified, accessRuleSet, externalAnnotationPath, true); + } + + + public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case + + try { + qualifiedBinaryFileName = new String(CharOperation.append(CLASSES_FOLDER, qualifiedBinaryFileName.toCharArray())); + IBinaryType reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName); + if (reader != null) { + char[] modName = this.module == null ? null : this.module.name(); + if (reader instanceof ClassFileReader) { + ClassFileReader classReader = (ClassFileReader) reader; + if (classReader.moduleName == null) + classReader.moduleName = modName; + else + modName = classReader.moduleName; + } + String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length); + if (this.externalAnnotationPath != null) { + try { + if (this.annotationZipFile == null) { + this.annotationZipFile = ExternalAnnotationDecorator + .getAnnotationZipFile(this.externalAnnotationPath, null); + } + + reader = ExternalAnnotationDecorator.create(reader, this.externalAnnotationPath, + fileNameWithoutExtension, this.annotationZipFile); + } catch (IOException e) { + // don't let error on annotations fail class reading + } + } + if (this.accessRuleSet == null) + return new NameEnvironmentAnswer(reader, null, modName); + return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()), modName); + } + } catch (IOException e) { // treat as if class file is missing + } catch (ClassFormatException e) { // treat as if class file is missing + } + return null; + } + protected String readJarContent(final SimpleSet packageSet) { + String modInfo = null; + for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { + ZipEntry entry = e.nextElement(); + char[] entryName = entry.getName().toCharArray(); + int index = CharOperation.indexOf('/', entryName); + if (index != -1) { + char[] folder = CharOperation.subarray(entryName, 0, index); + if (CharOperation.equals(CLASSES, folder)) { + char[] fileName = CharOperation.subarray(entryName, index + 1, entryName.length); + if (modInfo == null && fileName.length == MODULE_DESCRIPTOR_NAME_LENGTH) { + if (CharOperation.equals(fileName, IModule.MODULE_INFO_CLASS.toCharArray())) { + modInfo = new String(entryName); + } + } + addToPackageSet(packageSet, new String(fileName), false); + } + } + } + return modInfo; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java index 20fe32ff3b..210c43ce41 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.util.Date; import java.util.Enumeration; +import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -28,8 +29,10 @@ import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; import org.eclipse.jdt.internal.compiler.util.SimpleSet; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; @@ -50,41 +53,75 @@ static class PackageCacheEntry { } } -static SimpleLookupTable PackageCache = new SimpleLookupTable(); +protected static SimpleLookupTable PackageCache = new SimpleLookupTable(); +protected static SimpleLookupTable ModuleCache = new SimpleLookupTable(); + +protected static void addToPackageSet(SimpleSet packageSet, String fileName, boolean endsWithSep) { + int last = endsWithSep ? fileName.length() : fileName.lastIndexOf('/'); + while (last > 0) { + // extract the package name + String packageName = fileName.substring(0, last); + if (packageSet.addIfNotIncluded(packageName) == null) + return; // already existed + last = packageName.lastIndexOf('/'); + } +} /** * Calculate and cache the package list available in the zipFile. - * @param jar The ClasspathJar to use * @return A SimpleSet with the all the package names in the zipFile. */ -static SimpleSet findPackageSet(ClasspathJar jar) { - String zipFileName = jar.zipFilename; - long lastModified = jar.lastModified(); - long fileSize = new File(zipFileName).length(); +protected SimpleSet findPackageSet() { + String zipFileName = this.zipFilename; PackageCacheEntry cacheEntry = (PackageCacheEntry) PackageCache.get(zipFileName); - if (cacheEntry != null && cacheEntry.lastModified == lastModified && cacheEntry.fileSize == fileSize) + long timestamp = this.lastModified(); + long fileSize = new File(zipFileName).length(); + if (cacheEntry != null && cacheEntry.lastModified == timestamp && cacheEntry.fileSize == fileSize) { return cacheEntry.packageSet; - - SimpleSet packageSet = new SimpleSet(41); + } + final SimpleSet packageSet = new SimpleSet(41); packageSet.add(""); //$NON-NLS-1$ - nextEntry : for (Enumeration e = jar.zipFile.entries(); e.hasMoreElements(); ) { + readJarContent(packageSet); + PackageCache.put(zipFileName, new PackageCacheEntry(timestamp, fileSize, packageSet)); + return packageSet; +} +protected String readJarContent(final SimpleSet packageSet) { + String modInfo = null; + for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { String fileName = ((ZipEntry) e.nextElement()).getName(); - - // add the package name & all of its parent packages - int last = fileName.lastIndexOf('/'); - while (last > 0) { - // extract the package name - String packageName = fileName.substring(0, last); - if (packageSet.addIfNotIncluded(packageName) == null) - continue nextEntry; // already existed - last = packageName.lastIndexOf('/'); + if (modInfo == null) { + int folderEnd = fileName.lastIndexOf('/'); + folderEnd += 1; + String className = fileName.substring(folderEnd, fileName.length()); + if (className.equalsIgnoreCase(IModule.MODULE_INFO_CLASS)) { + modInfo = fileName; + } } + addToPackageSet(packageSet, fileName, false); } - - PackageCache.put(zipFileName, new PackageCacheEntry(lastModified, fileSize, packageSet)); - return packageSet; + return modInfo; +} +IModule initializeModule() { + IModule mod = null; + ZipFile file = null; + try { + file = new ZipFile(this.zipFilename); + ClassFileReader classfile = ClassFileReader.read(file, IModule.MODULE_INFO_CLASS); // FIXME: use jar cache + if (classfile != null) { + mod = classfile.getModuleDeclaration(); + } + } catch (ClassFormatException | IOException e) { + // do nothing + } finally { + try { + if (file != null) + file.close(); + } catch (IOException e) { + // do nothing + } + } + return mod; } - String zipFilename; // keep for equals IFile resource; @@ -92,11 +129,11 @@ static SimpleSet findPackageSet(ClasspathJar jar) { ZipFile annotationZipFile; long lastModified; boolean closeZipFileAtEnd; -SimpleSet knownPackageNames; +private SimpleSet knownPackageNames; AccessRuleSet accessRuleSet; String externalAnnotationPath; -ClasspathJar(IFile resource, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) { +ClasspathJar(IFile resource, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath) { this.resource = resource; try { java.net.URI location = resource.getLocationURI(); @@ -114,9 +151,10 @@ static SimpleSet findPackageSet(ClasspathJar jar) { this.accessRuleSet = accessRuleSet; if (externalAnnotationPath != null) this.externalAnnotationPath = externalAnnotationPath.toString(); + this.isOnModulePath = isOnModulePath; } -ClasspathJar(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) { +ClasspathJar(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath) { this.zipFilename = zipFilename; this.lastModified = lastModified; this.zipFile = null; @@ -124,14 +162,17 @@ static SimpleSet findPackageSet(ClasspathJar jar) { this.accessRuleSet = accessRuleSet; if (externalAnnotationPath != null) this.externalAnnotationPath = externalAnnotationPath.toString(); + this.isOnModulePath = isOnModulePath; } -public ClasspathJar(ZipFile zipFile, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) { - this.zipFilename = zipFile.getName(); +public ClasspathJar(ZipFile zipFile, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath) { + this(zipFile.getName(), accessRuleSet, externalAnnotationPath, isOnModulePath); this.zipFile = zipFile; - this.closeZipFileAtEnd = false; - this.knownPackageNames = null; - this.accessRuleSet = accessRuleSet; + this.closeZipFileAtEnd = true; +} + +public ClasspathJar(String fileName, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath) { + this(fileName, 0, accessRuleSet, externalAnnotationPath, isOnModulePath); if (externalAnnotationPath != null) this.externalAnnotationPath = externalAnnotationPath.toString(); } @@ -153,26 +194,36 @@ public void cleanup() { this.annotationZipFile = null; } } + this.module = null; // TODO(SHMOD): is this safe? this.knownPackageNames = null; } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof ClasspathJar)) return false; - ClasspathJar jar = (ClasspathJar) o; if (this.accessRuleSet != jar.accessRuleSet) if (this.accessRuleSet == null || !this.accessRuleSet.equals(jar.accessRuleSet)) return false; - return this.zipFilename.equals(jar.zipFilename) && lastModified() == jar.lastModified(); + return this.zipFilename.equals(jar.zipFilename) + && lastModified() == jar.lastModified() + && this.isOnModulePath == jar.isOnModulePath; } -public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName) { - if (!isPackage(qualifiedPackageName)) return null; // most common case +public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case try { IBinaryType reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName); if (reader != null) { + char[] modName = this.module == null ? null : this.module.name(); + if (reader instanceof ClassFileReader) { + ClassFileReader classReader = (ClassFileReader) reader; + if (classReader.moduleName == null) + classReader.moduleName = modName; + else + modName = classReader.moduleName; + } String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length); if (this.externalAnnotationPath != null) { try { @@ -192,8 +243,10 @@ public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPa } } if (this.accessRuleSet == null) - return new NameEnvironmentAnswer(reader, null); - return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray())); + return new NameEnvironmentAnswer(reader, null, modName); + return new NameEnvironmentAnswer(reader, + this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()), + modName); } } catch (IOException e) { // treat as if class file is missing } catch (ClassFormatException e) { // treat as if class file is missing @@ -210,10 +263,27 @@ public int hashCode() { return this.zipFilename == null ? super.hashCode() : this.zipFilename.hashCode(); } -public boolean isPackage(String qualifiedPackageName) { - if (this.knownPackageNames != null) - return this.knownPackageNames.includes(qualifiedPackageName); +public boolean isPackage(String qualifiedPackageName, String moduleName) { + if (moduleName != null) { + if (this.module == null || !moduleName.equals(String.valueOf(this.module.name()))) + return false; + } + if (this.knownPackageNames == null) + scanContent(); + return this.knownPackageNames.includes(qualifiedPackageName); +} +@Override +public boolean hasCompilationUnit(String pkgName, String moduleName) { + for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { + String fileName = e.nextElement().getName(); + if (fileName.startsWith(pkgName) && fileName.toLowerCase().endsWith(SuffixConstants.SUFFIX_STRING_class)) + return true; + } + return false; +} +/** Scan the contained packages and try to locate the module descriptor. */ +private void scanContent() { try { if (this.zipFile == null) { if (org.eclipse.jdt.internal.core.JavaModelManager.ZIP_ACCESS_VERBOSE) { @@ -221,12 +291,13 @@ public boolean isPackage(String qualifiedPackageName) { } this.zipFile = new ZipFile(this.zipFilename); this.closeZipFileAtEnd = true; + this.knownPackageNames = findPackageSet(); + } else { + this.knownPackageNames = findPackageSet(); } - this.knownPackageNames = findPackageSet(this); } catch(Exception e) { this.knownPackageNames = new SimpleSet(); // assume for this build the zipFile is empty } - return this.knownPackageNames.includes(qualifiedPackageName); } public long lastModified() { @@ -249,4 +320,27 @@ public String debugPathString() { return this.zipFilename + '(' + (new Date(time)) + " : " + time + ')'; //$NON-NLS-1$ } +@Override +public IModule getModule() { + if (this.knownPackageNames == null) + scanContent(); + return this.module; +} + +@Override +public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName) { + // + return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false); +} +public Manifest getManifest() { + scanContent(); // ensure zipFile is initialized + ZipEntry entry = this.zipFile.getEntry(TypeConstants.META_INF_MANIFEST_MF); + try { + if (entry != null) + return new Manifest(this.zipFile.getInputStream(entry)); + } catch (IOException e) { + // cannot use manifest + } + return null; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java new file mode 100644 index 0000000000..6e804e657a --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java @@ -0,0 +1,303 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.builder; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.zip.ZipFile; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator; +import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference; +import org.eclipse.jdt.internal.compiler.env.IMultiModuleEntry; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; +import org.eclipse.jdt.internal.compiler.util.SimpleSet; +import org.eclipse.jdt.internal.compiler.util.SuffixConstants; +import org.eclipse.jdt.internal.core.JavaProject; + +public class ClasspathJrt extends ClasspathLocation implements IMultiModuleEntry { + +//private HashMap packagesInModule = null; +private static HashMap> PackageCache = new HashMap<>(); +private static HashMap> ModulesCache = new HashMap<>(); +private String externalAnnotationPath; +private ZipFile annotationZipFile; +String zipFilename; // keep for equals + +public ClasspathJrt(String zipFilename, IPath externalAnnotationPath) { + this.zipFilename = zipFilename; + if (externalAnnotationPath != null) + this.externalAnnotationPath = externalAnnotationPath.toString(); + loadModules(this); +} +/** + * Calculate and cache the package list available in the zipFile. + * @param jrt The ClasspathJar to use + * @return A SimpleSet with the all the package names in the zipFile. + */ +static HashMap findPackagesInModules(final ClasspathJrt jrt) { + String zipFileName = jrt.zipFilename; + HashMap cache = PackageCache.get(zipFileName); + if (cache != null) { + return cache; + } + final HashMap packagesInModule = new HashMap<>(); + PackageCache.put(zipFileName, packagesInModule); + try { + final File imageFile = new File(zipFileName); + org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile, + new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor() { + SimpleSet packageSet = null; + @Override + public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs) throws IOException { + ClasspathJar.addToPackageSet(this.packageSet, dir.toString(), true); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, Path mod, BasicFileAttributes attrs) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitModule(Path mod) throws IOException { + String name = mod.toString(); + try { + jrt.acceptModule(JRTUtil.getClassfileContent(imageFile, IModule.MODULE_INFO_CLASS, name)); + } catch (ClassFormatException e) { + e.printStackTrace(); + } + this.packageSet = new SimpleSet(41); + this.packageSet.add(""); //$NON-NLS-1$ + packagesInModule.put(name, this.packageSet); + return FileVisitResult.CONTINUE; + } + }, JRTUtil.NOTIFY_PACKAGES | JRTUtil.NOTIFY_MODULES); + } catch (IOException e) { + // TODO: Java 9 Should report better + } + return packagesInModule; +} + +public static void loadModules(final ClasspathJrt jrt) { + String zipFileName = jrt.zipFilename; + Set cache = ModulesCache.get(zipFileName); + + if (cache == null) { + try { + final File imageFile = new File(zipFileName); + org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile, + new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor() { + SimpleSet packageSet = null; + + @Override + public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs) + throws IOException { + ClasspathJar.addToPackageSet(this.packageSet, dir.toString(), true); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, Path mod, BasicFileAttributes attrs) + throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitModule(Path mod) throws IOException { + try { + jrt.acceptModule(JRTUtil.getClassfileContent(imageFile, IModule.MODULE_INFO_CLASS, mod.toString())); + } catch (ClassFormatException e) { + e.printStackTrace(); + } + return FileVisitResult.SKIP_SUBTREE; + } + }, JRTUtil.NOTIFY_MODULES); + } catch (IOException e) { + // TODO: Java 9 Should report better + } + } else { +// for (IModuleDeclaration iModule : cache) { +// jimage.env.acceptModule(iModule, jimage); +// } + } +} +void acceptModule(byte[] content) { + if (content == null) + return; + ClassFileReader reader = null; + try { + reader = new ClassFileReader(content, IModule.MODULE_INFO_CLASS.toCharArray()); + } catch (ClassFormatException e) { + e.printStackTrace(); + } + if (reader != null) { + IModule moduleDecl = reader.getModuleDeclaration(); + if (moduleDecl != null) { + Set cache = ModulesCache.get(this.zipFilename); + if (cache == null) { + ModulesCache.put(this.zipFilename, cache = new HashSet()); + } + cache.add(moduleDecl); + } + } +} +public void cleanup() { + if (this.annotationZipFile != null) { + try { + this.annotationZipFile.close(); + } catch(IOException e) { // ignore it + } + this.annotationZipFile = null; + } +} + +public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ClasspathJrt)) return false; + ClasspathJrt jar = (ClasspathJrt) o; + return this.zipFilename.endsWith(jar.zipFilename); +} + +@Override +public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case + + try { + IBinaryType reader = ClassFileReader.readFromModule(new File(this.zipFilename), moduleName, qualifiedBinaryFileName); + if (reader != null) { + if (this.externalAnnotationPath != null) { + String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length); + try { + if (this.annotationZipFile == null) { + this.annotationZipFile = ExternalAnnotationDecorator.getAnnotationZipFile(this.externalAnnotationPath, null); + } + reader = ExternalAnnotationDecorator.create(reader, this.externalAnnotationPath, fileNameWithoutExtension, this.annotationZipFile); + } catch (IOException e) { + // don't let error on annotations fail class reading + } + } + return new NameEnvironmentAnswer(reader, null, reader.getModule()); + } + } catch (IOException e) { // treat as if class file is missing + } catch (ClassFormatException e) { // treat as if class file is missing + } + return null; +} + +public IPath getProjectRelativePath() { + return null; +} + +public int hashCode() { + return this.zipFilename == null ? super.hashCode() : this.zipFilename.hashCode(); +} +@Override +public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) { + List moduleNames = JRTUtil.getModulesDeclaringPackage(new File(this.zipFilename), qualifiedPackageName, moduleName); + return CharOperation.toCharArrays(moduleNames); +} +@Override +public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) { + return JRTUtil.hasCompilationUnit(new File(this.zipFilename), qualifiedPackageName, moduleName); +} +@Override +public boolean isPackage(String qualifiedPackageName, String moduleName) { + return JRTUtil.getModulesDeclaringPackage(new File(this.zipFilename), qualifiedPackageName, moduleName) != null; +} + +public String toString() { + String start = "Classpath jrt file " + this.zipFilename; //$NON-NLS-1$ + return start; +} + +public String debugPathString() { + return this.zipFilename; +} +public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + String fileName = new String(typeName); + return findClass(fileName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, asBinaryOnly); +} +@Override +public boolean hasModule() { + return true; +} +@Override +public IModule getModule(char[] moduleName) { + Set modules = ModulesCache.get(this.zipFilename); + if (modules != null) { + for (IModule mod : modules) { + if (CharOperation.equals(mod.name(), moduleName)) + return mod; + } + } + return null; +} +@Override +public Collection getModuleNames(Collection limitModules) { + HashMap cache = findPackagesInModules(this); + if (cache != null) + return selectModules(cache.keySet(), limitModules); + return Collections.emptyList(); +} + +private Collection selectModules(Set keySet, Collection limitModules) { + Collection rootModules; + if (limitModules != null) { + Set result = new HashSet<>(keySet); + result.retainAll(limitModules); + rootModules = result; + } else { + rootModules = JavaProject.internalDefaultRootModules(keySet, s -> s, m -> getModule(m.toCharArray())); + } + Set allModules = new HashSet<>(rootModules); + for (String mod : rootModules) + addRequired(mod, allModules); + return allModules; +} + +private void addRequired(String mod, Set allModules) { + IModule iMod = getModule(mod.toCharArray()); + for (IModuleReference requiredRef : iMod.requires()) { + IModule reqMod = getModule(requiredRef.name()); + if (reqMod != null) { + String reqModName = String.valueOf(reqMod.name()); + if (allModules.add(reqModName)) + addRequired(reqModName, allModules); + } + } +} +@Override +public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName) { + // + return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false); +} +/** TEST ONLY */ +public static void resetCaches() { + PackageCache.clear(); + ModulesCache.clear(); +} +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java index 8758a86628..938151fd31 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,35 +12,70 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core.builder; -import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.*; - +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.util.Util; public abstract class ClasspathLocation { -static ClasspathLocation forSourceFolder(IContainer sourceFolder, IContainer outputFolder, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) { - return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns, ignoreOptionalProblems); -} + protected boolean isOnModulePath; + protected IModule module; + // In the following signatures, passing a null moduleName signals "don't care": + abstract public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName); + abstract public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly); + abstract public boolean isPackage(String qualifiedPackageName, String moduleName); + public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) { + return singletonModuleNameIf(isPackage(qualifiedPackageName, moduleName)); + } + public boolean hasModule() { return getModule() != null; } + abstract public boolean hasCompilationUnit(String pkgName, String moduleName); -public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) { - return new ClasspathDirectory(binaryFolder, isOutputFolder, accessRuleSet, externalAnnotationPath); + public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { + String fileName = new String(typeName); + return findClass(fileName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, asBinaryOnly); + } + public void setModule (IModule mod) { + this.module = mod; + } + public IModule getModule() { + return this.module; + } + static ClasspathLocation forSourceFolder(IContainer sourceFolder, IContainer outputFolder, + char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) { + return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns, + ignoreOptionalProblems); + } +public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean autoModule) { + return new ClasspathDirectory(binaryFolder, isOutputFolder, accessRuleSet, externalAnnotationPath, autoModule); } -static ClasspathLocation forLibrary(String libraryPathname, long lastModified, AccessRuleSet accessRuleSet, IPath annotationsPath) { - return new ClasspathJar(libraryPathname, lastModified, accessRuleSet, annotationsPath); -} +static ClasspathLocation forLibrary(String libraryPathname, + long lastModified, + AccessRuleSet accessRuleSet, + IPath annotationsPath, + boolean autoModule) { + return Util.isJrt(libraryPathname) ? + new ClasspathJrt(libraryPathname, annotationsPath) : + Util.archiveFormat(libraryPathname) == Util.JMOD_FILE ? + new ClasspathJMod(libraryPathname, lastModified, accessRuleSet, annotationsPath) : + new ClasspathJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, autoModule); -static ClasspathLocation forLibrary(String libraryPathname, AccessRuleSet accessRuleSet, IPath annotationsPath) { - return forLibrary(libraryPathname, 0, accessRuleSet, annotationsPath); } -static ClasspathLocation forLibrary(IFile library, AccessRuleSet accessRuleSet, IPath annotationsPath) { - return new ClasspathJar(library, accessRuleSet, annotationsPath); +public static ClasspathLocation forLibrary(String libraryPathname, AccessRuleSet accessRuleSet, IPath annotationsPath, + boolean autoModule) { + return forLibrary(libraryPathname, 0, accessRuleSet, annotationsPath, autoModule); } -public abstract NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName); +static ClasspathLocation forLibrary(IFile library, AccessRuleSet accessRuleSet, IPath annotationsPath, + boolean autoModule) { + return new ClasspathJar(library, accessRuleSet, annotationsPath, autoModule); +} public abstract IPath getProjectRelativePath(); @@ -48,8 +83,6 @@ public boolean isOutputFolder() { return false; } -public abstract boolean isPackage(String qualifiedPackageName); - public void cleanup() { // free anything which is not required when the state is saved } @@ -59,4 +92,11 @@ public void reset() { public abstract String debugPathString(); +public char[][] singletonModuleNameIf(boolean condition) { + if (!condition) + return null; + if (this.module != null) + return new char[][] { this.module.name() }; + return new char[][] { ModuleBinding.UNNAMED }; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java index 991e98ec68..70165db3b7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java @@ -11,8 +11,13 @@ package org.eclipse.jdt.internal.core.builder; import org.eclipse.core.resources.*; - import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.batch.BasicModule; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.core.util.Util; public class ClasspathMultiDirectory extends ClasspathDirectory { @@ -24,7 +29,7 @@ public class ClasspathMultiDirectory extends ClasspathDirectory { public boolean ignoreOptionalProblems; ClasspathMultiDirectory(IContainer sourceFolder, IContainer binaryFolder, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) { - super(binaryFolder, true, null, null); + super(binaryFolder, true, null, null, false /* source never an automatic module*/); this.sourceFolder = sourceFolder; this.inclusionPatterns = inclusionPatterns; @@ -44,6 +49,10 @@ public boolean equals(Object o) { if (!(o instanceof ClasspathMultiDirectory)) return false; ClasspathMultiDirectory md = (ClasspathMultiDirectory) o; + // TODO: revisit this - is this really required?? +// if (this.module != md.module) +// if (this.module == null || !this.module.equals(md.module)) +// return false; return this.ignoreOptionalProblems == md.ignoreOptionalProblems && this.sourceFolder.equals(md.sourceFolder) && this.binaryFolder.equals(md.binaryFolder) && CharOperation.equals(this.inclusionPatterns, md.inclusionPatterns) @@ -61,4 +70,21 @@ public String toString() { return "Source classpath directory " + this.sourceFolder.getFullPath().toString() + //$NON-NLS-1$ " with " + super.toString(); //$NON-NLS-1$ } + +public void acceptModuleInfo(ICompilationUnit cu, Parser parser) { + CompilationResult compilationResult = new CompilationResult(cu, 0, 1, 10); + CompilationUnitDeclaration unit = parser.parse(cu, compilationResult); + // Request could also come in when module-info has changed or removed. + if (unit.isModuleInfo() && unit.moduleDeclaration != null) { + this.module = new BasicModule(unit.moduleDeclaration, null); + } +} +public void setModule(IModule mod) { + this.module = mod; +} + +public IModule module() { + return this.module; +} + } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java index 9238ba1dd5..fe4be3052e 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,6 +19,7 @@ import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.*; import org.eclipse.jdt.internal.compiler.classfmt.*; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.problem.*; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; @@ -84,7 +85,7 @@ public boolean build(SimpleLookupTable deltas) { this.notifier.subTask(Messages.build_analyzingDeltas); if (this.javaBuilder.hasBuildpathErrors()) { - // if a mssing class file was detected in the last build, a build state was saved since its no longer fatal + // if a missing class file was detected in the last build, a build state was saved since its no longer fatal // but we need to rebuild every source file since problems were not recorded // AND to avoid the infinite build scenario if this project is involved in a cycle, see bug 160550 // we need to avoid unnecessary deltas caused by doing a full build in this case @@ -420,7 +421,7 @@ protected void findAffectedSourceFiles(IResourceDelta binaryDelta, int segmentCo System.out.println("Skipped dependents of added package " + packageName); //$NON-NLS-1$ } else { // see if the package still exists on the classpath - if (!this.nameEnvironment.isPackage(packageName)) { + if (!this.nameEnvironment.isPackage(packageName, ModuleBinding.ANY)) { if (JavaBuilder.DEBUG) System.out.println("Found removed package " + packageName); //$NON-NLS-1$ addDependentsOf(packagePath, false); @@ -646,7 +647,8 @@ protected boolean findSourceFiles(IResourceDelta sourceDelta, ClasspathMultiDire return true; // skip it since it really isn't changed if (JavaBuilder.DEBUG) System.out.println("Compile this changed source file " + typeLocator); //$NON-NLS-1$ - this.sourceFiles.add(new SourceFile((IFile) resource, md, true)); + SourceFile unit = new SourceFile((IFile) resource, md, true); + this.sourceFiles.add(unit); } return true; } else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(resourceName)) { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleEntryProcessor.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleEntryProcessor.java new file mode 100644 index 0000000000..6005fdd130 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleEntryProcessor.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.builder; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jdt.core.IClasspathAttribute; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModulePathEntry; +import org.eclipse.jdt.internal.core.ClasspathEntry; +import org.eclipse.jdt.internal.core.ModuleUpdater; + +/** + * Collection of functions to process classpath attributes relating to modules (from JEP 261). + * For add-exports and add-reads see {@link ModuleUpdater}. + */ +class ModuleEntryProcessor { + + // ------------- patch-module: --------------- + + /** + * Establish that an entry with patch-module appears at position 0, if any. + * This ensures that in the first iteration we find the patchedModule (see e.g., collectModuleEntries()), + * which later can be combined into each src-entry (see {@link #combinePatchIntoModuleEntry(ClasspathLocation, IModule, Map)}). + * @see IClasspathAttribute#PATCH_MODULE + */ + static String pushPatchToFront(IClasspathEntry[] classpathEntries) { + String patchedModule = null; + for (int i = 0; i < classpathEntries.length; i++) { + IClasspathEntry entry = classpathEntries[i]; + patchedModule = ClasspathEntry.getExtraAttribute(entry, IClasspathAttribute.PATCH_MODULE); + if (patchedModule != null) { + if (i > 0) { + IClasspathEntry tmp = classpathEntries[0]; + classpathEntries[0] = entry; + classpathEntries[i] = tmp; + } + return patchedModule; + } + } + return null; + } + + /** + * Given that sourceLocation belongs to the project that patches another module, combine this source location + * into the existing {@link IModulePathEntry} for the module to be patched. + * @param sourceLocation source location of the patch project + * @param patchedModule module defined in the target location + * @param moduleEntries map of known module locations + */ + static void combinePatchIntoModuleEntry(ClasspathLocation sourceLocation, IModule patchedModule, Map moduleEntries) { + sourceLocation.setModule(patchedModule); + String patchedModuleName = String.valueOf(patchedModule.name()); + IModulePathEntry mainEntry = moduleEntries.get(patchedModuleName); + ClasspathLocation[] combinedLocations = null; + if (mainEntry instanceof ModulePathEntry.Multi) { + ((ModulePathEntry.Multi) mainEntry).addPatchLocation(sourceLocation); + return; + } else if (mainEntry instanceof ClasspathJrt) { + combinedLocations = new ClasspathLocation[] { (ClasspathLocation) mainEntry, sourceLocation }; + moduleEntries.put(patchedModuleName, new ModulePathEntry.Multi(null, patchedModule, combinedLocations)); + return; + } else if (mainEntry instanceof ModulePathEntry) { + ClasspathLocation[] mainLocs = ((ModulePathEntry) mainEntry).locations; + combinedLocations = Arrays.copyOf(mainLocs, mainLocs.length+1); + combinedLocations[combinedLocations.length-1] = sourceLocation; + } else if (mainEntry instanceof ClasspathLocation) { + combinedLocations = new ClasspathLocation[] { (ClasspathLocation) mainEntry, sourceLocation }; + } else { + throw new IllegalStateException("Cannot patch the module of classpath entry "+mainEntry); //$NON-NLS-1$ + } + moduleEntries.put(patchedModuleName, new ModulePathEntry(null, patchedModule, combinedLocations)); + } + + // ------------- limit-modules: --------------- + + /** + * Reads a limit-modules attribute + * @param entry the classpath entry to process + * @return a set of module names or null if the classpath attribute was not set. + * @see IClasspathAttribute#LIMIT_MODULES + */ + static Set computeLimitModules(ClasspathEntry entry) { + String extraAttribute = ClasspathEntry.getExtraAttribute(entry, IClasspathAttribute.LIMIT_MODULES); + if (extraAttribute == null) + return null; + + // collect the transitive closure of modules contained in limitSet + return new HashSet<>(Arrays.asList(extraAttribute.split(","))); //$NON-NLS-1$ + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleInfoBuilder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleInfoBuilder.java new file mode 100644 index 0000000000..1caca591b7 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleInfoBuilder.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2017 GK Software AG, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stephan Herrmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.builder; + +import java.util.Locale; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaModelStatusConstants; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModuleDescription; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.util.IAttributeNamesConstants; +import org.eclipse.jdt.internal.compiler.ClassFile; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.Compiler; +import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; +import org.eclipse.jdt.internal.compiler.ICompilerRequestor; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray; +import org.eclipse.jdt.internal.core.JavaModelStatus; +import org.eclipse.jdt.internal.core.ModuleUpdater; + +/** Implementation of {@link org.eclipse.jdt.core.JavaCore#compileWithAttributes(IModuleDescription, Map)}. */ +public class ModuleInfoBuilder { + + static class BytecodeCollector implements ICompilerRequestor { + byte[] bytes; + + @Override + public void acceptResult(CompilationResult result) { + assert this.bytes == null : "duplicate result"; //$NON-NLS-1$ + ClassFile[] classFiles = result.getClassFiles(); + assert classFiles.length == 1; + this.bytes = classFiles[0].getBytes(); + } + } + + public byte[] compileWithAttributes(IModuleDescription module, Map classFileAttributes) throws JavaModelException { + IJavaProject javaProject = module.getJavaProject(); + NameEnvironment nameEnvironment = new NameEnvironment(javaProject); + + addModuleUpdates(module, nameEnvironment.moduleUpdater, classFileAttributes); + + ClasspathMultiDirectory sourceLocation = getSourceLocation(javaProject, nameEnvironment, module); + IFile file = (IFile) module.getCompilationUnit().getCorrespondingResource(); + ICompilationUnit[] sourceUnits = { new SourceFile(file, sourceLocation) }; + BytecodeCollector collector = new BytecodeCollector(); + Compiler newCompiler = new Compiler( + nameEnvironment, + DefaultErrorHandlingPolicies.exitOnFirstError(), + new CompilerOptions(javaProject.getOptions(true)), + collector, + ProblemFactory.getProblemFactory(Locale.getDefault())); + newCompiler.compile(sourceUnits); + return collector.bytes; + } + + private void addModuleUpdates(IModuleDescription module, ModuleUpdater moduleUpdater, Map classFileAttributes) { + String mainClassName = classFileAttributes.remove(String.valueOf(IAttributeNamesConstants.MODULE_MAIN_CLASS)); + if (mainClassName != null) { + moduleUpdater.addModuleUpdate(module.getElementName(), m -> m.setMainClassName(mainClassName.toCharArray()), UpdateKind.MODULE); + } + String modulePackageNames = classFileAttributes.remove(String.valueOf(IAttributeNamesConstants.MODULE_PACKAGES)); + if (modulePackageNames != null) { + SimpleSetOfCharArray namesSet = new SimpleSetOfCharArray(); + String[] providedNames = modulePackageNames.split(","); //$NON-NLS-1$ + for (int i = 0; i < providedNames.length; i++) { + namesSet.add(providedNames[i].trim().toCharArray()); + } + moduleUpdater.addModuleUpdate(module.getElementName(), m -> m.setPackageNames(namesSet), UpdateKind.MODULE); + } + if (!classFileAttributes.isEmpty()) { + throw new IllegalArgumentException("Unsupported key(s): "+classFileAttributes.keySet().toString()); //$NON-NLS-1$ + } + } + + private ClasspathMultiDirectory getSourceLocation(IJavaProject javaProject, NameEnvironment nameEnvironment, IModuleDescription module) + throws JavaModelException { + IPackageFragmentRoot root = (IPackageFragmentRoot) module.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + IResource rootResource = root.getCorrespondingResource(); + for (ClasspathMultiDirectory sourceLocation : nameEnvironment.sourceLocations) { + if (sourceLocation.sourceFolder.equals(rootResource)) { + return sourceLocation; + } + } + throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH, module)); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java new file mode 100644 index 0000000000..c418cf4a01 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.builder; + + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModulePathEntry; +import org.eclipse.jdt.internal.compiler.env.IMultiModuleEntry; + +/** + * Represents a project on the module path. + */ +public class ModulePathEntry implements IModulePathEntry { + + private IPath path; + /*private*/ ClasspathLocation[] locations; + IModule module; + boolean isAutomaticModule; + + ModulePathEntry(IPath path, IModule module, ClasspathLocation[] locations) { + this.path = path; + this.locations = locations; + this.module = module; + this.isAutomaticModule = module.isAutomatic(); + initializeModule(); + } + public ModulePathEntry(IPath path, ClasspathLocation location) { + this.path = path; + initModule(location); + this.locations = new ClasspathLocation[] {location}; + } + public IPath getPath() { + return this.path; + } + public ClasspathLocation[] getClasspathLocations() { + return this.locations; + } + + @Override + public IModule getModule() { + // + return this.module; + } + + public boolean isAutomaticModule() { + return this.isAutomaticModule; + } + public static IModule getAutomaticModule(ClasspathLocation location) { + if (location instanceof ClasspathJar) { + ClasspathJar classpathJar = (ClasspathJar) location; + return IModule.createAutomatic(classpathJar.zipFilename, true, classpathJar.getManifest()); + } + if (location instanceof ClasspathDirectory) { + return IModule.createAutomatic(((ClasspathDirectory) location).binaryFolder.getName(), false, null); + } + return null; + } + private void initModule(ClasspathLocation location) { + IModule mod = null; + if (location instanceof ClasspathJar) { + mod = ((ClasspathJar) location).initializeModule(); + } else if (location instanceof ClasspathDirectory){ + mod = ((ClasspathDirectory) location).initializeModule(); + } + if (mod != null) { + this.module = mod; + this.isAutomaticModule = false; + } else { + this.module = getAutomaticModule(location); + this.isAutomaticModule = true; + } + location.setModule(this.module); + } + + // TODO: This is only needed because SourceFile.module() uses the module set on the location + // Once we have a mechanism to map a folder to a module path entry, this should no longer be + // needed + private void initializeModule() { + for (int i = 0; i < this.locations.length; i++) { + this.locations[i].setModule(this.module); + } + } + @Override + public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) { + if (moduleName != null && ((this.module == null) || !moduleName.equals(String.valueOf(this.module.name())))) + return null; + // search all locations + char[][] names = CharOperation.NO_CHAR_CHAR; + for (ClasspathLocation cp : this.locations) { + char[][] declaringModules = cp.getModulesDeclaringPackage(qualifiedPackageName, moduleName); + if (declaringModules != null) + names = CharOperation.arrayConcat(names, declaringModules); + } + return names == CharOperation.NO_CHAR_CHAR ? null : names; + } + @Override + public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) { + for (ClasspathLocation cp : this.locations) { + if (cp.hasCompilationUnit(qualifiedPackageName, moduleName)) + return true; + } + return false; + } + + /** + * Combines an IMultiModuleEntry with further locations in order to support patch-module. + * Implemented by adding IMultiModuleEntry functionality to ModulePathEntry. + */ + static public class Multi extends ModulePathEntry implements IMultiModuleEntry { + + Multi(IPath path, IModule module, ClasspathLocation[] locations) { + super(path, module, locations); + } + + void addPatchLocation(ClasspathLocation location) { + this.locations = Arrays.copyOf(this.locations, this.locations.length+1); + this.locations[this.locations.length-1] = location; + location.setModule(this.module); + } + + @Override + public IModule getModule(char[] name) { + for (ClasspathLocation loc : this.locations) { + if (loc instanceof IMultiModuleEntry) { + IModule mod = ((IMultiModuleEntry) loc).getModule(name); + if (mod != null) + return mod; + } else { + IModule mod = loc.getModule(); + if (CharOperation.equals(mod.name(), name)) + return mod; + } + } + return null; + } + + @Override + public Collection getModuleNames(Collection limitModules) { + Set result = new HashSet<>(); + for (ClasspathLocation loc : this.locations) { + if (loc instanceof IMultiModuleEntry) + result.addAll(((IMultiModuleEntry) loc).getModuleNames(limitModules)); + else + result.add(String.valueOf(loc.getModule().name())); + } + return result; + } + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java index a2f2fdc5bd..2fb5a883f1 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -22,26 +22,33 @@ import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.*; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; import org.eclipse.jdt.internal.compiler.util.SimpleSet; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; +import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.jdt.internal.core.*; import java.io.*; import java.util.*; +import java.util.stream.Collectors; @SuppressWarnings({"rawtypes", "unchecked"}) -public class NameEnvironment implements INameEnvironment, SuffixConstants { +public class NameEnvironment implements IModuleAwareNameEnvironment, SuffixConstants { boolean isIncrementalBuild; ClasspathMultiDirectory[] sourceLocations; ClasspathLocation[] binaryLocations; +Map modulePathEntries; // is null when performing a non-modular compilation BuildNotifier notifier; -SimpleSet initialTypeNames; // assumed that each name is of the form "a/b/ClassName" +SimpleSet initialTypeNames; // assumed that each name is of the form "a/b/ClassName", or, if a module is given: "my.mod:a/b/ClassName" SimpleLookupTable additionalUnits; +/** Tasks resulting from add-reads or add-exports classpath attributes. */ +ModuleUpdater moduleUpdater; NameEnvironment(IWorkspaceRoot root, JavaProject javaProject, SimpleLookupTable binaryLocationsPerProject, BuildNotifier notifier) throws CoreException { this.isIncrementalBuild = false; @@ -101,12 +108,38 @@ private void computeClasspathLocations( IClasspathEntry[] classpathEntries = javaProject.getExpandedClasspath(); ArrayList sLocations = new ArrayList(classpathEntries.length); ArrayList bLocations = new ArrayList(classpathEntries.length); + Map moduleEntries = null; + if (CompilerOptions.versionToJdkLevel(javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true)) >= ClassFileConstants.JDK9) { + moduleEntries = new HashMap<>(classpathEntries.length); + this.moduleUpdater = new ModuleUpdater(javaProject); + } + IModuleDescription mod = null; + + String patchedModuleName = ModuleEntryProcessor.pushPatchToFront(classpathEntries); + IModule patchedModule = null; + nextEntry : for (int i = 0, l = classpathEntries.length; i < l; i++) { + if (i == 1) { + if (patchedModuleName != null) { + // TODO(SHMOD) assert that patchModule has been assigned + patchedModuleName = null; // expire, applies to the first entry, only + } + } ClasspathEntry entry = (ClasspathEntry) classpathEntries[i]; IPath path = entry.getPath(); Object target = JavaModel.getTarget(path, true); IPath externalAnnotationPath = ClasspathEntry.getExternalAnnotationPath(entry, javaProject.getProject(), true); if (target == null) continue nextEntry; + boolean isOnModulePath = isOnModulePath(entry); + + Set limitModules = ModuleEntryProcessor.computeLimitModules(entry); + if (patchedModuleName != null && limitModules != null && !limitModules.contains(patchedModuleName)) { + // TODO(SHMOD) report an error + patchedModuleName = null; + } + + if (this.moduleUpdater != null) + this.moduleUpdater.computeModuleUpdates(entry); switch(entry.getEntryKind()) { case IClasspathEntry.CPE_SOURCE : @@ -122,8 +155,16 @@ private void computeClasspathLocations( if (!outputFolder.exists()) createOutputFolder(outputFolder); } - sLocations.add( - ClasspathLocation.forSourceFolder((IContainer) target, outputFolder, entry.fullInclusionPatternChars(), entry.fullExclusionPatternChars(), entry.ignoreOptionalProblems())); + ClasspathLocation sourceLocation = ClasspathLocation.forSourceFolder( + (IContainer) target, + outputFolder, + entry.fullInclusionPatternChars(), + entry.fullExclusionPatternChars(), + entry.ignoreOptionalProblems()); + if (patchedModule != null) { + ModuleEntryProcessor.combinePatchIntoModuleEntry(sourceLocation, patchedModule, moduleEntries); + } + sLocations.add(sourceLocation); continue nextEntry; case IClasspathEntry.CPE_PROJECT : @@ -134,6 +175,7 @@ private void computeClasspathLocations( JavaProject prereqJavaProject = (JavaProject) JavaCore.create(prereqProject); IClasspathEntry[] prereqClasspathEntries = prereqJavaProject.getRawClasspath(); ArrayList seen = new ArrayList(); + List projectLocations = new ArrayList(); nextPrereqEntry: for (int j = 0, m = prereqClasspathEntries.length; j < m; j++) { IClasspathEntry prereqEntry = prereqClasspathEntries[j]; if (prereqEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { @@ -147,8 +189,9 @@ private void computeClasspathLocations( : (IContainer) root.getFolder(prereqOutputPath); if (binaryFolder.exists() && !seen.contains(binaryFolder)) { seen.add(binaryFolder); - ClasspathLocation bLocation = ClasspathLocation.forBinaryFolder(binaryFolder, true, entry.getAccessRuleSet(), externalAnnotationPath); + ClasspathLocation bLocation = ClasspathLocation.forBinaryFolder(binaryFolder, true, entry.getAccessRuleSet(), externalAnnotationPath, isOnModulePath); bLocations.add(bLocation); + projectLocations.add(bLocation); if (binaryLocationsPerProject != null) { // normal builder mode ClasspathLocation[] existingLocations = (ClasspathLocation[]) binaryLocationsPerProject.get(prereqProject); if (existingLocations == null) { @@ -163,6 +206,27 @@ private void computeClasspathLocations( } } } + if (moduleEntries != null && isOnModulePath && projectLocations.size() > 0) { + IModule info = null; + try { + if ((mod = prereqJavaProject.getModuleDescription()) != null) { + SourceModule sourceModule = (SourceModule) mod; + info = (ModuleDescriptionInfo) sourceModule.getElementInfo(); + } + } catch (JavaModelException jme) { + // do nothing, probably a non module project + } + if (info == null) + info = IModule.createAutomatic(prereqJavaProject.getElementName(), false, prereqJavaProject.getManifest()); + ModulePathEntry projectEntry = new ModulePathEntry(prereqJavaProject.getPath(), info, + projectLocations.toArray(new ClasspathLocation[projectLocations.size()])); + String moduleName = String.valueOf(info.name()); + if (limitModules == null || limitModules.contains(moduleName)) { + moduleEntries.put(moduleName, projectEntry); + if (moduleName.equals(patchedModuleName)) + patchedModule = info; + } + } continue nextEntry; case IClasspathEntry.CPE_LIBRARY : @@ -175,16 +239,22 @@ private void computeClasspathLocations( && JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true))) ? null : entry.getAccessRuleSet(); - bLocation = ClasspathLocation.forLibrary((IFile) resource, accessRuleSet, externalAnnotationPath); + bLocation = ClasspathLocation.forLibrary((IFile) resource, accessRuleSet, externalAnnotationPath, isOnModulePath); } else if (resource instanceof IContainer) { AccessRuleSet accessRuleSet = (JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true)) && JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true))) ? null : entry.getAccessRuleSet(); - bLocation = ClasspathLocation.forBinaryFolder((IContainer) target, false, accessRuleSet, externalAnnotationPath); // is library folder not output folder + bLocation = ClasspathLocation.forBinaryFolder((IContainer) target, false, accessRuleSet, externalAnnotationPath, isOnModulePath); // is library folder not output folder } bLocations.add(bLocation); + // TODO: Ideally we need to do something like mapToModulePathEntry using the path and if it is indeed + // a module path entry, then add the corresponding entry here, but that would need the target platform + if (moduleEntries != null) { + patchedModule = collectModuleEntries(bLocation, path, isOnModulePath, + limitModules, patchedModuleName, patchedModule, moduleEntries); + } if (binaryLocationsPerProject != null) { // normal builder mode IProject p = resource.getProject(); // can be the project being built ClasspathLocation[] existingLocations = (ClasspathLocation[]) binaryLocationsPerProject.get(p); @@ -203,7 +273,12 @@ private void computeClasspathLocations( && JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true))) ? null : entry.getAccessRuleSet(); - bLocations.add(ClasspathLocation.forLibrary(path.toString(), accessRuleSet, externalAnnotationPath)); + ClasspathLocation bLocation = ClasspathLocation.forLibrary(path.toOSString(), accessRuleSet, externalAnnotationPath, isOnModulePath); + bLocations.add(bLocation); + if (moduleEntries != null) { + patchedModule = collectModuleEntries(bLocation, path, isOnModulePath, + limitModules, patchedModuleName, patchedModule, moduleEntries); + } } continue nextEntry; } @@ -214,7 +289,18 @@ private void computeClasspathLocations( this.sourceLocations = new ClasspathMultiDirectory[sLocations.size()]; if (!sLocations.isEmpty()) { sLocations.toArray(this.sourceLocations); - + if (moduleEntries != null && (mod = javaProject.getModuleDescription()) != null) { + try { + AbstractModule sourceModule = (AbstractModule)mod; + ModuleDescriptionInfo info = (ModuleDescriptionInfo) sourceModule.getElementInfo(); + ModulePathEntry projectEntry = new ModulePathEntry(javaProject.getPath(), info, this.sourceLocations); + if (!moduleEntries.containsKey(sourceModule.getElementName())) { // can be registered already, if patching + moduleEntries.put(sourceModule.getElementName(), projectEntry); + } + } catch (JavaModelException jme) { + // do nothing, probably a non module project + } + } // collect the output folders, skipping duplicates next : for (int i = 0, l = this.sourceLocations.length; i < l; i++) { ClasspathMultiDirectory md = this.sourceLocations[i]; @@ -242,6 +328,45 @@ private void computeClasspathLocations( this.binaryLocations[index++] = (ClasspathLocation) outputFolders.get(i); for (int i = 0, l = bLocations.size(); i < l; i++) this.binaryLocations[index++] = (ClasspathLocation) bLocations.get(i); + + if (moduleEntries != null && !moduleEntries.isEmpty()) + this.modulePathEntries = moduleEntries; +} + +/** Returns the patched module if that is served by the current (binary) location. */ +IModule collectModuleEntries(ClasspathLocation bLocation, IPath path, boolean isOnModulePath, Set limitModules, + String patchedModuleName, IModule patchedModule, Map moduleEntries) { + if (bLocation instanceof IMultiModuleEntry) { + IMultiModuleEntry binaryModulePathEntry = (IMultiModuleEntry) bLocation; + for (String moduleName : binaryModulePathEntry.getModuleNames(limitModules)) { + moduleEntries.put(moduleName, binaryModulePathEntry); + } + if (patchedModuleName != null) { + IModule module = binaryModulePathEntry.getModule(patchedModuleName.toCharArray()); + if (module != null) + return module; + // TODO(SHMOD): report problem: patchedModuleName didn't match a module from this location + } + } else if (isOnModulePath) { + IModulePathEntry binaryModulePathEntry = new ModulePathEntry(path, bLocation); + IModule module = binaryModulePathEntry.getModule(); + if (module != null) { + String moduleName = String.valueOf(module.name()); + if (limitModules == null || limitModules.contains(moduleName)) { + moduleEntries.put(moduleName, binaryModulePathEntry); + if (patchedModuleName != null) { + if (moduleName.equals(patchedModuleName)) + return module; + // TODO(SHMOD): report problem: patchedModuleName didn't match a module from this location + } + } + } + } + return patchedModule; +} + +protected boolean isOnModulePath(ClasspathEntry entry) { + return entry.isModular(); } public void cleanup() { @@ -251,6 +376,7 @@ public void cleanup() { this.sourceLocations[i].cleanup(); for (int i = 0, l = this.binaryLocations.length; i < l; i++) this.binaryLocations[i].cleanup(); + // assume modulePathEntries are cleaned-up via the corresponding source/binaryLocations } private void createOutputFolder(IContainer outputFolder) throws CoreException { @@ -270,11 +396,12 @@ private void createParentFolder(IContainer parent) throws CoreException { private static final char[] groovySuffixAsChars = ".groovy".toCharArray(); //$NON-NLS-1$ // GROOVY end -private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName) { +private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, LookupStrategy strategy, String moduleName) { if (this.notifier != null) this.notifier.checkCancelWithinCompiler(); - if (this.initialTypeNames != null && this.initialTypeNames.includes(qualifiedTypeName)) { + String moduleQualifiedName = moduleName != null ? moduleName+':'+qualifiedTypeName : qualifiedTypeName; + if (this.initialTypeNames != null && this.initialTypeNames.includes(moduleQualifiedName)) { if (this.isIncrementalBuild) // catch the case that a type inside a source file has been renamed but other class files are looking for it throw new AbortCompilation(true, new AbortIncrementalBuildException(qualifiedTypeName)); @@ -312,18 +439,29 @@ private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeNam } String qBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class; - String binaryFileName = qBinaryFileName; - String qPackageName = ""; //$NON-NLS-1$ - if (qualifiedTypeName.length() > typeName.length) { - int typeNameStart = qBinaryFileName.length() - typeName.length - 6; // size of ".class" - qPackageName = qBinaryFileName.substring(0, typeNameStart - 1); - binaryFileName = qBinaryFileName.substring(typeNameStart); + String qPackageName = (qualifiedTypeName.length() == typeName.length) ? Util.EMPTY_STRING : + qBinaryFileName.substring(0, qBinaryFileName.length() - typeName.length - 7); + char[] binaryFileName = CharOperation.concat(typeName, SUFFIX_class); + + ClasspathLocation[] relevantLocations; + if (moduleName != null && this.modulePathEntries != null) { + IModulePathEntry modulePathEntry = this.modulePathEntries.get(moduleName); + if (modulePathEntry instanceof ModulePathEntry) { + relevantLocations = ((ModulePathEntry) modulePathEntry).getClasspathLocations(); + } else if (modulePathEntry instanceof ClasspathLocation) { + return ((ClasspathLocation) modulePathEntry).findClass(typeName, qPackageName, moduleName, qBinaryFileName, false); + } else { + return null; + } + } else { + relevantLocations = this.binaryLocations; } - - // NOTE: the output folders are added at the beginning of the binaryLocations NameEnvironmentAnswer suggestedAnswer = null; - for (int i = 0, l = this.binaryLocations.length; i < l; i++) { - NameEnvironmentAnswer answer = this.binaryLocations[i].findClass(binaryFileName, qPackageName, qBinaryFileName); + for (ClasspathLocation classpathLocation : relevantLocations) { + if (!strategy.matches(classpathLocation, ClasspathLocation::hasModule)) { + continue; + } + NameEnvironmentAnswer answer = classpathLocation.findClass(binaryFileName, qPackageName, moduleName, qBinaryFileName, false); if (answer != null) { if (!answer.ignoreIfBetter()) { if (answer.isBetter(suggestedAnswer)) @@ -333,37 +471,151 @@ private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeNam suggestedAnswer = answer; } } - if (suggestedAnswer != null) - // no better answer was found - return suggestedAnswer; - return null; + return suggestedAnswer; } -public NameEnvironmentAnswer findType(char[][] compoundName) { +@Override +public NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName) { if (compoundName != null) return findClass( - new String(CharOperation.concatWith(compoundName, '/')), - compoundName[compoundName.length - 1]); + String.valueOf(CharOperation.concatWith(compoundName, '/')), + compoundName[compoundName.length - 1], + LookupStrategy.get(moduleName), + LookupStrategy.getStringName(moduleName)); return null; } -public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { - if (typeName != null) - return findClass( - new String(CharOperation.concatWith(packageName, typeName, '/')), - typeName); - return null; +@Override +public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName) { + return findClass( + String.valueOf(CharOperation.concatWith(packageName, typeName, '/')), + typeName, + LookupStrategy.get(moduleName), + LookupStrategy.getStringName(moduleName)); } -public boolean isPackage(char[][] compoundName, char[] packageName) { - return isPackage(new String(CharOperation.concatWith(compoundName, packageName, '/'))); +@Override +public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) { + String pkgName = new String(CharOperation.concatWith(parentPackageName, name, '/')); + String modName = new String(moduleName); + LookupStrategy strategy = LookupStrategy.get(moduleName); + switch (strategy) { + // include unnamed (search all locations): + case Any: + case Unnamed: + char[][] names = CharOperation.NO_CHAR_CHAR; + for (ClasspathLocation location : this.binaryLocations) { + if (strategy.matches(location, ClasspathLocation::hasModule)) { + char[][] declaringModules = location.getModulesDeclaringPackage(pkgName, null); + if (declaringModules != null) + names = CharOperation.arrayConcat(names, declaringModules); + } + } + for (ClasspathLocation location : this.sourceLocations) { + if (strategy.matches(location, ClasspathLocation::hasModule)) { + char[][] declaringModules = location.getModulesDeclaringPackage(pkgName, null); + if (declaringModules != null) + names = CharOperation.arrayConcat(names, declaringModules); + } + } + return names == CharOperation.NO_CHAR_CHAR ? null : names; + + // only named (rely on modulePathEntries): + case AnyNamed: + modName = null; + //$FALL-THROUGH$ + default: + if (this.modulePathEntries != null) { + names = CharOperation.NO_CHAR_CHAR; + for (IModulePathEntry modulePathEntry : this.modulePathEntries.values()) { + char[][] declaringModules = modulePathEntry.getModulesDeclaringPackage(pkgName, modName); + if (declaringModules != null) + names = CharOperation.arrayConcat(names, declaringModules); + } + return names == CharOperation.NO_CHAR_CHAR ? null : names; + } + } + return null; } -public boolean isPackage(String qualifiedPackageName) { - // NOTE: the output folders are added at the beginning of the binaryLocations - for (int i = 0, l = this.binaryLocations.length; i < l; i++) - if (this.binaryLocations[i].isPackage(qualifiedPackageName)) - return true; +@Override +public boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs) { + String pkgName = String.valueOf(CharOperation.concatWith(qualifiedPackageName, '/')); + LookupStrategy strategy = LookupStrategy.get(moduleName); + String modName = LookupStrategy.getStringName(moduleName); + switch (strategy) { + // include unnamed (search all locations): + case Any: + case Unnamed: + for (ClasspathLocation location : this.binaryLocations) { + if (strategy.matches(location, ClasspathLocation::hasModule)) + if (location.hasCompilationUnit(pkgName, null)) + return true; + } + for (ClasspathLocation location : this.sourceLocations) { + if (strategy.matches(location, ClasspathLocation::hasModule)) + if (location.hasCompilationUnit(pkgName, null)) + return true; + } + return false; + // only named (rely on modulePathEntries): + case Named: + if (this.modulePathEntries != null) { + IModulePathEntry modulePathEntry = this.modulePathEntries.get(modName); + return modulePathEntry != null && modulePathEntry.hasCompilationUnit(pkgName, modName); + } + return false; + case AnyNamed: + if (this.modulePathEntries != null) { + for (IModulePathEntry modulePathEntry : this.modulePathEntries.values()) + if (modulePathEntry.hasCompilationUnit(pkgName, modName)) + return true; + } + return false; + default: + throw new IllegalArgumentException("Unexpected LookupStrategy "+strategy); //$NON-NLS-1$ + } +} +public boolean isPackage(String qualifiedPackageName, char[] moduleName) { + String stringModuleName = null; + + LookupStrategy strategy = LookupStrategy.get(moduleName); + Collection entries = null; + switch (strategy) { + case Any: + case Unnamed: + // NOTE: the output folders are added at the beginning of the binaryLocations + for (int i = 0, l = this.binaryLocations.length; i < l; i++) { + if (strategy.matches(this.binaryLocations[i], ClasspathLocation::hasModule)) + if (this.binaryLocations[i].isPackage(qualifiedPackageName, null)) + return true; + } + for (int i = 0, l = this.sourceLocations.length; i < l; i++) { + if (strategy.matches(this.sourceLocations[i], ClasspathLocation::hasModule)) + if (this.sourceLocations[i].isPackage(qualifiedPackageName, null)) + return true; + } + return false; + case AnyNamed: + entries = this.modulePathEntries.values(); + break; + default: + stringModuleName = String.valueOf(moduleName); + IModulePathEntry entry = this.modulePathEntries.get(stringModuleName); + if (entry == null) + return false; + entries = Collections.singletonList(entry); + } + for (IModulePathEntry modulePathEntry : entries) { + if (modulePathEntry instanceof ModulePathEntry) { + for (ClasspathLocation classpathLocation : ((ModulePathEntry) modulePathEntry).getClasspathLocations()) { + if (classpathLocation.isPackage(qualifiedPackageName, stringModuleName)) + return true; + } + } else if (modulePathEntry instanceof ClasspathLocation) { + return ((ClasspathLocation) modulePathEntry).isPackage(qualifiedPackageName, stringModuleName); + } + } return false; } @@ -393,4 +645,30 @@ void setNames(String[] typeNames, SourceFile[] additionalFiles) { for (int i = 0, l = this.binaryLocations.length; i < l; i++) this.binaryLocations[i].reset(); } + +@Override +public IModule getModule(char[] name) { + if (this.modulePathEntries != null) { + IModulePathEntry modulePathEntry = this.modulePathEntries.get(String.valueOf(name)); + if (modulePathEntry instanceof IMultiModuleEntry) + return modulePathEntry.getModule(name); + else if (modulePathEntry != null) + return modulePathEntry.getModule(); + } + return null; +} + +@Override +public char[][] getAllAutomaticModules() { + if (this.modulePathEntries == null) + return CharOperation.NO_CHAR_CHAR; + Set set = this.modulePathEntries.values().stream().filter(m -> m.isAutomaticModule()).map(e -> e.getModule().name()) + .collect(Collectors.toSet()); + return set.toArray(new char[set.size()][]); +} +@Override +public void applyModuleUpdates(IUpdatableModule compilerModule, IUpdatableModule.UpdateKind kind) { + if (this.moduleUpdater != null) + this.moduleUpdater.applyModuleUpdates(compilerModule, kind); +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java index 70c082b794..6624500f73 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java @@ -1,6 +1,6 @@ // GROOVY PATCHED /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -17,6 +17,7 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.core.util.Util; @@ -115,6 +116,13 @@ public String toString() { return "SourceFile[" //$NON-NLS-1$ + this.resource.getFullPath() + "]"; //$NON-NLS-1$ } + +@Override +public char[] getModuleName() { + IModule mod = this.sourceLocation.module(); + return mod == null ? null : mod.name(); +} + // GROOVY add -- GRECLIPSE-963 public static final String LINK_TO_GRAILS_PLUGINS = ".link_to_grails_plugins"; //$NON-NLS-1$ public boolean isInLinkedSourceFolder() { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java index f7fb9fbfa3..a6d5695a59 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java @@ -19,6 +19,7 @@ import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.compiler.env.AccessRule; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; +import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.jdt.internal.core.ClasspathAccessRule; import org.eclipse.jdt.internal.core.JavaModelManager; @@ -47,7 +48,7 @@ public class State { private StringSet structurallyChangedTypes; public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed -public static final byte VERSION = 0x001D; +public static final byte VERSION = 0x001E; static final byte SOURCE_FOLDER = 1; static final byte BINARY_FOLDER = 2; @@ -268,13 +269,17 @@ static State read(IProject project, DataInputStream in) throws IOException { IContainer outputFolder = path.segmentCount() == 1 ? (IContainer) root.getProject(path.toString()) : (IContainer) root.getFolder(path); - newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean(), readRestriction(in), new Path(in.readUTF())); + newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean(), + readRestriction(in), new Path(in.readUTF()), in.readBoolean()); break; case EXTERNAL_JAR : - newState.binaryLocations[i] = ClasspathLocation.forLibrary(in.readUTF(), in.readLong(), readRestriction(in), new Path(in.readUTF())); + String jarPath = in.readUTF(); + newState.binaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(), + readRestriction(in), new Path(in.readUTF()), Util.isJrt(jarPath) ? false : in.readBoolean()); break; case INTERNAL_JAR : - newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())), readRestriction(in), new Path(in.readUTF())); + newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())), + readRestriction(in), new Path(in.readUTF()), in.readBoolean()); } } @@ -455,7 +460,8 @@ void write(DataOutputStream out) throws IOException { out.writeBoolean(cd.isOutputFolder); writeRestriction(cd.accessRuleSet, out); out.writeUTF(cd.externalAnnotationPath != null ? cd.externalAnnotationPath : ""); //$NON-NLS-1$ - } else { + out.writeBoolean(cd.isOnModulePath); + } else if (c instanceof ClasspathJar) { ClasspathJar jar = (ClasspathJar) c; if (jar.resource == null) { out.writeByte(EXTERNAL_JAR); @@ -467,6 +473,14 @@ void write(DataOutputStream out) throws IOException { } writeRestriction(jar.accessRuleSet, out); out.writeUTF(jar.externalAnnotationPath != null ? jar.externalAnnotationPath : ""); //$NON-NLS-1$ + out.writeBoolean(jar.isOnModulePath); + } else { + ClasspathJrt jrt = (ClasspathJrt) c; + out.writeByte(EXTERNAL_JAR); + out.writeUTF(jrt.zipFilename); + out.writeLong(-1); + writeRestriction(null, out); + out.writeUTF(""); //$NON-NLS-1$ } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java index 0427355e3b..d957576d53 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -301,6 +301,11 @@ public ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWal return walker; } @Override +public char[] getModule() { + // TODO Java 9 Auto-generated method stub + return null; +} +@Override public ExternalAnnotationStatus getExternalAnnotationStatus() { return ExternalAnnotationStatus.NOT_EEA_CONFIGURED; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java index 99113ce6fb..6ba23dc3c4 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java @@ -282,15 +282,15 @@ protected void worked(IProgressMonitor monitor, int work) { /** * Create an ICompilationUnit info from the given compilation unit on disk. */ -protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) { - final char[] elementName = handle.getElementName().toCharArray(); - return new ResourceCompilationUnit(file) { - @Override - public char[] getFileName() { - return elementName; - } - }; -} + protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) { + final char[] elementName = handle.getElementName().toCharArray(); + return new ResourceCompilationUnit(file, null) { + @Override + public char[] getFileName() { + return elementName; + } + }; + } /** * Creates the type info from the given class file on disk and * adds it to the given list of infos. diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java index 7316ed0218..ddb9c36f78 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java @@ -840,7 +840,6 @@ public void resolve(Openable[] openables, HashSet localTypes, IProgressMonitor m parsedUnit.scope.faultInTypes(); parsedUnit.resolve(); } - rememberAllTypes(parsedUnit, cus[i], containsLocalType); } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java index a81cfe6bae..a9f2f0cd17 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java @@ -234,7 +234,8 @@ public int compare(Object a, Object b) { // top level or member type if (!inProjectOfFocusType) { char[] typeQualifiedName = focusType.getTypeQualifiedName('.').toCharArray(); - String[] packageName = ((PackageFragment) focusType.getPackageFragment()).names; + PackageFragment fragment = (PackageFragment) focusType.getPackageFragment(); + String[] packageName = fragment.names; if (searchableEnvironment.findType(typeQualifiedName, Util.toCharArrays(packageName)) == null) { // focus type is not visible in this project: no need to go further return; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java index 3a4305fcbc..2ae71cc5d5 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,10 +16,10 @@ import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IOrdinaryClassFile; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; @@ -183,7 +183,7 @@ private void injectAllOpenablesForPackageFragment( openables.add(cus[i]); } } else { - IClassFile[] classFiles = packFrag.getClassFiles(); + IOrdinaryClassFile[] classFiles = packFrag.getOrdinaryClassFiles(); for (int i = 0, length = classFiles.length; i < length; i++) { openables.add(classFiles[i]); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java index c00aa48a7c..e6a1ebb112 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -57,4 +57,9 @@ public boolean ignoreOptionalProblems() { public String toString() { return "CompilationUnit[" + new String(this.fFileName) + "]"; //$NON-NLS-2$ //$NON-NLS-1$ } +@Override +public char[] getModuleName() { + // TODO Java 9 Auto-generated method stub + return null; +} } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java index a1f061c967..5f0919027f 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -34,7 +34,8 @@ static class Scanner { static final int CAPTURE = 8; static final int CAPTURE18 = 9; static final int BASE_TYPE = 10; - static final int END = 11; + static final int MODULE = 11; + static final int END = 12; static final int START = -1; @@ -152,6 +153,12 @@ boolean isAtTypeWithCaptureStart() { && this.source[this.index] == '&'; } + boolean isAtModuleStart() { + return + this.index < this.source.length + && this.source[this.index] == '"'; + } + int nextToken() { int previousTokenEnd = this.index; this.start = this.index; @@ -221,6 +228,9 @@ int nextToken() { } break; case '.': + if (this.token == MODULE) + break; // don't treat '.' as a separator in module names + //$FALL-THROUGH$ case '%': case ':': case '>': @@ -319,6 +329,10 @@ int nextToken() { this.index++; this.token = CAPTURE18; return this.token; + case '"': + this.index++; + this.token = MODULE; + return this.token; } this.index++; } @@ -436,6 +450,9 @@ public String toString() { case BASE_TYPE: buffer.append("BASE TYPE: "); //$NON-NLS-1$ break; + case MODULE: + buffer.append("MODULE: "); //$NON-NLS-1$ + break; case END: buffer.append("END: "); //$NON-NLS-1$ break; @@ -466,6 +483,8 @@ public String toString() { private Scanner scanner; private boolean hasTypeName = true; + + private boolean hasModuleName; private boolean isMalformed; @@ -596,6 +615,10 @@ public void consumeWildcardRank(int rank) { // default is to do nothing } + public void consumeModule(char[] moduleName) { + // default is to do nothing + } + /* * Returns the string that this binding key wraps. */ @@ -607,6 +630,10 @@ public boolean hasTypeName() { return this.hasTypeName; } + public boolean hasModuleName() { + return this.hasModuleName; + } + public void malformedKey() { this.isMalformed = true; } @@ -621,6 +648,8 @@ public void parse() { public void parse(boolean pauseAfterFullyQualifiedName) { if (!this.parsingPaused) { + if (parseModule()) + return; // fully qualified name parseFullyQualifiedName(); parseSecondaryType(); @@ -694,6 +723,22 @@ else if (this.scanner.isAtRawTypeEnd()) consumeKey(); } + private boolean parseModule() { + if (this.scanner.isAtModuleStart()) { + this.hasTypeName = false; + this.keyStart = 1; + if (this.scanner.nextToken() == Scanner.MODULE + && this.scanner.nextToken() == Scanner.END) + { + consumeModule(this.scanner.getTokenSource()); + this.hasModuleName = true; + return true; + } + malformedKey(); + } + return false; + } + private void parseFullyQualifiedName() { if (this.scanner.isAtCaptureStart()) { parseCapture(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java index 8fccd22da5..ed34cfbddd 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -108,6 +108,7 @@ public boolean equals(Object obj) { Binding compilerBinding; char[][] compoundName; + char[] moduleName; int dimension; LookupEnvironment environment; ReferenceBinding genericType; @@ -155,6 +156,10 @@ public char[][] compoundName() { return this.compoundName; } + public char[] moduleName() { + return this.moduleName; + } + public void consumeAnnotation() { int size = this.types.size(); if (size == 0) return; @@ -470,7 +475,7 @@ public void consumeMemberType(char[] simpleTypeName) { public void consumePackage(char[] pkgName) { this.compoundName = CharOperation.splitOn('/', pkgName); - this.compilerBinding = new PackageBinding(this.compoundName, null, this.environment); + this.compilerBinding = new PackageBinding(this.compoundName, null, this.environment, this.environment.module); //TODO(SHMOD) enclosingModule } public void consumeParameterizedType(char[] simpleTypeName, boolean isRaw) { @@ -610,6 +615,11 @@ public void consumeWildCard(int kind) { } } + public void consumeModule(char[] aModuleName) { + this.moduleName = aModuleName; + this.compilerBinding = this.environment.getModule(aModuleName); + } + public AnnotationBinding getAnnotationBinding() { return this.annotationBinding; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java index b5cc14429e..ef78e01144 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2011, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -154,6 +154,14 @@ public ClassFileReader(byte[] classFileBytes, int decodingFlags) throws ClassFor constantPoolOffsets[i] = readOffset; readOffset += IConstantPoolConstant.CONSTANT_InvokeDynamic_SIZE; break; + case IConstantPoolConstant.CONSTANT_Module: + constantPoolOffsets[i] = readOffset; + readOffset += IConstantPoolConstant.CONSTANT_Module_SIZE; + break; + case IConstantPoolConstant.CONSTANT_Package: + constantPoolOffsets[i] = readOffset; + readOffset += IConstantPoolConstant.CONSTANT_Package_SIZE; + break; default: throw new ClassFormatException(ClassFormatException.INVALID_TAG_CONSTANT); } @@ -281,6 +289,12 @@ public ClassFileReader(byte[] classFileBytes, int decodingFlags) throws ClassFor this.attributes[attributesIndex++] = new RuntimeVisibleTypeAnnotationsAttribute(classFileBytes, this.constantPool, readOffset); } else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS)) { this.attributes[attributesIndex++] = new RuntimeInvisibleTypeAnnotationsAttribute(classFileBytes, this.constantPool, readOffset); + } else if (equals(attributeName, IAttributeNamesConstants.MODULE)) { + this.attributes[attributesIndex++] = new ModuleAttribute(classFileBytes, this.constantPool, readOffset); + } else if (equals(attributeName, IAttributeNamesConstants.MODULE_PACKAGES)) { + this.attributes[attributesIndex++] = new ModulePackagesAttribute(classFileBytes, this.constantPool, readOffset); + } else if (equals(attributeName, IAttributeNamesConstants.MODULE_MAIN_CLASS)) { + this.attributes[attributesIndex++] = new ModuleMainClassAttribute(classFileBytes, this.constantPool, readOffset); } else { this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset); } @@ -442,7 +456,7 @@ public char[] getSuperclassName() { * @see IClassFileReader#isClass() */ public boolean isClass() { - return !isInterface(); + return !(isInterface() || isModule()); } /** @@ -451,4 +465,7 @@ public boolean isClass() { public boolean isInterface() { return (getAccessFlags() & IModifierConstants.ACC_INTERFACE) != 0; } + private boolean isModule() { + return (getAccessFlags() & IModifierConstants.ACC_MODULE) != 0; + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java index a9c4699b25..8d0351abb7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -151,6 +151,24 @@ public IConstantPoolEntry decodeEntry(int index) { constantPoolEntry2.setMethodDescriptor(getUtf8ValueAt(methodDescriptorIndex)); constantPoolEntry = constantPoolEntry2; break; + case IConstantPoolConstant.CONSTANT_Module : + constantPoolEntry2 = new ConstantPoolEntry2(); + constantPoolEntry2.reset(); + constantPoolEntry2.setKind(kind); + int moduleIndex = u2At(this.classFileBytes, 1, this.constantPoolOffset[index]); + constantPoolEntry2.setModuleIndex(moduleIndex); + constantPoolEntry2.setModuleName(getUtf8ValueAt(moduleIndex)); + constantPoolEntry = constantPoolEntry2; + break; + case IConstantPoolConstant.CONSTANT_Package : + constantPoolEntry2 = new ConstantPoolEntry2(); + constantPoolEntry2.reset(); + constantPoolEntry2.setKind(kind); + int packageIndex = u2At(this.classFileBytes, 1, this.constantPoolOffset[index]); + constantPoolEntry2.setPackageIndex(packageIndex); + constantPoolEntry2.setPackageName(getUtf8ValueAt(packageIndex)); + constantPoolEntry = constantPoolEntry2; + break; } return constantPoolEntry; } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java index 9f9cae6644..c2c92002e2 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,7 @@ /** * Default implementation of IConstantPoolEntry * + * @see ConstantPoolEntry2 * @since 2.0 */ public class ConstantPoolEntry implements IConstantPoolEntry { diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry2.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry2.java index c6c968625e..ebeee13572 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry2.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry2.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,20 +10,25 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core.util; -import org.eclipse.jdt.core.util.IConstantPoolEntry2; +import org.eclipse.jdt.core.util.IConstantPoolEntry3; /** - * Default implementation of IConstantPoolEntry + * Default implementation of IConstantPoolEntry2 and IConstantPoolEntry3. * * @since 2.0 */ -public class ConstantPoolEntry2 extends ConstantPoolEntry implements IConstantPoolEntry2 { - +public class ConstantPoolEntry2 extends ConstantPoolEntry implements IConstantPoolEntry3 { + private int descriptorIndex; private int referenceKind; private int referenceIndex; private int bootstrapMethodAttributeIndex; + private int moduleIndex; + private char[] moduleName; + private int packageIndex; + private char[] packageName; + public int getDescriptorIndex() { return this.descriptorIndex; } @@ -40,6 +45,22 @@ public int getBootstrapMethodAttributeIndex() { return this.bootstrapMethodAttributeIndex; } + public int getModuleIndex() { + return this.moduleIndex; + } + + public char[] getModuleName() { + return this.moduleName; + } + + public int getPackageIndex() { + return this.packageIndex; + } + + public char[] getPackageName() { + return this.packageName; + } + public void setDescriptorIndex(int descriptorIndex) { this.descriptorIndex = descriptorIndex; } @@ -56,11 +77,31 @@ public void setBootstrapMethodAttributeIndex(int bootstrapMethodAttributeIndex) this.bootstrapMethodAttributeIndex = bootstrapMethodAttributeIndex; } + public void setModuleIndex(int moduleIndex) { + this.moduleIndex = moduleIndex; + } + + public void setModuleName(char[] moduleName) { + this.moduleName = moduleName; + } + + public void setPackageIndex(int packageIndex) { + this.packageIndex = packageIndex; + } + + public void setPackageName(char[] packageName) { + this.packageName = packageName; + } + public void reset() { super.reset(); this.descriptorIndex = 0; this.referenceKind = 0; this.referenceIndex = 0; this.bootstrapMethodAttributeIndex = 0; + this.moduleIndex = 0; + this.moduleName = null; + this.packageIndex = 0; + this.packageName = null; } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DOMFinder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DOMFinder.java index 19629a2454..aa9391193f 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DOMFinder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DOMFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -35,6 +35,7 @@ import org.eclipse.jdt.core.dom.LambdaExpression; import org.eclipse.jdt.core.dom.MarkerAnnotation; import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.ModuleDeclaration; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.PackageDeclaration; import org.eclipse.jdt.core.dom.ParameterizedType; @@ -154,6 +155,12 @@ public boolean visit(MethodDeclaration node) { return true; } + public boolean visit(ModuleDeclaration node) { + if (found(node, node.getName()) && this.resolveBinding) { + this.foundBinding = node.resolveBinding(); + } + return true; + } public boolean visit(NormalAnnotation node) { if (found(node, node) && this.resolveBinding) this.foundBinding = node.resolveAnnotationBinding(); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java index 39e18969e1..e0936b494b 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -175,6 +175,30 @@ private final void decodeModifiersForType(StringBuffer buffer, int accessFlags) IModifierConstants.ACC_FINAL, }); } + private final void decodeModifiersForModuleRequires(StringBuffer buffer, int accessFlags) { + int[] checkBits = new int[] { + IModifierConstants.ACC_TRANSITIVE, + IModifierConstants.ACC_STATIC_PHASE, + }; + boolean firstModifier = true; + for (int i = 0, max = checkBits.length; i < max; i++) { + switch(checkBits[i]) { + case IModifierConstants.ACC_TRANSITIVE : + firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSITIVE, "transitive", firstModifier); //$NON-NLS-1$ + break; + case IModifierConstants.ACC_STATIC_PHASE : + firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC_PHASE, "protected", firstModifier); //$NON-NLS-1$ + break; + } + } + if (!firstModifier) { + buffer.append(Messages.disassembler_space); + } + } + private final void decodeModifiersForModule(StringBuffer buffer, int accessFlags) { + appendModifier(buffer, accessFlags, IModifierConstants.ACC_OPEN, "open", true); //$NON-NLS-1$ + buffer.append(Messages.disassembler_space); + } public static String escapeString(String s) { return decodeStringValue(s); } @@ -974,6 +998,8 @@ public String disassemble(IClassFileReader classFileReader, String lineSeparator versionNumber = JavaCore.VERSION_1_7; } else if (minorVersion == 0 && majorVersion == 52) { versionNumber = JavaCore.VERSION_1_8; + } else if (minorVersion == 0 && majorVersion == 53) { + versionNumber = JavaCore.VERSION_9; } buffer.append( Messages.bind(Messages.classfileformat_versiondetails, @@ -1009,7 +1035,8 @@ public String disassemble(IClassFileReader classFileReader, String lineSeparator IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); IClassFileAttribute bootstrapMethods = Util.getAttribute(classFileReader, IAttributeNamesConstants.BOOTSTRAP_METHODS); - + IModuleAttribute moduleAttribute = (IModuleAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE); + if (checkMode(mode, DETAILED)) { // disassemble compact version of annotations if (runtimeInvisibleAnnotationsAttribute != null) { @@ -1049,9 +1076,12 @@ public String disassemble(IClassFileReader classFileReader, String lineSeparator } final boolean isAnnotation = (accessFlags & IModifierConstants.ACC_ANNOTATION) != 0; + final boolean isModule = (accessFlags & IModifierConstants.ACC_MODULE) != 0; boolean isInterface = false; if (isEnum) { buffer.append("enum "); //$NON-NLS-1$ + } else if (isModule) { + // skip - process under module attribute } else if (classFileReader.isClass()) { buffer.append("class "); //$NON-NLS-1$ } else { @@ -1070,7 +1100,7 @@ public String disassemble(IClassFileReader classFileReader, String lineSeparator if (signatureAttribute != null) { disassembleGenericSignature(mode, buffer, signatureAttribute.getSignature()); } - } else { + } else if (!isModule) { buffer.append(className); } @@ -1104,15 +1134,29 @@ public String disassemble(IClassFileReader classFileReader, String lineSeparator } } } - buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration)); + if (!isModule) + buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration)); if (checkMode(mode, SYSTEM)) { disassemble(classFileReader.getConstantPool(), buffer, lineSeparator, 1); } + if (isModule && moduleAttribute != null) { // print attributes - module package and main class only if the mandatory module attribute non-null + decodeModifiersForModule(buffer, accessFlags); + buffer.append("module"); //$NON-NLS-1$ + buffer.append(Messages.disassembler_space); + buffer.append(moduleAttribute.getModuleName()); + buffer.append(Messages.disassembler_space); + buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration)); + disassembleModule(moduleAttribute, buffer, lineSeparator, 1); + IModulePackagesAttribute modulePackagesAttribute = (IModulePackagesAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE_PACKAGES); + disassembleModule(modulePackagesAttribute, buffer, lineSeparator, 1); + IModuleMainClassAttribute mainClassAttribute = (IModuleMainClassAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE_MAIN_CLASS); + disassembleModule(mainClassAttribute, buffer, lineSeparator, 1); + } disassembleTypeMembers(classFileReader, className, buffer, lineSeparator, 1, mode, isEnum); if (checkMode(mode, SYSTEM | DETAILED)) { IClassFileAttribute[] attributes = classFileReader.getAttributes(); int length = attributes.length; - IEnclosingMethodAttribute enclosingMethodAttribute = getEnclosingMethodAttribute(classFileReader); + IEnclosingMethodAttribute enclosingMethodAttribute = (IEnclosingMethodAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.ENCLOSING_METHOD); int remainingAttributesLength = length; if (innerClassesAttribute != null) { remainingAttributesLength--; @@ -1129,9 +1173,13 @@ public String disassemble(IClassFileReader classFileReader, String lineSeparator if (bootstrapMethods != null) { remainingAttributesLength--; } + if (moduleAttribute != null) { + remainingAttributesLength--; + } if (innerClassesAttribute != null || enclosingMethodAttribute != null || bootstrapMethods != null + || moduleAttribute != null || remainingAttributesLength != 0) { // this test is to ensure we don't insert more than one line separator if (buffer.lastIndexOf(lineSeparator) != buffer.length() - lineSeparator.length()) { @@ -1173,7 +1221,9 @@ public String disassemble(IClassFileReader classFileReader, String lineSeparator && attribute != runtimeVisibleTypeAnnotationsAttribute && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED) && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC) - && attribute != bootstrapMethods) { + && attribute != bootstrapMethods + && attribute != moduleAttribute + ) { disassemble(attribute, buffer, lineSeparator, 0, mode); } } @@ -1185,6 +1235,130 @@ public String disassemble(IClassFileReader classFileReader, String lineSeparator return buffer.toString(); } + private void disassembleModule(IModuleAttribute moduleAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { + writeNewLine(buffer, lineSeparator, tabNumber); + char[] moduleVersion = moduleAttribute.getModuleVersionValue(); + if (moduleVersion == null) { + moduleVersion = Messages.disassembler_module_version_none.toCharArray(); + } + buffer.append(Messages.bind(Messages.disassembler_module_version, new String(moduleVersion))); + IRequiresInfo[] requiresInfo = moduleAttribute.getRequiresInfo(); + if (requiresInfo.length > 0) { + writeNewLine(buffer, lineSeparator, 0); + for (int i = 0, max = requiresInfo.length; i < max; i++) { + writeNewLine(buffer, lineSeparator, tabNumber); + disassemble(requiresInfo[i], buffer, lineSeparator, tabNumber); + } + } + IPackageVisibilityInfo[] exportInfos = moduleAttribute.getExportsInfo(); + if (exportInfos.length > 0) { + writeNewLine(buffer, lineSeparator, 0); + for (int i = 0, max = exportInfos.length; i < max; i++) { + writeNewLine(buffer, lineSeparator, tabNumber); + disassemble(exportInfos[i], buffer, lineSeparator, tabNumber, true); + } + } + IPackageVisibilityInfo[] opensInfos = moduleAttribute.getOpensInfo(); + if (opensInfos.length > 0) { + writeNewLine(buffer, lineSeparator, 0); + for (int i = 0, max = opensInfos.length; i < max; i++) { + writeNewLine(buffer, lineSeparator, tabNumber); + disassemble(opensInfos[i], buffer, lineSeparator, tabNumber, false); + } + } + char[][] usesNames = moduleAttribute.getUsesClassNames(); + if (usesNames.length > 0) { + writeNewLine(buffer, lineSeparator, 0); + for (int i = 0, max = usesNames.length; i < max; i++) { + writeNewLine(buffer, lineSeparator, tabNumber); + buffer.append("uses " + CharOperation.charToString(CharOperation.replaceOnCopy(usesNames[i], '/','.'))); //$NON-NLS-1$ + } + } + IProvidesInfo[] providesInfos = moduleAttribute.getProvidesInfo(); + if (providesInfos.length > 0) { + writeNewLine(buffer, lineSeparator, 0); + for (int i = 0, max = providesInfos.length; i < max; i++) { + writeNewLine(buffer, lineSeparator, tabNumber); + disassemble(providesInfos[i], buffer, lineSeparator, tabNumber); + } + } + } + private void convertModuleNames(StringBuffer buffer, char[] name) { + buffer.append(CharOperation.replaceOnCopy(CharOperation.replaceOnCopy(name, '$','.'), '/','.')); + } + + private void disassembleModule(IModulePackagesAttribute modulePackagesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { + if (modulePackagesAttribute == null) return; + writeNewLine(buffer, lineSeparator, tabNumber); + writeNewLine(buffer, lineSeparator, tabNumber); + buffer.append(Messages.disassembler_modulepackagesattributeheader); + char[][] names = modulePackagesAttribute.getPackageNames(); + for (int i = 0, l = modulePackagesAttribute.getPackagesCount(); i < l; ++i) { + writeNewLine(buffer, lineSeparator, tabNumber + 1); + convertModuleNames(buffer, names[i]); + } + writeNewLine(buffer, lineSeparator, 0); + } + + private void disassembleModule(IModuleMainClassAttribute moduleMainClassAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { + if (moduleMainClassAttribute == null) return; + writeNewLine(buffer, lineSeparator, tabNumber); + buffer.append(Messages.disassembler_modulemainclassattributeheader); + writeNewLine(buffer, lineSeparator, tabNumber + 1); + convertModuleNames(buffer, moduleMainClassAttribute.getMainClassName()); + writeNewLine(buffer, lineSeparator, 0); + } + + private void disassemble(IProvidesInfo iProvidesInfo, StringBuffer buffer, String lineSeparator, int tabNumber) { + buffer.append("provides"); //$NON-NLS-1$ + buffer.append(Messages.disassembler_space); + convertModuleNames(buffer, iProvidesInfo.getServiceName()); + buffer.append(Messages.disassembler_space); + char[][] implementations = iProvidesInfo.getImplementationNames(); + if (implementations.length > 0) { + buffer.append( "with"); //$NON-NLS-1$ + buffer.append(Messages.disassembler_space); + for (int i = 0, l = implementations.length; i < l; ++i) { + if (i != 0) { + buffer + .append(Messages.disassembler_comma) + .append(Messages.disassembler_space); + } + convertModuleNames(buffer, implementations[i]); + } + } + buffer.append(';'); + } + + private void disassemble(IPackageVisibilityInfo iPackageVisibilityInfo, StringBuffer buffer, String lineSeparator, + int tabNumber, boolean isExports) { + buffer.append(isExports ? "exports" : "opens"); //$NON-NLS-1$ //$NON-NLS-2$ + buffer.append(Messages.disassembler_space); + convertModuleNames(buffer, iPackageVisibilityInfo.getPackageName()); + char[][] targets = iPackageVisibilityInfo.getTargetModuleNames(); + if (targets.length > 0) { + buffer.append(Messages.disassembler_space); + buffer.append( "to"); //$NON-NLS-1$ + buffer.append(Messages.disassembler_space); + for (int i = 0, l = targets.length; i < l; ++i) { + if (i != 0) { + buffer + .append(Messages.disassembler_comma) + .append(Messages.disassembler_space); + } + buffer.append(targets[i]); + } + } + buffer.append(';'); + } + + private void disassemble(IRequiresInfo iRequiresInfo, StringBuffer buffer, String lineSeparator, int tabNumber) { + buffer.append("requires "); //$NON-NLS-1$ + decodeModifiersForModuleRequires(buffer, iRequiresInfo.getRequiresFlags()); + buffer.append(iRequiresInfo.getRequiresModuleName()); + buffer.append(';'); + } + private void disassembleGenericSignature(int mode, StringBuffer buffer, final char[] signature) { CharOperation.replace(signature, '/', '.'); final char[][] typeParameters = Signature.getTypeParameters(signature); @@ -1331,7 +1505,7 @@ private void disassemble(ICodeAttribute codeAttribute, char[][] parameterNames, })); } } - final ILocalVariableTypeTableAttribute localVariableTypeAttribute= (ILocalVariableTypeTableAttribute) getAttribute(IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE, codeAttribute); + final ILocalVariableTypeTableAttribute localVariableTypeAttribute= (ILocalVariableTypeTableAttribute) Util.getAttribute(codeAttribute, IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE); final int localVariableTypeTableLength = localVariableTypeAttribute == null ? 0 : localVariableTypeAttribute.getLocalVariableTypeTableLength(); if (localVariableTypeTableLength != 0) { int tabNumberForLocalVariableAttribute = tabNumber + 2; @@ -2450,25 +2624,6 @@ public String getDescription() { return Messages.disassembler_description; } - private IEnclosingMethodAttribute getEnclosingMethodAttribute(IClassFileReader classFileReader) { - IClassFileAttribute[] attributes = classFileReader.getAttributes(); - for (int i = 0, max = attributes.length; i < max; i++) { - if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.ENCLOSING_METHOD)) { - return (IEnclosingMethodAttribute) attributes[i]; - } - } - return null; - } - private IClassFileAttribute getAttribute(final char[] attributeName, final ICodeAttribute codeAttribute) { - IClassFileAttribute[] attributes = codeAttribute.getAttributes(); - for (int i = 0, max = attributes.length; i < max; i++) { - if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) { - return attributes[i]; - } - } - return null; - } - private char[][] getParameterNames(char[] methodDescriptor, ICodeAttribute codeAttribute, IMethodParametersAttribute parametersAttribute, int accessFlags) { int paramCount = Signature.getParameterCount(methodDescriptor); char[][] parameterNames = new char[paramCount][]; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java index 94f0a2703c..352d19ad34 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java @@ -97,6 +97,12 @@ public Openable createOpenable(String resourcePath, IJavaSearchScope scope) { this.packageHandles= new HashtableOfArrayToObject(5); } // create handle + String module = null; + String rootPath = this.lastPkgFragmentRoot.getPath().toOSString(); + if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) { + module = resourcePath.substring(separatorIndex + 1, + (separatorIndex = resourcePath.lastIndexOf(IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR))); + } String classFilePath= resourcePath.substring(separatorIndex + 1); String[] simpleNames = new Path(classFilePath).segments(); String[] pkgName; @@ -109,7 +115,7 @@ public Openable createOpenable(String resourcePath, IJavaSearchScope scope) { } IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(pkgName); if (pkgFragment == null) { - pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(pkgName); + pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(pkgName, module); this.packageHandles.put(pkgName, pkgFragment); } IClassFile classFile= pkgFragment.getClassFile(simpleNames[length]); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/JavaElementFinder.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/JavaElementFinder.java index cefcf1a7c9..265b97d384 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/JavaElementFinder.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/JavaElementFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -139,6 +139,15 @@ public void consumeTypeVariable(char[] position, char[] typeVariableName) { } } + @Override + public void consumeModule(char[] moduleName) { + try { + this.element = this.project.findModule(new String(moduleName), null); + } catch (JavaModelException e) { + this.exception = e; + } + } + public BindingKeyParser newParser() { return new JavaElementFinder(this, this.project, this.owner); } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java index 06f26fb110..fc82168e0c 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2011 IBM Corporation and others. + * Copyright (c) 2004, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -22,7 +22,9 @@ public class MementoTokenizer { public static final String INITIALIZER = Character.toString(JavaElement.JEM_INITIALIZER); public static final String COMPILATIONUNIT = Character.toString(JavaElement.JEM_COMPILATIONUNIT); public static final String CLASSFILE = Character.toString(JavaElement.JEM_CLASSFILE); + public static final String MODULAR_CLASSFILE = Character.toString(JavaElement.JEM_MODULAR_CLASSFILE); public static final String TYPE = Character.toString(JavaElement.JEM_TYPE); + public static final String MODULE = Character.toString(JavaElement.JEM_MODULE); public static final String PACKAGEDECLARATION = Character.toString(JavaElement.JEM_PACKAGEDECLARATION); public static final String IMPORTDECLARATION = Character.toString(JavaElement.JEM_IMPORTDECLARATION); public static final String LOCALVARIABLE = Character.toString(JavaElement.JEM_LOCALVARIABLE); @@ -90,8 +92,12 @@ public String nextToken() { return COMPILATIONUNIT; case JavaElement.JEM_CLASSFILE: return CLASSFILE; + case JavaElement.JEM_MODULAR_CLASSFILE: + return MODULAR_CLASSFILE; case JavaElement.JEM_TYPE: return TYPE; + case JavaElement.JEM_MODULE: + return MODULE; case JavaElement.JEM_PACKAGEDECLARATION: return PACKAGEDECLARATION; case JavaElement.JEM_IMPORTDECLARATION: @@ -120,6 +126,7 @@ public String nextToken() { case JavaElement.JEM_COMPILATIONUNIT: case JavaElement.JEM_CLASSFILE: case JavaElement.JEM_TYPE: + case JavaElement.JEM_MODULE: case JavaElement.JEM_PACKAGEDECLARATION: case JavaElement.JEM_IMPORTDECLARATION: case JavaElement.JEM_LOCALVARIABLE: diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java index 7362b46e93..5ed4f9bc26 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -40,6 +40,7 @@ private Messages() { public static String element_nullName; public static String element_nullType; public static String element_illegalParent; + public static String element_moduleInfoNotSupported; public static String javamodel_initialization; public static String javamodel_initializing_delta_state; public static String javamodel_building_after_upgrade; @@ -212,6 +213,14 @@ private Messages() { public static String convention_package_nameWithBlanks; public static String convention_package_consecutiveDotsName; public static String convention_package_uppercaseName; + public static String convention_module_nullName; + public static String convention_module_emptyName; + public static String convention_module_dotName; + public static String convention_module_nameWithBlanks; + public static String convention_module_consecutiveDotsName; + public static String convention_module_uppercaseName; + public static String convention_module_terminalDigits; + public static String convention_module_javaName; public static String dom_cannotDetail; public static String dom_nullTypeParameter; public static String dom_nullNameParameter; @@ -323,6 +332,10 @@ private Messages() { public static String disassembler_extendedannotation_typepath_typeargument; public static String disassembler_extendedannotation_typepath_innertype; public static String disassembler_localvariabletargetheader; + public static String disassembler_module_version; + public static String disassembler_module_version_none; + public static String disassembler_modulepackagesattributeheader; + public static String disassembler_modulemainclassattributeheader; public static String disassembler_runtimevisibleannotationsattributeheader; public static String disassembler_runtimeinvisibleannotationsattributeheader; diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleAttribute.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleAttribute.java new file mode 100644 index 0000000000..ef97150ebe --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleAttribute.java @@ -0,0 +1,221 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.util.ClassFormatException; +import org.eclipse.jdt.core.util.IConstantPool; +import org.eclipse.jdt.core.util.IConstantPoolConstant; +import org.eclipse.jdt.core.util.IConstantPoolEntry; +import org.eclipse.jdt.core.util.IConstantPoolEntry3; +import org.eclipse.jdt.core.util.IModuleAttribute; +import org.eclipse.jdt.core.util.IPackageVisibilityInfo; +import org.eclipse.jdt.core.util.IProvidesInfo; +import org.eclipse.jdt.core.util.IRequiresInfo; + +/** + * @since 3.14 + */ +public class ModuleAttribute extends ClassFileAttribute implements IModuleAttribute { + + static final IRequiresInfo[] NO_REQUIRES = new IRequiresInfo[0]; + static final IPackageVisibilityInfo[] NO_PACKAGE_VISIBILITY_INFOS = new IPackageVisibilityInfo[0]; + static final int[] NO_USES = new int[0]; + static final IProvidesInfo[] NO_PROVIDES_INFOS = new IProvidesInfo[0]; + private int moduleNameIndex; + private char[] moduleName; + private int moduleFlags; + private int moduleVersionIndex; + private char[] moduleVersionValue; + private int requiresCount; + private IRequiresInfo[] requiresInfo; + private int exportsCount; + private IPackageVisibilityInfo[] exportsInfo; + private int opensCount; + private IPackageVisibilityInfo[] opensInfo; + private int usesCount; + private int[] usesIndices; + private char[][] usesNames; + private int providesCount; + private IProvidesInfo[] providesInfo; + + ModuleAttribute(byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException { + super(classFileBytes, constantPool, offset); + int readOffset = 6; // skip attribute_name_index & attribute_length + this.moduleNameIndex = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.moduleNameIndex); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Module) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.moduleName = ((IConstantPoolEntry3) constantPoolEntry).getModuleName(); + this.moduleFlags = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + this.moduleVersionIndex = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + if (this.moduleVersionIndex != 0) { + constantPoolEntry = constantPool.decodeEntry(this.moduleVersionIndex); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.moduleVersionValue = constantPoolEntry.getUtf8Value(); + } else { + this.moduleVersionValue = CharOperation.NO_CHAR; + } + + this.requiresCount = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + if (this.requiresCount != 0) { + this.requiresInfo = new RequiresInfo[this.requiresCount]; + for (int i = 0; i < this.requiresCount; i++) { + this.requiresInfo [i] = new RequiresInfo(classFileBytes, constantPool, offset + readOffset); + readOffset += 6; + } + } else { + this.requiresInfo = NO_REQUIRES; + } + + this.exportsCount = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + if (this.exportsCount != 0) { + this.exportsInfo = new PackageVisibilityInfo[this.exportsCount]; + for (int i = 0; i < this.exportsCount; i++) { + this.exportsInfo [i] = new PackageVisibilityInfo(classFileBytes, constantPool, offset + readOffset); + readOffset += 6 + 2 * this.exportsInfo[i].getTargetsCount(); + } + } else { + this.exportsInfo = NO_PACKAGE_VISIBILITY_INFOS; + } + + this.opensCount = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + if (this.opensCount != 0) { + this.opensInfo = new PackageVisibilityInfo[this.opensCount]; + for (int i = 0; i < this.opensCount; i++) { + this.opensInfo [i] = new PackageVisibilityInfo(classFileBytes, constantPool, offset + readOffset); + readOffset += 6 + 2 * this.opensInfo[i].getTargetsCount(); + } + } else { + this.opensInfo = NO_PACKAGE_VISIBILITY_INFOS; + } + + this.usesCount = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + if (this.usesCount != 0) { + this.usesIndices = new int[this.usesCount]; + this.usesNames = new char[this.usesCount][]; + for (int i = 0; i < this.usesCount; i++) { + this.usesIndices[i] = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + constantPoolEntry = constantPool.decodeEntry(this.usesIndices[i]); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.usesNames[i] = constantPoolEntry.getClassInfoName(); + } + } else { + this.usesIndices = NO_USES; + this.usesNames = CharOperation.NO_CHAR_CHAR; + } + + this.providesCount = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + if (this.providesCount != 0) { + this.providesInfo = new ProvidesInfo[this.providesCount]; + for (int i = 0; i < this.providesCount; i++) { + this.providesInfo[i] = new ProvidesInfo(classFileBytes, constantPool, offset + readOffset); + readOffset += 4 + 2 * this.providesInfo[i].getImplementationsCount(); + } + } else { + this.providesInfo = NO_PROVIDES_INFOS; + } + } + + @Override + public int getModuleNameIndex() { + return this.moduleNameIndex; + } + + @Override + public char[] getModuleName() { + return this.moduleName; + } + + @Override + public int getModuleFlags() { + return this.moduleFlags; + } + + @Override + public int getModuleVersionIndex() { + return this.moduleVersionIndex; + } + + @Override + public char[] getModuleVersionValue() { + return this.moduleVersionValue; + } + + @Override + public int getRequiresCount() { + return this.requiresCount; + } + + @Override + public IRequiresInfo[] getRequiresInfo() { + return this.requiresInfo; + } + + @Override + public int getExportsCount() { + return this.exportsCount; + } + + @Override + public IPackageVisibilityInfo[] getExportsInfo() { + return this.exportsInfo; + } + + @Override + public int getOpensCount() { + return this.opensCount; + } + + @Override + public IPackageVisibilityInfo[] getOpensInfo() { + return this.opensInfo; + } + + @Override + public int getUsesCount() { + return this.usesCount; + } + + @Override + public int[] getUsesIndices() { + return this.usesIndices; + } + + @Override + public char[][] getUsesClassNames() { + return this.usesNames; + } + + @Override + public int getProvidesCount() { + return this.providesCount; + } + + @Override + public IProvidesInfo[] getProvidesInfo() { + return this.providesInfo; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleMainClassAttribute.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleMainClassAttribute.java new file mode 100644 index 0000000000..c92c9ed589 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleMainClassAttribute.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import org.eclipse.jdt.core.util.ClassFormatException; +import org.eclipse.jdt.core.util.IConstantPool; +import org.eclipse.jdt.core.util.IConstantPoolConstant; +import org.eclipse.jdt.core.util.IConstantPoolEntry; +import org.eclipse.jdt.core.util.IModuleMainClassAttribute; + +/** + * Default implementation of IModuleMainClassAttribute + */ +public class ModuleMainClassAttribute extends ClassFileAttribute implements IModuleMainClassAttribute { + + private final int mainClassIndex; + private final char[] mainClassName; + + /** + * Constructor for ModuleMainClassAttribute. + * @param classFileBytes + * @param constantPool + * @param offset + * @throws ClassFormatException + */ + public ModuleMainClassAttribute( byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException { + super(classFileBytes, constantPool, offset); + int readOffset = 6; + this.mainClassIndex = u2At(classFileBytes, readOffset, offset); + IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.mainClassIndex); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.mainClassName = constantPoolEntry.getClassInfoName(); + } + + @Override + public int getMainClassIndex() { + return this.mainClassIndex; + } + + @Override + public char[] getMainClassName() { + return this.mainClassName; + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModulePackagesAttribute.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModulePackagesAttribute.java new file mode 100644 index 0000000000..5ec838624d --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModulePackagesAttribute.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.util.ClassFormatException; +import org.eclipse.jdt.core.util.IConstantPool; +import org.eclipse.jdt.core.util.IConstantPoolConstant; +import org.eclipse.jdt.core.util.IConstantPoolEntry; +import org.eclipse.jdt.core.util.IConstantPoolEntry3; +import org.eclipse.jdt.core.util.IModulePackagesAttribute; + +/** + * Default implementation of IModulePackagesAttribute + */ +public class ModulePackagesAttribute extends ClassFileAttribute implements IModulePackagesAttribute { + + private int packagesCount; + private int[] packageIndices; + private char[][] packageNames; + + /** + * Constructor for ModulePackagesAttribute. + * @param classFileBytes + * @param constantPool + * @param offset + * @throws ClassFormatException + */ + public ModulePackagesAttribute( byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException { + super(classFileBytes, constantPool, offset); + int readOffset = 6; + final int length = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + this.packagesCount = length; + if (length != 0) { + this.packageIndices = new int[length]; + this.packageNames = new char[length][0]; + for (int i = 0; i < length; i++) { + this.packageIndices[i] = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.packageIndices[i]); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Package) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + char[] name = ((IConstantPoolEntry3) constantPoolEntry).getPackageName(); + this.packageNames[i] = name != null ? name : CharOperation.NO_CHAR; + + } + } else { + this.packageNames = CharOperation.NO_CHAR_CHAR; + } + } + + @Override + public int getPackagesCount() { + return this.packagesCount; + } + + @Override + public int[] getPackageIndices() { + return this.packageIndices; + } + + @Override + public char[][] getPackageNames() { + return this.packageNames; + } +} \ No newline at end of file diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java new file mode 100644 index 0000000000..ae8c20d892 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.Compiler; +import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; +import org.eclipse.jdt.internal.compiler.ICompilerRequestor; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.core.BasicCompilationUnit; +import org.eclipse.jdt.internal.core.ClasspathEntry; +import org.eclipse.jdt.internal.core.builder.NameEnvironment; +import org.eclipse.jdt.internal.core.builder.ProblemFactory; + +public class ModuleUtil { + + static class ModuleAccumulatorEnvironment extends NameEnvironment { + public ModuleAccumulatorEnvironment(IJavaProject javaProject) { + super(javaProject); + } + + Set modules = new HashSet<>(); + public String[] getModules() { + this.modules.remove(String.valueOf(TypeConstants.JAVA_BASE)); + String[] mods = new String[this.modules.size()]; + return this.modules.toArray(mods); + } + + @Override + protected boolean isOnModulePath(ClasspathEntry entry) { + return true; // try to interpret all dependencies as modules from now on + } + + @Override + public void cleanup() { + this.modules.clear(); + } + + @Override + public NameEnvironmentAnswer findType(char[][] compoundTypeName, char[] moduleName) { + NameEnvironmentAnswer answer = super.findType(compoundTypeName, moduleName); + if (answer != null && answer.moduleName() != null) { + this.modules.add(String.valueOf(answer.moduleName())); + } + return answer; + } + + @Override + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName) { + NameEnvironmentAnswer answer = super.findType(typeName, packageName, moduleName); + if (answer != null && answer.moduleName() != null) { + this.modules.add(String.valueOf(answer.moduleName())); + } + return answer; + } + } + private static Compiler newCompiler(ModuleAccumulatorEnvironment environment, IJavaProject javaProject) { + Map projectOptions = javaProject.getOptions(true); + CompilerOptions compilerOptions = new CompilerOptions(projectOptions); + compilerOptions.performMethodsFullRecovery = true; + compilerOptions.performStatementsRecovery = true; + ICompilerRequestor requestor = new ICompilerRequestor() { + @Override + public void acceptResult(CompilationResult result) { + // Nothing to do here + } + }; + Compiler newCompiler = new Compiler( + environment, + DefaultErrorHandlingPolicies.proceedWithAllProblems(), + compilerOptions, + requestor, + ProblemFactory.getProblemFactory(Locale.getDefault())); + + return newCompiler; + } + public static String[] getReferencedModules(IJavaProject project) throws CoreException { + + ModuleAccumulatorEnvironment environment = new ModuleAccumulatorEnvironment(project); + Compiler compiler = newCompiler(environment, project); + // First go over the binary roots and see if any of them are modules + List required = new ArrayList<>(); + Set toCompile = new HashSet<>(); + IPackageFragmentRoot[] roots = project.getPackageFragmentRoots(); + for (IPackageFragmentRoot root : roots) { + if (root.getKind() == IPackageFragmentRoot.K_SOURCE) { + IJavaElement[] children = root.getChildren(); + for (IJavaElement child : children) { + if (child instanceof IPackageFragment) { + IPackageFragment fragment = (IPackageFragment) child; + if (fragment.isDefaultPackage()) continue; + ICompilationUnit[] units = fragment.getCompilationUnits(); + if (units.length != 0) { + String pack = fragment.getElementName(); + for (ICompilationUnit iUnit : units) { + org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceFile = + new BasicCompilationUnit(iUnit.getSource().toCharArray(), + CharOperation.splitOn('.', pack.toCharArray()), + iUnit.getPath().toOSString(), + iUnit); + toCompile.add(sourceFile); + } + } + } + } + } + } + + org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sources = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[toCompile.size()]; + toCompile.toArray(sources); + compiler.compile(sources); + String[] mods = environment.getModules(); + for (String string : mods) { + required.add(string); + } + Collections.sort(required, new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.compareTo(o2); + } + }); + return required.toArray(new String[required.size()]); + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PackageVisibilityInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PackageVisibilityInfo.java new file mode 100644 index 0000000000..aa47365b2f --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PackageVisibilityInfo.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.util.ClassFormatException; +import org.eclipse.jdt.core.util.IConstantPool; +import org.eclipse.jdt.core.util.IConstantPoolConstant; +import org.eclipse.jdt.core.util.IConstantPoolEntry; +import org.eclipse.jdt.core.util.IConstantPoolEntry3; +import org.eclipse.jdt.core.util.IPackageVisibilityInfo; + +public class PackageVisibilityInfo extends ClassFileStruct implements IPackageVisibilityInfo { + + private int index; + private char[] packageName; + private int flags; + private int targetsCount; + private int[] targetModuleIndices; + private char[][] targetModuleNames; + + public PackageVisibilityInfo(byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException { + int readOffset = 0; + this.index = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.index); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Package) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + char[] tmp = ((IConstantPoolEntry3) constantPoolEntry).getPackageName(); + this.packageName = tmp != null ? tmp : CharOperation.NO_CHAR; + + this.flags = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + this.targetsCount = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + + if (this.targetsCount != 0) { + this.targetModuleIndices = new int[this.targetsCount]; + this.targetModuleNames = new char[this.targetsCount][]; + for (int i = 0; i < this.targetsCount; i++) { + this.targetModuleIndices[i] = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + constantPoolEntry = constantPool.decodeEntry(this.targetModuleIndices[i]); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Module) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + tmp = ((IConstantPoolEntry3) constantPoolEntry).getModuleName(); + this.targetModuleNames[i] = tmp != null ? tmp : CharOperation.NO_CHAR; + } + } else { + this.targetModuleIndices = new int[0]; + this.targetModuleNames = CharOperation.NO_CHAR_CHAR; + } + } + @Override + public int getIndex() { + return this.index; + } + + @Override + public char[] getPackageName() { + return this.packageName; + } + + @Override + public int getFlags() { + return this.flags; + } + + @Override + public int getTargetsCount() { + return this.targetsCount; + } + + @Override + public int[] getTargetModuleIndices() { + return this.targetModuleIndices; + } + + @Override + public char[][] getTargetModuleNames() { + return this.targetModuleNames; + } +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ProvidesInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ProvidesInfo.java new file mode 100644 index 0000000000..6292d30132 --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ProvidesInfo.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import org.eclipse.jdt.core.util.ClassFormatException; +import org.eclipse.jdt.core.util.IConstantPool; +import org.eclipse.jdt.core.util.IConstantPoolConstant; +import org.eclipse.jdt.core.util.IConstantPoolEntry; +import org.eclipse.jdt.core.util.IProvidesInfo; + +public class ProvidesInfo extends ClassFileStruct implements IProvidesInfo { + private int index; + private char[] serviceName; + private int implementationsCount; + private int[] implementationIndices; + private char[][] implementationNames; + + public ProvidesInfo(byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException { + int readOffset = 0; + this.index = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.index); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.serviceName = constantPoolEntry.getClassInfoName(); + this.implementationsCount = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + + if (this.implementationsCount != 0) { + this.implementationIndices = new int[this.implementationsCount]; + this.implementationNames = new char[this.implementationsCount][]; + for (int i = 0; i < this.implementationsCount; i++) { + this.implementationIndices[i] = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + constantPoolEntry = constantPool.decodeEntry(this.implementationIndices[i]); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.implementationNames[i] = constantPoolEntry.getClassInfoName(); + } + } + } + @Override + public int getIndex() { + return this.index; + } + + @Override + public char[] getServiceName() { + return this.serviceName; + } + + @Override + public int getImplementationsCount() { + return this.implementationsCount; + } + + @Override + public int[] getImplementationIndices() { + return this.implementationIndices; + } + + @Override + public char[][] getImplementationNames() { + return this.implementationNames; + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RequiresInfo.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RequiresInfo.java new file mode 100644 index 0000000000..a2275474ab --- /dev/null +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RequiresInfo.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.util.ClassFormatException; +import org.eclipse.jdt.core.util.IConstantPool; +import org.eclipse.jdt.core.util.IConstantPoolConstant; +import org.eclipse.jdt.core.util.IConstantPoolEntry; +import org.eclipse.jdt.core.util.IConstantPoolEntry3; +import org.eclipse.jdt.core.util.IRequiresInfo; + +public class RequiresInfo extends ClassFileStruct implements IRequiresInfo { + + private int index; + private char[] moduleName; + private int flags; + private int versionIndex; + private char[] versionName; + + public RequiresInfo(byte[] classFileBytes, IConstantPool constantPool, int offset) throws ClassFormatException{ + int readOffset = 0; + this.index = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(this.index); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Module) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.moduleName = ((IConstantPoolEntry3) constantPoolEntry).getModuleName(); + this.flags = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + this.versionIndex = u2At(classFileBytes, readOffset, offset); + readOffset += 2; + if (this.versionIndex != 0) { + constantPoolEntry = constantPool.decodeEntry(this.versionIndex); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.versionName = constantPoolEntry.getUtf8Value(); + } else { + this.versionName = CharOperation.NO_CHAR; + } + } + @Override + public int getRequiresIndex() { + return this.index; + } + + @Override + public char[] getRequiresModuleName() { + return this.moduleName; + } + + @Override + public int getRequiresFlags() { + return this.flags; + } + + @Override + public int getRequiresVersionIndex() { + return this.versionIndex; + } + + @Override + public char[] getRequiresVersionValue() { + return this.versionName; + } + +} diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java index 98385b8b22..ac3c1dfdca 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -24,10 +24,10 @@ public class ResourceCompilationUnit implements ICompilationUnit { private char[] contents; private char[] fileName; private char[] mainTypeName; - - public ResourceCompilationUnit(IFile file) { + private char[] module; + public ResourceCompilationUnit(IFile file, char[] mod) { this.file = file; - + this.module = mod; String f = file.getFullPath().toString(); this.fileName = f.toCharArray(); int start = f.lastIndexOf("/") + 1; //$NON-NLS-1$ @@ -72,4 +72,9 @@ public char[][] getPackageName() { public boolean ignoreOptionalProblems() { return false; } + + @Override + public char[] getModuleName() { + return this.module; + } } diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java index 4ad1da72c6..2a31f706a7 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -46,6 +46,7 @@ import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.env.ClassSignature; @@ -751,7 +752,7 @@ public static IClassFileAttribute getAttribute(IMethodInfo methodInfo, char[] at } private static IClassFile getClassFile(char[] fileName) { - int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName); + int jarSeparator = CharOperation.lastIndexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName); int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive if (pkgEnd == -1) pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName); @@ -845,13 +846,17 @@ public static long getJdkLevel(Object targetLibrary) { } } if (path != null) { - jar = JavaModelManager.getJavaModelManager().getZipFile(path); - for (Enumeration e= jar.entries(); e.hasMoreElements();) { - ZipEntry member= (ZipEntry) e.nextElement(); - String entryName= member.getName(); - if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) { - reader = ClassFileReader.read(jar, entryName); - break; + if (JavaModelManager.isJrt(path)) { + return ClassFileConstants.JDK9; + } else { + jar = JavaModelManager.getJavaModelManager().getZipFile(path); + for (Enumeration e= jar.entries(); e.hasMoreElements();) { + ZipEntry member= (ZipEntry) e.nextElement(); + String entryName= member.getName(); + if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) { + reader = ClassFileReader.read(jar, entryName); + break; + } } } } @@ -1480,7 +1485,7 @@ public static JavaElement getUnresolvedJavaElement(TypeBinding typeBinding, Work if (referenceBinding.isLocalType() || referenceBinding.isAnonymousType()) { // local or anonymous type if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fileName)) { - int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName); + int jarSeparator = CharOperation.lastIndexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName); int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive if (pkgEnd == -1) pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName); diff --git a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties index f8399f7e4b..dd08247c95 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties +++ b/jdt-patch/e47/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2015 IBM Corporation and others. +# Copyright (c) 2000, 2017 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -32,6 +32,7 @@ element_invalidResourceForProject = Illegal argument - must be one of IProject, element_nullName = Name cannot be null element_nullType = Type cannot be null element_illegalParent = Illegal parent argument +element_moduleInfoNotSupported=module-info.class is not supported by method IPackageFragment.getClassFile(String). ### java model operations operation_needElements = Operation requires one or more elements @@ -225,6 +226,14 @@ convention_package_dotName = A package name cannot start or end with a dot convention_package_nameWithBlanks = A package name must not start or end with a blank convention_package_consecutiveDotsName = A package name must not contain two consecutive dots convention_package_uppercaseName = By convention, package names usually start with a lowercase letter +convention_module_nullName = A module name must not be null +convention_module_emptyName = A module name must not be empty +convention_module_dotName = A module name cannot start or end with a dot +convention_module_nameWithBlanks = A module name must not start or end with a blank +convention_module_consecutiveDotsName = A module name must not contain consecutive dots +convention_module_uppercaseName = By convention, module names usually start with a lowercase letter +convention_module_terminalDigits = A module name should avoid terminal digits +convention_module_javaName = 'java' is reserved for system modules ### DOM dom_cannotDetail = Unable to generate detailed source indexes @@ -379,6 +388,10 @@ disassembler_extendedannotation_typepath_array=ARRAY disassembler_extendedannotation_typepath_innertype=INNER_TYPE disassembler_extendedannotation_typepath_wildcard=WILDCARD disassembler_extendedannotation_typepath_typeargument=TYPE_ARGUMENT({0}) +disassembler_module_version=// Version: {0} +disassembler_module_version_none= +disassembler_modulepackagesattributeheader = Module packages: +disassembler_modulemainclassattributeheader=Module main class: ### classfileformat decoding classfileformat_versiondetails =\ (version {0} : {1}.{2}, {3}) diff --git a/jdt-patch/e47/org.eclipse.jdt.core/plugin.xml b/jdt-patch/e47/org.eclipse.jdt.core/plugin.xml index 318c37352f..d31c26e236 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/plugin.xml +++ b/jdt-patch/e47/org.eclipse.jdt.core/plugin.xml @@ -186,6 +186,17 @@ + + + + + + + + diff --git a/jdt-patch/e47/org.eclipse.jdt.core/pom.bak b/jdt-patch/e47/org.eclipse.jdt.core/pom.bak index fa54c9c94f..d8d557e08a 100644 --- a/jdt-patch/e47/org.eclipse.jdt.core/pom.bak +++ b/jdt-patch/e47/org.eclipse.jdt.core/pom.bak @@ -1,6 +1,6 @@